fix split bill

This commit is contained in:
Efril 2026-03-04 23:30:52 +07:00
parent a739e1c29e
commit 200f996d3e
6 changed files with 197 additions and 55 deletions

View File

@ -450,6 +450,23 @@ class PrintUi {
'${order.payments.last.splitNumber} / ${order.payments.last.splitTotal}', '${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( bytes += builder.summary(
totalItems: 0, totalItems: 0,
subtotal: order.payments.last.amount.currencyFormatRpV2, subtotal: order.payments.last.amount.currencyFormatRpV2,

View File

@ -167,9 +167,9 @@ class ReceiptComponentBuilder {
}) { }) {
List<int> bytes = []; List<int> bytes = [];
bytes += row2Columns('No. Pesanan', orderNumber); bytes += row2Columns('Nomor', orderNumber, leftWidth: 4, rightWidth: 8);
bytes += row2Columns('Pelanggan', customerName); bytes += row2Columns('Pelanggan', customerName);
bytes += row2Columns('Kasir', cashierName); bytes += row2Columns('Kasir', cashierName, leftWidth: 4, rightWidth: 8);
if (paymentMethod != null) { if (paymentMethod != null) {
bytes += row2Columns( bytes += row2Columns(
@ -209,11 +209,11 @@ class ReceiptComponentBuilder {
}) { }) {
List<int> bytes = []; List<int> bytes = [];
final variantText = variantName != null && variantName.isNotEmpty final displayName = (variantName != null && variantName.isNotEmpty)
? "($variantName)" ? '$productName ($variantName)'
: ''; : productName;
bytes += textLeft('$productName $variantText', bold: true); bytes += textLeft(displayName);
bytes += row2Columns( bytes += row2Columns(
'$quantity x $unitPrice', '$quantity x $unitPrice',
totalPrice, totalPrice,

View File

@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/order/order_loader/order_loader_bloc.dart'; import '../../../../../application/order/order_loader/order_loader_bloc.dart';
import '../../../../../application/printer/print_struck/print_struck_bloc.dart'; import '../../../../../application/printer/print_struck/print_struck_bloc.dart';
import '../../../../../common/theme/theme.dart'; import '../../../../../common/theme/theme.dart';
import '../../../../../domain/order/order.dart';
import '../../../../../injection.dart'; import '../../../../../injection.dart';
import '../../../../components/error/order_loader_error_state_widget.dart'; import '../../../../components/error/order_loader_error_state_widget.dart';
import '../../../../components/loader/loader_with_text.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 class PaymentSuccessSplitBillPage extends StatelessWidget
implements AutoRouteWrapper { implements AutoRouteWrapper {
final String orderId; final String orderId;
const PaymentSuccessSplitBillPage({super.key, required this.orderId}); final List<OrderItem> orderItems;
const PaymentSuccessSplitBillPage({
super.key,
required this.orderId,
required this.orderItems,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -51,7 +57,7 @@ class PaymentSuccessSplitBillPage extends StatelessWidget
Expanded( Expanded(
flex: 35, flex: 35,
child: PaymentSuccessSplitBillLeftPanel( child: PaymentSuccessSplitBillLeftPanel(
order: state.order, order: state.order.copyWith(orderItems: orderItems),
), ),
), ),
@ -61,7 +67,7 @@ class PaymentSuccessSplitBillPage extends StatelessWidget
Expanded( Expanded(
flex: 65, flex: 65,
child: PaymentSuccessSplitBillRightPanel( child: PaymentSuccessSplitBillRightPanel(
order: state.order, order: state.order.copyWith(orderItems: orderItems),
), ),
), ),
], ],

View File

@ -23,10 +23,10 @@ class PaymentSuccessSplitBillRightPanel extends StatelessWidget {
Expanded( Expanded(
child: ListView.separated( child: ListView.separated(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
itemCount: order.payments.length, itemCount: order.orderItems.length,
separatorBuilder: (context, index) => const SizedBox(height: 12), separatorBuilder: (context, index) => const SizedBox(height: 12),
itemBuilder: (context, index) { 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() { Widget _buildSummaryFooter() {
return Container( return Container(
width: double.infinity, width: double.infinity,
@ -212,47 +316,47 @@ class PaymentSuccessSplitBillRightPanel extends StatelessWidget {
); );
} }
Row _buildPaymentCard(int index) { // Row _buildPaymentCard(int index) {
final payment = order.payments[index]; // final payment = order.payments[index];
return Row( // return Row(
children: [ // children: [
Container( // Container(
width: 32, // width: 32,
height: 32, // height: 32,
decoration: BoxDecoration( // decoration: BoxDecoration(
color: AppColor.primary.withOpacity(0.1), // color: AppColor.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(4), // borderRadius: BorderRadius.circular(4),
), // ),
child: const Icon(Icons.payments, color: AppColor.primary, size: 16), // child: const Icon(Icons.payments, color: AppColor.primary, size: 16),
), // ),
const SizedBox(width: 12), // const SizedBox(width: 12),
Expanded( // Expanded(
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
children: [ // children: [
Text( // Text(
payment.paymentMethodName, // payment.paymentMethodName,
style: AppStyle.md.copyWith(fontWeight: FontWeight.w500), // style: AppStyle.md.copyWith(fontWeight: FontWeight.w500),
), // ),
if ((payment.splitTotal) > 1) // if ((payment.splitTotal) > 1)
Text( // Text(
'Split ${payment.splitNumber} of ${payment.splitTotal}', // 'Split ${payment.splitNumber} of ${payment.splitTotal}',
style: AppStyle.md.copyWith(color: AppColor.textSecondary), // style: AppStyle.md.copyWith(color: AppColor.textSecondary),
), // ),
], // ],
), // ),
), // ),
Text( // Text(
(payment.amount).currencyFormatRpV2, // (payment.amount).currencyFormatRpV2,
style: AppStyle.md.copyWith( // style: AppStyle.md.copyWith(
fontWeight: FontWeight.w600, // fontWeight: FontWeight.w600,
color: AppColor.primary, // color: AppColor.primary,
), // ),
), // ),
], // ],
); // );
} // }
Container _header() { Container _header() {
return Container( return Container(

View File

@ -63,7 +63,10 @@ class PaymentPage extends StatelessWidget implements AutoRouteWrapper {
(data) { (data) {
if (context.mounted) { if (context.mounted) {
context.router.replace( context.router.replace(
PaymentSuccessSplitBillRoute(orderId: order.id), PaymentSuccessSplitBillRoute(
orderId: order.id,
orderItems: order.orderItems,
),
); );
} }
}, },

View File

@ -293,10 +293,15 @@ class PaymentSuccessSplitBillRoute
PaymentSuccessSplitBillRoute({ PaymentSuccessSplitBillRoute({
_i23.Key? key, _i23.Key? key,
required String orderId, required String orderId,
required List<_i24.OrderItem> orderItems,
List<_i22.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
PaymentSuccessSplitBillRoute.name, PaymentSuccessSplitBillRoute.name,
args: PaymentSuccessSplitBillRouteArgs(key: key, orderId: orderId), args: PaymentSuccessSplitBillRouteArgs(
key: key,
orderId: orderId,
orderItems: orderItems,
),
initialChildren: children, initialChildren: children,
); );
@ -310,6 +315,7 @@ class PaymentSuccessSplitBillRoute
child: _i9.PaymentSuccessSplitBillPage( child: _i9.PaymentSuccessSplitBillPage(
key: args.key, key: args.key,
orderId: args.orderId, orderId: args.orderId,
orderItems: args.orderItems,
), ),
); );
}, },
@ -317,15 +323,21 @@ class PaymentSuccessSplitBillRoute
} }
class PaymentSuccessSplitBillRouteArgs { class PaymentSuccessSplitBillRouteArgs {
const PaymentSuccessSplitBillRouteArgs({this.key, required this.orderId}); const PaymentSuccessSplitBillRouteArgs({
this.key,
required this.orderId,
required this.orderItems,
});
final _i23.Key? key; final _i23.Key? key;
final String orderId; final String orderId;
final List<_i24.OrderItem> orderItems;
@override @override
String toString() { String toString() {
return 'PaymentSuccessSplitBillRouteArgs{key: $key, orderId: $orderId}'; return 'PaymentSuccessSplitBillRouteArgs{key: $key, orderId: $orderId, orderItems: $orderItems}';
} }
} }