feat: split add customer optional

This commit is contained in:
efrilm 2025-08-07 22:45:06 +07:00
parent de22251440
commit b1a1303a40
2 changed files with 138 additions and 106 deletions

View File

@ -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<PaymentPage> {
} else {
final request = PaymentSplitBillRequest(
amount: widget.order.totalAmount ?? 0,
customerId: '',
customerId: widget.customerId ?? "",
items: itemPending
?.map((item) => SplitItem(
orderItemId: item.id ?? "",

View File

@ -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<SplitBillPage> {
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<SplitBillPage> {
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<SplitBillPage> {
);
}
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<SplitBillPage> {
),
),
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<SplitBillPage> {
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<SplitBillPage> {
order: splitOrder,
isSplit: true,
splitType: 'AMOUNT',
customerId: selectedCustomer?.id,
),
);
} else if (splitAmount > totalAmount) {