import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:marco/controller/expense/expense_detail_controller.dart'; import 'package:marco/helpers/widgets/my_text.dart'; class ReimbursementBottomSheet extends StatefulWidget { final String expenseId; final String statusId; final void Function() onClose; final Future Function({ required String comment, required String reimburseTransactionId, required String reimburseDate, required String reimburseById, }) onSubmit; const ReimbursementBottomSheet({ super.key, required this.expenseId, required this.onClose, required this.onSubmit, required this.statusId, }); @override State createState() => _ReimbursementBottomSheetState(); } class _ReimbursementBottomSheetState extends State { final ExpenseDetailController controller = Get.find(); final TextEditingController commentCtrl = TextEditingController(); final TextEditingController txnCtrl = TextEditingController(); final RxString dateStr = ''.obs; @override void dispose() { commentCtrl.dispose(); txnCtrl.dispose(); super.dispose(); } void _showEmployeeList() { showModalBottomSheet( context: context, backgroundColor: Colors.white, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))), builder: (_) { return SizedBox( height: 300, child: Obx(() { final employees = controller.allEmployees; if (employees.isEmpty) return const Center(child: Text("No employees found")); return ListView.builder( itemCount: employees.length, itemBuilder: (_, index) { final emp = employees[index]; final fullName = '${emp.firstName} ${emp.lastName}'.trim(); return ListTile( title: Text(fullName.isNotEmpty ? fullName : "Unnamed"), onTap: () { controller.selectedReimbursedBy.value = emp; Navigator.pop(context); }, ); }, ); }), ); }, ); } @override Widget build(BuildContext context) { return SafeArea( child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Drag handle Container( width: 50, height: 4, margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.grey.shade300, borderRadius: BorderRadius.circular(20), ), ), // Title Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ MyText.titleLarge('Reimbursement Info', fontWeight: 700), const SizedBox(), ], ), const SizedBox(height: 20), Flexible( child: SingleChildScrollView( child: Column( children: [ _buildInputField(label: 'Comment', controller: commentCtrl), const SizedBox(height: 16), _buildInputField(label: 'Transaction ID', controller: txnCtrl), const SizedBox(height: 16), _buildDatePickerField(), const SizedBox(height: 16), _buildEmployeePickerField(), const SizedBox(height: 24), _buildActionButtons(), ], ), ), ), ], ), ), ); } Widget _buildInputField({required String label, required TextEditingController controller}) { return TextField( controller: controller, decoration: InputDecoration( labelText: label, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: Colors.grey.shade300), ), ), ); } Widget _buildDatePickerField() { return Obx(() { return InkWell( onTap: () async { final picked = await showDatePicker( context: context, initialDate: dateStr.value.isEmpty ? DateTime.now() : DateFormat('yyyy-MM-dd').parse(dateStr.value), firstDate: DateTime(2020), lastDate: DateTime(2100), ); if (picked != null) { dateStr.value = DateFormat('yyyy-MM-dd').format(picked); } }, child: InputDecorator( decoration: InputDecoration( labelText: 'Reimbursement Date', contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: Colors.grey.shade300), ), ), child: Row( children: [ Icon(Icons.date_range, color: Colors.grey.shade600), const SizedBox(width: 10), Text( dateStr.value.isEmpty ? "Select Date" : dateStr.value, style: TextStyle( fontSize: 14, color: dateStr.value.isEmpty ? Colors.grey : Colors.black, ), ), ], ), ), ); }); } Widget _buildEmployeePickerField() { return Obx(() { return GestureDetector( onTap: _showEmployeeList, child: InputDecorator( decoration: InputDecoration( labelText: 'Reimbursed By', contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: Colors.grey.shade300), ), ), child: Text( controller.selectedReimbursedBy.value == null ? "Select Reimbursed By" : '${controller.selectedReimbursedBy.value?.firstName ?? ''} ${controller.selectedReimbursedBy.value?.lastName ?? ''}', style: TextStyle( fontSize: 14, color: controller.selectedReimbursedBy.value == null ? Colors.grey : Colors.black, ), ), ), ); }); } Widget _buildActionButtons() { return Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: () { widget.onClose(); Get.back(); }, icon: const Icon(Icons.close, color: Colors.white), label: MyText.bodyMedium("Cancel", color: Colors.white, fontWeight: 600), style: ElevatedButton.styleFrom( backgroundColor: Colors.red, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), ), ), ), const SizedBox(width: 12), Expanded( child: Obx(() { return ElevatedButton.icon( onPressed: controller.isLoading.value ? null : () async { if (commentCtrl.text.trim().isEmpty || txnCtrl.text.trim().isEmpty || dateStr.value.isEmpty || controller.selectedReimbursedBy.value == null) { Get.snackbar("Incomplete", "Please fill all fields"); return; } final success = await widget.onSubmit( comment: commentCtrl.text.trim(), reimburseTransactionId: txnCtrl.text.trim(), reimburseDate: dateStr.value, reimburseById: controller.selectedReimbursedBy.value!.id, ); if (success) { Get.back(); Get.snackbar('Success', 'Reimbursement submitted'); } else { Get.snackbar('Error', controller.errorMessage.value); } }, icon: const Icon(Icons.check_circle_outline, color: Colors.white), label: MyText.bodyMedium( controller.isLoading.value ? "Submitting..." : "Submit", color: Colors.white, fontWeight: 600, ), style: ElevatedButton.styleFrom( backgroundColor: Colors.indigo, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), ), ); }), ), ], ); } }