From 200f996d3eda5aa03aa5c9f07f579023b185e93f Mon Sep 17 00:00:00 2001 From: Efril Date: Wed, 4 Mar 2026 23:30:52 +0700 Subject: [PATCH] fix split bill --- .../components/print/print_ui.dart | 17 ++ .../print/receipt_component_builder.dart | 12 +- .../payment_success_split_bill_page.dart | 12 +- ...ayment_success_split_bill_right_panel.dart | 188 ++++++++++++++---- .../pages/payment/payment_page.dart | 5 +- lib/presentation/router/app_router.gr.dart | 18 +- 6 files changed, 197 insertions(+), 55 deletions(-) diff --git a/lib/presentation/components/print/print_ui.dart b/lib/presentation/components/print/print_ui.dart index 1e4e060..6ea550b 100644 --- a/lib/presentation/components/print/print_ui.dart +++ b/lib/presentation/components/print/print_ui.dart @@ -450,6 +450,23 @@ class PrintUi { '${order.payments.last.splitNumber} / ${order.payments.last.splitTotal}', ); + bytes += builder.separator(); + + bytes += builder.emptyLines(1); + + for (final item in order.orderItems) { + bytes += builder.orderItem( + productName: item.productName, + quantity: item.quantity, + unitPrice: item.unitPrice.currencyFormatRpV2, + totalPrice: item.totalPrice.currencyFormatRpV2, + variantName: item.productVariantName, + notes: item.notes, + ); + } + + bytes += builder.emptyLines(1); + bytes += builder.summary( totalItems: 0, subtotal: order.payments.last.amount.currencyFormatRpV2, diff --git a/lib/presentation/components/print/receipt_component_builder.dart b/lib/presentation/components/print/receipt_component_builder.dart index 77bcf74..9691950 100644 --- a/lib/presentation/components/print/receipt_component_builder.dart +++ b/lib/presentation/components/print/receipt_component_builder.dart @@ -167,9 +167,9 @@ class ReceiptComponentBuilder { }) { List bytes = []; - bytes += row2Columns('No. Pesanan', orderNumber); + bytes += row2Columns('Nomor', orderNumber, leftWidth: 4, rightWidth: 8); bytes += row2Columns('Pelanggan', customerName); - bytes += row2Columns('Kasir', cashierName); + bytes += row2Columns('Kasir', cashierName, leftWidth: 4, rightWidth: 8); if (paymentMethod != null) { bytes += row2Columns( @@ -209,11 +209,11 @@ class ReceiptComponentBuilder { }) { List bytes = []; - final variantText = variantName != null && variantName.isNotEmpty - ? "($variantName)" - : ''; + final displayName = (variantName != null && variantName.isNotEmpty) + ? '$productName ($variantName)' + : productName; - bytes += textLeft('$productName $variantText', bold: true); + bytes += textLeft(displayName); bytes += row2Columns( '$quantity x $unitPrice', totalPrice, diff --git a/lib/presentation/pages/payment/pages/payment_success_split_bill/payment_success_split_bill_page.dart b/lib/presentation/pages/payment/pages/payment_success_split_bill/payment_success_split_bill_page.dart index f285ce1..7995df4 100644 --- a/lib/presentation/pages/payment/pages/payment_success_split_bill/payment_success_split_bill_page.dart +++ b/lib/presentation/pages/payment/pages/payment_success_split_bill/payment_success_split_bill_page.dart @@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../application/order/order_loader/order_loader_bloc.dart'; import '../../../../../application/printer/print_struck/print_struck_bloc.dart'; import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/order/order.dart'; import '../../../../../injection.dart'; import '../../../../components/error/order_loader_error_state_widget.dart'; import '../../../../components/loader/loader_with_text.dart'; @@ -16,7 +17,12 @@ import 'widgets/payment_success_split_bill_right_panel.dart'; class PaymentSuccessSplitBillPage extends StatelessWidget implements AutoRouteWrapper { final String orderId; - const PaymentSuccessSplitBillPage({super.key, required this.orderId}); + final List orderItems; + const PaymentSuccessSplitBillPage({ + super.key, + required this.orderId, + required this.orderItems, + }); @override Widget build(BuildContext context) { @@ -51,7 +57,7 @@ class PaymentSuccessSplitBillPage extends StatelessWidget Expanded( flex: 35, child: PaymentSuccessSplitBillLeftPanel( - order: state.order, + order: state.order.copyWith(orderItems: orderItems), ), ), @@ -61,7 +67,7 @@ class PaymentSuccessSplitBillPage extends StatelessWidget Expanded( flex: 65, child: PaymentSuccessSplitBillRightPanel( - order: state.order, + order: state.order.copyWith(orderItems: orderItems), ), ), ], diff --git a/lib/presentation/pages/payment/pages/payment_success_split_bill/widgets/payment_success_split_bill_right_panel.dart b/lib/presentation/pages/payment/pages/payment_success_split_bill/widgets/payment_success_split_bill_right_panel.dart index 0763c1a..1372e06 100644 --- a/lib/presentation/pages/payment/pages/payment_success_split_bill/widgets/payment_success_split_bill_right_panel.dart +++ b/lib/presentation/pages/payment/pages/payment_success_split_bill/widgets/payment_success_split_bill_right_panel.dart @@ -23,10 +23,10 @@ class PaymentSuccessSplitBillRightPanel extends StatelessWidget { Expanded( child: ListView.separated( padding: const EdgeInsets.all(24.0), - itemCount: order.payments.length, + itemCount: order.orderItems.length, separatorBuilder: (context, index) => const SizedBox(height: 12), itemBuilder: (context, index) { - return _buildPaymentCard(index); + return _buildProductCard(index); }, ), ), @@ -36,6 +36,110 @@ class PaymentSuccessSplitBillRightPanel extends StatelessWidget { ); } + Widget _buildProductCard(int index) { + final item = order.orderItems[index]; + + return Container( + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all(color: AppColor.border, width: 1), + ), + child: Row( + children: [ + // Enhanced Product Image + Container( + width: 70, + height: 70, + decoration: BoxDecoration( + color: AppColor.primaryWithOpacity(0.1), + borderRadius: BorderRadius.circular(16.0), + ), + child: const Icon( + Icons.restaurant_rounded, + color: AppColor.primary, + size: 28, + ), + ), + + const SpaceWidth(16), + + // Product Details + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.productName, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SpaceHeight(6), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(8), + ), + child: Text( + item.unitPrice.currencyFormatRpV2, + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + + const SpaceWidth(16), + + // Quantity and Total + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary, + AppColor.primary.withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + '${item.quantity}x', + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ), + const SpaceHeight(8), + Text( + item.totalPrice.toString().currencyFormatRpV2, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + ], + ), + ], + ), + ); + } + Widget _buildSummaryFooter() { return Container( width: double.infinity, @@ -212,47 +316,47 @@ class PaymentSuccessSplitBillRightPanel extends StatelessWidget { ); } - Row _buildPaymentCard(int index) { - final payment = order.payments[index]; + // Row _buildPaymentCard(int index) { + // final payment = order.payments[index]; - return Row( - children: [ - Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: AppColor.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(4), - ), - child: const Icon(Icons.payments, color: AppColor.primary, size: 16), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - payment.paymentMethodName, - style: AppStyle.md.copyWith(fontWeight: FontWeight.w500), - ), - if ((payment.splitTotal) > 1) - Text( - 'Split ${payment.splitNumber} of ${payment.splitTotal}', - style: AppStyle.md.copyWith(color: AppColor.textSecondary), - ), - ], - ), - ), - Text( - (payment.amount).currencyFormatRpV2, - style: AppStyle.md.copyWith( - fontWeight: FontWeight.w600, - color: AppColor.primary, - ), - ), - ], - ); - } + // return Row( + // children: [ + // Container( + // width: 32, + // height: 32, + // decoration: BoxDecoration( + // color: AppColor.primary.withOpacity(0.1), + // borderRadius: BorderRadius.circular(4), + // ), + // child: const Icon(Icons.payments, color: AppColor.primary, size: 16), + // ), + // const SizedBox(width: 12), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // payment.paymentMethodName, + // style: AppStyle.md.copyWith(fontWeight: FontWeight.w500), + // ), + // if ((payment.splitTotal) > 1) + // Text( + // 'Split ${payment.splitNumber} of ${payment.splitTotal}', + // style: AppStyle.md.copyWith(color: AppColor.textSecondary), + // ), + // ], + // ), + // ), + // Text( + // (payment.amount).currencyFormatRpV2, + // style: AppStyle.md.copyWith( + // fontWeight: FontWeight.w600, + // color: AppColor.primary, + // ), + // ), + // ], + // ); + // } Container _header() { return Container( diff --git a/lib/presentation/pages/payment/payment_page.dart b/lib/presentation/pages/payment/payment_page.dart index 9729911..af71bc4 100644 --- a/lib/presentation/pages/payment/payment_page.dart +++ b/lib/presentation/pages/payment/payment_page.dart @@ -63,7 +63,10 @@ class PaymentPage extends StatelessWidget implements AutoRouteWrapper { (data) { if (context.mounted) { context.router.replace( - PaymentSuccessSplitBillRoute(orderId: order.id), + PaymentSuccessSplitBillRoute( + orderId: order.id, + orderItems: order.orderItems, + ), ); } }, diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index 2ff9b5a..98a60e7 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -293,10 +293,15 @@ class PaymentSuccessSplitBillRoute PaymentSuccessSplitBillRoute({ _i23.Key? key, required String orderId, + required List<_i24.OrderItem> orderItems, List<_i22.PageRouteInfo>? children, }) : super( PaymentSuccessSplitBillRoute.name, - args: PaymentSuccessSplitBillRouteArgs(key: key, orderId: orderId), + args: PaymentSuccessSplitBillRouteArgs( + key: key, + orderId: orderId, + orderItems: orderItems, + ), initialChildren: children, ); @@ -310,6 +315,7 @@ class PaymentSuccessSplitBillRoute child: _i9.PaymentSuccessSplitBillPage( key: args.key, orderId: args.orderId, + orderItems: args.orderItems, ), ); }, @@ -317,15 +323,21 @@ class PaymentSuccessSplitBillRoute } class PaymentSuccessSplitBillRouteArgs { - const PaymentSuccessSplitBillRouteArgs({this.key, required this.orderId}); + const PaymentSuccessSplitBillRouteArgs({ + this.key, + required this.orderId, + required this.orderItems, + }); final _i23.Key? key; final String orderId; + final List<_i24.OrderItem> orderItems; + @override String toString() { - return 'PaymentSuccessSplitBillRouteArgs{key: $key, orderId: $orderId}'; + return 'PaymentSuccessSplitBillRouteArgs{key: $key, orderId: $orderId, orderItems: $orderItems}'; } }