diff --git a/lib/presentation/RaiseClaimForm.dart b/lib/presentation/RaiseClaimForm.dart index 2380ddc..6451d02 100644 --- a/lib/presentation/RaiseClaimForm.dart +++ b/lib/presentation/RaiseClaimForm.dart @@ -71,6 +71,7 @@ class _RaiseClaimDialogState extends State { dynamic emailId; List> employeePolicyList = []; String? selectedFileNames; + // html.File? uploadedFile; // List uploadedFiles = []; List uploadedFiles = []; @@ -144,6 +145,7 @@ class _RaiseClaimDialogState extends State { bool isIntimationDateValid = true; bool isAdmitDateValid = true; bool isDischargeDateValid = true; + bool isAccidentService = false; @override void initState() { @@ -372,7 +374,6 @@ class _RaiseClaimDialogState extends State { } Future sendFormDataToApi() async { - setState(() { isServiceValid = serviceId != null; isPolicyValid = selectedClientPolicyId != null; @@ -395,6 +396,8 @@ class _RaiseClaimDialogState extends State { // ☠ Accident / Death final isAccident = [2, 3, 4].contains(serviceId); + isAccidentService = isAccident ? true : false; + isAccidentDateValid = !isAccident || accidentDate != null; isIntimationDateValid = !isAccident || intimationDate != null; }); @@ -550,9 +553,10 @@ class _RaiseClaimDialogState extends State { pdf.addPage( pw.Page( - build: (pw.Context context) => pw.Center( - child: pw.Image(image, fit: pw.BoxFit.contain), - ), + build: (pw.Context context) => + pw.Center( + child: pw.Image(image, fit: pw.BoxFit.contain), + ), ), ); @@ -752,236 +756,291 @@ class _RaiseClaimDialogState extends State { const SizedBox(height: 16), - Form( - key: formKey, - child: Column( - children: [ - _row([ - buildDropdownField( - 'Service', - (value) { - final selectedItem = departmentList.firstWhere( - (item) => item['id'] == value, - orElse: () => {}, - ); - setState(() { - serviceId = value; - serviceName = selectedItem['name']; - policyNumberId = null; - isServiceValid = true; - }); - print('🔥 serviceId set to $serviceId'); - filterPoliciesByService(value!); - }, - departmentList, - 'name', - serviceId, - ), - buildDropdownField( - 'Select Policy', - (value) { - final selectedPolicy = - policyNumberList.firstWhere((p) => p['id'] == value); - - setState(() { - // ✅ THIS is what you send to API - selectedClientPolicyId = selectedPolicy['id']; - - // optional - selectedPolicyTypeId = selectedPolicy['policy_type_id']; - policyNumberId = value; - - isPolicyValid = true; - }); - - getCDPoliciesDetails(); - }, - policyNumberList, - 'label', // 👈 DISPLAY FIELD - policyNumberId, - ), - - buildDropdownFieldSearch( - 'Member Name', - (value) { - final member = employeePolicyList.firstWhere( - (m) => m['id'] == value, - ); - - setState(() { - selectedMemberId = value; - selectedMemberObject = member; // ✅ FULL OBJECT - selectedMemberName = member['name']; - isMemberValid = true; - print('selectedMemberObject $selectedMemberObject'); - }); - }, - employeePolicyList, - 'name', - selectedMemberId, - ), - - ]), - _row([ - buildTextField('Message', messageController), - if (serviceId == 1 || serviceId == 72)...[ - buildTextField('Hospital Name', hospitalNameController), - buildTextField('Hospital Address', hospitalAddressController), - ] - ]), - - if (serviceId == 1 || serviceId == 72) + Form( + key: formKey, + child: Column( + children: [ _row([ - buildTextField('Hospital City', hospitalCityController), - buildTextField('Hospital State', hospitalStateController), - buildTextField( - 'Hospital Pincode', - hospitalPinCodeController, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - LengthLimitingTextInputFormatter(6), - ], - ), - ]), - if (serviceId == 1 || serviceId == 72) - _row([ - buildTextField( - 'Hospital Phone No', - hospitalPhoneNoController, - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - LengthLimitingTextInputFormatter(10), - ], - ), - buildDatePickerField( - label: 'Admit Date', - selectedDate: admitDate, - allowFuture: false, - onDateSelected: (d) { + buildDropdownField( + 'Service', + (value) { + final selectedItem = departmentList + .firstWhere( + (item) => item['id'] == value, + orElse: () => {}, + ); setState(() { - admitDate = d; - dischargeDate = null; + serviceId = value; + serviceName = selectedItem['name']; + policyNumberId = null; + isServiceValid = true; + }); + print('🔥 serviceId set to $serviceId'); + filterPoliciesByService(value!); + }, + departmentList, + 'name', + serviceId, + isRequired: true, + isValid: isServiceValid, + ), + buildDropdownField( + 'Select Policy', + (value) { + final selectedPolicy = + policyNumberList.firstWhere(( + p) => p['id'] == value); + + setState(() { + // ✅ THIS is what you send to API + selectedClientPolicyId = + selectedPolicy['id']; + + // optional + selectedPolicyTypeId = + selectedPolicy['policy_type_id']; + policyNumberId = value; + + isPolicyValid = true; + }); + + getCDPoliciesDetails(); + }, + policyNumberList, + 'label', // 👈 DISPLAY FIELD + policyNumberId, + isRequired: true, + isValid: isPolicyValid, // 👈 Hooked to your state + ), + + buildDropdownFieldSearch( + 'Member Name', + (value) { + final member = employeePolicyList + .firstWhere( + (m) => m['id'] == value, + ); + + setState(() { + selectedMemberId = value; + selectedMemberObject = + member; // ✅ FULL OBJECT + selectedMemberName = member['name']; + isMemberValid = true; + print( + 'selectedMemberObject $selectedMemberObject'); }); }, + employeePolicyList, + 'name', + selectedMemberId, + isRequired: true, + isValid: isMemberValid, // 👈 Hooked to your state ), - buildDatePickerField( - label: 'Discharge Date', - selectedDate: dischargeDate, - allowFuture: true, - minDate: admitDate?.add(const Duration(days: 1)), - onDateSelected: (d) => setState(() => dischargeDate = d), - ), - buildTextField( - 'Claims Amount', - claimAmountController, - keyboardType: TextInputType.number, - inputFormatters: [FilteringTextInputFormatter.digitsOnly], - ), + + ]), + _row([ + buildTextField('Message', messageController, + isRequired: false, isValid: true), + if (serviceId == 1 || serviceId == 72)...[ + buildTextField( + 'Hospital Name', hospitalNameController, + isRequired: true, + isValid: isHospitalNameValid), + buildTextField('Hospital Address', + hospitalAddressController, + isRequired: true, + isValid: isHospitalAddressValid), + ] ]), - if ([2, 3, 4].contains(serviceId)) - _row([ - buildDatePickerField( - label: 'Date of Birth', - selectedDate: birthDate, - allowFuture: false, - onDateSelected: (d) => setState(() => birthDate = d), - ), - buildDatePickerField( - label: 'Accident Date', - selectedDate: accidentDate, - allowFuture: false, - onDateSelected: (d) { - setState(() { - accidentDate = d; - deathDate = null; - intimationDate = null; - }); - }, - ), - buildDatePickerField( - label: 'Date of Death', - selectedDate: deathDate, - allowFuture: false, - onDateSelected: (d) => setState(() => deathDate = d), - ), - ]), - if ([2, 3, 4].contains(serviceId)) - _row([ - buildDatePickerField( - label: 'Date of Intimation', - selectedDate: intimationDate, - allowFuture: false, - onDateSelected: (d) => setState(() => intimationDate = d), - ), - buildTextField( - 'Sum Insured', - sumInsuredController, - keyboardType: TextInputType.number, - inputFormatters: [FilteringTextInputFormatter.digitsOnly], - ), - const SizedBox(), - ]), - - _row([ - MultiFileUploadWidget(), - ]), - Align( - alignment: Alignment.centerRight, - child: SizedBox( - width: 120, - height: 42, - child: ElevatedButton( - onPressed: isSubmitting ? null : sendFormDataToApi, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFE26728), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), + if (serviceId == 1 || serviceId == 72) + _row([ + buildTextField( + 'Hospital City', hospitalCityController, + isRequired: true, + isValid: isHospitalCityValid), + buildTextField( + 'Hospital State', hospitalStateController, + isRequired: true, + isValid: isHospitalStateValid), + buildTextField( + 'Hospital Pincode', + hospitalPinCodeController, + keyboardType: TextInputType.number, + isRequired: true, + isValid: isHospitalPincodeValid, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(6), + ], ), - child: isSubmitting - ? const SizedBox( - height: 18, - width: 18, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.white, + ]), + if (serviceId == 1 || serviceId == 72) + _row([ + buildTextField( + 'Hospital Phone No', + hospitalPhoneNoController, + keyboardType: TextInputType.number, + isRequired: true, + isValid: isHospitalPhoneNoValid, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(10), + ], + ), + buildDatePickerField( + label: 'Admit Date', + selectedDate: admitDate, + allowFuture: false, + isRequired: true, + isValid: isAdmitDateValid, + onDateSelected: (d) { + setState(() { + admitDate = d; + dischargeDate = null; + }); + }, + ), + buildDatePickerField( + label: 'Discharge Date', + selectedDate: dischargeDate, + allowFuture: true, + minDate: admitDate?.add( + const Duration(days: 1)), + isRequired: true, + isValid: isDischargeDateValid, + onDateSelected: (d) => + setState(() => dischargeDate = d), + ), + buildTextField( + 'Claims Amount', + claimAmountController, + keyboardType: TextInputType.number, + isRequired: true, + isValid: isClaimAmountValid, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ], + ), + ]), + + if ([2, 3, 4].contains(serviceId)) + _row([ + buildDatePickerField( + label: 'Date of Birth', + selectedDate: birthDate, + allowFuture: false, + isRequired: false,isValid: true, + onDateSelected: (d) => + setState(() => birthDate = d), + ), + buildDatePickerField( + label: 'Accident Date', + selectedDate: accidentDate, + allowFuture: false, + isRequired: isAccidentService, + isValid: isAccidentDateValid, + onDateSelected: (d) { + setState(() { + accidentDate = d; + deathDate = null; + intimationDate = null; + }); + }, + ), + buildDatePickerField( + label: 'Date of Death', + selectedDate: deathDate, + allowFuture: false, + isRequired: false, + isValid: true, + onDateSelected: (d) => + setState(() => deathDate = d), + ), + ]), + if ([2, 3, 4].contains(serviceId)) + _row([ + buildDatePickerField( + label: 'Date of Intimation', + selectedDate: intimationDate, + allowFuture: false, + isRequired: isAccidentService, + isValid: isIntimationDateValid, + onDateSelected: (d) => + setState(() => intimationDate = d), + ), + buildTextField( + 'Sum Insured', + sumInsuredController, + keyboardType: TextInputType.number, + isRequired: false,isValid: true, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ], + ), + const SizedBox(), + ]), + + _row([ + MultiFileUploadWidget(), + ]), + Align( + alignment: Alignment.centerRight, + child: SizedBox( + width: 120, + height: 42, + child: ElevatedButton( + onPressed: isSubmitting + ? null + : sendFormDataToApi, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFE26728), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: isSubmitting + ? const SizedBox( + height: 18, + width: 18, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + : const Text( + 'Send', + style: TextStyle(color: Colors.white, + fontWeight: FontWeight.w600), ), - ) - : const Text( - 'Send', - style: TextStyle(color: Colors.white, - fontWeight: FontWeight.w600), ), ), ), - ), - ], + ], + ), ), - ), - ], - ), - ), - ), - - /// 🔄 LOADER OVERLAY (UNCHANGED) - if (isLoading) - Container( - color: const Color(0x98FFFCE5), - child: Center( - child: Image.asset( - 'assets/nhance-loader.gif', - height: 60, - width: 60, + ], ), ), ), - ], + + /// 🔄 LOADER OVERLAY (UNCHANGED) + if (isLoading) + Container( + color: const Color(0x98FFFCE5), + child: Center( + child: Image.asset( + 'assets/nhance-loader.gif', + height: 60, + width: 60, + ), + ), + ), + ], + ), ), - ), - ) + ) ); } @@ -1003,29 +1062,31 @@ class _RaiseClaimDialogState extends State { ); } - Widget buildTextField( - String label, - TextEditingController controller, { - TextInputType keyboardType = TextInputType.text, - List? inputFormatters, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - fieldLabel(label), - formBox( - child: TextField( - controller: controller, - keyboardType: keyboardType, - inputFormatters: inputFormatters, - decoration: const InputDecoration( - isDense: true, - border: InputBorder.none, + Widget buildTextField(String label, + TextEditingController controller, { + TextInputType keyboardType = TextInputType.text, + bool isRequired = true, bool isValid = true, + List? inputFormatters, + }) { + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + fieldLabel(label, isRequired: isRequired), + formBox( + child: TextField( + controller: controller, + keyboardType: keyboardType, + inputFormatters: inputFormatters, + decoration: const InputDecoration( + isDense: true, + border: InputBorder.none, + ), ), ), - ), - ], - ); + if (!isValid) validationText(), + ], + ),); } Widget buildTextAreaField(String label, TextEditingController controller) { @@ -1053,53 +1114,81 @@ class _RaiseClaimDialogState extends State { } Widget buildDropdownField( - String label, - void Function(int?) onChanged, - List> itemsList, - String displayField, - int? selectedValue, - ) { + String label, + void Function(int?) onChanged, + List> itemsList, + String displayField, + int? selectedValue, { + bool isRequired = true, + bool isValid = true, + }) { + + // Logic to calculate font size based on string length + double getDynamicFontSize(String text) { + if (text.length > 25) return 9.0; + if (text.length > 15) return 10.0; + return 12.0; + } + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - fieldLabel(label), + fieldLabel(label, isRequired: isRequired), formBox( child: DropdownButtonHideUnderline( child: DropdownButton( isExpanded: true, value: selectedValue, - hint: const Text('Select'), + hint: const Text( + 'Select', + style: TextStyle(fontSize: 12), + ), icon: const Icon(Icons.keyboard_arrow_down), items: itemsList.map>((item) { + String textValue = item[displayField].toString(); // Get the text first return DropdownMenuItem( value: item['id'], - child: Text(item[displayField]), + child: Text( + textValue, + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 1, // Strictly keep to one line + style: TextStyle( + // Call the function here and pass the textValue + fontSize: getDynamicFontSize(textValue), + ), + ), ); }).toList(), onChanged: onChanged, ), ), ), + if (!isValid) + Padding( + padding: const EdgeInsets.only(top: 4, left: 4), + child: Text( + "Required", + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ), ], ); } - - Widget buildDropdownFieldSearch( - String label, + Widget buildDropdownFieldSearch(String label, void Function(int?) onChanged, List> itemsList, String displayField, int? selectedValue, - ) { - + { + bool isRequired = true, // Added + bool isValid = true, // Added + }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - label, - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), - ), + fieldLabel(label, isRequired: isRequired), const SizedBox(height: 4), Container( height: 40, @@ -1179,6 +1268,12 @@ class _RaiseClaimDialogState extends State { ), ), ), + if (!isValid) + Padding( + padding: const EdgeInsets.only(top: 4, left: 4), + child: Text("Required", + style: GoogleFonts.poppins(color: Colors.red, fontSize: 12)), + ), ], ); } @@ -1191,18 +1286,20 @@ class _RaiseClaimDialogState extends State { required ValueChanged onDateSelected, DateTime? minDate, DateTime? maxDate, + bool isRequired = true, + bool isValid = true, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - fieldLabel(label), + fieldLabel(label, isRequired: isRequired), formBox( child: InkWell( onTap: () async { final DateTime now = DateTime.now(); final DateTime first = minDate ?? DateTime(1980); final DateTime last = - allowFuture ? (maxDate ?? DateTime(2100)) : now; + allowFuture ? (maxDate ?? DateTime(2100)) : now; final DateTime initialDate = selectedDate ?? (first.isAfter(now) ? first : now); @@ -1232,6 +1329,7 @@ class _RaiseClaimDialogState extends State { ), ), ), + if (!isValid) validationText(), ], ); } @@ -1270,19 +1368,39 @@ class _RaiseClaimDialogState extends State { ); } - Widget fieldLabel(String text) { + Widget fieldLabel(String text, {bool isRequired = false}) { return Padding( padding: const EdgeInsets.only(bottom: 6), - child: Text( - text, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Colors.black, + child: RichText( + text: TextSpan( + text: text, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + children: [ + if (isRequired) + const TextSpan( + text: ' *', + style: TextStyle( + color: Colors.red, fontWeight: FontWeight.bold), + ), + ], ), ), ); } + Widget validationText() { + return Padding( + padding: const EdgeInsets.only(top: 4, left: 4), + child: Text( + "Required", + style: GoogleFonts.poppins( + color: Colors.red, fontSize: 12, fontWeight: FontWeight.w500), + ), + ); + } } // class RaiseClaimDialog extends StatelessWidget { diff --git a/lib/presentation/excelVerification.dart b/lib/presentation/excelVerification.dart index 58e962a..6911202 100644 --- a/lib/presentation/excelVerification.dart +++ b/lib/presentation/excelVerification.dart @@ -114,7 +114,14 @@ class _activePolicyExcelErrorState extends State // 🟢 CASE 2: Success with data if (response['status'] == true) { - ToastHelper.showSuccessToast(context, response['message']); + if (response['message'] == "Error data feteched successfully") { + // This runs if the message matches EXACTLY (including the typo 'feteched') + ToastHelper.showErrorToast(context, response['message']); + }else { + ToastHelper.showSuccessToast(context, response['message']); + } + + setState(() { isLoading = false;