diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index 27da3a6..a1258a0 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -45,6 +45,7 @@ class FlightScreenState extends State { ApiService apiService = ApiService(); final GlobalKey _formKey = GlobalKey(); + String plantripType = ""; bool isCountryLoading = true; late Map countryMap; late Map countryCodeMap; @@ -102,6 +103,10 @@ class FlightScreenState extends State { }); print("TripType - ${widget.tripType}"); + setState(() { + plantripType = widget.tripType!; + }); + // final newTripType = widget.tripTypeNotifier.value; // print("TripType1 - $newTripType"); @@ -978,7 +983,7 @@ class FlightScreenState extends State { ), ), ), - + if (selectedTripType == "Multitrip") SizedBox(height: 10), // ...buildResponsiveRow(_buildvisa(isDesktop)), ...buildResponsiveRow(_buildThirdRow(isDesktop)), // Actions row remains a Row @@ -1185,99 +1190,1474 @@ class FlightScreenState extends State { ), ), ), - - // DropdownButtonFormField( - // isExpanded: true, - // // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // focusNode: focusNodes["_tripType1FocusNode"], - // value: selectedTripType, - // style: TextStyle(fontSize: 12), - // isDense: true, - // dropdownColor: Colors.white, - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: - // EdgeInsets.symmetric(horizontal: 10), // Proper padding - // ), - // onChanged: purposeList.isNotEmpty - // ? (newValue) { - // setState(() { - // selectedTripType = newValue; - // // selectedTripType = "Oneway"; - // // Reset `multiTripRowCount` when switching away from Multitrip - // if (selectedTripType != "Multitrip") { - // multiTripRowCount = 1; - // } - // errorMessages.clear(); - // }); - // print( - // "Updating form data: Flight -> trip_type -> $selectedTripType"); - // _initializeFields(); - // - // // _initializeRows(); - // } - // : null, - // - // items: dropdownItems, - // ), ), ), ]; } - // Widget _buildDelete(bool isDesktop, int index) { - // return Container( - // color: Colors.blueAccent, - // child: Row( - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - // Text( - // "Trip ${index}", - // style: TextStyle( - // fontSize: 14, - // fontWeight: FontWeight.w600, - // color: Color(0xFF575A74), - // ), - // ), - // SizedBox( - // width: isDesktop - // ? MediaQuery.of(context).size.width * 0.38 - // : MediaQuery.of(context).size.width * 0.3, - // child: Stack( - // alignment: Alignment.center, // Centers the icon - // children: [ - // Divider( - // color: Color(0xFF8B8FB2), - // thickness: 0.5, - // height: 20, - // ), - // Container( - // // padding: EdgeInsets.all(4), - // color: Colors.white, // Background to avoid overlapping - // child: Row( - // mainAxisSize: - // MainAxisSize.min, // Prevents row from taking full width - // children: [ - // Icon(Icons.add_circle_sharp, - // color: Colors.blue, size: 28), - // ], - // ), - // ), - // ], - // ), - // ), - // IconButton( - // onPressed: () { - // removeTrip(index); - // }, - // icon: Icon(Icons.delete), - // color: Colors.red, - // iconSize: 20, - // ) - // ], - // ), - // ); - // } + List _buildSecondRow(bool isDesktop, int index) { + return isDesktop + ? [ + _buildFrom(isDesktop, index), + Spacer(), + _buildTo(isDesktop, index), + Spacer(), + _buildClass(isDesktop, index), + Spacer(), + _buildDate(isDesktop, index), + Spacer(), + _buildTime(isDesktop, index), + Spacer(), + 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), + ), + ), + ] + : [ + 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.0), + child: Column( + children: [ + _buildFrom(isDesktop, index), + SizedBox(height: 8), + _buildTo(isDesktop, index), + SizedBox(height: 8), + _buildClass(isDesktop, index), + SizedBox(height: 8), + _buildDate(isDesktop, index), + SizedBox(height: 8), + _buildTime(isDesktop, index), + + 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), + ), + ), + ), + ), + if (selectedTripType == "Multitrip") SizedBox(height: 8), + ], + ), + ), + ), + ]; + } + + Widget _buildFrom(bool isDesktop, int index) { + return 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), + ), + ], + ], + ); + } + + Widget _buildTo(bool isDesktop, int index) { + return 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), + ), + ], + ], + ); + } + + Widget _buildClass(bool isDesktop, int index) { + 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), + ), + ), + ); + } + return 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), + ), + ), + ], + ); + } + + Widget _buildDate(bool isDesktop, int index) { + 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); + }); + } + } + + return 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), + + 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), + ), + ], + ], + ); + } + + Widget _buildTime(bool isDesktop, int index) { + TimeOfDay? _selectedCheckOutTime; + 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 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), + ), + ], + ], + ); + } + + List _buildThirdRow(bool isDesktop) { + return isDesktop + ? [ + if (plantripType == "2") _buildVisaRequired(isDesktop), + if (plantripType == "2") SizedBox(width: 20), + _buildComments(isDesktop), + if (isDesktop) Spacer(), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _handleAction(isDesktop), + ), + ], + ), + ] + : [ + if (plantripType == "2") _buildVisaRequired(isDesktop), + if (plantripType == "2") SizedBox(height: 5), + _buildComments(isDesktop), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _handleAction(isDesktop), + ), + ]; + } + + Widget _buildVisaRequired(bool isDesktop) { + List visa_available = + widget.apiData?['flight_visa_available'] ?? []; + // Default selected value + + List> dropdownItems = + visa_available + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + selectedvisa_available ??= + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Visa Required", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // use same wrapper as class + // isFocused: focusStates["_visa1Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 35, + width: double.infinity, + child: Focus( + focusNode: focusNodes["_visa1FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_visa1Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_visa1FocusNode"]?.requestFocus(); + }, + child: DropdownSearch>( + items: visa_available.cast>(), + selectedItem: visa_available.firstWhere( + (item) => item['dropdown_key'] == selectedvisa_available, + orElse: () => {}, + ), + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_visa1Focused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_visa1Focused"] ?? 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 Option", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ); + }, + onChanged: + visa_available.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedvisa_available = + newValue?['dropdown_key']; + print("Selected Visa: $selectedvisa_available"); + }); + } + : null, + ), + ), + ), + ), + ), + ], + ); + } + + Widget _buildComments(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Comments", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_comments1Focused"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, + child: TextField( + focusNode: focusNodes["_comments1FocusNode"], + // controller: _commentsController, + controller: textControllers["_comments1Controller"], + // maxLines: 6, + // keyboardType: TextInputType.multiline, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Comments", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 1), + ), + ), + ), + ], + ); + } + + List _handleAction(bool isDesktop) { + return [ + // Close Button + ElevatedButton( + onPressed: () { + widget.onClose("Flight", false); + // widget.onClose(false); // Close the dialog or screen + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey[400], // Light grey color + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: Text( + "Close", + style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), + ), + ), + SizedBox(width: 10), // Space between buttons + // Save Changes Button + ElevatedButton( + onPressed: () { + handleSave(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), // Primary color for save + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: Text( + "Save Changes", + style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), + ), + ), + ]; + } + + List _buildvisa(bool isDesktop) { + List visa_available = + widget.apiData?['flight_visa_available'] ?? []; + // Default selected value + + List> dropdownItems = + visa_available + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + selectedvisa_available ??= + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + + return [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Visa Required", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: _tripTypeFocused, + isFocused: focusStates["_visa1Focused"] ?? false, + isDesktop: isDesktop, + // width: + // isDesktop + // ? MediaQuery.of(context).size.width * 0.34 + // : MediaQuery.of(context).size.width * 0.66, + child: SizedBox( + height: 40, + child: DropdownButtonFormField( + // focusNode: _tripTypeFocusNode, // Assign the correct focus node + focusNode: focusNodes["_visa1FocusNode"], + value: selectedvisa_available, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + ), // Proper padding + ), + onChanged: + visa_available.isNotEmpty + ? (newValue) { + setState(() { + selectedvisa_available = newValue; + // selectedTripType = "Oneway"; + // Reset `multiTripRowCount` when switching away from Multitrip + }); + print( + "Updating form data: Flight -> trip_type -> $selectedvisa_available", + ); + + // _initializeRows(); + } + : null, + + items: dropdownItems, + ), + ), + ), + ], + ), + ]; + } List _buildDelete(bool isDesktop, int index) { return [ @@ -1360,7 +2740,7 @@ class FlightScreenState extends State { ]; } - List _buildSecondRow(bool isDesktop, int index) { + List _buildSecondRow1(bool isDesktop, int index) { bool isFlightClassLoading = widget.apiDataForClass?['flight_class'] == null; List purposeList = widget.apiDataForClass?['flight_class'] ?? []; @@ -2056,58 +3436,6 @@ class FlightScreenState extends State { ), 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, - // isDesktop: isDesktop, - // // width: isDesktop - // // ? MediaQuery.of(context).size.width * 0.34 - // // : MediaQuery.of(context).size.width * 0.66, - // child: SizedBox( - // height: 40, - // child: - // isFlightClassLoading - // ? const Center(child: CircularProgressIndicator()) - // : DropdownButtonFormField( - // focusNode: focusNodes["_class${index}FocusNode"], - // // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // // controller: _hotelNameController, - // value: selectedClasses[index], - // - // style: TextStyle(fontSize: 12), - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric( - // horizontal: 10, - // ), // Proper padding - // ), - // onChanged: - // purposeList.isNotEmpty - // ? (newValue) { - // setState(() { - // selectedClasses[index] = newValue; - // }); - // - // print(selectedClasses[index]); - // } - // : null, - // items: dropdownItems, - // ), - // ), - // ), - // ], - // ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -2526,1010 +3854,14 @@ class FlightScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - 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") if (multiTripRowCount > 1) Padding( @@ -3558,578 +3890,10 @@ class FlightScreenState extends State { ), ), ), - // 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), - // ), - // ), ], ), ), ), ]; } - - List _buildThirdRow(bool isDesktop) { - List visa_available = - widget.apiData?['flight_visa_available'] ?? []; - // Default selected value - - List> dropdownItems = - visa_available - .map( - (item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - ), - ) - .toList(); - - selectedvisa_available ??= - dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - - if (dropdownItems.isEmpty) { - dropdownItems.add( - DropdownMenuItem( - value: null, - child: Text( - "No options available", - style: TextStyle(color: Colors.grey), - ), - ), - ); - } - - return isDesktop - ? [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // use same wrapper as class - // isFocused: focusStates["_visa1Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 35, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_visa1FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_visa1Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_visa1FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: visa_available.cast>(), - selectedItem: visa_available.firstWhere( - (item) => - item['dropdown_key'] == selectedvisa_available, - orElse: () => {}, - ), - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? 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 Option", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - visa_available.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedvisa_available = - newValue?['dropdown_key']; - print( - "Selected Visa: $selectedvisa_available", - ); - }); - } - : null, - ), - ), - ), - ), - ), - ], - ), - if (isDesktop) SizedBox(width: 20), - SizedBox(height: 5), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Comments", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_comments1Focused"] ?? false, - isDesktop: isDesktop, - width: - isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, - child: TextField( - focusNode: focusNodes["_comments1FocusNode"], - // controller: _commentsController, - controller: textControllers["_comments1Controller"], - // maxLines: 6, - // keyboardType: TextInputType.multiline, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Comments", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 1), - ), - ), - ), - ], - ), - if (isDesktop) Spacer(), - SizedBox(height: 5), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _handleAction(isDesktop), - ), - ], - ), - ] - : [ - 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: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // use same wrapper as class - // isFocused: focusStates["_visa1Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 35, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_visa1FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_visa1Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_visa1FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: - visa_available.cast>(), - selectedItem: visa_available.firstWhere( - (item) => - item['dropdown_key'] == - selectedvisa_available, - orElse: () => {}, - ), - itemAsString: - (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? - 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 Option", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - visa_available.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedvisa_available = - newValue?['dropdown_key']; - print( - "Selected Visa: $selectedvisa_available", - ); - }); - } - : null, - ), - ), - ), - ), - ), - ], - ), - if (isDesktop) SizedBox(width: 20), - SizedBox(height: 5), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Comments", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_comments1Focused"] ?? false, - isDesktop: isDesktop, - width: - isDesktop - ? MediaQuery.of(context).size.width * 0.32 - : null, - child: TextField( - focusNode: focusNodes["_comments1FocusNode"], - // controller: _commentsController, - controller: textControllers["_comments1Controller"], - // maxLines: 6, - // keyboardType: TextInputType.multiline, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Comments", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 1), - ), - ), - ), - ], - ), - ], - ), - ), - ), - if (isDesktop) Spacer(), - SizedBox(height: 10), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _handleAction(isDesktop), - ), - ], - ), - ]; - } - - List _buildvisa(bool isDesktop) { - List visa_available = - widget.apiData?['flight_visa_available'] ?? []; - // Default selected value - - List> dropdownItems = - visa_available - .map( - (item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - ), - ) - .toList(); - - selectedvisa_available ??= - dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - - if (dropdownItems.isEmpty) { - dropdownItems.add( - DropdownMenuItem( - value: null, - child: Text( - "No options available", - style: TextStyle(color: Colors.grey), - ), - ), - ); - } - - return [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: _tripTypeFocused, - isFocused: focusStates["_visa1Focused"] ?? false, - isDesktop: isDesktop, - // width: - // isDesktop - // ? MediaQuery.of(context).size.width * 0.34 - // : MediaQuery.of(context).size.width * 0.66, - child: SizedBox( - height: 40, - child: DropdownButtonFormField( - // focusNode: _tripTypeFocusNode, // Assign the correct focus node - focusNode: focusNodes["_visa1FocusNode"], - value: selectedvisa_available, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), // Proper padding - ), - onChanged: - visa_available.isNotEmpty - ? (newValue) { - setState(() { - selectedvisa_available = newValue; - // selectedTripType = "Oneway"; - // Reset `multiTripRowCount` when switching away from Multitrip - }); - print( - "Updating form data: Flight -> trip_type -> $selectedvisa_available", - ); - - // _initializeRows(); - } - : null, - - items: dropdownItems, - ), - ), - ), - ], - ), - ]; - } - - List _handleAction(bool isDesktop) { - return [ - // Close Button - ElevatedButton( - onPressed: () { - widget.onClose("Flight", false); - // widget.onClose(false); // Close the dialog or screen - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.grey[400], // Light grey color - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - child: Text( - "Close", - style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), - ), - ), - SizedBox(width: 10), // Space between buttons - // Save Changes Button - ElevatedButton( - onPressed: () { - handleSave(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), // Primary color for save - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - child: Text( - "Save Changes", - style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), - ), - ), - ]; - } } diff --git a/lib/Screens/itnerary_list/accomodation_list.dart b/lib/Screens/itnerary_list/accomodation_list.dart index 03d8aa4..f4cd400 100644 --- a/lib/Screens/itnerary_list/accomodation_list.dart +++ b/lib/Screens/itnerary_list/accomodation_list.dart @@ -320,7 +320,7 @@ class _AccomodationListWidgetState extends State { style: GoogleFonts.poppins( fontSize: 14, fontWeight: - isDesktop ? FontWeight.w800 : FontWeight.w500, + isDesktop ? FontWeight.w800 : FontWeight.w600, color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), diff --git a/lib/Screens/itnerary_list/flight_list.dart b/lib/Screens/itnerary_list/flight_list.dart index 6ee238b..76b58c1 100644 --- a/lib/Screens/itnerary_list/flight_list.dart +++ b/lib/Screens/itnerary_list/flight_list.dart @@ -423,7 +423,7 @@ class _FlightListWidgetState extends State { style: GoogleFonts.poppins( fontSize: 14, fontWeight: - isDesktop ? FontWeight.w800 : FontWeight.w500, + isDesktop ? FontWeight.w800 : FontWeight.w600, color: !isDesktop ? Colors.black : Color(0xFF575A74), // Color(0xFF114D8B) diff --git a/lib/Screens/itnerary_list/forex_list.dart b/lib/Screens/itnerary_list/forex_list.dart index 6662d52..a31e233 100644 --- a/lib/Screens/itnerary_list/forex_list.dart +++ b/lib/Screens/itnerary_list/forex_list.dart @@ -181,7 +181,7 @@ class _ForexListWidgetState extends State { // // ), // ], // ), - const SizedBox(height: 16), + SizedBox(height: isDesktop ? 16 : 4), // Scroll behavior based on device _buildData(context, isDesktop), @@ -324,8 +324,10 @@ class _ForexListWidgetState extends State { Text( getRequestForCountry(item["country_code"]!.toString()), style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), Spacer(), @@ -377,7 +379,7 @@ class _ForexListWidgetState extends State { : SizedBox.shrink(), // or Container() ], ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), // SizedBox(height: 4), isDesktop ? Row( @@ -771,7 +773,7 @@ class _ForexListWidgetState extends State { title, style: GoogleFonts.poppins( fontSize: 12, - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, ), ), ), diff --git a/lib/Screens/itnerary_list/insurance_list.dart b/lib/Screens/itnerary_list/insurance_list.dart index c4e3d4f..dd7a459 100644 --- a/lib/Screens/itnerary_list/insurance_list.dart +++ b/lib/Screens/itnerary_list/insurance_list.dart @@ -4,7 +4,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class InsuranceListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class InsuranceListWidget extends StatefulWidget { final List> insuranceList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteInsurance; @@ -13,21 +15,67 @@ class InsuranceListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const InsuranceListWidget( - {super.key, - required this.insuranceList, - required this.onOpen, - required this.apiData, - required this.onDeleteInsurance, - required this.onAddNew, - required this.isViewMode}); + const InsuranceListWidget({ + super.key, + required this.insuranceList, + required this.onOpen, + required this.apiData, + required this.onDeleteInsurance, + required this.onAddNew, + required this.isViewMode, + }); + + @override + State createState() => _InsuranceListWidgetState(); +} + +class _InsuranceListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -107,10 +155,10 @@ class InsuranceListWidget extends StatelessWidget { // ), // ], // ), - const SizedBox(height: 16), - // Scroll behavior based on device + // const SizedBox(height: 16), - _buildData(context, isDesktop) + // Scroll behavior based on device + _buildData(context, isDesktop), ], ), ), @@ -119,11 +167,11 @@ class InsuranceListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - insuranceList.where((item) => item["is_active"] == "1").toList(); + widget.insuranceList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); List insurancetypeList = - apiData?['insurance_type_of_insurance'] ?? []; + widget.apiData?['insurance_type_of_insurance'] ?? []; String getRequestForInsuranceType(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -146,7 +194,7 @@ class InsuranceListWidget extends StatelessWidget { String getRequestValue(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; - return (apiData?['miscellaneous_special_request'] ?? []) + return (widget.apiData?['miscellaneous_special_request'] ?? []) .firstWhere( (element) => element["dropdown_key"].toString() == specialRequestKey, @@ -177,14 +225,18 @@ class InsuranceListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + // color: Colors.white, + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -193,176 +245,206 @@ class InsuranceListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - getRequestForInsuranceType(item["type_of_insurance"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + Expanded( + flex: 1, + child: Text( + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Insurance"), + onTap: () => widget.onOpen(true, item, "Insurance"), child: Tooltip( message: 'Edit Insurance Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, + ), + ), + ), + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteInsurance(item), + child: Tooltip( + message: 'Delete Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + color: Colors.red, ), ), ), - // SizedBox(width: 10), - // GestureDetector( - // onTap: () => onDeleteInsurance(item), - // child: Tooltip( - // message: 'Delete Insurance Details', - // child: Image.asset( - // 'assets/images/IconsImg/delete.png', - // width: 20, - // height: 15, - // color: Colors.red, - // ), - // ), - // ), ], ), SizedBox(height: 4), - Divider( - color: Colors.blueGrey.shade50, - ), - SizedBox(height: 4), + // Divider(color: Colors.blueGrey.shade50), + // SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - " InsuranceType", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Time Period ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) + children: [ + Expanded( + flex: 2, + child: Text( + " InsuranceType", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Time Period ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + ], + ) : SizedBox.shrink(), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - getRequestForInsuranceType( - item["type_of_insurance"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows children: [ - _infoBlock("Insurance Type", getRequestForInsuranceType(item["type_of_insurance"]!.toString()) ?? "N/A"), - _infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"), - _infoBlock("End Date", formatDate(item["end_date"]) ?? "N/A"), + Expanded( + flex: 2, + child: Text( + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), ], - ), - const SizedBox(height: 16), + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + children: [ + _buildRow( + "InsuranceType", + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + ), + SizedBox(width: 10), + _buildRow( + "TimePeriod", + '${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"])} ', + ), - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, + SizedBox(width: 10), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], ), ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), + // Column( - // children: [ - // _buildRow( - // "InsuranceType:", - // getRequestForInsuranceType( - // item["type_of_insurance"]!.toString())), - // SizedBox(width: 10), - // _buildRow( - // "StartDate:", formatDate(item["start_date"]!)), - // SizedBox(width: 10), - // _buildRow("EndDate:", formatDate(item["end_date"])), - // SizedBox(width: 10), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // children: [ + // _infoBlock( + // "Insurance Type", + // getRequestForInsuranceType( + // item["type_of_insurance"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Start Date", + // formatDate(item["start_date"]!) ?? "N/A", + // ), + // _infoBlock( + // "End Date", + // formatDate(item["end_date"]) ?? "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, // ), + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -391,31 +473,35 @@ class InsuranceListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, ), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), - ), ), ], ); @@ -439,16 +525,14 @@ class InsuranceListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), ), ); } + Widget _buildRow(String title, String value) { // Define character limits based on title Map limits = { @@ -468,40 +552,39 @@ class InsuranceListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, fontSize: 12), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - style: GoogleFonts.poppins( - fontSize: 12, + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), ), - overflow: TextOverflow.ellipsis, - ), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - ), - ), + textStyle: TextStyle( + color: Colors.black, + fontSize: 12, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: GoogleFonts.poppins(fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: GoogleFonts.poppins(fontSize: 12)), ), ], ); @@ -509,11 +592,11 @@ class InsuranceListWidget extends StatelessWidget { List _buildDataRows() { List> filteredList = - insuranceList.where((item) => item["is_active"] == "1").toList(); + widget.insuranceList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); List insurancetypeList = - apiData?['insurance_type_of_insurance'] ?? []; + widget.apiData?['insurance_type_of_insurance'] ?? []; String getRequestForInsuranceType(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -529,47 +612,55 @@ class InsuranceListWidget extends StatelessWidget { return filteredList.asMap().entries.map((entry) { Map item = entry.value; - return DataRow(cells: [ - // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column - // DataCell(Text(item["type_of_insurance"]!)), - DataCell(Text( - getRequestForInsuranceType(item["type_of_insurance"]!.toString()))), - DataCell(Text(item["start_date"]!)), - DataCell(Text(item["end_date"]!)), - DataCell(Row( - children: [ - GestureDetector( - onTap: () => onOpen(true, item, "Insurance"), - child: Tooltip( - message: 'Edit Insurance Details', - child: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, + return DataRow( + cells: [ + // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column + // DataCell(Text(item["type_of_insurance"]!)), + DataCell( + Text( + getRequestForInsuranceType(item["type_of_insurance"]!.toString()), + ), + ), + DataCell(Text(item["start_date"]!)), + DataCell(Text(item["end_date"]!)), + DataCell( + Row( + children: [ + GestureDetector( + onTap: () => widget.onOpen(true, item, "Insurance"), + child: Tooltip( + message: 'Edit Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), ), - ), - ), - SizedBox(width: 10), - GestureDetector( - onTap: () => onDeleteInsurance(item), - child: Tooltip( - message: 'Delete Insurance Details', - child: Image.asset( - 'assets/images/IconsImg/delete.png', - width: 20, - height: 15, + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteInsurance(item), + child: Tooltip( + message: 'Delete Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ), + ), ), - ), + IconButton( + icon: Icon( + Icons.keyboard_arrow_down_outlined, + size: 28, + color: Color(0xFF475569), + ), + onPressed: () { + // Expand logic + }, + ), + ], ), - IconButton( - icon: Icon(Icons.keyboard_arrow_down_outlined, - size: 28, color: Color(0xFF475569)), - onPressed: () { - // Expand logic - }, - ), - ], - ) // Row( // children: [ @@ -593,9 +684,9 @@ class InsuranceListWidget extends StatelessWidget { // ), // ], // ) - - ), - ]); + ), + ], + ); }).toList(); } } diff --git a/lib/Screens/itnerary_list/miscellaneous_list.dart b/lib/Screens/itnerary_list/miscellaneous_list.dart index 48b79fc..72261fc 100644 --- a/lib/Screens/itnerary_list/miscellaneous_list.dart +++ b/lib/Screens/itnerary_list/miscellaneous_list.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -class MiscellaneousListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class MiscellaneousListWidget extends StatefulWidget { final List> miscellaneousList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteMiscellaneous; @@ -19,12 +21,58 @@ class MiscellaneousListWidget extends StatelessWidget { required this.isViewMode, }); + @override + State createState() => + _MiscellaneousListWidgetState(); +} + +class _MiscellaneousListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -34,7 +82,7 @@ class MiscellaneousListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && miscellaneousList.isNotEmpty) + if ((!isDesktop) && widget.miscellaneousList.isNotEmpty) Text( " ", style: const TextStyle( @@ -44,20 +92,20 @@ class MiscellaneousListWidget extends StatelessWidget { ), MouseRegion( cursor: - isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + widget.isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: GestureDetector( onTap: - isViewMode - ? null - : () { - print("New data"); - onAddNew("Miscellaneous", true); - }, + widget.isViewMode + ? null + : () { + print("New data"); + widget.onAddNew("Miscellaneous", true); + }, child: Row( mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely + MainAxisSize.min, // Ensures content fits nicely children: [ // Text( // "Add New", @@ -133,7 +181,9 @@ class MiscellaneousListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - miscellaneousList.where((item) => item["is_active"] == "1").toList(); + widget.miscellaneousList + .where((item) => item["is_active"] == "1") + .toList(); return ListView.builder( shrinkWrap: true, @@ -144,12 +194,12 @@ class MiscellaneousListWidget extends StatelessWidget { String getRequestValue(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; - return (apiData?['miscellaneous_special_request'] ?? []) + return (widget.apiData?['miscellaneous_special_request'] ?? []) .firstWhere( (element) => - element["dropdown_key"].toString() == specialRequestKey, - orElse: () => {"dropdown_value": "N/A"}, - )["dropdown_value"] + element["dropdown_key"].toString() == specialRequestKey, + orElse: () => {"dropdown_value": "N/A"}, + )["dropdown_value"] .toString(); } @@ -158,14 +208,17 @@ class MiscellaneousListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.yellow.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -174,7 +227,7 @@ class MiscellaneousListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -185,26 +238,28 @@ class MiscellaneousListWidget extends StatelessWidget { getRequestValue(item["special_request"]?.toString()), style: GoogleFonts.poppins( fontSize: 14, - fontWeight: FontWeight.w800, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Miscellaneous"), + onTap: () => widget.onOpen(true, item, "Miscellaneous"), child: Tooltip( message: 'Edit Miscellaneous Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( // onTap: () => onOpen(true, item, "Miscellaneous"), - onTap: () => onDeleteMiscellaneous(item), + onTap: () => widget.onDeleteMiscellaneous(item), child: Tooltip( message: 'Delete Miscellaneous Details', child: Image.asset( @@ -217,95 +272,69 @@ class MiscellaneousListWidget extends StatelessWidget { ), ], ), - Divider(color: Colors.blueGrey.shade50), - SizedBox(height: 4), + // Divider(color: Colors.blueGrey.shade50), + // SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - "Special Request", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - Expanded( - flex: 3, - child: Text( - " Comments", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - ], - ) - // : SizedBox.shrink(), - // isDesktop - // ? Row( - // children: [ - // Expanded( - // flex: 2, - // child: Text( - // getRequestValue( - // item["special_request"]?.toString(), - // ), - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // ), - // Expanded( - // flex: 3, - // child: Text( - // item["comments"], - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // ), - // ], - // ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), + children: [ + Expanded( + flex: 2, + child: Text( + "Special Request", + style: GoogleFonts.poppins(fontSize: 11), + ), ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + Expanded( + flex: 3, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), - // Column( - // children: [ - // _buildRow( - // "Special Request:", - // getRequestValue(item["special_request"]?.toString()), - // ), - // SizedBox(width: 10), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ), + ], + ) + : SizedBox.shrink(), + isDesktop + ? Row( + children: [ + Expanded( + flex: 2, + child: Text( + getRequestValue( + item["special_request"]?.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + Expanded( + flex: 3, + child: Text( + item["comments"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + children: [ + // _buildRow( + // "Special Request", + // getRequestValue(item["special_request"]?.toString()), + // ), + SizedBox(width: 10), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], + ), + ), ], ), ), @@ -335,34 +364,34 @@ class MiscellaneousListWidget extends StatelessWidget { children: [ Expanded( child: - exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, - ), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - overflow: TextOverflow.ellipsis, - ), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), ], ); @@ -387,102 +416,108 @@ class MiscellaneousListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), SizedBox(width: 8), Expanded( child: - exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, - fontSize: 12, - ), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - overflow: TextOverflow.ellipsis, - ), - ) - : Text(value), + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + fontSize: 12, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value), ), ], ); } -// -// Widget _buildData(BuildContext context) { -// return Container( -// width: MediaQuery.of(context).size.width, -// child: DataTable( -// border: TableBorder( -// bottom: BorderSide(color: Colors.black12), -// horizontalInside: BorderSide(color: Colors.black12), -// ), -// columns: const [ -// DataColumn(label: Text('Special Request')), -// DataColumn(label: Text('Comments')), -// DataColumn(label: Text('Actions')), -// ], -// rows: _buildDataRows(), -// ), -// ); -// } -// -// List _buildDataRows() { -// List purposeList = apiData?['miscellaneous_special_request'] ?? []; -// -// String getRequestValue(String? specialRequestKey) { -// if (specialRequestKey == null) return "N/A"; -// return purposeList -// .firstWhere( -// (element) => -// element["dropdown_key"].toString() == specialRequestKey, -// orElse: () => {"dropdown_value": "N/A"}, -// )["dropdown_value"] -// .toString(); -// } -// -// List> filteredList = -// miscellaneousList.where((item) => item["is_active"] == "1").toList(); -// -// return filteredList.asMap().entries.map((entry) { -// Map item = entry.value; -// -// return DataRow(cells: [ -// DataCell(Text(getRequestValue(item["special_request"]?.toString()))), -// DataCell(Text(item["comments"] ?? "N/A")), -// DataCell(Row( -// children: [ -// GestureDetector( -// onTap: () => onOpen(true, item, "Miscellaneous"), -// child: Image.asset('assets/images/IconsImg/edit.png', -// width: 20, height: 15), -// ), -// SizedBox(width: 10), -// GestureDetector( -// onTap: () => onOpen(true, item, "Miscellaneous"), -// child: Image.asset('assets/images/IconsImg/delete.png', -// width: 20, height: 15), -// ), -// IconButton( -// icon: Icon(Icons.keyboard_arrow_down_outlined, -// size: 28, color: Color(0xFF475569)), -// onPressed: () { -// // Expand logic (optional) -// }, -// ), -// ], -// )), -// ]); -// }).toList(); -// } -} \ No newline at end of file + // + // Widget _buildData(BuildContext context) { + // return Container( + // width: MediaQuery.of(context).size.width, + // child: DataTable( + // border: TableBorder( + // bottom: BorderSide(color: Colors.black12), + // horizontalInside: BorderSide(color: Colors.black12), + // ), + // columns: const [ + // DataColumn(label: Text('Special Request')), + // DataColumn(label: Text('Comments')), + // DataColumn(label: Text('Actions')), + // ], + // rows: _buildDataRows(), + // ), + // ); + // } + // + // List _buildDataRows() { + // List purposeList = apiData?['miscellaneous_special_request'] ?? []; + // + // String getRequestValue(String? specialRequestKey) { + // if (specialRequestKey == null) return "N/A"; + // return purposeList + // .firstWhere( + // (element) => + // element["dropdown_key"].toString() == specialRequestKey, + // orElse: () => {"dropdown_value": "N/A"}, + // )["dropdown_value"] + // .toString(); + // } + // + // List> filteredList = + // miscellaneousList.where((item) => item["is_active"] == "1").toList(); + // + // return filteredList.asMap().entries.map((entry) { + // Map item = entry.value; + // + // return DataRow(cells: [ + // DataCell(Text(getRequestValue(item["special_request"]?.toString()))), + // DataCell(Text(item["comments"] ?? "N/A")), + // DataCell(Row( + // children: [ + // GestureDetector( + // onTap: () => onOpen(true, item, "Miscellaneous"), + // child: Image.asset('assets/images/IconsImg/edit.png', + // width: 20, height: 15), + // ), + // SizedBox(width: 10), + // GestureDetector( + // onTap: () => onOpen(true, item, "Miscellaneous"), + // child: Image.asset('assets/images/IconsImg/delete.png', + // width: 20, height: 15), + // ), + // IconButton( + // icon: Icon(Icons.keyboard_arrow_down_outlined, + // size: 28, color: Color(0xFF475569)), + // onPressed: () { + // // Expand logic (optional) + // }, + // ), + // ], + // )), + // ]); + // }).toList(); + // } +} diff --git a/lib/Screens/itnerary_list/taxi_list.dart b/lib/Screens/itnerary_list/taxi_list.dart index 3c960f3..90032b4 100644 --- a/lib/Screens/itnerary_list/taxi_list.dart +++ b/lib/Screens/itnerary_list/taxi_list.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class TaxiListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class TaxiListWidget extends StatefulWidget { final List> taxiList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteTaxi; @@ -21,12 +23,57 @@ class TaxiListWidget extends StatelessWidget { required this.isViewMode, }); + @override + State createState() => _TaxiListWidgetState(); +} + +class _TaxiListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -36,7 +83,7 @@ class TaxiListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && taxiList.isNotEmpty) + if ((!isDesktop) && widget.taxiList.isNotEmpty) Text( " ", style: const TextStyle( @@ -46,17 +93,17 @@ class TaxiListWidget extends StatelessWidget { ), MouseRegion( cursor: - isViewMode + widget.isViewMode ? SystemMouseCursors.forbidden : SystemMouseCursors.click, child: GestureDetector( onTap: - isViewMode + widget.isViewMode ? null : () { print("New data"); - onAddNew("Taxi", true); + widget.onAddNew("Taxi", true); }, child: Row( mainAxisSize: @@ -121,11 +168,12 @@ class TaxiListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - taxiList.where((item) => item["is_active"] == "1").toList(); + widget.taxiList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - List taxiClassList = apiData?['taxt_car_type'] ?? []; - List taxirequiredFor = apiData?['taxi_car_required_for'] ?? []; + List taxiClassList = widget.apiData?['taxt_car_type'] ?? []; + List taxirequiredFor = + widget.apiData?['taxi_car_required_for'] ?? []; String getRequestForTaxiClass(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -228,14 +276,17 @@ class TaxiListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -244,37 +295,41 @@ class TaxiListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - "${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + Expanded( + flex: 1, + child: Text( + "${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Taxi"), + onTap: () => widget.onOpen(true, item, "Taxi"), child: Tooltip( message: 'Edit Taxi Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteTaxi(item), + onTap: () => widget.onDeleteTaxi(item), child: Tooltip( message: 'Delete Taxi Details', child: Image.asset( @@ -287,7 +342,7 @@ class TaxiListWidget extends StatelessWidget { ), ], ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( @@ -369,72 +424,75 @@ class TaxiListWidget extends StatelessWidget { ), ], ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // First row: City & Location - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoColumn("City", item["destination_city"] ?? "N/A"), - _infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true), - ], + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow("City", item["destination_city"]), + SizedBox(width: 10), + _buildRow("Location", item["location_of_pickup"]!), + SizedBox(width: 10), + _buildDateTimeRow( + "Date", + formatDate(item["date"]!), + formatTime(item["time"]!), ), - const SizedBox(height: 16), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], + ), - // Second row: Date & Time - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"), - _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true), - ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - - // Comment box - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - )else const Text( "N/A", style: TextStyle(fontSize: 12), ), - - ] ) - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow("City:", item["destination_city"]), - // SizedBox(width: 10), - // _buildRow("Pickup:", item["location_of_pickup"]!), - // SizedBox(width: 10), - // _buildDateTimeRow( - // "Date:", - // formatDate(item["date"]!), - // formatTime(item["time"]!), - // ), - // _buildRow("TaxiFor:", item["car_required_for"]!), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // First row: City & Location + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn("City", item["destination_city"] ?? "N/A"), + // _infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true), + // ], + // ), + // const SizedBox(height: 16), + // + // // Second row: Date & Time + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"), + // _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, + // ), + // ), + // const SizedBox(height: 8), + // + // // Comment box + // if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all(color: const Color(0xFF7098DD), width: 1), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + // ), + // )else const Text( "N/A", style: TextStyle(fontSize: 12), ), + // + // ] ), + ), ], ), ), @@ -516,9 +574,12 @@ class TaxiListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + SizedBox( + width: 100, + child: Text( + title, + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + ), ), SizedBox(width: 8), Expanded( @@ -551,9 +612,15 @@ class TaxiListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), SizedBox(width: 8), Expanded( @@ -562,30 +629,27 @@ class TaxiListWidget extends StatelessWidget { ], ); } - Widget _infoColumn(String label, String value, {bool alignEnd = false}) { - return Column( - // crossAxisAlignment: CrossAxisAlignment.start, - crossAxisAlignment: - alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, - children: [ - Text( - label, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), - ), - const SizedBox(height: 4), - Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), - ), - ], - ); - } + Widget _infoColumn(String label, String value, {bool alignEnd = false}) { + return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, + children: [ + Text( + label, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + const SizedBox(height: 4), + Text( + value, + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + ), + ], + ); + } } diff --git a/lib/Screens/itnerary_list/visa_list.dart b/lib/Screens/itnerary_list/visa_list.dart index 93f1a31..e8b91f3 100644 --- a/lib/Screens/itnerary_list/visa_list.dart +++ b/lib/Screens/itnerary_list/visa_list.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class VisaListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class VisaListWidget extends StatefulWidget { final List> visaList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteMiscellaneous; @@ -12,91 +14,138 @@ class VisaListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const VisaListWidget( - {super.key, - required this.visaList, - required this.onOpen, - required this.onDeleteMiscellaneous, - required this.apiData, - required this.apiCountryData, - required this.onAddNew, - required this.isViewMode}); + const VisaListWidget({ + super.key, + required this.visaList, + required this.onOpen, + required this.onDeleteMiscellaneous, + required this.apiData, + required this.apiCountryData, + required this.onAddNew, + required this.isViewMode, + }); + + State createState() => _VisaListWidgetState(); +} + +class _VisaListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Header with title and button - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if ((!isDesktop) && visaList.isNotEmpty) - Text( - " ", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - MouseRegion( - cursor: isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // if ((!isDesktop) && widget.visaList.isNotEmpty) + // Text( + // " ", + // style: const TextStyle( + // fontSize: 18, + // fontWeight: FontWeight.bold, + // ), + // ), + // MouseRegion( + // cursor: + // widget.isViewMode + // ? SystemMouseCursors.forbidden + // : SystemMouseCursors.click, + // + // child: GestureDetector( + // onTap: + // widget.isViewMode + // ? null + // : () { + // print("New data"); + // widget.onAddNew("Visa", true); + // }, + // child: Row( + // mainAxisSize: + // MainAxisSize.min, // Ensures content fits nicely + // children: [ + // // Text( + // // "Add New", + // // style: TextStyle(fontSize: 13), + // // ), + // // SizedBox(width: 8), // spacing between icon and text + // // Icon( + // // Icons.add_circle_sharp, + // // size: 30, + // // color: Color(0xFF114D8B), + // // ) + // ], + // ), + // ), + // // onPressed: isViewMode + // // ? null + // // : () { + // // print("New data"); + // // + // // }, + // // child: Row( + // // mainAxisSize: MainAxisSize.min, + // // children: [ + // // Icon( + // // Icons.add_circle_sharp, + // // size: 30, + // // color: Color(0xFF114D8B), + // // ) + // // ], + // // ), + // ), + // ], + // ), + // const SizedBox(height: 16), - child: GestureDetector( - onTap: isViewMode - ? null - : () { - print("New data"); - onAddNew("Visa", true); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - // Text( - // "Add New", - // style: TextStyle(fontSize: 13), - // ), - // SizedBox(width: 8), // spacing between icon and text - // Icon( - // Icons.add_circle_sharp, - // size: 30, - // color: Color(0xFF114D8B), - // ) - ], - ), - ), - // onPressed: isViewMode - // ? null - // : () { - // print("New data"); - // - // }, - // child: Row( - // mainAxisSize: MainAxisSize.min, - // children: [ - // Icon( - // Icons.add_circle_sharp, - // size: 30, - // color: Color(0xFF114D8B), - // ) - // ], - // ), - ), - ], - ), - const SizedBox(height: 16), // Scroll behavior based on device - - _buildData(context, isDesktop) + _buildData(context, isDesktop), ], ), ), @@ -191,11 +240,11 @@ class VisaListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - visaList.where((item) => item["is_active"] == "1").toList(); + widget.visaList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - List visatypeList = apiData?['visa_type_of_visa'] ?? []; - List countryList = apiCountryData ?? []; + List visatypeList = widget.apiData?['visa_type_of_visa'] ?? []; + List countryList = widget.apiCountryData ?? []; String getRequestForVisa(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -249,8 +298,11 @@ class VisaListWidget extends StatelessWidget { if (hour == 24 && minute == 0) { // 24:00 is treated as 00:00 on the next day - dateTime = DateTime(now.year, now.month, now.day) - .add(const Duration(days: 1)); + dateTime = DateTime( + now.year, + now.month, + now.day, + ).add(const Duration(days: 1)); } else { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw FormatException("Invalid hour or minute"); @@ -276,14 +328,17 @@ class VisaListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -292,7 +347,7 @@ class VisaListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -303,26 +358,27 @@ class VisaListWidget extends StatelessWidget { getRequestForVisa(item["type_of_visa"]!.toString()), style: GoogleFonts.poppins( fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Visa"), + onTap: () => widget.onOpen(true, item, "Visa"), child: Tooltip( message: 'Edit Visa Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteMiscellaneous(item), + onTap: () => widget.onDeleteMiscellaneous(item), child: Tooltip( message: 'Delete Visa Details', child: Image.asset( @@ -335,155 +391,179 @@ class VisaListWidget extends StatelessWidget { ), ], ), - Divider( - color: Colors.blueGrey.shade50, - ), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - " Country", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Visa Type", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Date", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) + children: [ + Expanded( + flex: 2, + child: Text( + " Country", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Visa Type", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Date", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + ], + ) : SizedBox.shrink(), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - getRequestForCountry( - item["country_code"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - getRequestForVisa( - item["type_of_visa"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - formatDate(item["start_date"]!), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows children: [ - _infoBlock("Visa Type", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), - _infoBlock("Country", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), - _infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"), + Expanded( + flex: 2, + child: Text( + getRequestForCountry( + item["country_code"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + getRequestForVisa(item["type_of_visa"]!.toString()), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + formatDate(item["start_date"]!), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow( + "VisaType", + getRequestForVisa(item["type_of_visa"]!.toString()), + ), + SizedBox(height: 6), + _buildRow( + "Country", + getRequestForCountry( + item["country_code"]!.toString(), + ), + ), + SizedBox(height: 6), + _buildRow("StartDate", item["start_date"]!), + SizedBox(height: 6), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], ), ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), + // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow( - // "VisaType:", - // getRequestForVisa( - // item["type_of_visa"]!.toString())), - // SizedBox(height: 6), - // _buildRow( - // "Country:", - // getRequestForCountry( - // item["country_code"]!.toString())), - // SizedBox(height: 6), - // _buildRow("StartDate:", item["start_date"]!), - // SizedBox(height: 6), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // children: [ + // _infoBlock( + // "Visa Type", + // getRequestForCountry( + // item["country_code"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Country", + // getRequestForCountry( + // item["country_code"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Start Date", + // formatDate(item["start_date"]!) ?? "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, // ), + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -512,31 +592,37 @@ class VisaListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - fontFamily: "Archivo"), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + fontFamily: "Archivo", + ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - fontFamily: "Archivo"), - ), + fontFamily: "Archivo", + ), + ), ), ], ); @@ -560,16 +646,14 @@ class VisaListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), ), ); } + Widget _buildRow(String title, String value) { // Define character limits based on title Map limits = { @@ -589,34 +673,38 @@ class VisaListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: TextStyle(fontSize: 12), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: TextStyle(fontSize: 12), - ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: TextStyle(fontSize: 12)), ), ], ); diff --git a/web/index.html b/web/index.html index eea2d20..6ca87d1 100644 --- a/web/index.html +++ b/web/index.html @@ -13,7 +13,7 @@ This is a placeholder for base href that will be replaced by the value of the `--base-href` argument provided to `flutter build`. - --> + --> TSTAT_TEST_19July.