1106 lines
52 KiB
Dart
1106 lines
52 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:niogu_app/core/constants/app_color.dart';
|
|
import 'package:niogu_app/core/constants/app_font_size.dart';
|
|
import 'package:niogu_app/core/router/app_route.dart';
|
|
import 'package:niogu_app/core/utils/currency_format.dart';
|
|
import 'package:niogu_app/core/utils/extension_format.dart';
|
|
import 'package:niogu_app/core/utils/login_required.dart';
|
|
import 'package:niogu_app/core/enums/user_role.dart';
|
|
import 'package:niogu_app/core/widgets/custom_form_input.dart';
|
|
import 'package:niogu_app/core/widgets/custom_proof_image_uploader.dart';
|
|
import 'package:niogu_app/core/widgets/custom_text_form_field.dart';
|
|
import 'package:niogu_app/features/pos/domain/entities/pos.dart';
|
|
import 'package:niogu_app/features/pos/presentation/widgets/bill_summary.dart';
|
|
import 'package:niogu_app/features/pos/presentation/widgets/cart_item_tile.dart';
|
|
import 'package:niogu_app/features/pos/presentation/widgets/information_header.dart';
|
|
import 'package:sizer/sizer.dart';
|
|
|
|
class CartBottomSheet extends StatelessWidget {
|
|
final bool isLoggedIn;
|
|
final DraggableScrollableController sheetController;
|
|
final GlobalKey<FormState> formKey;
|
|
final String? currentUserName;
|
|
final String? currentOutletName;
|
|
final UserRole? currentUserRole;
|
|
final List<CartItems> cartItems;
|
|
final double shoppingAmount;
|
|
final int productAmount;
|
|
final double totalQty;
|
|
final TextEditingController discountController;
|
|
final TextEditingController taxController;
|
|
final TextEditingController noteController;
|
|
final TextEditingController nameController;
|
|
final TextEditingController phoneNumberController;
|
|
final TextEditingController addressController;
|
|
final bool validateChange;
|
|
final double totalBill;
|
|
final VoidCallback onViewOrderPressed;
|
|
final VoidCallback onOtherFormTap;
|
|
final VoidCallback onCustomerFormTap;
|
|
final bool isOtherFormVisible;
|
|
final bool isCustomerFormVisible;
|
|
final SelectedCustomer? selectedCustomer;
|
|
final VoidCallback? onTapCloseSelectedCustomer;
|
|
final TextEditingController payController;
|
|
final void Function(String)? calculateChange;
|
|
final double changeAmount;
|
|
final String? imagePath;
|
|
final void Function(CartItems) onDecrementTap;
|
|
final void Function(CartItems) onIncrementTap;
|
|
final void Function(CartItems) onEditPressed;
|
|
final void Function(CartItems) onDeletePressed;
|
|
final void Function(String)? discountOnChanged;
|
|
final void Function(String)? taxOnChanged;
|
|
final VoidCallback onTapImageAdd;
|
|
final VoidCallback onTapImageRemove;
|
|
final VoidCallback? onProccessPressed;
|
|
|
|
const CartBottomSheet({
|
|
super.key,
|
|
required this.isLoggedIn,
|
|
required this.sheetController,
|
|
required this.formKey,
|
|
this.currentUserName,
|
|
this.currentOutletName,
|
|
this.currentUserRole,
|
|
required this.cartItems,
|
|
required this.shoppingAmount,
|
|
required this.productAmount,
|
|
required this.totalQty,
|
|
required this.discountController,
|
|
required this.taxController,
|
|
required this.noteController,
|
|
required this.nameController,
|
|
required this.phoneNumberController,
|
|
required this.addressController,
|
|
required this.validateChange,
|
|
required this.totalBill,
|
|
required this.onViewOrderPressed,
|
|
required this.onOtherFormTap,
|
|
required this.onCustomerFormTap,
|
|
required this.isOtherFormVisible,
|
|
required this.isCustomerFormVisible,
|
|
required this.selectedCustomer,
|
|
this.onTapCloseSelectedCustomer,
|
|
required this.payController,
|
|
required this.calculateChange,
|
|
required this.changeAmount,
|
|
required this.imagePath,
|
|
required this.onDecrementTap,
|
|
required this.onIncrementTap,
|
|
required this.onEditPressed,
|
|
required this.onDeletePressed,
|
|
required this.discountOnChanged,
|
|
required this.taxOnChanged,
|
|
required this.onTapImageAdd,
|
|
required this.onTapImageRemove,
|
|
required this.onProccessPressed,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final bool isTablet = 100.w >= 600;
|
|
|
|
return DraggableScrollableSheet(
|
|
controller: sheetController,
|
|
initialChildSize: 0.24,
|
|
minChildSize: 0.24,
|
|
maxChildSize: 0.9,
|
|
builder: (context, scrollController) {
|
|
String? discountErrorText;
|
|
String? taxErrorText;
|
|
String? payErrorText;
|
|
|
|
final double payAmount =
|
|
double.tryParse(payController.text.trim()) ?? 0.0;
|
|
|
|
final bool isViewChangeAmount =
|
|
payAmount >= totalBill && cartItems.isNotEmpty;
|
|
|
|
try {
|
|
if (discountController.text.isNotEmpty) {
|
|
final double discount = double.parse(
|
|
discountController.text.trim(),
|
|
);
|
|
if (discount <= 0) {
|
|
discountErrorText = "Diskon harus lebih dari 0";
|
|
}
|
|
}
|
|
} catch (e) {
|
|
discountErrorText = "Nominal diskon tidak valid";
|
|
}
|
|
|
|
try {
|
|
if (taxController.text.isNotEmpty) {
|
|
final double tax = double.parse(taxController.text.trim());
|
|
if (tax <= 0) {
|
|
taxErrorText = "Pajak harus lebih dari 0";
|
|
}
|
|
}
|
|
} catch (e) {
|
|
taxErrorText = "Nominal pajak tidak valid";
|
|
}
|
|
|
|
try {
|
|
if (payController.text.isNotEmpty && validateChange) {
|
|
final double payAmount = double.parse(payController.text.trim());
|
|
if (payAmount <= 0) {
|
|
payErrorText = "Nominal pembayaran harus lebih dari 0";
|
|
}
|
|
if (totalBill > payAmount) {
|
|
payErrorText =
|
|
"Kurang ${CurrencyFormat.formatToIdr((totalBill - payAmount), 0)}";
|
|
}
|
|
}
|
|
} catch (e) {
|
|
payErrorText = "Nominal pembayaran tidak valid";
|
|
}
|
|
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(5.w)),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 20,
|
|
offset: const Offset(0, -5),
|
|
),
|
|
],
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadiusGeometry.circular(2.5.w),
|
|
child: Material(
|
|
color: Colors.white,
|
|
type: MaterialType.canvas,
|
|
child: LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
final List<Widget> listChildren = [
|
|
Text(
|
|
"Daftar Pesanan",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
),
|
|
SizedBox(height: 2.h),
|
|
|
|
if (cartItems.isEmpty)
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.add_box_outlined,
|
|
size: 5.w,
|
|
color: Colors.grey,
|
|
),
|
|
SizedBox(width: 2.5.w),
|
|
Text(
|
|
"Keranjang Kosong, Tambah Produk",
|
|
style: TextStyle(
|
|
color: Colors.grey,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
),
|
|
],
|
|
)
|
|
else
|
|
...List.generate(cartItems.length, (index) {
|
|
return CartItemTile(
|
|
cartItem: cartItems[index],
|
|
onDecrementTap: onDecrementTap,
|
|
onIncrementTap: onIncrementTap,
|
|
onEditPressed: onEditPressed,
|
|
onDeletePressed: onDeletePressed,
|
|
);
|
|
}),
|
|
Divider(height: 4.h),
|
|
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
Expanded(
|
|
child: CustomTextFormField(
|
|
label: "Jumlah Produk",
|
|
controller: TextEditingController(
|
|
text: productAmount > 0
|
|
? productAmount.toString()
|
|
: '',
|
|
),
|
|
readOnly: true,
|
|
),
|
|
),
|
|
SizedBox(width: 4.w),
|
|
Expanded(
|
|
child: CustomTextFormField(
|
|
label: "Total Kuantitas Produk",
|
|
controller: TextEditingController(
|
|
text: totalQty > 0
|
|
? totalQty.toStringWithoutTrailingZero()
|
|
: '',
|
|
),
|
|
readOnly: true,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 3.h),
|
|
|
|
CustomTextFormField(
|
|
label: "Subtotal",
|
|
controller: TextEditingController(
|
|
text: shoppingAmount > 0
|
|
? shoppingAmount.toStringWithoutTrailingZero()
|
|
: '',
|
|
),
|
|
readOnly: true,
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
InkWell(
|
|
onTap: onOtherFormTap,
|
|
borderRadius: BorderRadius.vertical(
|
|
top: Radius.circular(2.5.w),
|
|
bottom: Radius.circular(
|
|
isOtherFormVisible ? 0 : 2.5.w,
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 4.w,
|
|
vertical: 1.5.h,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.all(1.5.w),
|
|
decoration: BoxDecoration(
|
|
color: isOtherFormVisible
|
|
? AppColor.primaryColor.withOpacity(
|
|
0.1,
|
|
)
|
|
: Colors.grey[100],
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
Icons.info_outlined,
|
|
color: isOtherFormVisible
|
|
? AppColor.primaryColor
|
|
: Colors.grey,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
SizedBox(width: 3.w),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Informasi Lain",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
SizedBox(height: 1.h),
|
|
Text(
|
|
"Opsional (Diskon, Pajak, Catatan)",
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Icon(
|
|
isOtherFormVisible
|
|
? Icons.keyboard_arrow_up_rounded
|
|
: Icons.keyboard_arrow_down_rounded,
|
|
color: Colors.grey,
|
|
size: 6.w,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (isOtherFormVisible) ...[
|
|
Divider(height: 1, color: Colors.grey.shade200),
|
|
Padding(
|
|
padding: EdgeInsets.all(4.w),
|
|
child: Column(
|
|
children: [
|
|
CustomFormInput(
|
|
label: "Diskon (Rp)",
|
|
icon: Icons.discount_outlined,
|
|
controller: discountController,
|
|
onChanged: discountOnChanged,
|
|
inputType: TextInputType.number,
|
|
validator: (value) {
|
|
if (value != null && value.isNotEmpty) {
|
|
try {
|
|
final double discount = double.parse(
|
|
value,
|
|
);
|
|
if (discount <= 0) {
|
|
return "Diskon harus lebih dari 0";
|
|
}
|
|
} catch (e) {
|
|
return "Nominal diskon tidak valid";
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
errorText: discountErrorText,
|
|
),
|
|
SizedBox(height: 1.5.h),
|
|
CustomFormInput(
|
|
label: "Pajak (Rp)",
|
|
icon: Icons.money_outlined,
|
|
controller: taxController,
|
|
onChanged: taxOnChanged,
|
|
inputType: TextInputType.number,
|
|
validator: (value) {
|
|
if (value != null && value.isNotEmpty) {
|
|
try {
|
|
final double tax = double.parse(
|
|
value,
|
|
);
|
|
if (tax <= 0) {
|
|
return "Pajak harus lebih dari 0";
|
|
}
|
|
} catch (e) {
|
|
return "Nominal pajak tidak valid";
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
errorText: taxErrorText,
|
|
),
|
|
SizedBox(height: 1.5.h),
|
|
CustomFormInput(
|
|
label: "Catatan",
|
|
icon: Icons.note_alt_outlined,
|
|
controller: noteController,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
InkWell(
|
|
onTap: onCustomerFormTap,
|
|
borderRadius: BorderRadius.vertical(
|
|
top: Radius.circular(2.5.w),
|
|
bottom: Radius.circular(
|
|
isCustomerFormVisible ? 0 : 2.5.w,
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 4.w,
|
|
vertical: 1.5.h,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.all(1.5.w),
|
|
decoration: BoxDecoration(
|
|
color: isCustomerFormVisible
|
|
? AppColor.primaryColor.withOpacity(
|
|
0.1,
|
|
)
|
|
: Colors.grey[100],
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
Icons.person_outline_rounded,
|
|
color: isCustomerFormVisible
|
|
? AppColor.primaryColor
|
|
: Colors.grey,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
SizedBox(width: 3.w),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Informasi Pelanggan",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
SizedBox(height: 1.h),
|
|
Text(
|
|
"Opsional (Nama, No. Hp / WA)",
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Icon(
|
|
isCustomerFormVisible
|
|
? Icons.keyboard_arrow_up_rounded
|
|
: Icons.keyboard_arrow_down_rounded,
|
|
color: Colors.grey,
|
|
size: 6.w,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (isCustomerFormVisible) ...[
|
|
Divider(height: 1, color: Colors.grey.shade200),
|
|
Padding(
|
|
padding: EdgeInsets.all(4.w),
|
|
child: selectedCustomer != null
|
|
? Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.all(4.w),
|
|
decoration: BoxDecoration(
|
|
color: AppColor.primaryColor
|
|
.withOpacity(0.05),
|
|
borderRadius: BorderRadius.circular(
|
|
2.5.w,
|
|
),
|
|
border: Border.all(
|
|
color: AppColor.primaryColor
|
|
.withOpacity(0.3),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.all(2.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
shape: BoxShape.circle,
|
|
border: Border.all(
|
|
color: AppColor.primaryColor
|
|
.withOpacity(0.2),
|
|
),
|
|
),
|
|
child: Icon(
|
|
Icons.person,
|
|
color: AppColor.primaryColor,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
SizedBox(width: 3.w),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
selectedCustomer!.name,
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
if (selectedCustomer!
|
|
.phoneNumber
|
|
.isNotEmpty) ...[
|
|
SizedBox(height: 0.75.h),
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.phone_android,
|
|
size: 5.w,
|
|
color: Colors.grey[600],
|
|
),
|
|
SizedBox(width: 1.w),
|
|
Text(
|
|
selectedCustomer!
|
|
.phoneNumber,
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize
|
|
.medium
|
|
.sp
|
|
: AppFontSize
|
|
.small
|
|
.sp,
|
|
color:
|
|
Colors.grey[700],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
|
|
if (selectedCustomer!
|
|
.address
|
|
.isNotEmpty) ...[
|
|
SizedBox(height: 0.75.h),
|
|
Row(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.start,
|
|
children: [
|
|
Icon(
|
|
Icons
|
|
.location_on_outlined,
|
|
size: 5.w,
|
|
color: Colors.grey[600],
|
|
),
|
|
SizedBox(width: 1.w),
|
|
Expanded(
|
|
child: Text(
|
|
selectedCustomer!
|
|
.address,
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize
|
|
.medium
|
|
.sp
|
|
: AppFontSize
|
|
.small
|
|
.sp,
|
|
color: Colors
|
|
.grey[700],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: onTapCloseSelectedCustomer,
|
|
child: Icon(
|
|
Icons.close,
|
|
color: Colors.grey,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
: Column(
|
|
children: [
|
|
SizedBox(
|
|
width: double.infinity,
|
|
height: 5.5.h,
|
|
child: OutlinedButton.icon(
|
|
onPressed: () => !isLoggedIn
|
|
? LoginRequired.showLoginRequired(
|
|
context,
|
|
)
|
|
: context.pushNamed(
|
|
AppRoute
|
|
.alreadyCustomerScreen,
|
|
),
|
|
style: OutlinedButton.styleFrom(
|
|
side: BorderSide(
|
|
color: AppColor.primaryColor,
|
|
),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
2.5.w,
|
|
),
|
|
),
|
|
backgroundColor: Colors.blue[50],
|
|
),
|
|
icon: Icon(
|
|
Icons.people_alt_rounded,
|
|
color: AppColor.primaryColor,
|
|
size: 5.w,
|
|
),
|
|
label: Text(
|
|
"Pilih Pelanggan Tersedia",
|
|
style: TextStyle(
|
|
color: AppColor.primaryColor,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: AppFontSize.medium.sp,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 2.h),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Divider(
|
|
color: Colors.grey.shade300,
|
|
),
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 3.w,
|
|
),
|
|
child: Text(
|
|
"Atau Input Manual",
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? (AppFontSize.medium - 2)
|
|
.sp
|
|
: (AppFontSize.small - 2)
|
|
.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey[400],
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Divider(
|
|
color: Colors.grey.shade300,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 2.h),
|
|
CustomFormInput(
|
|
label: "Nama Pelanggan",
|
|
icon: Icons.person,
|
|
controller: nameController,
|
|
),
|
|
SizedBox(height: 1.5.h),
|
|
CustomFormInput(
|
|
label: "No. Hp / WA",
|
|
hint: "Opsional",
|
|
icon: Icons.phone_android,
|
|
controller: phoneNumberController,
|
|
inputType: TextInputType.phone,
|
|
),
|
|
/**
|
|
SizedBox(height: 1.5.h),
|
|
CustomFormInput(
|
|
label: "Alamat",
|
|
hint: "Opsional",
|
|
icon: Icons.location_on_outlined,
|
|
controller: addressController,
|
|
),
|
|
*/
|
|
],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
BillSummary(
|
|
label: "Total Tagihan",
|
|
value: totalBill > 0
|
|
? CurrencyFormat.formatToIdr(totalBill, 0)
|
|
: '',
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
Text(
|
|
"Pembayaran",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
),
|
|
SizedBox(height: 1.h),
|
|
|
|
TextFormField(
|
|
controller: payController,
|
|
keyboardType: TextInputType.number,
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
|
validator: (value) {
|
|
try {
|
|
if (value == null || value.isEmpty) {
|
|
return "Masukkan nominal pembayaran";
|
|
}
|
|
final double payAmount = double.parse(value);
|
|
if (payAmount <= 0) {
|
|
return "Nominal pembayaran harus lebih dari 0";
|
|
}
|
|
} catch (e) {
|
|
return "Nominal pembayaran tidak valid";
|
|
}
|
|
return null;
|
|
},
|
|
onChanged: calculateChange,
|
|
decoration: InputDecoration(
|
|
labelText: "Bayar (Rp)",
|
|
labelStyle: TextStyle(
|
|
color: Colors.blue,
|
|
fontSize: AppFontSize.medium.sp,
|
|
),
|
|
prefixIcon: Padding(
|
|
padding: isTablet
|
|
? EdgeInsets.symmetric(horizontal: 3.w)
|
|
: EdgeInsets.zero,
|
|
child: Icon(
|
|
Icons.payments_outlined,
|
|
color: Colors.blue,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
),
|
|
errorText: payErrorText,
|
|
errorStyle: TextStyle(
|
|
color: Colors.red,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
errorBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
borderSide: const BorderSide(color: Colors.redAccent),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
borderSide: const BorderSide(color: Colors.blue),
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(
|
|
vertical: isTablet ? 3.6.h : 1.8.h,
|
|
),
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 2.h),
|
|
|
|
TextField(
|
|
controller: TextEditingController(
|
|
text: isViewChangeAmount
|
|
? CurrencyFormat.formatToIdr(changeAmount, 0)
|
|
: '',
|
|
),
|
|
readOnly: true,
|
|
decoration: InputDecoration(
|
|
labelText: "Kembali",
|
|
labelStyle: TextStyle(fontSize: AppFontSize.medium.sp),
|
|
prefixIcon: Padding(
|
|
padding: isTablet
|
|
? EdgeInsets.symmetric(horizontal: 3.w)
|
|
: EdgeInsets.zero,
|
|
child: Icon(
|
|
Icons.change_circle_outlined,
|
|
color: Colors.green,
|
|
size: 5.w,
|
|
),
|
|
),
|
|
filled: true,
|
|
fillColor: Colors.grey[100],
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(
|
|
vertical: isTablet ? 3.6.h : 1.8.h,
|
|
),
|
|
),
|
|
style: TextStyle(
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.green[700],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
CustomProofImageUploader(
|
|
imagePath: imagePath,
|
|
title: "Upload Bukti Pembayaran",
|
|
onTapImageAdd: onTapImageAdd,
|
|
onTapImageRemove: onTapImageRemove,
|
|
),
|
|
|
|
SizedBox(height: 3.h),
|
|
|
|
SizedBox(
|
|
width: double.infinity,
|
|
height: 6.5.h,
|
|
child: ElevatedButton(
|
|
onPressed: onProccessPressed,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColor.primaryColor,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
),
|
|
disabledBackgroundColor: Colors.grey.shade300,
|
|
),
|
|
child: Text(
|
|
"Proses Penjualan",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: AppFontSize.medium.sp,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
SizedBox(
|
|
height: MediaQuery.of(context).viewInsets.bottom + 2.h,
|
|
),
|
|
];
|
|
|
|
final bool isSquashed = constraints.maxHeight < 250;
|
|
|
|
if (isSquashed) {
|
|
return SingleChildScrollView(
|
|
controller: scrollController,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
InformationHeader(
|
|
|
|
currentUserName: currentUserName,
|
|
currentOutletName: currentOutletName,
|
|
currentUserRole: currentUserRole,
|
|
),
|
|
Center(
|
|
child: Container(
|
|
margin: EdgeInsets.only(top: 1.5.h),
|
|
width: 15.w,
|
|
height: 0.6.h,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[300],
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 5.w,
|
|
vertical: 1.h,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Total Belanja",
|
|
style: TextStyle(
|
|
color: Colors.grey,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
),
|
|
Text(
|
|
CurrencyFormat.formatToIdr(
|
|
shoppingAmount,
|
|
0,
|
|
),
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: AppFontSize.medium.sp,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
ElevatedButton.icon(
|
|
onPressed: onViewOrderPressed,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColor.primaryColor,
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 6.w,
|
|
vertical: 1.h,
|
|
),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(
|
|
2.5.w,
|
|
),
|
|
),
|
|
),
|
|
icon: Icon(
|
|
Icons.shopping_bag_outlined,
|
|
color: Colors.white,
|
|
size: 5.w,
|
|
),
|
|
label: Text(
|
|
"Lihat Pesanan",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: AppFontSize.medium.sp,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 1),
|
|
Form(
|
|
key: formKey,
|
|
child: Padding(
|
|
padding: EdgeInsets.fromLTRB(5.w, 2.h, 5.w, 5.h),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: listChildren,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
InformationHeader(
|
|
currentUserName: currentUserName,
|
|
currentOutletName: currentOutletName,
|
|
currentUserRole: currentUserRole,
|
|
),
|
|
Center(
|
|
child: Container(
|
|
margin: EdgeInsets.only(top: 1.5.h),
|
|
width: 15.w,
|
|
height: 0.6.h,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[300],
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 5.w,
|
|
vertical: 1.h,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Total Belanja",
|
|
style: TextStyle(
|
|
color: Colors.grey,
|
|
fontSize: isTablet
|
|
? AppFontSize.medium.sp
|
|
: AppFontSize.small.sp,
|
|
),
|
|
),
|
|
Text(
|
|
CurrencyFormat.formatToIdr(shoppingAmount, 0),
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: AppFontSize.medium.sp,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
ElevatedButton.icon(
|
|
onPressed: onViewOrderPressed,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColor.primaryColor,
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 6.w,
|
|
vertical: 1.h,
|
|
),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(2.5.w),
|
|
),
|
|
),
|
|
icon: Icon(
|
|
Icons.shopping_bag_outlined,
|
|
color: Colors.white,
|
|
size: 5.w,
|
|
),
|
|
label: Text(
|
|
"Lihat Pesanan",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: AppFontSize.medium.sp,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 1),
|
|
Expanded(
|
|
child: Form(
|
|
key: formKey,
|
|
child: ListView(
|
|
controller: scrollController,
|
|
padding: EdgeInsets.fromLTRB(5.w, 2.h, 5.w, 5.h),
|
|
children: listChildren,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|