import 'dart:convert'; import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import '../../config/apiUrl.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../widgets/custom_text_field.dart'; import '../../widgets/custom_user_form.dart'; class PolicyCriteria extends StatefulWidget { bool isDesktop; String selectedService; final ValueNotifier selectedTabNotifier; final ValueNotifier selectedIdNotifier; String? userId; bool isClass = true; bool isCost = true; final List serviceDBValueList; final Function(List>?) onPolicyDataChanged; PolicyCriteria({ super.key, required this.isDesktop, required this.selectedService, required this.selectedTabNotifier, required this.selectedIdNotifier, required this.userId, required this.isClass, required this.isCost, required this.onPolicyDataChanged, required this.serviceDBValueList, }); @override PolicyCriteriaState createState() => PolicyCriteriaState(); } class PolicyCriteriaState extends State { String? ServiceId;// = "1"; String? ServiceIndxId = "1"; String? orgId; String? userId; Map? apiDataForClass; bool isLoading = true; // final TextEditingController _costController = TextEditingController(); // final TextEditingController _classController = TextEditingController(); // String? FirstApproverAction; // String? SecondApproverAction; // String? ThirdApproverAction; // String? SelectedParallelProcess = "3"; final ApiService apiService = ApiService(); Map costController = {}; // Map classController = {}; Map classAction = {}; Map FirstApproverAction = {}; Map SecondApproverAction = {}; Map ThirdApproverAction = {}; Map SelectedParallelProcess = {}; Map FirstExceptionalApproverAction = {}; Map SecondExceptionalApproverAction = {}; Map ThirdExceptionalApproverAction = {}; Map FourthExceptionalApproverAction = {}; Map SelectedParallelExceptionalProcess = {}; Map FirstAmendApproverAction = {}; Map SecondAmendApproverAction = {}; Map ThirdAmendApproverAction = {}; Map FourthAmendApproverAction = {}; Map SelectedParallelAmendProcess = {}; Map policyDetailsIdMap = {}; // new Map policyIdMap = {}; // new Map validationErrors = {}; // bool isClass = true; // bool isCost = true; List>? policyData = []; // Map get policyServices { // Map data = { // "service_id": ServiceId, // "cost": costController[ServiceId]?.text, // "class": classController[ServiceId]?.text, // "a1_action": FirstApproverAction[ServiceId], // "a2_action": SecondApproverAction[ServiceId], // "a3_action": ThirdApproverAction[ServiceId], // "parallel_process_from": SelectedParallelProcess[ServiceId], // "created_by": widget.userId // }; // return data; // } @override void initState() { super.initState(); fetchTrainFlightClass(); print("whole value here - ${widget.serviceDBValueList}"); print(widget.serviceDBValueList); fieldForPolicy(); widget.selectedIdNotifier.addListener(() { setState(() { ServiceId = widget.selectedIdNotifier.value ?? "1"; print("new :) ${widget.selectedIdNotifier.value}"); print("ServiceIndxId changed: $ServiceId"); }); }); widget.selectedTabNotifier.addListener(() { print("selectedTab changed: ${widget.selectedTabNotifier.value}"); setState(() { ServiceIndxId = widget.selectedTabNotifier.value ?? "1"; // ServiceId = widget.selectedIdNotifier.value ?? "1"; print("ServiceIndxId changed: $ServiceIndxId"); }); fieldForPolicy(); // fetchTrainFlightClass(); // old here }); } void loadinitializeData() async { orgId = await getOrgId(); userId = await getUserId(); } // void saveCurrentPolicy(List> services) { // print("saveCurrentPolicy- $services"); // if (ServiceId != null) { // print("Saving curremt Add or Update"); // addOrUpdatePolicy(ServiceId!); // } // } void saveCurrentPolicy(List> services) { print("saveCurrentPolicy- $services"); // Step 1: Save currently selected policy first (if not already saved) if (ServiceId != null) { print("Saving current Add or Update"); addOrUpdatePolicy(ServiceId!); } // Step 2: Collect existing service_ids from policyData final existingServiceIds = policyData?.map((e) => e['service_id'].toString()).toSet(); // Step 3: Loop through all service definitions for (var service in services) { String id = service['service_id'].toString(); print("164 service == $id"); // Skip if already present if (existingServiceIds!.contains(id)) continue; // Step 4: Initialize any missing controllers or data costController.putIfAbsent(id, () => TextEditingController()); classAction.putIfAbsent(id, () => "1"); // working fine FirstApproverAction.putIfAbsent(id, () => "None"); SecondApproverAction.putIfAbsent(id, () => "None"); ThirdApproverAction.putIfAbsent(id, () => "None"); SelectedParallelProcess.putIfAbsent(id, () => "3"); FirstExceptionalApproverAction.putIfAbsent(id, () => "None"); SecondExceptionalApproverAction.putIfAbsent(id, () => "None"); ThirdExceptionalApproverAction.putIfAbsent(id, () => "None"); FourthExceptionalApproverAction.putIfAbsent(id, () => "None"); SelectedParallelExceptionalProcess.putIfAbsent(id, () => "4"); FirstAmendApproverAction.putIfAbsent(id, () => "None"); SecondAmendApproverAction.putIfAbsent(id, () => "None"); ThirdAmendApproverAction.putIfAbsent(id, () => "None"); FourthAmendApproverAction.putIfAbsent(id, () => "None"); SelectedParallelAmendProcess.putIfAbsent(id, () => "4"); // Step 5: Add default policy entry policyData?.add({ "service_id": int.parse(id), "cost": "", "class": classAction[id], // working fine "a1_action": FirstApproverAction[id], "a2_action": SecondApproverAction[id], "a3_action": ThirdApproverAction[id], "parallel_process_from": SelectedParallelProcess[id], "a1_exceptional_action": FirstExceptionalApproverAction[id], "a2_exceptional_action": SecondExceptionalApproverAction[id], "a3_exceptional_action": ThirdExceptionalApproverAction[id], "a4_exceptional_action": FourthExceptionalApproverAction[id], "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[id], "a1_amendment_action": FirstAmendApproverAction[id], "a2_amendment_action": SecondAmendApproverAction[id], "a3_amendment_action": ThirdAmendApproverAction[id], "a4_amendment_action": FourthAmendApproverAction[id], "amendment_parallel_process_from": SelectedParallelAmendProcess[id], "created_by": widget.userId, }); } // Step 6: Emit updated policy data widget.onPolicyDataChanged(policyData); } // To set the data (update) void loadPolicyDetails(List> details) { print("loadPolicyDetails"); for (var item in details) { final serviceId = item['service_id'].toString(); costController[serviceId] = TextEditingController( text: item['cost'] ?? '', ); // classAction[serviceId] = classAction[serviceId]?.toString(); classAction[serviceId] = item['class']?.toString() ?? ''; // working fine FirstApproverAction[serviceId] = item['a1_action']?.toString(); SecondApproverAction[serviceId] = item['a2_action']?.toString(); ThirdApproverAction[serviceId] = item['a3_action']?.toString(); SelectedParallelProcess[serviceId] = item['parallel_process_from']?.toString() ?? "3"; FirstExceptionalApproverAction[serviceId] = item['a1_exceptional_action']?.toString(); SecondExceptionalApproverAction[serviceId] = item['a2_exceptional_action']?.toString(); ThirdExceptionalApproverAction[serviceId] = item['a3_exceptional_action']?.toString(); FourthExceptionalApproverAction[serviceId] = item['a4_exceptional_action']?.toString(); SelectedParallelExceptionalProcess[serviceId] = item['exceptional_parallel_process_from']?.toString() ?? "3"; FirstAmendApproverAction[serviceId] = item['a1_amendment_action']?.toString(); SecondAmendApproverAction[serviceId] = item['a2_amendment_action']?.toString(); ThirdAmendApproverAction[serviceId] = item['a3_amendment_action']?.toString(); FourthAmendApproverAction[serviceId] = item['a4_amendment_action']?.toString(); SelectedParallelAmendProcess[serviceId] = item['amendment_parallel_process_from']?.toString() ?? "4"; if (item['policy_details_id'] != null) { policyDetailsIdMap[serviceId] = item['policy_details_id'].toString(); } if (item['policy_id'] != null) { policyIdMap[serviceId] = item['policy_id'].toString(); } } policyData = details; widget.onPolicyDataChanged(policyData); if (details.isNotEmpty) { final firstServiceId = details.first['service_id'].toString(); print('First Service ID is: $firstServiceId'); // firstServiceId == "1" // ? fetchTrainFlightClass(1) // : fetchTrainFlightClass(2); } setState(() {}); print("detailsdetails- $details"); } void addOrUpdatePolicy(String serviceId) { print("addOrUpdatePolicyserviceId - $serviceId"); // 1. First, find existing item if any final existingIndex = policyData!.indexWhere( (item) => item["service_id"] == serviceId, ); print(FirstApproverAction); Map data = { "service_id": serviceId, "cost": costController[serviceId]?.text, // "class": classController[serviceId]?.text, "class": classAction[serviceId] ?? "", // working fine "a1_action": FirstApproverAction[serviceId], "a2_action": SecondApproverAction[serviceId], "a3_action": ThirdApproverAction[serviceId], "parallel_process_from": SelectedParallelProcess[serviceId], "a1_exceptional_action": FirstExceptionalApproverAction[serviceId], "a2_exceptional_action": SecondExceptionalApproverAction[serviceId], "a3_exceptional_action": ThirdExceptionalApproverAction[serviceId], "a4_exceptional_action": FourthExceptionalApproverAction[serviceId], "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[serviceId], "a1_amendment_action": FirstAmendApproverAction[serviceId], "a2_amendment_action": SecondAmendApproverAction[serviceId], "a3_amendment_action": ThirdAmendApproverAction[serviceId], "a4_amendment_action": FourthAmendApproverAction[serviceId], "amendment_parallel_process_from": SelectedParallelAmendProcess[serviceId], "created_by": widget.userId, }; final cost = costController[serviceId]?.text ?? ""; // final travelClass = classController[serviceId]?.text ?? ""; final travelClass = classAction[serviceId]; // working fine final a1 = FirstApproverAction[serviceId]; final a2 = SecondApproverAction[serviceId]; final a3 = ThirdApproverAction[serviceId]; final ae1 = FirstExceptionalApproverAction[serviceId]; final ae2 = SecondExceptionalApproverAction[serviceId]; final ae3 = ThirdExceptionalApproverAction[serviceId]; final ae4 = FourthExceptionalApproverAction[serviceId]; final aa1 = FirstAmendApproverAction[serviceId]; final aa2 = SecondAmendApproverAction[serviceId]; final aa3 = ThirdAmendApproverAction[serviceId]; final aa4 = FourthAmendApproverAction[serviceId]; // bool hasValue = cost.trim().isNotEmpty; // bool hasValue = cost.trim().isNotEmpty || travelClass!.isNotEmpty; bool hasValue = cost.trim().isNotEmpty || (travelClass?.isNotEmpty ?? false); bool allActionsNull = a1 == null && a2 == null && a3 == null; bool someActionsMissing = [a1, a2, a3].where((a) => a != null).length > 0 && [a1, a2, a3].where((a) => a == null).length > 0; bool allExceptionalActionsNull = ae1 == null && ae2 == null && ae3 == null && ae4 == null; bool someExceptionalActionsMissing = [ae1, ae2, ae3, ae4].where((a) => a != null).length > 0 && [ae1, ae2, ae3, ae4].where((a) => a == null).length > 0; bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null && aa4 == null; bool someAmendActionsMissing = [aa1, aa2, aa3, aa4].where((a) => a != null).length > 0 && [aa1, aa2, aa3, aa4].where((a) => a == null).length > 0; if (someActionsMissing) { validationErrors[serviceId] = "All 3 approver actions must be selected."; return; } if (someExceptionalActionsMissing) { validationErrors[serviceId] = "All 4 exceptional approver actions must be selected."; return; } if (someAmendActionsMissing) { validationErrors[serviceId] = "All 4 amendment approver actions must be selected."; return; } if (hasValue && allActionsNull && allExceptionalActionsNull && allAmendActionsNull) { validationErrors[serviceId] = "Please select all actions."; return; } else { print("HAS VAlue"); } validationErrors.remove(serviceId); // 2. ⚡ If updating an existing item, also **keep its IDs** if (existingIndex != -1) { final existingItem = policyData![existingIndex]; if (existingItem.containsKey("policy_details_id")) { data["policy_details_id"] = existingItem["policy_details_id"]; } if (existingItem.containsKey("policy_id")) { data["policy_id"] = existingItem["policy_id"]; } // 3. Now update it policyData![existingIndex] = data; print("🔁 Updated policy for ServiceId: $serviceId"); } else { // 4. Else add as new policyData!.add(data); print("➕ Added policy for ServiceId: $serviceId"); } // int index = // policyData!.indexWhere((item) => item["service_id"] == serviceId); // if (index != -1) { // policyData![index] = data; // Replace existing entry // print("🔁 Updated policy for ServiceId: $serviceId"); // } else { // policyData!.add(data); // Add new entry // print("➕ Added policy for ServiceId: $serviceId"); // } print("📋 policyData - $policyData"); } // Future fetchTrainFlightClass(int tripId) async { // // final String apiUrldata = '$apiUrl/api/getDropdownMaster'; // // // final String apiUrldata = // // '$apiUrl/api/getFlightAndTrainClass?user_id=${widget.userId}&trip_type=tripId'; // final String apiUrldata = await apiService.fetchMasterDropdown(); // // final token = await getToken(); // // if (token == null) { // throw Exception('Token not found. Please log in.'); // } // // final response = await http.get( // Uri.parse(apiUrldata), // headers: { // 'Authorization': 'Bearer $token', // 'Content-Type': 'application/json', // }, // ); // // if (response.statusCode == 200) { // try { // final data = json.decode(response.body); // print(data); // // if (!data.containsKey('data') || data['data'] is! Map) { // throw Exception( // "Invalid response format: 'data' field is missing or not a Map"); // } // // Map plansJson = // data['data']; // 'data' is a Map, not a List // setState(() { // apiDataForClass = plansJson; // Store API response in state // isLoading = false; // }); // } catch (e) { // throw Exception('Error parsing response: $e'); // } // } else { // throw Exception('Failed to load plans'); // } // } Future fetchTrainFlightClass() async { print("ftech api"); try { final data = await apiService.fetchMasterDropdown(); print("fetchTrainFlightClass - $data"); if (data is! Map) { throw Exception("Invalid response format: expected a Map"); } setState(() { apiDataForClass = data; // Store API response in state isLoading = false; }); } catch (e) { print('Error fetching role list: $e'); } } void fieldForPolicy() { print("fieldForPolicy - ${widget.selectedTabNotifier.value}"); // Save current input to policyData before switching if (ServiceId != null) { print("Calling addOrUpdatePolicy"); addOrUpdatePolicy( ServiceId!, ); // 👈 Save current values for existing service } setState(() { // ServiceId = widget.selectedTabNotifier.value ?? "1"; final String tabIndexStr = widget.selectedTabNotifier.value; print(" fns - $ServiceId"); // Safely convert tab index to int final int? tabIndex = int.tryParse(tabIndexStr); print(" tb inx - $tabIndex"); print(" db - ${widget.serviceDBValueList.length}"); print(" db list - ${widget.serviceDBValueList}"); if (tabIndex != null && tabIndex >= 0 && tabIndex <= widget.serviceDBValueList.length) { ServiceId = widget.serviceDBValueList[tabIndex-1].toString(); print('✅ 484 Selected ServiceId: $ServiceId'); } else { print('❌ Invalid tab index or out of range'); } print("502 ServiceId $ServiceId"); // Initialize controllers and variables if not present costController.putIfAbsent(ServiceId!, () => TextEditingController()); classAction.putIfAbsent((ServiceId!), () => "1"); // classController.putIfAbsent(ServiceId!, () => TextEditingController()); FirstApproverAction.putIfAbsent(ServiceId!, () => "None"); SecondApproverAction.putIfAbsent(ServiceId!, () => "None"); ThirdApproverAction.putIfAbsent(ServiceId!, () => "None"); SelectedParallelProcess.putIfAbsent(ServiceId!, () => "3"); FirstExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); SecondExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); ThirdExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); FourthExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "4"); FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); ThirdAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); FourthAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); SelectedParallelAmendProcess.putIfAbsent(ServiceId!, () => "4"); }); widget.onPolicyDataChanged(policyData); } void printData() { // print("policyServices - $policyServices"); } Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ // widget.isDesktop ? SizedBox(height: 10) : SizedBox(height: 5), // Row( // mainAxisAlignment: MainAxisAlignment.start, // children: [ // Padding( // padding: widget.isDesktop // ? const EdgeInsets.only(left: 28.0) // : const EdgeInsets.only(left: 0), // child: Text( // " Policy Criteria For ${widget.selectedService} ", // style: GoogleFonts.poppins( // fontSize: 13, // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold), // ), // ) // ], // ), if (widget.isClass!) widget.isDesktop ? SizedBox(height: 1) : SizedBox(height: 1), Padding( padding: widget.isDesktop ? const EdgeInsets.only(left: 0.0) : const EdgeInsets.only(left: 0), child: Row( children: [ Container( // color: Colors.grey, padding: const EdgeInsets.only( top: 2, bottom: 2, left: 5, right: 5, ), child: widget.isDesktop ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (widget.isClass) buildClassWidget(widget.isDesktop), SizedBox(width: 45), if (widget.isCost!) buildCostWidget(widget.isDesktop), ], ) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (widget.isClass!) buildClassWidget(widget.isDesktop), SizedBox(height: 10), if (widget.isCost!) buildCostWidget(widget.isDesktop), ], ), ), ], ), ), if (widget.isCost!) SizedBox(height: 5), if (validationErrors[ServiceId] != null) Row( children: [ Text( validationErrors[ServiceId]!, style: GoogleFonts.poppins( color: Colors.red, fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), if (validationErrors[ServiceId] != null) SizedBox(height: 5), Container( decoration: BoxDecoration( border: null, // border: Border.all( // color: Color(0xFFEBEBF7), // ), borderRadius: BorderRadius.circular(8), // color: Colors.brown.shade200, ), child: Container( child: Row( children: [ Column( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( // color: Colors.yellow, width: widget.isDesktop ? MediaQuery.of(context).size.width * 0.18 : 600, height: widget.isDesktop ? MediaQuery.of(context).size.height * 0.56 : null, child: Column( children: [ Container( margin: const EdgeInsets.only(right: 0), decoration: BoxDecoration( // color: Colors.grey.shade100, // border: Border.all( // color: Colors.grey.shade100, // ), ), padding: const EdgeInsets.only( top: 10, bottom: 0, left: 0, right: 35, ), child: Row( mainAxisAlignment: widget.isDesktop ? MainAxisAlignment.spaceAround : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, child: Align( alignment: Alignment.center, child: Text( "Normal Approval", style: GoogleFonts.poppins( color: Color(0xFF9E9DBD), fontWeight: FontWeight.bold, fontSize: 12, ), ), ), ), // Expanded( // flex: 2, // child: Text( // "Actions", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ), // ), // Text( // "Parallel Action", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ) ], ), ), Divider(thickness: 0.2, color: Colors.grey), SizedBox( // height: 180, // scrollDirection: Axis.vertical, child: Container( // height: MediaQuery.of(context).size.height * 3, // color: Colors.grey, decoration: BoxDecoration( border: Border( right: BorderSide( color: Colors .blueGrey .shade50, // Change this to your desired color width: 1.0, // Change this to your desired width ), ), ), margin: const EdgeInsets.only(right: 5, left: 0), // color: Colors.grey.shade100, child: Column( children: [ Container( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 1", "A1", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: FirstApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name FirstApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = "1"; }); print( "SelectedParallelProcess - $SelectedParallelProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: (SelectedParallelProcess[ServiceId] == "1") ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: (SelectedParallelProcess[ServiceId] == "1") ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 2", "A2", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: SecondApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: TextStyle( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name SecondApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = "2"; }); print( "SelectedParallelProcess - $SelectedParallelProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelProcess[ServiceId] == "1") || (SelectedParallelProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelProcess[ServiceId] == "1") || (SelectedParallelProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( "A3", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: ThirdApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: (context, selectedItem) => // Center-align selected item Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name ThirdApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = "3"; }); print( "SelectedParallelProcess - $SelectedParallelProcess[ServiceId]", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelProcess[ServiceId] == "1") || (SelectedParallelProcess[ServiceId] == "2") || (SelectedParallelProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelProcess[ServiceId] == "1") || (SelectedParallelProcess[ServiceId] == "2") || (SelectedParallelProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), ], ), ), ), ], ), ), ], ), Column( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( width: widget.isDesktop ? MediaQuery.of(context).size.width * 0.18 : 600, height: widget.isDesktop ? MediaQuery.of(context).size.height * 0.56 : null, child: Column( children: [ Container( margin: const EdgeInsets.only(right: 0), decoration: BoxDecoration( // color: Colors.grey.shade100, // border: Border.all( // color: Colors.grey.shade100, // ), ), padding: const EdgeInsets.only( top: 10, bottom: 0, left: 0, right: 35, ), child: Row( mainAxisAlignment: widget.isDesktop ? MainAxisAlignment.spaceAround : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, child: Align( alignment: Alignment.center, child: Text( "Exceptional Approval", style: GoogleFonts.poppins( color: Color(0xFF9E9DBD), fontWeight: FontWeight.bold, fontSize: 12, ), ), ), ), // Expanded( // flex: 2, // child: Text( // "Actions", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ), // ), // Text( // "Parallel Action", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ) ], ), ), Divider(thickness: 0.2, color: Colors.grey), SizedBox( // height: 180, // scrollDirection: Axis.vertical, child: Container( // height: MediaQuery.of(context).size.height * 3, // color: Colors.grey, decoration: BoxDecoration( border: Border( right: BorderSide( color: Colors .blueGrey .shade50, // Change this to your desired color width: 1.0, // Change this to your desired width ), ), ), margin: const EdgeInsets.only(right: 5, left: 0), // color: Colors.grey.shade100, child: Column( children: [ Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 1", "A1", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: FirstExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name FirstExceptionalApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = "1"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: (SelectedParallelExceptionalProcess[ServiceId] == "1") ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: (SelectedParallelExceptionalProcess[ServiceId] == "1") ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 2", "A2", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: SecondExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: TextStyle( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name SecondExceptionalApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = "2"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( "A3", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: ThirdExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: (context, selectedItem) => // Center-align selected item Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name ThirdExceptionalApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = "3"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2") || (SelectedParallelExceptionalProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2") || (SelectedParallelExceptionalProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( "A4", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: FourthExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: (context, selectedItem) => // Center-align selected item Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name FourthExceptionalApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = "4"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2") || (SelectedParallelExceptionalProcess[ServiceId] == "3") || (SelectedParallelExceptionalProcess[ServiceId] == "4")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || (SelectedParallelExceptionalProcess[ServiceId] == "2") || (SelectedParallelExceptionalProcess[ServiceId] == "3") || (SelectedParallelExceptionalProcess[ServiceId] == "4")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), ], ), ), ), ], ), ), ], ), Column( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( //color: Colors.grey.shade100, width: widget.isDesktop ? MediaQuery.of(context).size.width * 0.18 : 600, height: widget.isDesktop ? MediaQuery.of(context).size.height * 0.56 : null, child: Column( children: [ Container( margin: const EdgeInsets.only(right: 0), decoration: BoxDecoration( // color: Colors.grey.shade100, // border: Border.all( // color: Colors.grey.shade100, // ), ), padding: const EdgeInsets.only( top: 10, bottom: 0, left: 0, right: 35, ), child: Row( mainAxisAlignment: widget.isDesktop ? MainAxisAlignment.spaceAround : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, child: Align( alignment: Alignment.center, child: Text( "Amendment Approval", style: GoogleFonts.poppins( color: Color(0xFF9E9DBD), fontWeight: FontWeight.bold, fontSize: 12, ), ), ), ), // Expanded( // flex: 2, // child: Text( // "Actions", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ), // ), // Text( // "Parallel Action", // style: GoogleFonts.poppins( // color: Color(0xFF9E9DBD), // fontWeight: FontWeight.bold, // fontSize: 12), // ) ], ), ), Divider(thickness: 0.2, color: Colors.grey), SizedBox( // height: 180, // scrollDirection: Axis.vertical, child: Container( // height: MediaQuery.of(context).size.height * 3, // color: Colors.grey, margin: const EdgeInsets.only(right: 5, left: 0), // color: Colors.grey.shade100, child: Column( children: [ Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 1", "A1", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: FirstAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name FirstAmendApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = "1"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: (SelectedParallelAmendProcess[ServiceId] == "1") ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: (SelectedParallelAmendProcess[ServiceId] == "1") ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( // "Approver 2", "A2", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: SecondAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: TextStyle( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: ( context, selectedItem, ) => Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name SecondAmendApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = "2"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( "A3", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: ThirdAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: (context, selectedItem) => // Center-align selected item Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name ThirdAmendApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = "3"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2") || (SelectedParallelAmendProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2") || (SelectedParallelAmendProcess[ServiceId] == "3")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( "A4", style: GoogleFonts.poppins( fontSize: 13, ), ), Spacer(), CustomTextFieldUserWrapper( width: MediaQuery.of( context, ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: DropdownSearch( selectedItem: FourthAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: FlexFit .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( context, item, isSelected, ) => Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Text( item, style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here color: Colors .black, // You can customize this ), ), ), ), items: [ "Approval", "Notification", "None", ], dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 1, vertical: 5, ), ), ), dropdownBuilder: (context, selectedItem) => // Center-align selected item Text( selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), ), ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name FourthAmendApproverAction[ServiceId!] = newValue; // print("selectedUserType - $selectedUserType"); // if (selectedCountry!.isNotEmpty) { // errorMessages.remove("country_code"); // } }); }, ), ), ), Spacer(), GestureDetector( onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = "4"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]", ); }, child: Container( height: 25, width: 25, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2") || (SelectedParallelAmendProcess[ServiceId] == "3") || (SelectedParallelAmendProcess[ServiceId] == "4")) ? Colors.green : Colors.grey, width: 2, ), ), child: Icon( Icons.check_circle, size: 20, color: ((SelectedParallelAmendProcess[ServiceId] == "1") || (SelectedParallelAmendProcess[ServiceId] == "2") || (SelectedParallelAmendProcess[ServiceId] == "3") || (SelectedParallelAmendProcess[ServiceId] == "4")) ? Colors.green : Colors.grey, // color: Colors.grey, ), ), ), ], ), ), ], ), ), ), ], ), ), ], ), ], ), ), ), ], ); } Widget buildClassWidget(isDesktop) { List purposeList = []; String textLabel = "Class"; // if (ServiceId != null) { // purposeList = (ServiceId == "1") // ? (apiDataForClass?['flight_class'] ?? []) // : (apiDataForClass?['train_class'] ?? []); // } if (ServiceId != null) { // ServiceId = '1'; print("sid $ServiceId"); switch (ServiceId) { case "1": textLabel = "Class"; purposeList = apiDataForClass?['flight_class'] ?? []; break; case "5": textLabel = "Category"; purposeList = apiDataForClass?['hotel_class'] ?? []; break; case "2": textLabel = "Class"; purposeList = apiDataForClass?['train_class'] ?? []; break; default: textLabel = "Class"; purposeList = []; } } print("CLASS-ServiceId- $ServiceId"); print("CLASS-ServiceIndxId- $ServiceIndxId"); print("CLASS-purposeList - $purposeList"); print("CLASS-Action - ${classAction[ServiceId]}"); // ✅ Sort by dropdown_key purposeList.sort((a, b) { int aKey = int.tryParse(a['dropdown_key'].toString()) ?? 0; int bKey = int.tryParse(b['dropdown_key'].toString()) ?? 0; return aKey.compareTo(bKey); }); List> dropdownItems = purposeList .map( (item) => DropdownMenuItem( value: item['dropdown_key'], child: Text(item['dropdown_value']), ), ) .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, child: Text( "No options available", style: GoogleFonts.poppins(color: Colors.grey), ), ), ); } // if (ServiceId != null) { // if (classAction[ServiceId!] == null && dropdownItems.isNotEmpty) { // classAction[ServiceId!] = dropdownItems.first.value!; // } // } // if (ServiceId != null && // classAction[ServiceId!] == null && // dropdownItems.isNotEmpty) { // classAction[ServiceId!] = dropdownItems.first.value!; // } // 1. First, when dropdownItems are ready, assign default value: if ((ServiceId) != null && classAction[ServiceId] == null && dropdownItems.isNotEmpty) { // Important to wrap inside setState if async WidgetsBinding.instance.addPostFrameCallback((_) { setState(() { classAction[ServiceId!] = dropdownItems.first.value!; }); }); } return Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( textLabel, style: GoogleFonts.poppins( fontSize: 12, // fontWeight: FontWeight.w200, color: Colors.black, ), ), SizedBox(height: 5), // CustomTextFieldUserWrapper( // isFocused: false, // isDesktop: widget.isDesktop, // // child: SizedBox( // height: 40, // child: ServiceId != null && (isLoading || dropdownItems.isEmpty) // ? const Center(child: CircularProgressIndicator()) // : DropdownButtonFormField( // // Assign the correct focus node // // controller: _hotelNameController, // value: classAction[ServiceId], // // style: GoogleFonts.poppins(fontSize: 12), // decoration: InputDecoration( // hintText: "Select", // hintStyle: GoogleFonts.poppins(fontSize: 12), // border: InputBorder.none, // contentPadding: EdgeInsets.symmetric( // horizontal: 10), // Proper padding // ), // onChanged: (newValue) { // if (ServiceId != null && newValue != null) { // setState(() { // classAction[ServiceId!] = newValue; // }); // } // }, // // items: dropdownItems, // ), // ), // ), CustomTextFieldUserWrapper( isFocused: false, isDesktop: isDesktop, child: SizedBox( height: 40, width: double.infinity, child: (ServiceId!) != null && (isLoading || dropdownItems.isEmpty) ? const Center(child: CircularProgressIndicator()) : DropdownSearch>( key: classAction[(ServiceId!)] == null ? UniqueKey() : ValueKey(classAction[(ServiceId!)]), items: purposeList.cast>(), // selectedItem: purposeList.firstWhere( // (item) => item['dropdown_key'] == selectedClass, // orElse: () => {}, // ), selectedItem: classAction[(ServiceId!)] != null ? purposeList.firstWhere( (item) => item['dropdown_key'] == classAction[(ServiceId!)], orElse: () => {}, ) : null, itemAsString: (item) => item['dropdown_value'] ?? '', popupProps: PopupProps.menu( showSearchBox: false, fit: FlexFit.loose, menuProps: const MenuProps( backgroundColor: Colors.white, ), itemBuilder: (context, item, isSelected) { final bool isNotAllowed = item['is_allowed'] == 'No'; return Padding( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), child: Text( item['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: isNotAllowed ? Colors.redAccent : Colors.black, ), ), ); }, ), dropdownDecoratorProps: const DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 10, vertical: 10, ), ), ), dropdownBuilder: (context, selectedItem) { if (selectedItem == null || selectedItem.isEmpty) { return Text( "Select ", style: GoogleFonts.poppins( color: Colors.grey, fontSize: 13, ), ); } return Text( selectedItem['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, ), ); }, onChanged: purposeList.isNotEmpty ? (Map? newValue) async { setState(() { classAction[(ServiceId!)] = newValue?['dropdown_key']; print( "Selected Purpose: ${classAction[(ServiceId!)]}", ); }); } : null, ), ), ), ], ), ], ); } Widget buildCostWidget(isDesktop) { return Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Cost", style: GoogleFonts.poppins( fontSize: 12, // fontWeight: FontWeight.w200, color: Colors.black, ), ), SizedBox(height: 5), CustomTextFieldUserWrapper( isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( height: 40, child: TextField( style: GoogleFonts.poppins(fontSize: 12), controller: costController[ServiceId], // enabled: !isViewMode, onChanged: (value) { printData(); }, decoration: InputDecoration( labelText: "Cost", labelStyle: GoogleFonts.poppins( fontSize: 12, color: Colors.grey, ), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), ), ], ), ], ); } }