284 lines
6.5 KiB
Dart
284 lines
6.5 KiB
Dart
import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
/// Reusable component builder untuk thermal receipt printer
|
|
class ReceiptComponentBuilder {
|
|
final Generator generator;
|
|
final int paperSize;
|
|
|
|
ReceiptComponentBuilder({required this.generator, this.paperSize = 58});
|
|
|
|
/// Get separator line based on paper size
|
|
String get _separator => paperSize == 80
|
|
? '------------------------------------------------'
|
|
: '--------------------------------';
|
|
|
|
/// Print text centered with custom style
|
|
List<int> textCenter(
|
|
String text, {
|
|
bool bold = false,
|
|
PosTextSize height = PosTextSize.size1,
|
|
PosTextSize width = PosTextSize.size1,
|
|
}) {
|
|
return generator.text(
|
|
text,
|
|
styles: PosStyles(
|
|
bold: bold,
|
|
align: PosAlign.center,
|
|
height: height,
|
|
width: width,
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Print text aligned left
|
|
List<int> textLeft(String text, {bool bold = false}) {
|
|
return generator.text(
|
|
text,
|
|
styles: PosStyles(bold: bold, align: PosAlign.left),
|
|
);
|
|
}
|
|
|
|
/// Print text aligned right
|
|
List<int> textRight(String text, {bool bold = false}) {
|
|
return generator.text(
|
|
text,
|
|
styles: PosStyles(bold: bold, align: PosAlign.right),
|
|
);
|
|
}
|
|
|
|
/// Print separator line
|
|
List<int> separator({bool bold = false}) {
|
|
return generator.text(
|
|
_separator,
|
|
styles: PosStyles(bold: bold, align: PosAlign.center),
|
|
);
|
|
}
|
|
|
|
/// Print row with 2 columns (label: value)
|
|
List<int> row2Columns(
|
|
String leftText,
|
|
String rightText, {
|
|
bool bold = false,
|
|
int leftWidth = 6,
|
|
int rightWidth = 6,
|
|
}) {
|
|
return generator.row([
|
|
PosColumn(
|
|
text: leftText,
|
|
width: leftWidth,
|
|
styles: PosStyles(align: PosAlign.left, bold: bold),
|
|
),
|
|
PosColumn(
|
|
text: rightText,
|
|
width: rightWidth,
|
|
styles: PosStyles(align: PosAlign.right, bold: bold),
|
|
),
|
|
]);
|
|
}
|
|
|
|
/// Print row with 3 columns
|
|
List<int> row3Columns(
|
|
String leftText,
|
|
String centerText,
|
|
String rightText, {
|
|
int leftWidth = 4,
|
|
int centerWidth = 4,
|
|
int rightWidth = 4,
|
|
}) {
|
|
return generator.row([
|
|
PosColumn(
|
|
text: leftText,
|
|
width: leftWidth,
|
|
styles: const PosStyles(align: PosAlign.left),
|
|
),
|
|
PosColumn(
|
|
text: centerText,
|
|
width: centerWidth,
|
|
styles: const PosStyles(align: PosAlign.center),
|
|
),
|
|
PosColumn(
|
|
text: rightText,
|
|
width: rightWidth,
|
|
styles: const PosStyles(align: PosAlign.right),
|
|
),
|
|
]);
|
|
}
|
|
|
|
/// Print empty lines
|
|
List<int> emptyLines(int count) {
|
|
return generator.emptyLines(count);
|
|
}
|
|
|
|
/// Print feed lines
|
|
List<int> feed(int count) {
|
|
return generator.feed(count);
|
|
}
|
|
|
|
/// Print header (outlet info)
|
|
List<int> header({
|
|
required String outletName,
|
|
required String address,
|
|
required String phoneNumber,
|
|
}) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += textCenter(
|
|
outletName,
|
|
bold: true,
|
|
height: PosTextSize.size1,
|
|
width: PosTextSize.size1,
|
|
);
|
|
bytes += textCenter(address);
|
|
bytes += textCenter(phoneNumber);
|
|
bytes += separator();
|
|
|
|
return bytes;
|
|
}
|
|
|
|
List<int> printerType({required String printerType}) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += textCenter(
|
|
printerType,
|
|
bold: true,
|
|
height: PosTextSize.size1,
|
|
width: PosTextSize.size1,
|
|
);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print date and time
|
|
List<int> dateTime(DateTime dateTime) {
|
|
return row2Columns(
|
|
DateFormat('dd MMM yyyy').format(dateTime),
|
|
DateFormat('HH:mm').format(dateTime),
|
|
);
|
|
}
|
|
|
|
/// Print order info section
|
|
List<int> orderInfo({
|
|
required String orderNumber,
|
|
required String customerName,
|
|
required String cashierName,
|
|
String? paymentMethod,
|
|
String? tableNumber,
|
|
}) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += row2Columns('No. Pesanan', orderNumber);
|
|
bytes += row2Columns('Pelanggan', customerName);
|
|
bytes += row2Columns('Kasir', cashierName);
|
|
|
|
if (paymentMethod != null) {
|
|
bytes += row2Columns(
|
|
'Pembayaran',
|
|
paymentMethod,
|
|
leftWidth: 8,
|
|
rightWidth: 4,
|
|
);
|
|
}
|
|
|
|
if (tableNumber != null && tableNumber.isNotEmpty) {
|
|
bytes += row2Columns('Meja', tableNumber, leftWidth: 8, rightWidth: 4);
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print order type (Dine In, Take Away, etc)
|
|
List<int> orderType(String type) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += separator();
|
|
bytes += textCenter(type, bold: true);
|
|
bytes += separator();
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print single item
|
|
List<int> orderItem({
|
|
required String productName,
|
|
required int quantity,
|
|
required String unitPrice,
|
|
required String totalPrice,
|
|
String? variantName,
|
|
String? notes,
|
|
}) {
|
|
List<int> bytes = [];
|
|
|
|
final variantText = variantName != null && variantName.isNotEmpty
|
|
? "($variantName)"
|
|
: '';
|
|
|
|
bytes += textLeft('$productName $variantText', bold: true);
|
|
bytes += row2Columns(
|
|
'$quantity x $unitPrice',
|
|
totalPrice,
|
|
leftWidth: 8,
|
|
rightWidth: 4,
|
|
);
|
|
|
|
if (notes != null && notes.isNotEmpty) {
|
|
bytes += row2Columns('Note', notes, leftWidth: 4, rightWidth: 8);
|
|
}
|
|
|
|
bytes += emptyLines(1);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print summary section
|
|
List<int> summary({
|
|
required int totalItems,
|
|
required String subtotal,
|
|
required String discount,
|
|
required String total,
|
|
required String paid,
|
|
}) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += separator();
|
|
bytes += row2Columns('Total Item', totalItems.toString());
|
|
bytes += row2Columns('Subtotal', subtotal);
|
|
bytes += row2Columns('Diskon', discount);
|
|
bytes += separator();
|
|
bytes += row2Columns('Total', total, bold: true);
|
|
bytes += row2Columns('Bayar', paid);
|
|
bytes += separator();
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print footer (thank you message)
|
|
List<int> footer({String message = 'Terima kasih'}) {
|
|
List<int> bytes = [];
|
|
|
|
bytes += emptyLines(2);
|
|
bytes += textCenter(
|
|
message,
|
|
bold: true,
|
|
height: PosTextSize.size1,
|
|
width: PosTextSize.size1,
|
|
);
|
|
bytes += feed(paperSize == 80 ? 3 : 1);
|
|
bytes += generator.cut();
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/// Print QR Code
|
|
List<int> qrCode(String data, {PosAlign align = PosAlign.center}) {
|
|
return generator.qrcode(data, align: align);
|
|
}
|
|
|
|
/// Print barcode
|
|
// List<int> barcode(String data, {BarcodeType type = BarcodeType.code128}) {
|
|
// return generator.barcode(
|
|
// Barcode.code128(data),
|
|
// );
|
|
// }
|
|
}
|