From b1a1303a40c659b33592bef73329a86cebc4a1f6 Mon Sep 17 00:00:00 2001 From: efrilm Date: Thu, 7 Aug 2025 22:45:06 +0700 Subject: [PATCH] feat: split add customer optional --- .../payment/pages/payment_page.dart | 4 +- .../split_bill/pages/split_bill_page.dart | 240 ++++++++++-------- 2 files changed, 138 insertions(+), 106 deletions(-) diff --git a/lib/presentation/payment/pages/payment_page.dart b/lib/presentation/payment/pages/payment_page.dart index 6a153e1..4c99448 100644 --- a/lib/presentation/payment/pages/payment_page.dart +++ b/lib/presentation/payment/pages/payment_page.dart @@ -19,11 +19,13 @@ class PaymentPage extends StatefulWidget { final Order order; final bool isSplit; final String? splitType; + final String? customerId; const PaymentPage({ super.key, required this.order, this.isSplit = false, this.splitType, + this.customerId, }); @override @@ -462,7 +464,7 @@ class _PaymentPageState extends State { } else { final request = PaymentSplitBillRequest( amount: widget.order.totalAmount ?? 0, - customerId: '', + customerId: widget.customerId ?? "", items: itemPending ?.map((item) => SplitItem( orderItemId: item.id ?? "", diff --git a/lib/presentation/split_bill/pages/split_bill_page.dart b/lib/presentation/split_bill/pages/split_bill_page.dart index 3057d8e..c10c57f 100644 --- a/lib/presentation/split_bill/pages/split_bill_page.dart +++ b/lib/presentation/split_bill/pages/split_bill_page.dart @@ -2,7 +2,9 @@ import 'dart:developer'; import 'package:enaklo_pos/core/components/flushbar.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; +import 'package:enaklo_pos/data/models/response/customer_response_model.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart'; +import 'package:enaklo_pos/presentation/home/widgets/customer_auto_complete_field.dart'; import 'package:enaklo_pos/presentation/payment/pages/payment_page.dart'; import 'package:flutter/material.dart'; @@ -26,6 +28,9 @@ class SplitBillPage extends StatefulWidget { } class _SplitBillPageState extends State { + final customerController = TextEditingController(); + Customer? selectedCustomer; + int selectedSplitType = 0; // 0 = Per Product, 1 = Per Amount // Per Product Split Data @@ -186,64 +191,70 @@ class _SplitBillPageState extends State { flex: 3, child: Container( padding: EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Bagi Bill', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColorSplitBill.textPrimary, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Bagi Bill', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: AppColorSplitBill.textPrimary, + ), ), - ), - SizedBox(height: 24), + SizedBox(height: 24), - // Split Type Selection - Row( - children: [ - _buildSplitTypeButton('Per Produk', 0), - SizedBox(width: 16), - _buildSplitTypeButton('Per Jumlah', 1), - ], - ), + _buildCustomer(context), - SizedBox(height: 32), + SizedBox(height: 24), - // Split Content - Expanded( - child: selectedSplitType == 0 - ? _buildPerProductSplit() - : _buildPerAmountSplit(), - ), + // Split Type Selection + Row( + children: [ + _buildSplitTypeButton('Per Produk', 0), + SizedBox(width: 16), + _buildSplitTypeButton('Per Jumlah', 1), + ], + ), - SizedBox(height: 24), + SizedBox(height: 32), - // Action Buttons - Row( - children: [ - Expanded( - child: _buildActionButton( - 'Batal', - AppColorSplitBill.textSecondary, - Colors.transparent, - () => Navigator.pop(context), + // Split Content + Container( + child: selectedSplitType == 0 + ? _buildPerProductSplit() + : _buildPerAmountSplit(), + ), + + SizedBox(height: 24), + + // Action Buttons + Row( + children: [ + Expanded( + child: _buildActionButton( + 'Batal', + AppColorSplitBill.textSecondary, + Colors.transparent, + () => Navigator.pop(context), + ), ), - ), - SizedBox(width: 16), - Expanded( - child: _buildActionButton( - 'Konfirmasi Split', - Colors.white, - AppColorSplitBill.primary, - () { - _confirmSplit(); - }, + SizedBox(width: 16), + Expanded( + child: _buildActionButton( + 'Konfirmasi Split', + Colors.white, + AppColorSplitBill.primary, + () { + _confirmSplit(); + }, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), @@ -252,6 +263,26 @@ class _SplitBillPageState extends State { ); } + Widget _buildCustomer(BuildContext context) { + return Container( + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColorSplitBill.cardBackground, + border: Border.all(color: AppColorSplitBill.border), + borderRadius: BorderRadius.circular(8), + ), + child: CustomerAutocomplete( + controller: customerController, + selectedCustomer: selectedCustomer, + onSelected: (customer) { + setState(() { + selectedCustomer = customer; + }); + }, + ), + ); + } + Widget _buildOrderItem(OrderItem item) { return Container( padding: EdgeInsets.symmetric(vertical: 12), @@ -347,64 +378,61 @@ class _SplitBillPageState extends State { ), ), SizedBox(height: 16), - Expanded( - child: Container( - padding: EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColorSplitBill.cardBackground, - border: Border.all(color: AppColorSplitBill.border), - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Split Bill', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColorSplitBill.primary, - ), + Container( + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColorSplitBill.cardBackground, + border: Border.all(color: AppColorSplitBill.border), + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Split Bill', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppColorSplitBill.primary, ), - SizedBox(height: 16), - Expanded( - child: ListView.builder( - itemCount: getOrderItemPending().length, - itemBuilder: (context, index) { - return _buildProductSplitItem( - getOrderItemPending()[index]); - }, - ), - ), - Container( - width: double.infinity, - height: 1, - color: AppColorSplitBill.border, - margin: EdgeInsets.symmetric(vertical: 12), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Total Split:', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColorSplitBill.textPrimary, - ), + ), + SizedBox(height: 16), + ListView.builder( + itemCount: getOrderItemPending().length, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return _buildProductSplitItem(getOrderItemPending()[index]); + }, + ), + Container( + width: double.infinity, + height: 1, + color: AppColorSplitBill.border, + margin: EdgeInsets.symmetric(vertical: 12), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Total Split:', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColorSplitBill.textPrimary, ), - Text( - 'Rp ${_formatCurrency(_calculateSplitTotal())}', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColorSplitBill.primary, - ), + ), + Text( + 'Rp ${_formatCurrency(_calculateSplitTotal())}', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColorSplitBill.primary, ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), ], @@ -764,6 +792,7 @@ class _SplitBillPageState extends State { order: splitOrder, isSplit: true, splitType: 'ITEM', + customerId: selectedCustomer?.id, )); } else { AppFlushbar.showError(context, "Pilih minimal satu produk untuk split"); @@ -790,6 +819,7 @@ class _SplitBillPageState extends State { order: splitOrder, isSplit: true, splitType: 'AMOUNT', + customerId: selectedCustomer?.id, ), ); } else if (splitAmount > totalAmount) {