import 'dart:convert'; import 'package:dropdown_search/dropdown_search.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:nhance_partner/data/utils/toastNotification.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../../../core/config/env.dart'; import '../../../../../core/routing/routes.dart'; import '../../../../../core/services/api_service.dart'; import '../../../../../data/services/auth_service.dart'; import '../../../../../data/utils/validators.dart'; import '../../../../layouts/responsive_layout.dart'; import '../../../../providers/manager_provider.dart'; import '../../../../providers/quotation_staff_proivder.dart'; import '../../../../providers/userRoleProvider.dart'; import '../../../../themes/indicators/customizd_file_upload.dart'; import '../../../../themes/indicators/input_field_decoration.dart'; import '../../../../themes/indicators/text_field_theme.dart'; import '../../../../themes/indicators/text_field_theme_inline_editor.dart' hide UpperCaseTextFormatter; class CreateProposal_Quick extends ConsumerStatefulWidget { // final dynamic userId; // final dynamic managerId; // final dynamic selectedEnquiryId; // final dynamic selectedInsurdId; // final dynamic selectedQuotationFrmListdata; // final dynamic selectedQuotationFrmListId; // final void Function(String value) onSubmit; const CreateProposal_Quick({ super.key, // required this.userId, // required this.managerId, // required this.selectedEnquiryId, // required this.selectedInsurdId, // this.selectedQuotationFrmListdata, // this.selectedQuotationFrmListId, // required this.onSubmit, }); @override ConsumerState createState() => CreateProposal_QuickFormState(); } class CreateProposal_QuickFormState extends ConsumerState { late ApiService apiService; String? _token; String? selectedFileNames; List> getInsurersData = []; List> filteredInsurersData = []; String? selectedInsurer; bool isLoading = false; bool _autoValidate = false; late TextEditingController controller; Map controllers = {}; final _formKey = GlobalKey(); String? docUploadedFileUrlFromApi; String? selectedId; PlatformFile? docUploadedFile; final GlobalKey>> dropDownKey = GlobalKey>>(); final GlobalKey>> dropDownKeyBroker = GlobalKey>>(); final GlobalKey>> dropDownKeyAgent = GlobalKey>>(); final GlobalKey>> dropDownKeyInsurer = GlobalKey>>(); final GlobalKey>> dropDownKeyInsurerEnqAsgn = GlobalKey>>(); final GlobalKey>> dropDownSelectPaymentModeKey = GlobalKey>>(); List tabHeader = ['idv', 'premium_Amount', 'insurer', 'regNo']; List> getBrokerData = []; List> filteredBrokerData = []; String? selectedBroker; List> getPaymentModeData = []; List> filteredPaymentModeData = []; List> getInsuranceTypeData = []; List> filteredInsuranceData = []; List> getAgentListData = []; List> filteredAgentData = []; String? selectedAgent; String? selectedInsPlanType; String? selectedEndorsement; String? selectedPaymentMode; dynamic roleId; dynamic userId; dynamic managerId; Map quotationData() { final data = { // "enquiry_id": widget.selectedEnquiryId, // "insured_declared_value": controllers["idv"]?.text, "insurer_id": selectedInsurer, "premium_amount": controllers["premium_Amount"]?.text, "insurance_plan_type_id": selectedInsPlanType, // "payment_mode_id": selectedPaymentMode, // "broker_id": selectedBroker, // "additional_uploaded_file_name": "extra_doc.pdf", // "created_by": widget.userId, // "manager_id": widget.managerId, }; return data; } Map dataDetails() { print('checking agent id $selectedAgent'); final data = { "agent_id": ((roleId == 'handler') || (roleId == 'manager') || (roleId == 'staff')) ? selectedAgent : userId, // "name": controllers["name"]?.text, // "mobile": controllers["mobile"]?.text, // "email": controllers["email"]?.text, "reg_no": controllers["regNo"]?.text, "is_data_created_by_staff": roleId != null ? '1' : '0', // "insurer_id": selectedInsurer, // "rc_file_name": "rc_doc.pdf", // "id_proof_file_name": "id_proof.pdf", // "previous_policy_file_name": "previous_policy.pdf", "remarks": controllers["remarks"]?.text, // "assigned_to": (roleId == 'staff') ? userId : selectedStaff, "is_quick_quote": "1", "quotation": [quotationData], "insurer_id": selectedInsurer, "broker_id": selectedBroker, "manager_id": managerId, "created_by": userId, }; return data; } @override void initState() { super.initState(); apiService = ApiService(); for (String field in tabHeader) { controllers[field] = TextEditingController(); } Future.microtask(() async { roleId = ref.read(userRoleProvider); userId = ref.read(userIdProvider); managerId = ref.read(managerIdProvider); final prefs = await SharedPreferences.getInstance(); if (managerId != null) { print('managerId - $managerId'); getAgentList(managerId); } }); // 🔹 Init logic here (API calls, token fetch, etc.) _initializeToken(); getInsuranceType(); getPaymentMode(); getInsurers(); updateData(); getBroker(); } Future _initializeToken() async { _token = await AuthService.getToken(); print("APISERTOKEN - $_token"); } @override void dispose() { // Dispose all TextEditingControllers for (var controller in controllers.values) { controller.dispose(); } super.dispose(); } void reset() { print('RESET'); _formKey.currentState?.reset(); // Clear all TextEditingControllers for (var controller in controllers.values) { controller.clear(); } dropDownKey.currentState?.changeSelectedItem(null); dropDownKeyInsurer.currentState?.changeSelectedItem(null); // Reset dropdowns / selections selectedInsurer = null; selectedInsPlanType = null; selectedEndorsement = null; // Reset file selection selectedFileNames = null; docUploadedFile = null; docUploadedFileUrlFromApi = null; // Reset selected ID selectedId = null; // Trigger UI update setState(() {}); } Future getAgentList(id) async { print('getAgentListData called'); setState(() { isLoading = true; }); try { final response = await apiService.fetchAgentNameDropDown(id); print('getAgentListData called response'); print('get Agent- ${response['data']}'); if (response['status'] == 'success') { print('get Agent- ${response['data']}'); setState(() { getAgentListData = List>.from(response['data']); print('API Data - $getAgentListData'); filteredAgentData = List.from(getAgentListData); print('originalAgentData - $filteredAgentData'); }); } else { getAgentListData = []; filteredAgentData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } Future 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>.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; }); } } void updateData() {} Future getInsurers() async { print('Insurers called'); setState(() { isLoading = true; }); try { final response = await apiService.fetchMasterDropDown('Insurers'); if (response['status'] == 200) { print('getInsurers - ${response['data']}'); setState(() { getInsurersData = List>.from(response['data']); print('API Data - $getInsurersData'); filteredInsurersData = List.from(getInsurersData); print('originalData - $filteredInsurersData'); }); } else { getInsurersData = []; filteredInsurersData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } Future getInsuranceType() async { print('getClaimList called'); setState(() { isLoading = true; }); try { final response = await apiService.fetchMasterDropDown('InsuranceType'); if (response['status'] == 200) { print('getInsuranceTypeData - ${response['data']}'); setState(() { getInsuranceTypeData = List>.from( response['data'], ); print('API Data - $getInsuranceTypeData'); filteredInsuranceData = List.from(getInsuranceTypeData); print('originalData - $filteredInsuranceData'); }); } else { getInsuranceTypeData = []; filteredInsuranceData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } Future getPaymentMode() async { print('getPaymentMode called'); setState(() { isLoading = true; }); try { final response = await apiService.fetchMasterDropDown('PaymentMode'); if (response['status'] == 200) { print('getPaymentModeData - ${response['data']}'); setState(() { getPaymentModeData = List>.from( response['data'], ); print('API Data - $getPaymentModeData'); filteredPaymentModeData = List.from(getPaymentModeData); print('originalData - $filteredPaymentModeData'); }); } else { getPaymentModeData = []; filteredPaymentModeData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } void handleDone() { if (!_formKey.currentState!.validate()) return; // setState(() { // _autoValidate = true; // enable autovalidation after first save attempt // }); setState(() { if (_formKey.currentState!.validate()) { dataDetails(); final dataSet = dataDetails(); print("dataSetAgent - $dataSet"); // print("managerId - $managerId ,userId - $userId "); createUserData(dataSet); } else { // isDi sable = false; } }); } Future createUserData(Map userData) async { // final bool isUpdating = widget.selectedQuotationFrmListId != null; // final id = widget.selectedQuotationFrmListId!; print("userDatauserData1 - $userData"); // final bool isUpdating = widget.selectedQuotationFrmListId != null; // final id = widget.selectedQuotationFrmListId; // keep nullable // print('id - $id'); final uri = Uri.parse( // isUpdating // ? '${Env.apiUrl}quotation/updateQuotation' // : '${Env.apiUrl}quotation/createQuotation', '${Env.apiUrl}quotation/proceedQuotation', ); if (_token == null) { throw Exception('Token not found. Please log in.'); } // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $_token'; request.headers['app-signature'] = Env.App_Signature; // If updating, spoof the method Laravel-style // if (isUpdating) { // print('Updatrinf'); // // request.fields['_method'] = 'PUT'; // request.fields['id'] = id!; // request.fields['updated_by'] = widget.userId!.toString(); // request.fields['created_by'] = widget.userId!.toString(); // } else { // print('Not Updatrinf'); // request.fields['created_by'] = widget.userId!.toString(); // } print("USerDAta - $userData"); // userData.forEach((key, value) { // request.fields[key] = value.toString(); // print("✅ Encoded travel_details2: ${request.fields[key]}"); // }); userData.forEach((key, value) { // if (key != 'certificate_file_name') { request.fields[key] = value.toString(); print("✅ Encoded $key: ${request.fields[key]}"); // } }); if (docUploadedFile != null) { try { if (docUploadedFile!.bytes != null) { final multipartFile = http.MultipartFile.fromBytes( 'policy_pdf_file_name', docUploadedFile!.bytes!, filename: docUploadedFile!.name, ); request.files.add(multipartFile); } else if (docUploadedFile!.path != null) { final multipartFile = await http.MultipartFile.fromPath( 'policy_pdf_file_name', docUploadedFile!.path!, filename: docUploadedFile!.name, ); request.files.add(multipartFile); } print("📎 File attached: ${docUploadedFile!.name}"); } catch (e) { print("❌ Failed to attach file: $e"); } } print(" Sending request with fields: ${request.fields}"); try { final streamedResponse = await request.send(); final response = await http.Response.fromStream(streamedResponse); print("Response status: ${response.statusCode}"); print("Response body: ${response.body}"); if (response.statusCode == 200 || response.statusCode == 201) { // dispose(); print("✅ Agent submitted successfully!"); print("Response: ${response.body}"); // ToastHelper.showErrorToast(context, 'Proposal Created'); reset(); Navigator.of(context).pop(); } else if (response.statusCode == 403) { await apiService.clearLocalStorageAndRedirect(); } else { final responseBody = jsonDecode(response.body); dynamic msg = responseBody['data']; print("❌ Submission failed. Status: ${response.statusCode}"); print("Body: ${response.body}"); ToastHelper.showErrorToast(context, 'Proposal Creation Failed'); } } catch (e) { print("🔥 Error submitting user: $e"); } } @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ buildAgentName(context), const SizedBox(width: 20), buildVehicleNumber(context), ], ), SizedBox(height: 5), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ buildInsurer(context), const SizedBox(width: 20), buildInsurancePlanType(context), const SizedBox(width: 20), buildPremiumAmnt(context), const SizedBox(width: 10), Row( // mainAxisAlignment: MainAxisAlignment.end, children: [ GestureDetector( onTap: () { // handleDone(); }, child: Container( padding: const EdgeInsets.symmetric( horizontal: 2, vertical: 2, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.0), color: Colors.blue, ), child: Icon(Icons.add, color: Colors.white, size: 14), ), ), ], ), ], ), SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ GestureDetector( onTap: () { handleDone(); // widget.onSubmit(controller.text.trim()); // Navigator.of(context).pop(); }, child: Container( padding: const EdgeInsets.symmetric( horizontal: 5, vertical: 5, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4.0), color: const Color(0xFF2E7D6E), ), child: Text( 'Save', style: GoogleFonts.poppins( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w400, ), ), ), ), ], ), ], ), ); } // ------------------------- Claims Part ----------------------------------- Widget buildIdv(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('IDV *', style: _textStyle), SizedBox(height: 10), ThemedFormField( controller: controllers['idv']!, inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), ], validator: (value) => Validators.doubleNumber(value, "IDV"), borderColor: Color(0xFFE2E8F0), highlightColor: Color(0xFF50A398), // validator: (value) => Validators.number(value, "IDV"), // backgroundColor: Color(0xFFEDF6F5), // readOnly: true, txtwidth: ResponsiveLayout.isMobile(context) ? null : MediaQuery.of(context).size.width * 0.08, // txtheight: 35, ), ], ); } Widget buildAgentName(BuildContext context, {fromHeader = true}) { Map? selectedAgntName = filteredAgentData.firstWhere( (item) => item['id'].toString() == selectedAgent, orElse: () => {}, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Partner *', style: _textStyle), SizedBox(height: 5), SizedBox( width: MediaQuery.of(context).size.width * 0.1, // width: fromHeader // ? MediaQuery.of(context).size.width * 0.11 // : MediaQuery.of(context).size.width * 0.08, height: 30, child: DropdownSearch>( key: dropDownKeyAgent, selectedItem: selectedAgntName.isNotEmpty ? selectedAgntName : null, // items: (filter, infiniteScrollProps) { // return filteredAgentData; // }, items: (filter, infiniteScrollProps) async { if (filter.isEmpty) { return filteredAgentData; } return filteredAgentData.where((item) { return item['name'].toString().toLowerCase().contains( filter.toLowerCase(), ); }).toList(); }, itemAsString: (val) => val['name'].toString(), // what to show compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id 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['name'].toString() : "", // ✅ FIXED style: GoogleFonts.poppins(fontSize: 11, color: Colors.black), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, ), ), decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( label: "Partner Name", ).copyWith( errorStyle: const TextStyle(fontSize: 0, height: 0.0), 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, decoration: InputDecoration( contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Partner Name", hintStyle: GoogleFonts.inter( fontSize: 10, color: Colors.grey, ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white, ), // 👈 Normal border ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white, width: 1.5, ), // 👈 Focused border ), ), ), // constraints: BoxConstraints(), itemBuilder: (context, item, isDisabled, isSelected) { return Container( // color: isSelected ? Colors.blue.withOpacity(0.1) : null, padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 3, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Text( item['name'].toString(), style: GoogleFonts.inter( fontSize: 12, color: Colors.black, ), ), Text( item['agent_code'].toString(), style: GoogleFonts.inter( fontSize: 11, color: Colors.grey, ), ), ], ), ); }, ), onChanged: (val) { if (val != null) { print("Selected Partner : ${val['name']}"); print("Id: ${val['id']}"); selectedAgent = val['id']; // controllers['agentId']?.text = val['agent_code']; // agentId = agent['id']; } }, ), ), ], ); } Widget buildVehicleNumber(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Vehicle Number *', style: _textStyle), SizedBox(height: 5), SizedBox( width: MediaQuery.of(context).size.width * 0.1, height: 30, child: ThemedFormInlineField( controller: controllers['regNo']!, hintText: 'Vehicle Number', borderColor: Color(0xFFE2E8F0), highlightColor: Color(0xFF50A398), padVertical: 10, isdense: true, inputFormatters: [ UpperCaseTextFormatter(), // 👈 custom formatter for uppercase FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9- ]')), ], validator: (value) => Validators.requiredField(value, "regNo"), // validator: (value) => Validators.requiredVechileNum(value, "regNo"), widthNone: true, ), ), ], ); } Widget buildInsurer(BuildContext context, {fromHeader = true}) { Map? selectedInsurerd = filteredInsurersData.firstWhere( (item) => item['id'].toString() == selectedInsurer, orElse: () => {}, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Insurer *', style: _textStyle), SizedBox(height: 5), Container( height: 30, width: MediaQuery.of(context).size.width * 0.1, child: DropdownSearch>( key: dropDownKeyInsurerEnqAsgn, selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null, items: (filter, infiniteScrollProps) async { if (filter.isEmpty) { return filteredInsurersData; } return filteredInsurersData.where((item) { return item['name'].toString().toLowerCase().contains( filter.toLowerCase(), ); }).toList(); }, itemAsString: (val) => val['name'].toString(), // what to show compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id 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) { return Container( padding: EdgeInsets.symmetric(vertical: 0, horizontal: 4), alignment: Alignment.centerLeft, height: 22, // 👈 FORCE HEIGHT child: Text( selectedItem?['name'] ?? '', style: GoogleFonts.poppins(fontSize: 11), overflow: TextOverflow.ellipsis, ), ); }, decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( label: "Insurer", ).copyWith( errorStyle: const TextStyle(fontSize: 0, height: 0.0), filled: true, fillColor: Colors.white, // 👈 makes the dropdown input white isDense: true, // contentPadding: EdgeInsets.zero, 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: 4, vertical: 1, ), ), ), popupProps: PopupProps.menu( fit: FlexFit.loose, searchDelay: Duration(milliseconds: 200), constraints: BoxConstraints(maxHeight: 250), menuProps: MenuProps( backgroundColor: Colors.white, // 👈 sets dropdown background to white ), showSearchBox: true, searchFieldProps: TextFieldProps( autofocus: true, decoration: InputDecoration( contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Insurer...", hintStyle: GoogleFonts.inter( fontSize: 11, 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: 1, ), child: Text( item['name'].toString(), style: GoogleFonts.inter(fontSize: 12, color: Colors.black), ), ); }, // constraints: BoxConstraints(), ), onChanged: (val) { if (val != null) { print("Selected Insurer : ${val['name']}"); print("Id: ${val['id']}"); selectedInsurer = val['id']; // controllers['agentId']?.text = val['agent_code']; // agentId = agent['id']; } }, ), ), ], ); } Widget buildPremiumAmnt(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Premium Amount *', style: _textStyle), SizedBox(height: 5), SizedBox( height: 30, child: ThemedFormField( controller: controllers['premium_Amount']!, borderColor: Color(0xFFE2E8F0), highlightColor: Color(0xFF50A398), // backgroundColor: Color(0xFFEDF6F5), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')), ], validator: (value) => Validators.doubleNumber(value, "PremiumAmount"), // validator: (value) => Validators.number(value, "PremiumAmount "), txtwidth: ResponsiveLayout.isMobile(context) ? null : MediaQuery.of(context).size.width * 0.08, // txtheight: 35, ), ), ], ); } Widget buildInsurancePlanType(context) { Map? selectedVehicle = filteredInsuranceData.firstWhere( (item) => item['id'].toString() == selectedInsPlanType, orElse: () => {}, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Plan Type *", style: _textStyle), SizedBox(height: 5), SizedBox( // color: Colors.white, width: ResponsiveLayout.isMobile(context) ? null : MediaQuery.of(context).size.width * 0.1, height: 30, child: DropdownSearch>( key: dropDownKey, selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, // items: (filter, infiniteScrollProps) { // return filteredInsuranceData; // }, items: (filter, infiniteScrollProps) async { if (filter.isEmpty) { return filteredInsuranceData; } return filteredInsuranceData.where((item) { return item['name'].toString().toLowerCase().contains( filter.toLowerCase(), ); }).toList(); }, itemAsString: (val) => val['insurance_plan_type'].toString(), compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id validator: (val) { if (val == null) { return "Required"; // ✅ error message } return null; }, decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( label: "Select Staff Member", ).copyWith( errorStyle: const TextStyle(fontSize: 0, height: 0.0), 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, decoration: InputDecoration( contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Plan 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['insurance_plan_type'].toString(), style: GoogleFonts.inter(fontSize: 12, color: Colors.black), ), ); }, // searchFieldProps: TextFieldProps( // decoration: InputDecoration( // filled: true, // fillColor: Colors.white, // hintText: "Search Plan Type...", // enabledBorder: OutlineInputBorder( // borderSide: BorderSide( // color: Colors.white, // ), // 👈 Normal border // ), // focusedBorder: OutlineInputBorder( // borderSide: BorderSide( // color: Colors.white, // width: 1.5, // ), // 👈 Focused border // ), // ), // ), // constraints: BoxConstraints(), ), onChanged: (val) { if (val != null) { print("Selected ClaimsType : ${val['insurance_plan_type']}"); print("Id: ${val['id']}"); selectedInsPlanType = val['id']; // controllers['agentId']?.text = val['agent_code']; // agentId = agent['id']; } }, ), ), ], ); } Widget buildPaymentMode(context) { Map? selectedVehicle = filteredPaymentModeData.firstWhere( (item) => item['id'].toString() == selectedPaymentMode, orElse: () => {}, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Payment Mode", style: _textStyle), SizedBox(height: 10), Container( color: Colors.white, width: ResponsiveLayout.isMobile(context) ? null : MediaQuery.of(context).size.width * 0.18, height: 35, child: DropdownSearch>( key: dropDownSelectPaymentModeKey, selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null, // items: (filter, infiniteScrollProps) { // return filteredInsuranceData; // }, items: (filter, infiniteScrollProps) async { if (filter.isEmpty) { return filteredPaymentModeData; } return filteredPaymentModeData.where((item) { return item['name'].toString().toLowerCase().contains( filter.toLowerCase(), ); }).toList(); }, itemAsString: (val) => val['value'].toString(), compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id validator: (val) { if (val == null) { return "Required"; // ✅ error message } return null; }, decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( label: "Select Payment Mode", ).copyWith( errorStyle: const TextStyle(fontSize: 0, height: 0.0), 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, decoration: InputDecoration( contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Payment Mode ...", 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['value'].toString(), style: GoogleFonts.inter(fontSize: 12, color: Colors.black), ), ); }, ), onChanged: (val) { if (val != null) { print("Selected value : ${val['value']}"); print("Id: ${val['id']}"); selectedPaymentMode = val['id']; // controllers['agentId']?.text = val['agent_code']; // agentId = agent['id']; } }, ), ), ], ); } Widget buildBroker(context) { Map? selectedBrokers = filteredBrokerData.firstWhere( (item) => item['id'].toString() == selectedBroker, orElse: () => {}, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Broker", style: _textStyle), SizedBox(height: 10), Container( color: Colors.white, width: ResponsiveLayout.isMobile(context) ? null : MediaQuery.of(context).size.width * 0.18, height: 35, child: DropdownSearch>( key: dropDownKeyBroker, selectedItem: selectedBrokers.isNotEmpty ? selectedBrokers : null, // items: (filter, infiniteScrollProps) { // return filteredInsuranceData; // }, items: (filter, infiniteScrollProps) async { if (filter.isEmpty) { return filteredBrokerData; } return filteredBrokerData.where((item) { return item['name'].toString().toLowerCase().contains( filter.toLowerCase(), ); }).toList(); }, itemAsString: (val) => val['name'].toString(), compareFn: (item, selectedItem) => item['id'] == selectedItem['id'], // ✅ compare by id validator: (val) { if (val == null) { return "Required"; // ✅ error message } return null; }, decoratorProps: DropDownDecoratorProps( decoration: AppInputDecorations.dropdownDecoration( label: "Select Broker", ).copyWith( errorStyle: const TextStyle(fontSize: 0, height: 0.0), 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, decoration: InputDecoration( contentPadding: EdgeInsets.all(1), filled: true, fillColor: Colors.white, hintText: "Search Broker...", 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['name'].toString(), style: GoogleFonts.inter(fontSize: 12, color: Colors.black), ), ); }, ), onChanged: (val) { if (val != null) { print("Selected ClaimsType : ${val['id']}"); print("Id: ${val['id']}"); selectedBroker = val['id']; } }, ), ), ], ); } // ------------------- STyle --------------------------------- static final TextStyle _textStyle = TextStyle( fontSize: 11, color: Color(0XFF334155), fontWeight: FontWeight.w500, ); }