From a7310238c03d27b05055ccd53a72c6702ac0b876 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 5 Aug 2025 15:19:26 +0530 Subject: [PATCH] UI_SEMATICS --- lib/Screens/itnerary/accomodations.dart | 287 +-- lib/Screens/itnerary/flights.dart | 2320 +++++++++++------------ lib/Screens/itnerary/train.dart | 657 +++---- lib/Screens/policy/policyCriteria.dart | 42 +- 4 files changed, 1680 insertions(+), 1626 deletions(-) diff --git a/lib/Screens/itnerary/accomodations.dart b/lib/Screens/itnerary/accomodations.dart index 222ee9b..a6b2e5c 100644 --- a/lib/Screens/itnerary/accomodations.dart +++ b/lib/Screens/itnerary/accomodations.dart @@ -137,7 +137,7 @@ class _AccomodationScreenState extends State { _hotelNameFocusNode, (focus) => _isHotelNameFocused = focus, ); - _addFocusListener( _CategoryFocusNode, (focus) => _CategoryFocused = focus); + _addFocusListener(_CategoryFocusNode, (focus) => _CategoryFocused = focus); _addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus); _addFocusListener( _checkInTimeFocusNode, @@ -201,7 +201,7 @@ class _AccomodationScreenState extends State { // flightLastTripDateNotifier.value = checkoutDate; // } - final tripType = result['tripType'] ; + final tripType = result['tripType']; if (checkinDate != null) { flightFirstTripDateNotifier.value = checkinDate; @@ -230,7 +230,9 @@ class _AccomodationScreenState extends State { final checkInDateInput = flightFirstTripDateNotifier.value; if (checkInDateInput != null && checkInDateInput.isNotEmpty) { try { - final parsedDate = DateFormat("dd-MM-yyyy").parseStrict(checkInDateInput); + final parsedDate = DateFormat( + "dd-MM-yyyy", + ).parseStrict(checkInDateInput); _checkInController.text = DateFormat("dd-MM-yyyy").format(parsedDate); } catch (e) { _checkInController.text = ''; @@ -241,8 +243,12 @@ class _AccomodationScreenState extends State { final checkOutDateInput = flightLastTripDateNotifier.value; if (checkOutDateInput != null && checkOutDateInput.isNotEmpty) { try { - final parsedDate = DateFormat("dd-MM-yyyy").parseStrict(checkOutDateInput); - _checkOutController.text = DateFormat("dd-MM-yyyy").format(parsedDate); + final parsedDate = DateFormat( + "dd-MM-yyyy", + ).parseStrict(checkOutDateInput); + _checkOutController.text = DateFormat( + "dd-MM-yyyy", + ).format(parsedDate); } catch (e) { _checkOutController.text = ''; } @@ -280,9 +286,9 @@ class _AccomodationScreenState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; }); } @@ -581,7 +587,7 @@ class _AccomodationScreenState extends State { ), ); } - + final List items = ['Apple', 'Banana', 'Orange', 'Mango']; // Default selected value // selectedClass ??= // dropdownItems.isNotEmpty ? dropdownItems.first.value : null; @@ -619,7 +625,7 @@ class _AccomodationScreenState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.34 - : null,//MediaQuery.of(context).size.width * 0.66, + : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, child: TextField( @@ -660,6 +666,7 @@ class _AccomodationScreenState extends State { SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( isFocused: _isHotelNameFocused, + isDesktop: isDesktop, // width: // isDesktop @@ -725,140 +732,144 @@ class _AccomodationScreenState extends State { // Request focus when user taps _CategoryFocusNode?.requestFocus(); }, - child: DropdownSearch>( - key: - selectedClass == null - ? UniqueKey() - : ValueKey(selectedClass), + child: DropdownSearch>( + // key: + // selectedClass == null + // ? UniqueKey() + // : ValueKey(selectedClass), + items: purposeList.cast>(), + // selectedItem: purposeList.firstWhere( + // (item) => item['dropdown_key'] == selectedClass, + // orElse: () => {}, + // ), + selectedItem: + selectedClass != null + ? purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedClass, + orElse: () => {}, + ) + : null, - items: purposeList.cast>(), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClass, - // orElse: () => {}, - // ), - selectedItem: - selectedClass != null - ? purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedClass, - 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) { - print("categotey - $item "); - 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, + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + print("categotey - $item "); + 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: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_CategoryFocused ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_CategoryFocused ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, ), ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_CategoryFocused ?? false) - ? layoutColor! - : Colors.white, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_CategoryFocused ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 1, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: const 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.red, + color: Colors.black, + ), + ); + }, + onChanged: + purposeList.isNotEmpty + ? (Map? newValue) async { + if (newValue != null && + newValue['is_allowed'] == 'No') { + final confirm = await showNotAllowedDialog( + context, + message: + "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", + ); + + if (confirm) { + setState(() { + exceptionalClass = "1"; + selectedClass = newValue['dropdown_key']; + }); + print("Selected Purpose: ${selectedClass}"); + } else { + setState(() { + exceptionalClass = "0"; + selectedClass = + null; // ❌ Clear selection if user cancels + }); + print( + "selectedItem resolved to: ${selectedClass}", + ); + } + + return; + } else if (newValue != null && + newValue['is_allowed'] == 'yes') { + setState(() { + exceptionalClass = "0"; + selectedClass = newValue?['dropdown_key']; + print("Selected Purpose: ${selectedClass}"); + }); + } + } + : null, ), ), - 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.red, - color: Colors.black, - ), - ); - }, - onChanged: - purposeList.isNotEmpty - ? (Map? newValue) async { - if (newValue != null && - newValue['is_allowed'] == 'No') { - final confirm = await showNotAllowedDialog( - context, - message: - "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", - ); - - if (confirm) { - setState(() { - exceptionalClass = "1"; - selectedClass = newValue['dropdown_key']; - }); - print("Selected Purpose: ${selectedClass}"); - } else { - setState(() { - exceptionalClass = "0"; - selectedClass = - null; // ❌ Clear selection if user cancels - }); - print( - "selectedItem resolved to: ${selectedClass}", - ); - } - - return; - } else if (newValue != null && - newValue['is_allowed'] == 'yes') { - setState(() { - exceptionalClass = "0"; - selectedClass = newValue?['dropdown_key']; - print("Selected Purpose: ${selectedClass}"); - }); - } - } - : null, - ),),), + ), ), ), if (errorMessages["class"] != null) ...[ diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index 3828f58..3c94eb4 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -1846,10 +1846,10 @@ class FlightScreenState extends State { }, child: DropdownSearch>( items: purposeList.cast>(), - key: - selectedClasses[index] == null - ? UniqueKey() - : ValueKey(selectedClasses[index]), + // key: + // selectedClasses[index] == null + // ? UniqueKey() + // : ValueKey(selectedClasses[index]), // selectedItem: purposeList.firstWhere( // (item) => item['dropdown_key'] == selectedClasses[index], // orElse: () => {}, @@ -2740,1160 +2740,1160 @@ class FlightScreenState extends State { ]; } - List _buildSecondRow1(bool isDesktop, int index) { - bool isFlightClassLoading = widget.apiDataForClass?['flight_class'] == null; - - List purposeList = widget.apiDataForClass?['flight_class'] ?? []; - - 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: TextStyle(color: Colors.grey), - ), - ), - ); - } - - // Default selected value - // selectedClasses[index] ??= - // dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - // ------------------------------------------------- - - DateTime? _selectedCheckOutDate; - TimeOfDay? _selectedCheckOutTime; - - Future _selectCheckOutDate(BuildContext context) async { - DateTime now = DateTime.now(); - DateTime today = DateTime(now.year, now.month, now.day); - // Determine the minimum date (firstDate) based on previous index if available - DateTime firstDate = today; - - if (index == 1 && - flightLastTripDateNotifier.value != null && - flightLastTripDateNotifier.value!.isNotEmpty) { - try { - final tripDate = DateFormat( - 'dd-MM-yyyy', - ).parseStrict(flightLastTripDateNotifier.value!); - if (tripDate.isAfter(today)) { - firstDate = tripDate; - } - } catch (_) { - // handle parse error if needed - } - } else if (index > 1) { - final previousDateString = - textControllers["_date${index - 1}Controller"]?.text; - if (previousDateString != null && previousDateString.isNotEmpty) { - try { - final previousDate = DateFormat( - 'dd-MM-yyyy', - ).parseStrict(previousDateString); - if (previousDate.isAfter(today)) { - firstDate = previousDate; - } - } catch (_) { - // handle parse error if necessary - } - } - } - - DateTime initialDate = - _selectedCheckOutDate != null && - _selectedCheckOutDate!.isAfter(firstDate) - ? _selectedCheckOutDate! - : firstDate; - - DateTime? pickedDate = await showDatePicker( - context: context, - initialDate: initialDate, - firstDate: firstDate, - lastDate: DateTime(2100), - initialEntryMode: DatePickerEntryMode.calendarOnly, - ); - - if (pickedDate != null && pickedDate != _selectedCheckOutDate) { - setState(() { - _selectedCheckOutDate = pickedDate; - // _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); - textControllers["_date${index}Controller"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - }); - } - } - - Future _selectCheckOutTime( - BuildContext context, - int index, - VoidCallback onPicked, - ) async { - TimeOfDay? pickedTime = await showTimePicker( - context: context, - initialTime: _selectedCheckOutTime ?? TimeOfDay.now(), - ); - - if (pickedTime != null) { - final now = DateTime.now(); - - // Parse the selected date - final dateText = textControllers["_date${index}Controller"]?.text ?? ""; - final selectedDate = DateFormat( - 'dd-MM-yyyy', - ).parse(dateText); // or 'yyyy-MM-dd' depending on your format - - final selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - pickedTime.hour, - pickedTime.minute, - ); - - // ✅ Only validate past time if date is today - final isToday = - selectedDate.year == now.year && - selectedDate.month == now.month && - selectedDate.day == now.day; - - bool isPastTime = selectedDateTime.isBefore(now); - - if (isToday && isPastTime) { - setState(() { - errorMessages["time_$index"] = "You can't select a past time."; - }); - return; - } - - // ✅ Valid time selection - setState(() { - _selectedCheckOutTime = pickedTime; - - final formattedTime = DateFormat('HH:mm').format(selectedDateTime); - textControllers["_time${index}Controller"]?.text = formattedTime; - // errorMessages["time_$index"] = ""; // clear previous error - errorMessages.remove("time_$index"); - onPicked(); // Trigger callback - }); - } - - // if (pickedTime != null && pickedTime != _selectedCheckOutTime) { - // setState(() { - // _selectedCheckOutTime = pickedTime; - // // Formatting time to HH:mm (24-hour format) - // final now = DateTime.now(); - // final formattedTime = DateFormat('HH:mm').format( - // DateTime( - // now.year, - // now.month, - // now.day, - // pickedTime.hour, - // pickedTime.minute, - // ), - // ); - // - // // _timeController.text = formattedTime; - // textControllers["_time${index}Controller"]?.text = formattedTime; - // - // onPicked(); - // }); - // } - } - - return isDesktop - ? [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: _fromFocus, - // isFocused: focusStates["_from${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: - isCountryLoading - ? Center(child: CircularProgressIndicator()) - : Focus( - focusNode: focusNodes["_from${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_from${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_from${index}FocusNode"] - ?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedFrom[index] != null - ? countryMap[selectedFrom[index]] - : null, - items: countryMap.values.toList(), - // asyncItems: (String filter) async { - // final allItems = countryMap.values.toSet().toList(); - // print("Original items: ${allItems.length}"); - // final filtered = filterAndSortCountryList(allItems, filter); - // // print("Filtered items: ${filtered.length} -> $filtered"); - // return filtered; - // }, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, - ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - Text( - code, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - }, - - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - // items: countryMap.values.toList(), - // filterFn: (item, filter) { - // final lowerFilter = filter.toLowerCase(); - // - // final parts = item.split('\n'); - // final cityAndCode = parts[0]; - // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; - // - // // Extract city and code from "City (CODE)" - // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); - // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; - // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; - // - // // Priority: Code > City > Airport - // return code.contains(lowerFilter) || - // city.contains(lowerFilter) || - // airport.contains(lowerFilter); - // }, - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } - - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), - ); - }, - - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select", - // style: TextStyle(fontSize: 12), - // ), - // ), - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("from_place_$index"); - // selectedFrom[index] = countryMap.entries - // .firstWhere((entry) => entry.value == newValue) - // .key; - - selectedFrom[index] = - countryMap.entries - .firstWhere( - (entry) => - entry.value == newValue, - ) - .key; - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedFrom[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedTo[2] = selectedFrom[index]!; - } - }); - }, - ), - ), - ), - ), - - // child: SizedBox( - // height: 40, - // child: TextField( - // // focusNode: _fromFocusNode, - // focusNode: focusNodes["_from${index}FocusNode"], - // controller: textControllers["_from${index}Controller"], - // style: const TextStyle(fontSize: 12), - // decoration: const InputDecoration( - // labelText: "From", - // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - // floatingLabelBehavior: FloatingLabelBehavior.never, - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 16), - // ), - // ), - // ), - ), - if (errorMessages["from_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_to${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: - isCountryLoading - ? Center(child: CircularProgressIndicator()) - : Focus( - focusNode: focusNodes["_to${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_to${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_to${index}FocusNode"] - ?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedTo[index] != null - ? countryMap[selectedTo[index]] - : null, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, - ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - Text( - code, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - }, - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select Country", - // style: TextStyle(fontSize: 12), - // ), - // ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } - - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), - ); - }, - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("to_place_$index"); - selectedTo[index] = - countryMap.entries - .firstWhere( - (entry) => - entry.value == newValue, - ) - .key; - - print(selectedTo[index]); - - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedTo[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedFrom[2] = selectedTo[index]!; - } - }); - }, - ), - ), - ), - ), - ), - if (errorMessages["to_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Class *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_class${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_class${index}FocusNode"], - - onFocusChange: (hasFocus) { - setState(() { - focusStates["_class${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_class${index}FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: purposeList.cast>(), - key: - selectedClasses[index] == null - ? UniqueKey() - : ValueKey(selectedClasses[index]), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClasses[index], - // orElse: () => {}, - // ), - selectedItem: - selectedClasses[index] != null - ? purposeList.firstWhere( - (item) => - item['dropdown_key'] == - selectedClasses[index], - 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: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: - isNotAllowed - ? Colors.redAccent - : Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select Class", - 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 { - // if (newValue != null && - // newValue['is_allowed'] == 'No') { - // print('not allowed'); - // - // exceptionalClass[index] = "1"; - // } else if (newValue != null && - // newValue['is_allowed'] == 'yes') { - // print('not allowed'); - // - // exceptionalClass[index] = "0"; - // } - // - // setState(() { - // selectedClasses[index] = - // newValue?['dropdown_key']; - // print( - // "Selected Class: ${selectedClasses[index]}", - // ); - // }); - - if (newValue != null && - newValue['is_allowed'] == 'No') { - final confirm = await showNotAllowedDialog( - context, - message: - "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", - ); - - if (confirm) { - setState(() { - exceptionalClass[index] = "1"; - selectedClasses[index] = - newValue['dropdown_key']; - }); - print( - "Selected Purpose: ${selectedClasses[index]}", - ); - } else { - setState(() { - exceptionalClass[index] = "0"; - selectedClasses[index] = - null; // ❌ Clear selection if user cancels - }); - print( - "selectedItem resolved to: ${selectedClasses[index]}", - ); - } - - return; - } else if (newValue != null && - newValue['is_allowed'] == 'yes') { - setState(() { - exceptionalClass[index] = "0"; - selectedClasses[index] = - newValue?['dropdown_key']; - print( - "Selected Purpose: ${selectedClasses[index]}", - ); - }); - } - } - : null, - ), - ), - ), - ), - ), - if (errorMessages["class_$index"] != null) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - errorMessages["class_$index"]!, - style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), - ), - ), - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Date*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_date${index}Focused"] ?? false, - - isDesktop: isDesktop, - width: - isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_date${index}FocusNode"]?.requestFocus(); - _selectCheckOutDate(context); - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_date${index}FocusNode"], - // controller: _dateController, - controller: textControllers["_date${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Select Date", - labelStyle: const TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor! - // : Colors.white, - // width: 0.5, - // ), - // ), - // enabledBorder: OutlineInputBorder( - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor - // : Colors.white, - // // : const Color(0xFFD6D5E6), - // width: 0.5, - // // const Color(0xFFD6D5E6), - // ), - // ), - // focusedBorder: OutlineInputBorder( - // borderSide: BorderSide(color: layoutColor, width: 1), - // ), - // contentPadding: const EdgeInsets.symmetric( - // horizontal: 10, - // vertical: 5, - // ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["date_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["date_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Time*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_time${index}Focused"] ?? false, - isDesktop: isDesktop, - width: - isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_time${index}FocusNode"]?.requestFocus(); - textControllers["_time${index}Controller"]?.text = ""; - _clearError("time_$index"); - // validateTimeDifference(index); - // _selectCheckOutTime(context); - - _selectCheckOutTime(context, index, () { - validateTimeDifference(index); - setState( - () {}, - ); // ✅ Force rebuild to show the error immediately - }); - }, - - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_time${index}FocusNode"], - // controller: _timeController, - controller: textControllers["_time${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Time", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon( - Icons.access_time, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - // Focus( - // focusNode: focusNodes["_time${index}FocusNode"], - // onFocusChange: (hasFocus) { - // setState(() { - // focusStates["_time${index}Focused"] = hasFocus; - // }); - // }, - // child: GestureDetector( - // // - // onTap: () { - // // Request focus when user taps - // focusNodes["_time${index}FocusNode"]?.requestFocus(); - // }, - ), - ), - ), - if (errorMessages["time_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["time_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (selectedTripType == "Multitrip") - Container( - // color: Colors.blueGrey, - // padding: const EdgeInsets.only(top: 50, bottom: 50), - child: IconButton( - onPressed: () { - removeTrip(index); - }, - icon: Icon(Icons.close, color: Colors.redAccent, size: 20), - ), - ), - ] - : [ - // For mobile, wrap inside a card with padding and grey background - Card( - elevation: 1, - margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), - color: const Color(0xFFF5F5F5), // Light grey - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), - - if (isDesktop) Spacer() else SizedBox(height: 8), - - if (isDesktop) Spacer() else SizedBox(height: 8), - - if (isDesktop) Spacer() else SizedBox(height: 8), - - if (selectedTripType == "Multitrip") - if (multiTripRowCount > 1) - Padding( - padding: const EdgeInsets.only(top: 10), - child: SizedBox( - width: double.infinity, // ensure full width - child: ElevatedButton( - style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight( - 48, - ), // set height - backgroundColor: Colors.red, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onPressed: () { - print("Pressed: $index"); - removeTrip(index); - }, - child: const Text( - "Remove", - style: TextStyle(fontSize: 14), - ), - ), - ), - ), - ], - ), - ), - ), - ]; - } + // List _buildSecondRow1(bool isDesktop, int index) { + // bool isFlightClassLoading = widget.apiDataForClass?['flight_class'] == null; + // + // List purposeList = widget.apiDataForClass?['flight_class'] ?? []; + // + // 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: TextStyle(color: Colors.grey), + // ), + // ), + // ); + // } + // + // // Default selected value + // // selectedClasses[index] ??= + // // dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + // // ------------------------------------------------- + // + // DateTime? _selectedCheckOutDate; + // TimeOfDay? _selectedCheckOutTime; + // + // Future _selectCheckOutDate(BuildContext context) async { + // DateTime now = DateTime.now(); + // DateTime today = DateTime(now.year, now.month, now.day); + // // Determine the minimum date (firstDate) based on previous index if available + // DateTime firstDate = today; + // + // if (index == 1 && + // flightLastTripDateNotifier.value != null && + // flightLastTripDateNotifier.value!.isNotEmpty) { + // try { + // final tripDate = DateFormat( + // 'dd-MM-yyyy', + // ).parseStrict(flightLastTripDateNotifier.value!); + // if (tripDate.isAfter(today)) { + // firstDate = tripDate; + // } + // } catch (_) { + // // handle parse error if needed + // } + // } else if (index > 1) { + // final previousDateString = + // textControllers["_date${index - 1}Controller"]?.text; + // if (previousDateString != null && previousDateString.isNotEmpty) { + // try { + // final previousDate = DateFormat( + // 'dd-MM-yyyy', + // ).parseStrict(previousDateString); + // if (previousDate.isAfter(today)) { + // firstDate = previousDate; + // } + // } catch (_) { + // // handle parse error if necessary + // } + // } + // } + // + // DateTime initialDate = + // _selectedCheckOutDate != null && + // _selectedCheckOutDate!.isAfter(firstDate) + // ? _selectedCheckOutDate! + // : firstDate; + // + // DateTime? pickedDate = await showDatePicker( + // context: context, + // initialDate: initialDate, + // firstDate: firstDate, + // lastDate: DateTime(2100), + // initialEntryMode: DatePickerEntryMode.calendarOnly, + // ); + // + // if (pickedDate != null && pickedDate != _selectedCheckOutDate) { + // setState(() { + // _selectedCheckOutDate = pickedDate; + // // _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); + // textControllers["_date${index}Controller"]?.text = DateFormat( + // 'dd-MM-yyyy', + // ).format(pickedDate); + // }); + // } + // } + // + // Future _selectCheckOutTime( + // BuildContext context, + // int index, + // VoidCallback onPicked, + // ) async { + // TimeOfDay? pickedTime = await showTimePicker( + // context: context, + // initialTime: _selectedCheckOutTime ?? TimeOfDay.now(), + // ); + // + // if (pickedTime != null) { + // final now = DateTime.now(); + // + // // Parse the selected date + // final dateText = textControllers["_date${index}Controller"]?.text ?? ""; + // final selectedDate = DateFormat( + // 'dd-MM-yyyy', + // ).parse(dateText); // or 'yyyy-MM-dd' depending on your format + // + // final selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // pickedTime.hour, + // pickedTime.minute, + // ); + // + // // ✅ Only validate past time if date is today + // final isToday = + // selectedDate.year == now.year && + // selectedDate.month == now.month && + // selectedDate.day == now.day; + // + // bool isPastTime = selectedDateTime.isBefore(now); + // + // if (isToday && isPastTime) { + // setState(() { + // errorMessages["time_$index"] = "You can't select a past time."; + // }); + // return; + // } + // + // // ✅ Valid time selection + // setState(() { + // _selectedCheckOutTime = pickedTime; + // + // final formattedTime = DateFormat('HH:mm').format(selectedDateTime); + // textControllers["_time${index}Controller"]?.text = formattedTime; + // // errorMessages["time_$index"] = ""; // clear previous error + // errorMessages.remove("time_$index"); + // onPicked(); // Trigger callback + // }); + // } + // + // // if (pickedTime != null && pickedTime != _selectedCheckOutTime) { + // // setState(() { + // // _selectedCheckOutTime = pickedTime; + // // // Formatting time to HH:mm (24-hour format) + // // final now = DateTime.now(); + // // final formattedTime = DateFormat('HH:mm').format( + // // DateTime( + // // now.year, + // // now.month, + // // now.day, + // // pickedTime.hour, + // // pickedTime.minute, + // // ), + // // ); + // // + // // // _timeController.text = formattedTime; + // // textControllers["_time${index}Controller"]?.text = formattedTime; + // // + // // onPicked(); + // // }); + // // } + // } + // + // return isDesktop + // ? [ + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "From*", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldItnerarySubWrapper( + // // isFocused: _fromFocus, + // // isFocused: focusStates["_from${index}Focused"] ?? false, + // isFocused: false, + // padding: const EdgeInsets.symmetric(horizontal: 0), + // // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, + // isDesktop: isDesktop, + // child: SizedBox( + // height: 40, + // child: + // isCountryLoading + // ? Center(child: CircularProgressIndicator()) + // : Focus( + // focusNode: focusNodes["_from${index}FocusNode"], + // onFocusChange: (hasFocus) { + // setState(() { + // focusStates["_from${index}Focused"] = hasFocus; + // }); + // }, + // child: GestureDetector( + // // + // onTap: () { + // // Request focus when user taps + // focusNodes["_from${index}FocusNode"] + // ?.requestFocus(); + // }, + // child: DropdownSearch( + // enabled: + // !(selectedTripType == "Roundtrip" && + // index == 2), + // selectedItem: + // selectedFrom[index] != null + // ? countryMap[selectedFrom[index]] + // : null, + // items: countryMap.values.toList(), + // // asyncItems: (String filter) async { + // // final allItems = countryMap.values.toSet().toList(); + // // print("Original items: ${allItems.length}"); + // // final filtered = filterAndSortCountryList(allItems, filter); + // // // print("Filtered items: ${filtered.length} -> $filtered"); + // // return filtered; + // // }, + // popupProps: PopupProps.menu( + // fit: FlexFit.loose, + // constraints: BoxConstraints(maxHeight: 220), + // showSearchBox: + // true, // Enables search functionality + // searchFieldProps: TextFieldProps( + // decoration: InputDecoration( + // hintText: "Search...", + // contentPadding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 1, + // ), + // ), + // style: TextStyle(fontSize: 12), + // ), + // menuProps: MenuProps( + // backgroundColor: Colors.white, + // ), + // itemBuilder: (context, item, isSelected) { + // final parts = item.split('\n'); + // final cityAndCode = parts[0]; + // final airport = + // parts.length > 1 ? parts[1] : ''; + // + // // Extract city and code from "City (CODE)" + // final cityMatch = RegExp( + // r'^(.*)\s+\(([^)]+)\)$', + // ).firstMatch(cityAndCode); + // final city = cityMatch?.group(1) ?? ''; + // final code = cityMatch?.group(2) ?? ''; + // + // return Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: + // MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // city, + // style: const TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.bold, + // ), + // ), + // Text( + // code, + // style: const TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.bold, + // ), + // ), + // ], + // ), + // const SizedBox(height: 1), + // Text( + // airport, + // style: const TextStyle( + // fontSize: 11, + // color: Colors.grey, + // overflow: TextOverflow.ellipsis, + // ), + // ), + // ], + // ), + // ); + // }, + // + // // itemBuilder: + // // (context, item, isSelected) => Padding( + // // padding: const EdgeInsets.symmetric( + // // horizontal: 8.0, + // // vertical: 6.0, + // // ), + // // child: Text( + // // item, + // // style: TextStyle( + // // fontSize: 13, + // // ), // 👈 Set your desired text size here + // // ), + // // ), + // ), + // // items: countryMap.values.toList(), + // // filterFn: (item, filter) { + // // final lowerFilter = filter.toLowerCase(); + // // + // // final parts = item.split('\n'); + // // final cityAndCode = parts[0]; + // // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; + // // + // // // Extract city and code from "City (CODE)" + // // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); + // // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; + // // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; + // // + // // // Priority: Code > City > Airport + // // return code.contains(lowerFilter) || + // // city.contains(lowerFilter) || + // // airport.contains(lowerFilter); + // // }, + // dropdownDecoratorProps: DropDownDecoratorProps( + // dropdownSearchDecoration: InputDecoration( + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // borderSide: BorderSide( + // color: + // (focusStates["_from${index}Focused"] ?? + // false) + // ? layoutColor! + // : Colors.white, + // width: 0.5, + // ), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: + // (focusStates["_from${index}Focused"] ?? + // false) + // ? layoutColor + // : Colors.white, + // // : const Color(0xFFD6D5E6), + // width: 0.5, + // // const Color(0xFFD6D5E6), + // ), + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: layoutColor, + // width: 1, + // ), + // ), + // contentPadding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 5, + // ), + // ), + // ), + // dropdownBuilder: (context, selectedItem) { + // if (selectedItem == null) { + // return Align( + // alignment: Alignment.centerLeft, + // child: const Text( + // "Select", + // style: TextStyle(fontSize: 12), + // ), + // ); + // } + // + // final parts = selectedItem.split('\n'); + // final cityAndCode = parts[0]; + // final airport = + // parts.length > 1 ? parts[1] : ''; + // + // return Align( + // alignment: Alignment.centerLeft, + // child: Text( + // cityAndCode ?? "Select", + // style: const TextStyle(fontSize: 12), + // ), + // ); + // }, + // + // // dropdownBuilder: + // // (context, selectedItem) => Align( + // // alignment: Alignment.centerLeft, + // // child: Text( + // // selectedItem ?? "Select", + // // style: TextStyle(fontSize: 12), + // // ), + // // ), + // onChanged: (String? newValue) { + // setState(() { + // errorMessages.remove("from_place_$index"); + // // selectedFrom[index] = countryMap.entries + // // .firstWhere((entry) => entry.value == newValue) + // // .key; + // + // selectedFrom[index] = + // countryMap.entries + // .firstWhere( + // (entry) => + // entry.value == newValue, + // ) + // .key; + // if (selectedTripType == "Roundtrip") { + // print('rounfTo${selectedFrom[index]}'); + // // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + // selectedTo[2] = selectedFrom[index]!; + // } + // }); + // }, + // ), + // ), + // ), + // ), + // + // // child: SizedBox( + // // height: 40, + // // child: TextField( + // // // focusNode: _fromFocusNode, + // // focusNode: focusNodes["_from${index}FocusNode"], + // // controller: textControllers["_from${index}Controller"], + // // style: const TextStyle(fontSize: 12), + // // decoration: const InputDecoration( + // // labelText: "From", + // // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // // floatingLabelBehavior: FloatingLabelBehavior.never, + // // border: InputBorder.none, + // // contentPadding: EdgeInsets.symmetric(vertical: 16), + // // ), + // // ), + // // ), + // ), + // if (errorMessages["from_place_$index"] != null) ...[ + // SizedBox(height: 5), // Space before error message + // Text( + // errorMessages["from_place_$index"]!, + // style: TextStyle(color: Colors.red, fontSize: 12), + // ), + // ], + // ], + // ), + // if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "To*", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldItnerarySubWrapper( + // // isFocused: focusStates["_to${index}Focused"] ?? false, + // isFocused: false, + // padding: const EdgeInsets.symmetric(horizontal: 0), + // isDesktop: isDesktop, + // child: SizedBox( + // height: 40, + // child: + // isCountryLoading + // ? Center(child: CircularProgressIndicator()) + // : Focus( + // focusNode: focusNodes["_to${index}FocusNode"], + // onFocusChange: (hasFocus) { + // setState(() { + // focusStates["_to${index}Focused"] = hasFocus; + // }); + // }, + // child: GestureDetector( + // // + // onTap: () { + // // Request focus when user taps + // focusNodes["_to${index}FocusNode"] + // ?.requestFocus(); + // }, + // child: DropdownSearch( + // enabled: + // !(selectedTripType == "Roundtrip" && + // index == 2), + // selectedItem: + // selectedTo[index] != null + // ? countryMap[selectedTo[index]] + // : null, + // popupProps: PopupProps.menu( + // fit: FlexFit.loose, + // constraints: BoxConstraints(maxHeight: 220), + // showSearchBox: + // true, // Enables search functionality + // searchFieldProps: TextFieldProps( + // decoration: InputDecoration( + // hintText: "Search...", + // contentPadding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 1, + // ), + // ), + // style: TextStyle(fontSize: 12), + // ), + // menuProps: MenuProps( + // backgroundColor: Colors.white, + // ), + // itemBuilder: (context, item, isSelected) { + // final parts = item.split('\n'); + // final cityAndCode = parts[0]; + // final airport = + // parts.length > 1 ? parts[1] : ''; + // + // // Extract city and code from "City (CODE)" + // final cityMatch = RegExp( + // r'^(.*)\s+\(([^)]+)\)$', + // ).firstMatch(cityAndCode); + // final city = cityMatch?.group(1) ?? ''; + // final code = cityMatch?.group(2) ?? ''; + // + // return Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: + // MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // city, + // style: const TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.bold, + // ), + // ), + // Text( + // code, + // style: const TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.bold, + // ), + // ), + // ], + // ), + // const SizedBox(height: 1), + // Text( + // airport, + // style: const TextStyle( + // fontSize: 11, + // color: Colors.grey, + // overflow: TextOverflow.ellipsis, + // ), + // ), + // ], + // ), + // ); + // }, + // // itemBuilder: + // // (context, item, isSelected) => Padding( + // // padding: const EdgeInsets.symmetric( + // // horizontal: 8.0, + // // vertical: 6.0, + // // ), + // // child: Text( + // // item, + // // style: TextStyle( + // // fontSize: 13, + // // ), // 👈 Set your desired text size here + // // ), + // // ), + // ), + // items: countryMap.values.toList(), + // dropdownDecoratorProps: DropDownDecoratorProps( + // dropdownSearchDecoration: InputDecoration( + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // borderSide: BorderSide( + // color: + // (focusStates["_to${index}Focused"] ?? + // false) + // ? layoutColor! + // : Colors.white, + // width: 0.5, + // ), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: + // (focusStates["_to${index}Focused"] ?? + // false) + // ? layoutColor + // : Colors.white, + // // : const Color(0xFFD6D5E6), + // width: 0.5, + // // const Color(0xFFD6D5E6), + // ), + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: layoutColor, + // width: 1, + // ), + // ), + // contentPadding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 5, + // ), + // ), + // ), + // + // // dropdownBuilder: + // // (context, selectedItem) => Align( + // // alignment: Alignment.centerLeft, + // // child: Text( + // // selectedItem ?? "Select Country", + // // style: TextStyle(fontSize: 12), + // // ), + // // ), + // dropdownBuilder: (context, selectedItem) { + // if (selectedItem == null) { + // return Align( + // alignment: Alignment.centerLeft, + // child: const Text( + // "Select", + // style: TextStyle(fontSize: 12), + // ), + // ); + // } + // + // final parts = selectedItem.split('\n'); + // final cityAndCode = parts[0]; + // final airport = + // parts.length > 1 ? parts[1] : ''; + // + // return Align( + // alignment: Alignment.centerLeft, + // child: Text( + // cityAndCode ?? "Select", + // style: const TextStyle(fontSize: 12), + // ), + // ); + // }, + // onChanged: (String? newValue) { + // setState(() { + // errorMessages.remove("to_place_$index"); + // selectedTo[index] = + // countryMap.entries + // .firstWhere( + // (entry) => + // entry.value == newValue, + // ) + // .key; + // + // print(selectedTo[index]); + // + // if (selectedTripType == "Roundtrip") { + // print('rounfTo${selectedTo[index]}'); + // // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + // selectedFrom[2] = selectedTo[index]!; + // } + // }); + // }, + // ), + // ), + // ), + // ), + // ), + // if (errorMessages["to_place_$index"] != null) ...[ + // SizedBox(height: 5), // Space before error message + // Text( + // errorMessages["to_place_$index"]!, + // style: TextStyle(color: Colors.red, fontSize: 12), + // ), + // ], + // ], + // ), + // if (isDesktop) Spacer() else SizedBox(height: 8), + // + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Class *", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldItnerarySubWrapper( + // // isFocused: focusStates["_class${index}Focused"] ?? false, + // isFocused: false, + // padding: const EdgeInsets.symmetric(horizontal: 0), + // isDesktop: isDesktop, + // child: SizedBox( + // height: 40, + // width: double.infinity, + // child: Focus( + // focusNode: focusNodes["_class${index}FocusNode"], + // + // onFocusChange: (hasFocus) { + // setState(() { + // focusStates["_class${index}Focused"] = hasFocus; + // }); + // }, + // child: GestureDetector( + // // + // onTap: () { + // // Request focus when user taps + // focusNodes["_class${index}FocusNode"]?.requestFocus(); + // }, + // child: DropdownSearch>( + // items: purposeList.cast>(), + // key: + // selectedClasses[index] == null + // ? UniqueKey() + // : ValueKey(selectedClasses[index]), + // // selectedItem: purposeList.firstWhere( + // // (item) => item['dropdown_key'] == selectedClasses[index], + // // orElse: () => {}, + // // ), + // selectedItem: + // selectedClasses[index] != null + // ? purposeList.firstWhere( + // (item) => + // item['dropdown_key'] == + // selectedClasses[index], + // 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: 8, + // ), + // child: Text( + // item['dropdown_value'] ?? '', + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: + // isNotAllowed + // ? Colors.redAccent + // : Colors.black, + // ), + // ), + // ); + // }, + // ), + // dropdownDecoratorProps: DropDownDecoratorProps( + // dropdownSearchDecoration: InputDecoration( + // // border: InputBorder.none, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // borderSide: BorderSide( + // color: + // (focusStates["_class${index}Focused"] ?? + // false) + // ? layoutColor! + // : Colors.white, + // width: 0.5, + // ), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: + // (focusStates["_class${index}Focused"] ?? + // false) + // ? layoutColor + // : Colors.white, + // // : const Color(0xFFD6D5E6), + // width: 0.5, + // // const Color(0xFFD6D5E6), + // ), + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: layoutColor, + // width: 1, + // ), + // ), + // contentPadding: const EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 5, + // ), + // ), + // ), + // dropdownBuilder: (context, selectedItem) { + // if (selectedItem == null || selectedItem.isEmpty) { + // return Text( + // "Select Class", + // 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 { + // // if (newValue != null && + // // newValue['is_allowed'] == 'No') { + // // print('not allowed'); + // // + // // exceptionalClass[index] = "1"; + // // } else if (newValue != null && + // // newValue['is_allowed'] == 'yes') { + // // print('not allowed'); + // // + // // exceptionalClass[index] = "0"; + // // } + // // + // // setState(() { + // // selectedClasses[index] = + // // newValue?['dropdown_key']; + // // print( + // // "Selected Class: ${selectedClasses[index]}", + // // ); + // // }); + // + // if (newValue != null && + // newValue['is_allowed'] == 'No') { + // final confirm = await showNotAllowedDialog( + // context, + // message: + // "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", + // ); + // + // if (confirm) { + // setState(() { + // exceptionalClass[index] = "1"; + // selectedClasses[index] = + // newValue['dropdown_key']; + // }); + // print( + // "Selected Purpose: ${selectedClasses[index]}", + // ); + // } else { + // setState(() { + // exceptionalClass[index] = "0"; + // selectedClasses[index] = + // null; // ❌ Clear selection if user cancels + // }); + // print( + // "selectedItem resolved to: ${selectedClasses[index]}", + // ); + // } + // + // return; + // } else if (newValue != null && + // newValue['is_allowed'] == 'yes') { + // setState(() { + // exceptionalClass[index] = "0"; + // selectedClasses[index] = + // newValue?['dropdown_key']; + // print( + // "Selected Purpose: ${selectedClasses[index]}", + // ); + // }); + // } + // } + // : null, + // ), + // ), + // ), + // ), + // ), + // if (errorMessages["class_$index"] != null) + // Padding( + // padding: const EdgeInsets.only(top: 4), + // child: Text( + // errorMessages["class_$index"]!, + // style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), + // ), + // ), + // ], + // ), + // if (isDesktop) Spacer() else SizedBox(height: 8), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Date*", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_date${index}Focused"] ?? false, + // + // isDesktop: isDesktop, + // width: + // isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + // child: SizedBox( + // height: 40, + // child: GestureDetector( + // onTap: () { + // focusNodes["_date${index}FocusNode"]?.requestFocus(); + // _selectCheckOutDate(context); + // }, + // child: AbsorbPointer( + // child: TextField( + // focusNode: focusNodes["_date${index}FocusNode"], + // // controller: _dateController, + // controller: textControllers["_date${index}Controller"], + // readOnly: true, + // style: const TextStyle(fontSize: 12), + // decoration: InputDecoration( + // labelText: "Select Date", + // labelStyle: const TextStyle( + // fontSize: 12, + // color: Colors.grey, + // ), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // // border: OutlineInputBorder( + // // borderRadius: BorderRadius.circular(8), + // // borderSide: BorderSide( + // // color: + // // (focusStates["_date${index}Focused"] ?? false) + // // ? layoutColor! + // // : Colors.white, + // // width: 0.5, + // // ), + // // ), + // // enabledBorder: OutlineInputBorder( + // // borderSide: BorderSide( + // // color: + // // (focusStates["_date${index}Focused"] ?? false) + // // ? layoutColor + // // : Colors.white, + // // // : const Color(0xFFD6D5E6), + // // width: 0.5, + // // // const Color(0xFFD6D5E6), + // // ), + // // ), + // // focusedBorder: OutlineInputBorder( + // // borderSide: BorderSide(color: layoutColor, width: 1), + // // ), + // // contentPadding: const EdgeInsets.symmetric( + // // horizontal: 10, + // // vertical: 5, + // // ), + // suffixIcon: const Icon( + // Icons.calendar_today, + // size: 16, + // color: Colors.grey, + // ), + // ), + // ), + // ), + // ), + // ), + // ), + // if (errorMessages["date_$index"] != null) ...[ + // SizedBox(height: 5), // Space before error message + // Text( + // errorMessages["date_$index"]!, + // style: TextStyle(color: Colors.red, fontSize: 12), + // ), + // ], + // ], + // ), + // if (isDesktop) Spacer() else SizedBox(height: 8), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Time*", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_time${index}Focused"] ?? false, + // isDesktop: isDesktop, + // width: + // isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, + // child: SizedBox( + // height: 40, + // child: GestureDetector( + // onTap: () { + // focusNodes["_time${index}FocusNode"]?.requestFocus(); + // textControllers["_time${index}Controller"]?.text = ""; + // _clearError("time_$index"); + // // validateTimeDifference(index); + // // _selectCheckOutTime(context); + // + // _selectCheckOutTime(context, index, () { + // validateTimeDifference(index); + // setState( + // () {}, + // ); // ✅ Force rebuild to show the error immediately + // }); + // }, + // + // child: AbsorbPointer( + // child: TextField( + // focusNode: focusNodes["_time${index}FocusNode"], + // // controller: _timeController, + // controller: textControllers["_time${index}Controller"], + // readOnly: true, + // style: const TextStyle(fontSize: 12), + // decoration: const InputDecoration( + // labelText: "Time", + // labelStyle: TextStyle( + // fontSize: 12, + // color: Colors.grey, + // ), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // suffixIcon: Icon( + // Icons.access_time, + // size: 16, + // color: Colors.grey, + // ), + // ), + // ), + // ), + // // Focus( + // // focusNode: focusNodes["_time${index}FocusNode"], + // // onFocusChange: (hasFocus) { + // // setState(() { + // // focusStates["_time${index}Focused"] = hasFocus; + // // }); + // // }, + // // child: GestureDetector( + // // // + // // onTap: () { + // // // Request focus when user taps + // // focusNodes["_time${index}FocusNode"]?.requestFocus(); + // // }, + // ), + // ), + // ), + // if (errorMessages["time_$index"] != null) ...[ + // SizedBox(height: 5), // Space before error message + // Text( + // errorMessages["time_$index"]!, + // style: TextStyle(color: Colors.red, fontSize: 12), + // ), + // ], + // ], + // ), + // if (selectedTripType == "Multitrip") + // Container( + // // color: Colors.blueGrey, + // // padding: const EdgeInsets.only(top: 50, bottom: 50), + // child: IconButton( + // onPressed: () { + // removeTrip(index); + // }, + // icon: Icon(Icons.close, color: Colors.redAccent, size: 20), + // ), + // ), + // ] + // : [ + // // For mobile, wrap inside a card with padding and grey background + // Card( + // elevation: 1, + // margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + // color: const Color(0xFFF5F5F5), // Light grey + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(12), + // ), + // child: Padding( + // padding: const EdgeInsets.all(12), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), + // + // if (isDesktop) Spacer() else SizedBox(height: 8), + // + // if (isDesktop) Spacer() else SizedBox(height: 8), + // + // if (isDesktop) Spacer() else SizedBox(height: 8), + // + // if (selectedTripType == "Multitrip") + // if (multiTripRowCount > 1) + // Padding( + // padding: const EdgeInsets.only(top: 10), + // child: SizedBox( + // width: double.infinity, // ensure full width + // child: ElevatedButton( + // style: ElevatedButton.styleFrom( + // minimumSize: const Size.fromHeight( + // 48, + // ), // set height + // backgroundColor: Colors.red, + // foregroundColor: Colors.white, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // onPressed: () { + // print("Pressed: $index"); + // removeTrip(index); + // }, + // child: const Text( + // "Remove", + // style: TextStyle(fontSize: 14), + // ), + // ), + // ), + // ), + // ], + // ), + // ), + // ), + // ]; + // } } diff --git a/lib/Screens/itnerary/train.dart b/lib/Screens/itnerary/train.dart index 58342e1..d47bf24 100644 --- a/lib/Screens/itnerary/train.dart +++ b/lib/Screens/itnerary/train.dart @@ -239,9 +239,9 @@ class _TrainScreenState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; }); } @@ -662,163 +662,168 @@ class _TrainScreenState extends State { child: SizedBox( height: 40, width: double.infinity, - child: Focus( - focusNode: _typeOfClassFocusNode, - onFocusChange: (hasFocus) { - setState(() { - _typeOfClassFocus = hasFocus; - }); + child: Focus( + focusNode: _typeOfClassFocusNode, + onFocusChange: (hasFocus) { + setState(() { + _typeOfClassFocus = hasFocus; + }); + }, + child: GestureDetector( + onTap: () { + _typeOfClassFocusNode?.requestFocus(); }, - child: GestureDetector( - onTap: () { - _typeOfClassFocusNode?.requestFocus(); - }, - child: DropdownSearch>( - key: - selectedClass == null - ? UniqueKey() - : ValueKey(selectedClass), - items: purposeList.cast>(), + child: DropdownSearch>( + // key: + // selectedClass == null + // ? UniqueKey() + // : ValueKey(selectedClass), + items: purposeList.cast>(), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClass, - // orElse: () => {}, - // ), - selectedItem: - selectedClass != null - ? purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedClass, - 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, + // selectedItem: purposeList.firstWhere( + // (item) => item['dropdown_key'] == selectedClass, + // orElse: () => {}, + // ), + selectedItem: + selectedClass != null + ? purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedClass, + 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: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_typeOfClassFocus ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_typeOfClassFocus ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, ), ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_typeOfClassFocus ?? false) - ? layoutColor! - : Colors.white, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_typeOfClassFocus ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 1, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - 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 { + if (newValue != null && + newValue['is_allowed'] == 'No') { + final confirm = await showNotAllowedDialog( + context, + message: + "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", + ); + + if (confirm) { + setState(() { + exceptionalClass = "1"; + selectedClass = newValue['dropdown_key']; + }); + print("Selected Purpose: ${selectedClass}"); + } else { + setState(() { + exceptionalClass = "0"; + selectedClass = + null; // ❌ Clear selection if user cancels + }); + print( + "selectedItem resolved to: ${selectedClass}", + ); + } + + return; + } else if (newValue != null && + newValue['is_allowed'] == 'yes') { + setState(() { + exceptionalClass = "0"; + selectedClass = newValue?['dropdown_key']; + print("Selected Purpose: ${selectedClass}"); + }); + } + + // if (newValue != null && + // newValue['is_allowed'] == 'No') { + // print('not allowed'); + // + // setState(() { + // exceptionalClass = "1"; + // // hasExceptionalClass = true; + // }); + // } + + setState(() { + selectedClass = newValue?['dropdown_key']; + print("Selected Purpose: ${selectedClass}"); + }); + } + : null, ), ), - 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 { - if (newValue != null && - newValue['is_allowed'] == 'No') { - final confirm = await showNotAllowedDialog( - context, - message: - "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", - ); - - if (confirm) { - setState(() { - exceptionalClass = "1"; - selectedClass = newValue['dropdown_key']; - }); - print("Selected Purpose: ${selectedClass}"); - } else { - setState(() { - exceptionalClass = "0"; - selectedClass = - null; // ❌ Clear selection if user cancels - }); - print( - "selectedItem resolved to: ${selectedClass}", - ); - } - - return; - } else if (newValue != null && - newValue['is_allowed'] == 'yes') { - setState(() { - exceptionalClass = "0"; - selectedClass = newValue?['dropdown_key']; - print("Selected Purpose: ${selectedClass}"); - }); - } - - // if (newValue != null && - // newValue['is_allowed'] == 'No') { - // print('not allowed'); - // - // setState(() { - // exceptionalClass = "1"; - // // hasExceptionalClass = true; - // }); - // } - - setState(() { - selectedClass = newValue?['dropdown_key']; - print("Selected Purpose: ${selectedClass}"); - }); - } - : null, - ),),) + ), ), ), if (errorMessages["class"] != null) ...[ @@ -937,94 +942,98 @@ class _TrainScreenState extends State { isDesktop: isDesktop, child: SizedBox( height: 40, - child: Focus( - focusNode: _fromFocusNode, - onFocusChange: (hasFocus) { - setState(() { - _fromFocus = hasFocus; - }); - }, - child: GestureDetector( - onTap: () { - _fromFocusNode?.requestFocus(); - }, - child: DropdownSearch( - selectedItem: countryMap[selectedFrom], - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 150),// maxHeight: 250 - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: - (context, item, isSelected) => Container( - color: Colors.white, - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_fromFocus ?? false) - ? layoutColor! - : Colors.white, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_fromFocus ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 1, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ), - onChanged: (String? newValue) { + child: Focus( + focusNode: _fromFocusNode, + onFocusChange: (hasFocus) { setState(() { - selectedFrom = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; + _fromFocus = hasFocus; }); }, - ),),) + child: GestureDetector( + onTap: () { + _fromFocusNode?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: countryMap[selectedFrom], + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, + constraints: BoxConstraints( + maxHeight: 150, + ), // maxHeight: 250 + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: + (context, item, isSelected) => Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_fromFocus ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_fromFocus ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), + onChanged: (String? newValue) { + setState(() { + selectedFrom = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; + }); + }, + ), + ), + ), ), ), if (errorMessages["from_station"] != null) ...[ @@ -1106,94 +1115,96 @@ class _TrainScreenState extends State { padding: const EdgeInsets.symmetric(horizontal: 0), child: SizedBox( height: 40, - child: Focus( - focusNode: _toFocusNode, - onFocusChange: (hasFocus) { - setState(() { - _toFocus = hasFocus; - }); - }, - child: GestureDetector( - onTap: () { - _toFocusNode?.requestFocus(); - }, - child: DropdownSearch( - selectedItem: countryMap[selectedTo], - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 150), - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: - (context, item, isSelected) => Container( - color: Colors.white, - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(5), - borderSide: BorderSide( - color: - (_toFocus ?? false) - ? layoutColor! - : Colors.white, - width: 1, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_toFocus ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 1, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ), - onChanged: (String? newValue) { + child: Focus( + focusNode: _toFocusNode, + onFocusChange: (hasFocus) { setState(() { - selectedTo = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; + _toFocus = hasFocus; }); }, - ),),), + child: GestureDetector( + onTap: () { + _toFocusNode?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: countryMap[selectedTo], + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 150), + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: + (context, item, isSelected) => Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_toFocus ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_toFocus ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), + onChanged: (String? newValue) { + setState(() { + selectedTo = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; + }); + }, + ), + ), + ), ), ), if (errorMessages["to_station"] != null) ...[ diff --git a/lib/Screens/policy/policyCriteria.dart b/lib/Screens/policy/policyCriteria.dart index 440eb43..4336d7c 100644 --- a/lib/Screens/policy/policyCriteria.dart +++ b/lib/Screens/policy/policyCriteria.dart @@ -768,9 +768,11 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "NA1", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here + color: Colors .black, // You can customize this @@ -802,6 +804,7 @@ class PolicyCriteriaState extends State { selectedItem, ) => Text( selectedItem ?? "Select", + semanticsLabel: "NA1", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -845,6 +848,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "NPP1", size: 15, color: (SelectedParallelProcess[ServiceId] == @@ -945,6 +949,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "NA2", style: TextStyle( fontSize: 12, // 👈 Smaller text size here @@ -978,6 +983,7 @@ class PolicyCriteriaState extends State { context, selectedItem, ) => Text( + semanticsLabel: "NA2", selectedItem ?? "Select", style: GoogleFonts.poppins( fontSize: 12, @@ -1023,6 +1029,7 @@ class PolicyCriteriaState extends State { child: Icon( Icons.circle, size: 15, + semanticLabel: "NPP2", color: ((SelectedParallelProcess[ServiceId] == "1") || @@ -1128,6 +1135,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "NA3", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -1161,6 +1169,7 @@ class PolicyCriteriaState extends State { // Center-align selected item Text( selectedItem ?? "Select", + semanticsLabel: "NA3", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -1204,6 +1213,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "NPP3", size: 15, color: ((SelectedParallelProcess[ServiceId] == @@ -1409,6 +1419,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "EA1", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -1486,6 +1497,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "EPP1", size: 15, color: (SelectedParallelExceptionalProcess[ServiceId] == @@ -1588,6 +1600,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "EA2", style: TextStyle( fontSize: 12, // 👈 Smaller text size here @@ -1622,6 +1635,7 @@ class PolicyCriteriaState extends State { selectedItem, ) => Text( selectedItem ?? "Select", + semanticsLabel: "EA2", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -1665,6 +1679,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "EPP2", size: 15, color: ((SelectedParallelExceptionalProcess[ServiceId] == @@ -1774,6 +1789,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "EA3", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -1807,6 +1823,7 @@ class PolicyCriteriaState extends State { // Center-align selected item Text( selectedItem ?? "Select", + semanticsLabel: "EA3", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -1849,6 +1866,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "EPP3", size: 15, color: ((SelectedParallelExceptionalProcess[ServiceId] == @@ -1966,6 +1984,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "EA4", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -1999,6 +2018,7 @@ class PolicyCriteriaState extends State { // Center-align selected item Text( selectedItem ?? "Select", + semanticsLabel: "EA4", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -2055,7 +2075,7 @@ class PolicyCriteriaState extends State { child: Icon( Icons.circle, size: 15, - + semanticLabel: "EPP4", color: ((SelectedParallelExceptionalProcess[ServiceId] == "1") || @@ -2216,6 +2236,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "AA1", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -2250,6 +2271,7 @@ class PolicyCriteriaState extends State { selectedItem, ) => Text( selectedItem ?? "Select", + semanticsLabel: "AA1", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -2293,6 +2315,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "AAPP1", size: 15, color: (SelectedParallelAmendProcess[ServiceId] == @@ -2395,6 +2418,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "AA2", style: TextStyle( fontSize: 12, // 👈 Smaller text size here @@ -2429,6 +2453,7 @@ class PolicyCriteriaState extends State { selectedItem, ) => Text( selectedItem ?? "Select", + semanticsLabel: "AA2", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -2472,6 +2497,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "AAPP2", size: 15, color: ((SelectedParallelAmendProcess[ServiceId] == @@ -2582,6 +2608,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "AA3", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -2615,6 +2642,7 @@ class PolicyCriteriaState extends State { // Center-align selected item Text( selectedItem ?? "Select", + semanticsLabel: "AA3", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -2657,6 +2685,7 @@ class PolicyCriteriaState extends State { width: 25, child: Icon( Icons.circle, + semanticLabel: "AAPP3", size: 15, color: ((SelectedParallelAmendProcess[ServiceId] == @@ -2774,6 +2803,7 @@ class PolicyCriteriaState extends State { ), child: Text( item, + semanticsLabel: "AA4", style: GoogleFonts.poppins( fontSize: 12, // 👈 Smaller text size here @@ -2807,6 +2837,7 @@ class PolicyCriteriaState extends State { // Center-align selected item Text( selectedItem ?? "Select", + semanticsLabel: "AA4", style: GoogleFonts.poppins( fontSize: 12, color: Color(0xFF114D8B), @@ -2862,6 +2893,7 @@ class PolicyCriteriaState extends State { // ), child: Icon( Icons.circle, + semanticLabel: "AAPP4", size: 15, color: ((SelectedParallelAmendProcess[ServiceId] == @@ -3048,10 +3080,10 @@ class PolicyCriteriaState extends State { (ServiceId!) != null && (isLoading || dropdownItems.isEmpty) ? const Center(child: CircularProgressIndicator()) : DropdownSearch>( - key: - classAction[(ServiceId!)] == null - ? UniqueKey() - : ValueKey(classAction[(ServiceId!)]), + // key: + // classAction[(ServiceId!)] == null + // ? UniqueKey() + // : ValueKey(classAction[(ServiceId!)]), items: purposeList.cast>(), // selectedItem: purposeList.firstWhere(