FIX_Account Login - Policy Report - Commission popup kannan sir

This commit is contained in:
sanjeev.p 2026-01-14 11:41:20 +05:30
parent fba7f9a639
commit e59d163a2e
6 changed files with 1423 additions and 622 deletions

File diff suppressed because one or more lines are too long

View File

@ -607,7 +607,7 @@ class AgentState extends ConsumerState<Agent> {
validator: (value) => Validators.requiredField(value, "name"), validator: (value) => Validators.requiredField(value, "name"),
inputFormatters: [ inputFormatters: [
// This line now allows letters, numbers, hyphens, and underscores // This line now allows letters, numbers, hyphens, and underscores
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_]')), FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_ ]')),
], ],
borderColor: Color(0xFFE2E8F0), borderColor: Color(0xFFE2E8F0),
highlightColor: Color(0xFF50A398), highlightColor: Color(0xFF50A398),

View File

@ -55,7 +55,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
]; ];
List<Map<String, dynamic>> getVehicleTypeData = []; List<Map<String, dynamic>> getVehicleTypeData = [];
List<Map<String, dynamic>> filteredVechicleData = []; List<Map<String, dynamic>> filteredVehicleData = [];
List<Map<String, dynamic>> getAgentListData = []; List<Map<String, dynamic>> getAgentListData = [];
List<Map<String, dynamic>> filteredAgentData = []; List<Map<String, dynamic>> filteredAgentData = [];
@ -73,6 +73,10 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
dropDownSelectStaffKey = dropDownSelectStaffKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>(); GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
dropDownSelectVehicleTypeKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey = final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>(); GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
@ -232,12 +236,12 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
); );
print('API Data - $getVehicleTypeData'); print('API Data - $getVehicleTypeData');
filteredVechicleData = List.from(getVehicleTypeData); filteredVehicleData = List.from(getVehicleTypeData);
print('originalData - $filteredVechicleData'); print('originalData - $filteredVehicleData');
}); });
} else { } else {
getVehicleTypeData = []; getVehicleTypeData = [];
filteredVechicleData = []; filteredVehicleData = [];
} }
} catch (e) { } catch (e) {
print('Exception occurred: $e'); print('Exception occurred: $e');
@ -310,6 +314,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
} }
} }
Future<void> getAgentList(id) async { Future<void> getAgentList(id) async {
print('getAgentListData called'); print('getAgentListData called');
setState(() { setState(() {
@ -419,7 +424,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
buildAgentName(context, fromHeader: true), buildAgentName(context, fromHeader: true),
buildBroker(context), buildBroker(context),
buildInsurer(context, fromHeader: true), buildInsurer(context, fromHeader: true),
buildVehicleType(context),
// buildInsuredName(context, fromHeader: true), // buildInsuredName(context, fromHeader: true),
buildVehicleNumber(context), buildVehicleNumber(context),
Row( Row(
@ -1242,6 +1247,153 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
); );
} }
Widget buildVehicleType(BuildContext context) {
Map<String, dynamic>? selectedVehicleTypes = filteredVehicleData.firstWhere(
(item) => item['id'].toString() == selectedVehicleType,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Vehicle Type *', style: _subLabelTimeStyle),
SizedBox(height: 5),
SizedBox(
// height: 30,
width: MediaQuery.of(context).size.width * 0.12,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownSelectVehicleTypeKey,
selectedItem: selectedVehicleTypes.isNotEmpty ? selectedVehicleTypes : null,
items: (filter, infiniteScrollProps) {
return filteredVehicleData;
},
itemAsString: (val) => val['vehicle_type'].toString(), // what to show
compareFn: (item, selectedItem) =>
item['vehicle_type'].toString() == selectedItem['vehicle_type'].toString(),
validator: (val) {
if (val == null) {
return "Required"; // error message
}
return null;
},
suffixProps: DropdownSuffixProps(
// make sure the dropdown button is visible
dropdownButtonProps: DropdownButtonProps(
isVisible: true,
padding: EdgeInsets.zero, // remove default padding
constraints: const BoxConstraints(
// shrink icon tap area
minWidth: 12,
minHeight: 12,
),
iconSize: 15, // smaller icon
// icon: const Icon(Icons.arrow_drop_down),
),
),
dropdownBuilder: (context, selectedItem) => Align(
alignment: Alignment.centerLeft,
child: Text(
selectedItem != null ? selectedItem['vehicle_type'].toString() : "",
style: GoogleFonts.poppins(fontSize: 11, color: Colors.black),
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
),
),
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Vehicle Type",
).copyWith(
filled: true,
fillColor:
Colors.white, // 👈 makes the dropdown input white
isDense: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(
color: Color(0xFFE2E8F0),
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(
color: Color(0xFFE2E8F0),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 8,
vertical: 6,
),
),
),
popupProps: PopupProps.menu(
fit: FlexFit.loose,
constraints: BoxConstraints(maxHeight: 250),
menuProps: MenuProps(
backgroundColor:
Colors.white, // 👈 sets dropdown background to white
),
showSearchBox: true,
searchFieldProps: TextFieldProps(
autofocus: true,
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(1),
filled: true,
fillColor: Colors.white,
hintText: "Search Vehicle Type...",
hintStyle: GoogleFonts.inter(
fontSize: 12,
color: Colors.black,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
itemBuilder: (context, item, isDisabled, isSelected) {
return Container(
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 3,
),
child: Text(
item['vehicle_type'].toString(),
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
),
);
},
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
// print("Selected vehicletype : ${val['vehicle_type']}");
// print("Id: ${val['id']}");
// print("Value: ${val}");
selectedVehicleType = val['id'];
}
},
),
),
],
);
}
Widget buildSave(context) { Widget buildSave(context) {
return InkWell( return InkWell(
onTap: () { onTap: () {
@ -1303,6 +1455,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
dropDownKeyAgent.currentState?.clear(); dropDownKeyAgent.currentState?.clear();
dropDownKeyInsurerEnqAsgn.currentState?.clear(); dropDownKeyInsurerEnqAsgn.currentState?.clear();
dropDownSelectStaffKey.currentState?.clear(); dropDownSelectStaffKey.currentState?.clear();
dropDownSelectVehicleTypeKey.currentState?.clear();
dropDownKeyInsurer.currentState?.clear(); dropDownKeyInsurer.currentState?.clear();
dropDownKey.currentState?.clear(); dropDownKey.currentState?.clear();
dropDownKeyBroker.currentState?.clear(); dropDownKeyBroker.currentState?.clear();

View File

@ -1331,7 +1331,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('Vehicle Number*', style: _textStyle), Text('Vehicle Number *', style: _textStyle),
SizedBox(height: 10), SizedBox(height: 10),
ThemedFormField( ThemedFormField(
controller: controllers['regNum']!, controller: controllers['regNum']!,

View File

@ -973,7 +973,7 @@ class PolicyScreenState extends ConsumerState<PolicyScreen> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('Vehicle Number*', style: _textStyle), Text('Vehicle Number *', style: _textStyle),
SizedBox(height: 10), SizedBox(height: 10),
ThemedFormField( ThemedFormField(
controller: controllers['regNum']!, controller: controllers['regNum']!,

View File

@ -79,6 +79,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
'chassisNo', 'chassisNo',
'make', 'make',
'model', 'model',
// 'cubic_capacity', // Ensure this matches your dataDetails call
'cubicCapacity', 'cubicCapacity',
'vehicleType', 'vehicleType',
@ -86,6 +87,11 @@ class _policyValidationState extends ConsumerState<policyValidation> {
'broker_name', 'broker_name',
'commission_amount', 'commission_amount',
// Enquiry
'enquiry_broker_id_for_commission',
'enquiry_reg_no_for_commission',
'enquiry_vehicle_type_id_for_commission',
//find Policy //find Policy
'insurance_plan_type', 'insurance_plan_type',
]; ];
@ -101,11 +107,23 @@ class _policyValidationState extends ConsumerState<policyValidation> {
List<String> getFuelTypeData = []; List<String> getFuelTypeData = [];
List<String> filteredFuelTypeData = []; List<String> filteredFuelTypeData = [];
List<Map<String, dynamic>> getBrokerData = [];
List<Map<String, dynamic>> filteredBrokerData = [];
List<Map<String, dynamic>> getInsurancPlanTypeData = [];
List<Map<String, dynamic>> filteredInsurancPlanTypeData = [];
List<Map<String, dynamic>> getVehicleTypeForEnquiryData = [];
List<Map<String, dynamic>> filteredVehicleDataForEnquiryData = [];
final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey(); final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
String? selectedVehicleTypeForEnquiryID;
String? selectedVehicleTypeForEnquiryVAL;
String? selectedVehicleType; String? selectedVehicleType;
String? selectedFuelType; String? selectedFuelType;
String? selectedBroker;
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey = final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>(); GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
@ -113,6 +131,15 @@ class _policyValidationState extends ConsumerState<policyValidation> {
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyFuel = final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyFuel =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>(); GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyBroker =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyVehicleTypeForEnquiry =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyInsurancPlanType =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
bool _hasLoadedInitialData = false; bool _hasLoadedInitialData = false;
Map<String, dynamic> dataDetails() { Map<String, dynamic> dataDetails() {
@ -165,13 +192,11 @@ class _policyValidationState extends ConsumerState<policyValidation> {
? null ? null
: controllers["fuelType"]?.text, : controllers["fuelType"]?.text,
"date_of_registration": "date_of_registration": controllers["dateOfRegistration"]?.text?.isEmpty ?? true
controllers["dateOfRegistration"]?.text?.isEmpty ?? true
? null ? null
: controllers["dateOfRegistration"]?.text, : controllers["dateOfRegistration"]?.text,
"year_of_manufacture": "year_of_manufacture": controllers["yearOfManufacture"]?.text.isEmpty ?? true
controllers["yearOfManufacture"]?.text.isEmpty ?? true
? null ? null
: controllers["yearOfManufacture"]?.text, : controllers["yearOfManufacture"]?.text,
@ -196,15 +221,26 @@ class _policyValidationState extends ConsumerState<policyValidation> {
: controllers["cubicCapacity"]?.text, : controllers["cubicCapacity"]?.text,
"vehicle_type": controllers["vehicleType"]?.text?.isEmpty ?? true "vehicle_type": controllers["vehicleType"]?.text?.isEmpty ?? true
? null ? selectedVehicleTypeForEnquiryVAL
: controllers["vehicleType"]?.text, : controllers["vehicleType"]?.text,
"broker_name": controllers["broker_name"]?.text?.isEmpty ?? true "broker_name": controllers["broker_name"]?.text?.isEmpty ?? true
? null ? null
: controllers["broker_name"]?.text, : controllers["broker_name"]?.text,
"commission_amount": "enquiry_broker_id_for_commission": controllers["enquiry_broker_id_for_commission"]?.text?.isEmpty ?? true
controllers["commission_amount"]?.text?.isEmpty ?? true ? null
: controllers["enquiry_broker_id_for_commission"]?.text,
"enquiry_reg_no_for_commission": controllers["enquiry_reg_no_for_commission"]?.text?.isEmpty ?? true
? null
: controllers["enquiry_reg_no_for_commission"]?.text,
"enquiry_vehicle_type_id_for_commission": controllers["enquiry_vehicle_type_id_for_commission"]?.text?.isEmpty ?? true
? null
: controllers["enquiry_vehicle_type_id_for_commission"]?.text,
"commission_amount": controllers["commission_amount"]?.text?.isEmpty ?? true
? null ? null
: controllers["commission_amount"]?.text, : controllers["commission_amount"]?.text,
}; };
@ -215,7 +251,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
final policyId = widget.item?['policy_id']; final policyId = widget.item?['policy_id'];
return { return {
"vehicle_type": data["vehicle_type"], "vehicle_type": data["vehicle_type"] ?? selectedVehicleTypeForEnquiryVAL,
"insurance_plan_type": selectedInsurancPlanType, "insurance_plan_type": selectedInsurancPlanType,
"premium_amount": data["premium_amount"], "premium_amount": data["premium_amount"],
"od": data["od"], "od": data["od"],
@ -236,6 +272,9 @@ class _policyValidationState extends ConsumerState<policyValidation> {
"manager_retention_rate": selectedManagerRentionRate, "manager_retention_rate": selectedManagerRentionRate,
"id": policyId, "id": policyId,
"updated_by": userId, "updated_by": userId,
"enquiry_broker_id_for_commission": selectedBroker,
"enquiry_reg_no_for_commission": data["enquiry_reg_no_for_commission"],
"enquiry_vehicle_type_id_for_commission": selectedVehicleTypeForEnquiryID,
}; };
} }
@ -292,6 +331,9 @@ class _policyValidationState extends ConsumerState<policyValidation> {
getVehicleType(), getVehicleType(),
getFuelType(), getFuelType(),
getPolicyFilePath(), getPolicyFilePath(),
getBroker(),
getInsurancPlanType(),
getEnquiryVehicleTypeForCommission()
]); ]);
} }
@ -315,6 +357,123 @@ class _policyValidationState extends ConsumerState<policyValidation> {
}); });
} }
Future<void> getBroker() async {
print('getBroker called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchMasterDropDown('Broker');
if (response['status'] == 200) {
print('getBroker - ${response['data']}');
setState(() {
getBrokerData = List<Map<String, dynamic>>.from(response['data']);
print('API Data - $getBrokerData');
filteredBrokerData = List.from(getBrokerData);
print('originalData - $filteredBrokerData');
});
} else {
getBrokerData = [];
filteredBrokerData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
Future<void> getInsurancPlanType() async {
print('getInsurancPlanType called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchMasterDropDown('InsuranceType');
if (response['status'] == 200) {
print('getPlanType - ${response['data']}');
setState(() {
getInsurancPlanTypeData =
List<Map<String, dynamic>>.from(response['data']);
print('API Data - $getInsurancPlanTypeData');
filteredInsurancPlanTypeData =
List<Map<String, dynamic>>.from(getInsurancPlanTypeData);
print('originalData - $filteredInsurancPlanTypeData');
});
} else {
getInsurancPlanTypeData = [];
filteredInsurancPlanTypeData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
Future<void> getEnquiryVehicleTypeForCommission() async {
setState(() => isLoading = true);
try {
final response =
await apiService.fetchMasterDropDown('vehicleType');
if (response['status'] == 200 && response['data'] != null) {
final allData = List<Map<String, dynamic>>.from(response['data']);
final activeVehicles = allData.where((item) => item['is_active'] == "1").toList();
setState(() {
// 2. Assign the full objects
getVehicleTypeForEnquiryData = allData;
filteredVehicleDataForEnquiryData = List.from(activeVehicles);
// 3. Extract just the names for your String list
getVehicleTypeData = activeVehicles
.map((item) => item['vehicle_type'].toString())
.toList();
filteredVehicleTypeData = List.from(getVehicleTypeData);
});
} else {
getVehicleTypeForEnquiryData.clear();
filteredVehicleDataForEnquiryData.clear();
getVehicleTypeData.clear();
filteredVehicleTypeData.clear();
}
// if (response['status'] == 200 && response['data'] != null) {
// setState(() {
// getVehicleTypeForEnquiryData =
// List<Map<String, dynamic>>.from(response['data']);
//
// filteredVehicleDataForEnquiryData =
// List<Map<String, dynamic>>.from(
// getVehicleTypeForEnquiryData);
// });
// } else {
// getVehicleTypeForEnquiryData.clear();
// filteredVehicleDataForEnquiryData.clear();
// }
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() => isLoading = false);
}
}
Future<void> getVehicleType() async { Future<void> getVehicleType() async {
print('getvehicleType called'); print('getvehicleType called');
setState(() => isLoadingVehicleType = true); setState(() => isLoadingVehicleType = true);
@ -432,11 +591,11 @@ class _policyValidationState extends ConsumerState<policyValidation> {
if (response != null && response['status'] == 'success') { if (response != null && response['status'] == 'success') {
final data = (response['data'] ?? {}) as Map<String, dynamic>; final data = (response['data'] ?? {}) as Map<String, dynamic>;
debugPrint('findPolicyApi response1:'); debugPrint('findPolicyApi response1: ');
if (!mounted) return; if (!mounted) return;
debugPrint('findPolicyApi response2:'); debugPrint('findPolicyApi response2:');
setState(() { setState(() {
controllers["policyNumber"]!.text = safeText(data['policy_number']); controllers["policyNumber"]?.text = safeText(data['policy_number']);
controllers["insuredName"]!.text = safeText(data['insured_name']); controllers["insuredName"]!.text = safeText(data['insured_name']);
controllers["premiumAmount"]!.text = safeText(data['premium_amount']); controllers["premiumAmount"]!.text = safeText(data['premium_amount']);
controllers["rcNo"]!.text = safeText(data['rc_no']); controllers["rcNo"]!.text = safeText(data['rc_no']);
@ -480,9 +639,13 @@ class _policyValidationState extends ConsumerState<policyValidation> {
selectedAgentRentionRate = safeText(data['agent_retention_rate']); selectedAgentRentionRate = safeText(data['agent_retention_rate']);
selectedManagerRentionRate = safeText(data['manager_retention_rate']); selectedManagerRentionRate = safeText(data['manager_retention_rate']);
controllers["commission_amount"]?.text = safeText( // controllers["commission_amount"]?.text = safeText(
data['commission_amount'], // data['commission_amount'],
); // );
// FIX: Removed the invalid "data['key'] ? ..." syntax
selectedBroker = data['enquiry_broker_id_for_commission']?.toString() ?? '';
selectedVehicleTypeForEnquiryID = data['enquiry_vehicle_type_id_for_commission']?.toString() ?? '';
controllers["enquiry_reg_no_for_commission"]?.text = safeText(data['enquiry_reg_no_for_commission']);
}); });
debugPrint('findPolicyApi response3:'); debugPrint('findPolicyApi response3:');
@ -791,14 +954,13 @@ class _policyValidationState extends ConsumerState<policyValidation> {
// ToastHelper.showWarningToast(context, 'Exception: $e'); // ToastHelper.showWarningToast(context, 'Exception: $e');
// } // }
// } // }
Widget buildVehicleType(BuildContext context) { Widget buildVehicleType(BuildContext context) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"Vehicle Type", "Product (as per Document)",
style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11), style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
@ -825,7 +987,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
decoratorProps: DropDownDecoratorProps( decoratorProps: DropDownDecoratorProps(
decoration: decoration:
AppInputDecorations.dropdownDecoration( AppInputDecorations.dropdownDecoration(
label: "Select Vehicle Type", label: "Select Product",
).copyWith( ).copyWith(
filled: true, filled: true,
fillColor: Colors.white, fillColor: Colors.white,
@ -872,7 +1034,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
contentPadding: const EdgeInsets.all(6), contentPadding: const EdgeInsets.all(6),
filled: true, filled: true,
fillColor: Colors.white, fillColor: Colors.white,
hintText: "Search Vehicle Type...", hintText: "Search Product...",
hintStyle: GoogleFonts.inter(fontSize: 12, color: Colors.black), hintStyle: GoogleFonts.inter(fontSize: 12, color: Colors.black),
enabledBorder: const OutlineInputBorder( enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFFE2E8F0)), borderSide: BorderSide(color: Color(0xFFE2E8F0)),
@ -898,13 +1060,12 @@ class _policyValidationState extends ConsumerState<policyValidation> {
], ],
); );
} }
Widget buildFuelType(BuildContext context) { Widget buildFuelType(BuildContext context) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Fuel Type ", "Fuel Type *",
style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11), style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
@ -921,9 +1082,20 @@ class _policyValidationState extends ConsumerState<policyValidation> {
itemAsString: (val) => val, // 👈 String directly itemAsString: (val) => val, // 👈 String directly
// validator: (val) {
// if (val == null || val.isEmpty) {
// return ""; // 👈 triggers error border, no text
// }
// return null;
// },
validator: (val) { validator: (val) {
if (val == null || val.isEmpty) { if (val == null || val.isEmpty) {
return ""; // 👈 triggers error border, no text return ""; // Triggers red border for empty
}
// NEW: Also return error if it's a junk value
if (val.startsWith('UN_') || val.toLowerCase().contains('undefined')) {
return "Invalid Selection";
} }
return null; return null;
}, },
@ -1003,6 +1175,359 @@ class _policyValidationState extends ConsumerState<policyValidation> {
], ],
); );
} }
// Widget buildInsurancPlanType(BuildContext context) {
//
// final Map<String, dynamic>? selectedInsurancPlanTypes =
// selectedInsurancPlanType != null
// ? filteredInsurancPlanTypeData.firstWhere(
// (item) =>
// item['insurance_plan_type'].toString() ==
// selectedInsurancPlanType,
// orElse: () => {},
// )
// : null;
//
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// "Insurance Plan Type ",
// style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11),
// ),
// const SizedBox(height: 6),
// DropdownSearch<String>(
// key: dropDownKeyInsurancPlanType,
//
// selectedItem: selectedInsurancPlanType?.isNotEmpty == true
// ? selectedInsurancPlanType
// : null,
//
// items: (filter, _) => filteredInsurancPlanTypeData,
//
// itemAsString: (val) => val, // 👈 String directly
//
// validator: (val) {
// if (val == null || val.isEmpty) {
// return ""; // 👈 triggers error border, no text
// }
// return null;
// },
//
// decoratorProps: DropDownDecoratorProps(
// decoration:
// AppInputDecorations.dropdownDecoration(
// label: "Select Plan Type",
// ).copyWith(
// filled: true,
// fillColor: Colors.white,
// isDense: true,
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(
// // color: Color(0xFFE2E8F0),
// width: 0.6,
// ),
// ),
// enabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(
// // color: Color(0xFFE2E8F0),
// width: 0.6,
// ),
// ),
// errorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(color: Colors.red),
// ),
// focusedErrorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(color: Colors.red),
// ),
// contentPadding: const EdgeInsets.symmetric(
// horizontal: 8,
// vertical: 10,
// ),
// ),
// ),
//
// popupProps: PopupProps.menu(
// fit: FlexFit.loose,
// constraints: const BoxConstraints(maxHeight: 250),
// menuProps: const MenuProps(backgroundColor: Colors.white),
// showSearchBox: true,
//
// searchFieldProps: TextFieldProps(
// autofocus: true,
// decoration: InputDecoration(
// contentPadding: const EdgeInsets.all(6),
// filled: true,
// fillColor: Colors.white,
// hintText: "Search Plan Type...",
// hintStyle: GoogleFonts.inter(fontSize: 12, color: Colors.black),
// enabledBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Color(0xFFE2E8F0)),
// ),
// focusedBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Color(0xFFE2E8F0), width: 1.5),
// ),
// ),
// ),
// ),
//
// onChanged: (val) {
// if (val != null) {
// // setState(() {
// selectedInsurancPlanType = val;
// controllers['insurance_plan_type']?.text = val;
// // });
// // setState(() {});
// print("Selected InsurancPlanType: $val");
// }
// },
// ),
// ],
// );
// }
Widget buildBrokerAsPerEnquiry(BuildContext context) {
final Map<String, dynamic>? selectedBrokers =
selectedBroker != null
? filteredBrokerData.firstWhere(
(item) => item['id'].toString() == selectedBroker,
orElse: () => {},
)
: null;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Broker (as per Enquiry)",
style: GoogleFonts.poppins(
fontWeight: FontWeight.w500,
fontSize: 11,
),
),
const SizedBox(height: 6),
DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyBroker,
items: (filter, _) => filteredBrokerData,
selectedItem:
selectedBrokers != null && selectedBrokers.isNotEmpty
? selectedBrokers
: null,
itemAsString: (item) => item['name'].toString(),
compareFn: (item1, item2) =>
item1['id'].toString() == item2['id'].toString(),
onChanged: (val) {
if (val != null) {
selectedBroker = val['id'].toString();
controllers['enquiry_broker_id_for_commission']?.text =
val['id'].toString();
}
},
validator: (val) {
if (val == null) return "";
return null;
},
),
],
);
}
Widget buildVehicleTypeAsPerEnquiry(BuildContext context) {
final Map<String, dynamic>? selectedVehicle =
selectedVehicleTypeForEnquiryID != null
? filteredVehicleDataForEnquiryData.firstWhere(
(item) =>
item['id'].toString() ==
selectedVehicleTypeForEnquiryID,
orElse: () => {},
)
: null;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Product (as per Enquiry) *",
style: GoogleFonts.poppins(
fontWeight: FontWeight.w500,
fontSize: 11,
),
),
const SizedBox(height: 6),
DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyVehicleTypeForEnquiry,
items: (filter, _) => filteredVehicleDataForEnquiryData,
// disabledItemFn: (item) => item['is_active'] == "0",
compareFn: (a, b) =>
a['id'].toString() == b['id'].toString(),
selectedItem: selectedVehicle != null && selectedVehicle.isNotEmpty
? selectedVehicle
: null,
itemAsString: (item) => item['vehicle_type'].toString(),
// 2. Styling for the items in the list
popupProps: PopupProps.menu(
itemBuilder: (context, item, isSelected, isHovered) {
final bool isActive = item['is_active'] == "1";
return ListTile(
title: Text(
item['vehicle_type'].toString(),
style: TextStyle(
// Gray out text if inactive
color: isActive ? Colors.black : Colors.grey,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
// Add a "Disabled" subtitle for clarity
subtitle: isActive ? null : const Text("Inactive", style: TextStyle(fontSize: 10, color: Colors.red)),
);
},
),
onChanged: (val) {
if (val != null) {
selectedVehicleTypeForEnquiryID = val['id'].toString(); // store ID
selectedVehicleTypeForEnquiryVAL = val['vehicle_type'].toString();
controllers['enquiry_vehicle_type_id_for_commission']?.text =
val['id'].toString();
}
},
validator: (val) {
if (val == null) return "";
return null;
},
),
],
);
}
// Map<String, dynamic>? selectedVehicleTypes = filteredVehicleDataForEnquiryData.firstWhere(
// (item) => item['id'].toString() == selectedVehicleTypeForEnquiry,
// orElse: () => {},
// );
// Widget (BuildContext context) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// "Broker (as per Enquiry)",
// style: GoogleFonts.poppins(fontWeight: FontWeight.w500, fontSize: 11),
// ),
// const SizedBox(height: 6),
// DropdownSearch<String>(
// key: dropDownKeyBroker,
//
// selectedItem: selectedBroker?.isNotEmpty == true
// ? selectedBroker
// : null,
//
// items: (filter, infiniteScrollProps) {
// return filteredBrokerData;
// },
//
// itemAsString: (val) => val, // 👈 String directly
//
// validator: (val) {
// if (val == null || val.isEmpty) {
// return ""; // 👈 triggers error border, no text
// }
// return null;
// },
//
// decoratorProps: DropDownDecoratorProps(
// decoration:
// AppInputDecorations.dropdownDecoration(
// label: "Select Broker as per Enquiry",
// ).copyWith(
// filled: true,
// fillColor: Colors.white,
// isDense: true,
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(
// // color: Color(0xFFE2E8F0),
// width: 0.6,
// ),
// ),
// enabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(
// // color: Color(0xFFE2E8F0),
// width: 0.6,
// ),
// ),
// errorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(color: Colors.red),
// ),
// focusedErrorBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(6),
// borderSide: const BorderSide(color: Colors.red),
// ),
// contentPadding: const EdgeInsets.symmetric(
// horizontal: 8,
// vertical: 10,
// ),
// ),
// ),
//
// popupProps: PopupProps.menu(
// fit: FlexFit.loose,
// constraints: const BoxConstraints(maxHeight: 250),
// menuProps: const MenuProps(backgroundColor: Colors.white),
// showSearchBox: true,
//
// searchFieldProps: TextFieldProps(
// autofocus: true,
// decoration: InputDecoration(
// contentPadding: const EdgeInsets.all(6),
// filled: true,
// fillColor: Colors.white,
// hintText: "Search Broker as per Enquiry...",
// hintStyle: GoogleFonts.inter(fontSize: 12, color: Colors.black),
// enabledBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Color(0xFFE2E8F0)),
// ),
// focusedBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Color(0xFFE2E8F0), width: 1.5),
// ),
// ),
// ),
// ),
//
// onChanged: (val) {
// if (val != null) {
// // setState(() {
// selectedBroker = val;
// controllers['enquiry_broker_id_for_commission']?.text = val;
// // });
// // setState(() {});
// print("SelectedBrokerAsPerEnquiry: $val");
// }
// },
// ),
// ],
// );
// }
Widget _sectionHeader(String title, {IconData icon = Icons.info}) { Widget _sectionHeader(String title, {IconData icon = Icons.info}) {
return Container( return Container(
@ -1038,6 +1563,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
bool readOnly = false, bool readOnly = false,
VoidCallback? onTap, VoidCallback? onTap,
bool required = false, bool required = false,
String? hintText,
List<TextInputFormatter>? inputFormatters, // 👈 ADD THIS List<TextInputFormatter>? inputFormatters, // 👈 ADD THIS
}) { }) {
return Column( return Column(
@ -1071,7 +1597,13 @@ class _policyValidationState extends ConsumerState<policyValidation> {
decoration: InputDecoration( decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(6)), border: OutlineInputBorder(borderRadius: BorderRadius.circular(6)),
isDense: true, isDense: true,
hintText: hintText,
hintStyle: hintText == null
? null
: GoogleFonts.poppins(
fontSize: 12,
color: Colors.grey,
),
// alignment fix // alignment fix
helperText: ' ', helperText: ' ',
helperStyle: const TextStyle(height: 1), helperStyle: const TextStyle(height: 1),
@ -1322,6 +1854,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
// RIGHT - Grouped Form // RIGHT - Grouped Form
Expanded( Expanded(
flex: 1, flex: 1,
child: SelectionArea(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Form( child: Form(
key: _formKey, key: _formKey,
@ -1600,8 +2133,18 @@ class _policyValidationState extends ConsumerState<policyValidation> {
'Vehicle Details', 'Vehicle Details',
icon: Icons.directions_car, icon: Icons.directions_car,
), ),
SizedBox(height: 10), SizedBox(height: 10),
Row(
children: [
Expanded(
child: _buildInput(
'Reg No *',
controllers['enquiry_reg_no_for_commission']!,
required: true,
),
),
]
),
Row( Row(
children: [ children: [
Expanded( Expanded(
@ -1650,16 +2193,29 @@ class _policyValidationState extends ConsumerState<policyValidation> {
// ), // ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
// Expanded(
// child: _buildInput(
// 'Date of Registration *',
// controllers['dateOfRegistration']!,
// required: true,
// readOnly: true,
// onTap: () => _pickDate(
// controllers['dateOfRegistration']!,
// context,
// ),
// ),
// ),
Expanded( Expanded(
child: _buildInput( child: _buildInput(
'Date of Registration *', 'Date of Registration *',
controllers['dateOfRegistration']!, controllers['dateOfRegistration']!,
required: true, required: true,
readOnly: true, keyboardType: TextInputType.number,
onTap: () => _pickDate( hintText: 'DD-MM-YYYY',
controllers['dateOfRegistration']!, inputFormatters: [
context, LengthLimitingTextInputFormatter(10), // DD-MM-YYYY
), DateInputFormatter(),
],
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
@ -1735,7 +2291,12 @@ class _policyValidationState extends ConsumerState<policyValidation> {
decimalFormatter, decimalFormatter,
), ),
), ),
const SizedBox(width: 8), ],
),
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Expanded( Expanded(
// child: _buildInput( // child: _buildInput(
// 'Vehicle Type', // 'Vehicle Type',
@ -1746,6 +2307,12 @@ class _policyValidationState extends ConsumerState<policyValidation> {
context, context,
), ),
), ),
const SizedBox(width: 8),
Expanded(
child: buildVehicleTypeAsPerEnquiry(
context,
),
),
], ],
), ),
], ],
@ -1772,11 +2339,17 @@ class _policyValidationState extends ConsumerState<policyValidation> {
icon: Icons.person, icon: Icons.person,
), ),
SizedBox(height: 10), SizedBox(height: 10),
Row(
children: [
Expanded(child:buildBrokerAsPerEnquiry(context)),
const SizedBox(width: 8),
],
),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: _buildInput( child: _buildInput(
'Broker Name *', 'Broker (as per Document) *',
controllers['broker_name']!, controllers['broker_name']!,
required: true, required: true,
), ),
@ -1843,6 +2416,7 @@ class _policyValidationState extends ConsumerState<policyValidation> {
), ),
), ),
), ),
),
], ],
), ),
), ),
@ -1859,3 +2433,77 @@ class _policyValidationState extends ConsumerState<policyValidation> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
); );
} }
// class DateInputFormatter extends TextInputFormatter {
// @override
// TextEditingValue formatEditUpdate(
// TextEditingValue oldValue,
// TextEditingValue newValue,
// ) {
// // Allow backspace
// if (newValue.text.length < oldValue.text.length) {
// return newValue;
// }
//
// // Allow ONLY digits
// String digits = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
//
// if (digits.length > 8) {
// digits = digits.substring(0, 8);
// }
//
// StringBuffer formatted = StringBuffer();
//
// for (int i = 0; i < digits.length; i++) {
// if (i == 2 || i == 4) {
// formatted.write('-');
// }
// formatted.write(digits[i]);
// }
//
// return TextEditingValue(
// text: formatted.toString(),
// selection: TextSelection.collapsed(
// offset: formatted.length,
// ),
// );
// }
// }
class DateInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
// Backspace allowed
if (newValue.text.length < oldValue.text.length) {
return newValue;
}
String digits = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
if (digits.length > 8) {
digits = digits.substring(0, 8);
}
String formatted = '';
if (digits.isNotEmpty) {
formatted += digits.substring(0, digits.length.clamp(0, 2));
}
if (digits.length >= 2) {
formatted += '-';
formatted += digits.substring(2, digits.length.clamp(2, 4));
}
if (digits.length >= 4) {
formatted += '-';
formatted += digits.substring(4);
}
return TextEditingValue(
text: formatted,
selection: TextSelection.collapsed(offset: formatted.length),
);
}
}