diff --git a/lib/Screens/costCenter/costCenter_list.dart b/lib/Screens/costCenter/costCenter_list.dart index af92cdb..1970b8b 100644 --- a/lib/Screens/costCenter/costCenter_list.dart +++ b/lib/Screens/costCenter/costCenter_list.dart @@ -336,7 +336,7 @@ class CostCenterListState extends State { MainAxisSize.min, // Ensures content fits nicely children: [ Text( - "Add CostCenter", + "Add Cost Center", style: GoogleFonts.poppins( fontSize: isDesktop ? 13 : 11, ), diff --git a/lib/Screens/forex/forexDetails.dart b/lib/Screens/forex/forexDetails.dart index 44c60bc..78002e5 100644 --- a/lib/Screens/forex/forexDetails.dart +++ b/lib/Screens/forex/forexDetails.dart @@ -396,7 +396,7 @@ class ForexDataState extends State { ), searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Search Country...", + hintText: "Search ...", hintStyle: GoogleFonts.poppins(fontSize: 11), contentPadding: EdgeInsets.symmetric(horizontal: 4), ), @@ -414,7 +414,7 @@ class ForexDataState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Country", + selectedItem ?? "Select ", style: GoogleFonts.poppins(fontSize: 11), ), ), diff --git a/lib/Screens/forex/forex_list.dart b/lib/Screens/forex/forex_list.dart index 64daa91..2d99fc6 100644 --- a/lib/Screens/forex/forex_list.dart +++ b/lib/Screens/forex/forex_list.dart @@ -746,9 +746,9 @@ class ForexDataListState extends State { style: TextStyle( fontSize: 13, fontFamily: "Inter", - // color: forex['is_active'] == "1" - // ? Colors.green - // : Colors.grey, + color: forex['is_active'] == "1" + ? Colors.green + : Colors.grey, ), softWrap: true, overflow: TextOverflow.ellipsis, diff --git a/lib/Screens/group/groupDetails.dart b/lib/Screens/group/groupDetails.dart index fc3156b..9f0cb19 100644 --- a/lib/Screens/group/groupDetails.dart +++ b/lib/Screens/group/groupDetails.dart @@ -407,7 +407,7 @@ class GroupDataState extends State { ), searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Select Policy For International", + hintText: "Search ...", hintStyle: GoogleFonts.poppins(fontSize: 11), contentPadding: EdgeInsets.symmetric(horizontal: 4), ), @@ -425,7 +425,7 @@ class GroupDataState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Policy For International", + selectedItem ?? "Select", style: GoogleFonts.poppins(fontSize: 11), ), ), @@ -481,7 +481,7 @@ class GroupDataState extends State { ), searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Select Policy For Domestic...", + hintText: "Search ...", hintStyle: GoogleFonts.poppins(fontSize: 11), contentPadding: EdgeInsets.symmetric(horizontal: 4), ), @@ -499,7 +499,7 @@ class GroupDataState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Policy For Domestic", + selectedItem ?? "Select ", style: GoogleFonts.poppins(fontSize: 11), ), ), diff --git a/lib/Screens/group/groupList.dart b/lib/Screens/group/groupList.dart index d653297..02e0ff4 100644 --- a/lib/Screens/group/groupList.dart +++ b/lib/Screens/group/groupList.dart @@ -353,7 +353,7 @@ class _GroupListState extends State { MainAxisSize.min, // Ensures content fits nicely children: [ Text( - "Add New Group", + "Add Group", style: GoogleFonts.poppins( fontSize: isDesktop ? 13 : 11, ), diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index e759d09..76eb5f9 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -418,7 +418,7 @@ class HotelsDataState extends State { ), searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Search Country...", + hintText: "Search ...", hintStyle: GoogleFonts.poppins(fontSize: 11), contentPadding: EdgeInsets.symmetric(horizontal: 4), ), @@ -436,7 +436,7 @@ class HotelsDataState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Country", + selectedItem ?? "Select ", style: GoogleFonts.poppins(fontSize: 11), ), ), diff --git a/lib/Screens/itnerary/accomodations.dart b/lib/Screens/itnerary/accomodations.dart index 2d085f1..061f1bb 100644 --- a/lib/Screens/itnerary/accomodations.dart +++ b/lib/Screens/itnerary/accomodations.dart @@ -437,7 +437,7 @@ class _AccomodationScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Destination", + "Destination *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, @@ -485,7 +485,7 @@ class _AccomodationScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Hotel Name", + "Hotel Name *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, @@ -695,7 +695,7 @@ class _AccomodationScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Check-in*", + "Check-in *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, @@ -747,7 +747,7 @@ class _AccomodationScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Time (Check-in)", + "Time (Check-in) *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, @@ -817,7 +817,7 @@ class _AccomodationScreenState extends State { child: TextField( focusNode: _checkOutFocusNode, controller: _checkOutController, - style: const TextStyle(fontSize: 12), + style: const TextStyle(fontSize: 12, color: Colors.black), decoration: const InputDecoration( labelText: "Select Date", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -851,7 +851,7 @@ class _AccomodationScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Time (Check-out)", + "Time (Check-out) *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, diff --git a/lib/Screens/itnerary/bus.dart b/lib/Screens/itnerary/bus.dart index 6738e33..56c39b4 100644 --- a/lib/Screens/itnerary/bus.dart +++ b/lib/Screens/itnerary/bus.dart @@ -327,7 +327,8 @@ class _BusScreenState extends State { child: DropdownButtonFormField( focusNode: _tripTypeFocusNode, // Assign the correct focus node value: selectedPurpose, - style: TextStyle(fontSize: 12), + // style: TextStyle(fontSize: 12), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), decoration: InputDecoration( border: InputBorder.none, contentPadding: @@ -401,7 +402,7 @@ class _BusScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "From", + "From *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -446,7 +447,7 @@ class _BusScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "To", + "To *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -491,7 +492,7 @@ class _BusScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Date", + "Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -543,7 +544,7 @@ class _BusScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Time", + "Time *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -561,7 +562,7 @@ class _BusScreenState extends State { child: TextField( focusNode: _timeFocusNode, controller: _timeController, - style: const TextStyle(fontSize: 12), + style: const TextStyle(fontSize: 12, color: Colors.black), decoration: const InputDecoration( labelText: "Select Time", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index 111a598..2fe0357 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -55,6 +55,8 @@ class FlightScreenState extends State { Map selectedValues = {}; + int rowCount = 1; + String? selectedTripType; Map selectedClasses = {}; // Store class selection for each trip Map selectedFrom = {}; // Store class selection for each trip @@ -251,9 +253,14 @@ class FlightScreenState extends State { Map tempCountryMap = {}; for (var country in result) { - String city = country['City'] ?? ''; - String airport = country['Airport'] ?? ''; - String displayName = '${country['City']} - ${country['Airport']}'; + // String city = country['City'] ?? ''; + // String airport = country['Airport'] ?? ''; + // String displayName = '${country['City']} - ${country['Airport']}'; + + final code = country['Code'] ?? ''; + final city = country['City'] ?? ''; + final airport = country['Airport'] ?? ''; + final displayName = '$city ($code)\n$airport'; tempCountryMap[country['Code']] = displayName; } @@ -563,7 +570,7 @@ class FlightScreenState extends State { bool validateFields() { errorMessages.clear(); // Reset errors - int rowCount = 1; // Default row count for One-way + rowCount = 1; // Default row count for One-way if (selectedTripType == "Roundtrip") { rowCount = 2; // Fixed for Roundtrip } else if (selectedTripType == "Multitrip") { @@ -579,9 +586,31 @@ class FlightScreenState extends State { if (selectedFrom[i] == null) { errorMessages["from_place_$i"] = "Required"; } + + // if (selectedTo[i] == null) { + // errorMessages["to_place_$i"] = "Required"; + // }else if ( + // selectedFrom[i] == selectedTo[i]) { + // errorMessages["to_place_$i"] = "Change Destination"; + // } + + if (selectedTo[i] == null) { errorMessages["to_place_$i"] = "Required"; + print("Error: to_place_$i -> Required (selectedTo[$i] is null)"); + } else if (selectedFrom[i] == selectedTo[i]) { + + if(selectedTripType == "Roundtrip"){ + errorMessages["to_place_1"] = "Change Destination"; + } + else{ + errorMessages["to_place_$i"] = "Change Destination"; + } + + print("Error: to_place_$i -> Change Destination (selectedFrom[$i] == selectedTo[$i])"); } + + // if (textControllers["_to${i}Controller"]?.text.trim().isEmpty ?? true) { // errorMessages["to_place_$i"] = "Required"; // } @@ -591,8 +620,13 @@ class FlightScreenState extends State { if (textControllers["_time${i}Controller"]?.text.trim().isEmpty ?? true) { errorMessages["time_$i"] = "Required"; } + + } + + + setState(() {}); // Update UI to show error messages return errorMessages @@ -882,6 +916,15 @@ class FlightScreenState extends State { multiTripRowCount = 1; } errorMessages.clear(); + + for (int i = 1; i <= rowCount; i++) { + textControllers["_date${i}Controller"]?.clear(); + textControllers["_time${i}Controller"]?.clear(); + + // Also clear the actual selected data (not just the text in controllers) + selectedFrom[i] = null; // Assuming null means no selection + selectedTo[i] = null; + } }); print( "Updating form data: Flight -> trip_type -> $selectedTripType", @@ -1254,6 +1297,7 @@ class FlightScreenState extends State { isCountryLoading ? Center(child: CircularProgressIndicator()) : DropdownSearch( + enabled: !(selectedTripType == "Roundtrip" && index == 2), selectedItem: selectedFrom[index] != null ? countryMap[selectedFrom[index]] @@ -1273,19 +1317,61 @@ class FlightScreenState extends State { style: TextStyle(fontSize: 12), ), menuProps: MenuProps(backgroundColor: Colors.white), - 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 - ), + 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( @@ -1294,14 +1380,33 @@ class FlightScreenState extends State { contentPadding: EdgeInsets.symmetric(horizontal: 1), ), ), - dropdownBuilder: - (context, selectedItem) => Align( + 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( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), - ), - ), + 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(() { // selectedFrom[index] = countryMap.entries @@ -1315,7 +1420,13 @@ class FlightScreenState extends State { ) .key; - print(selectedFrom[index]); + if(selectedTripType == "Roundtrip"){ + + print('rounfTo${selectedFrom[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedTo[2]= selectedFrom[index]!; + } + }); }, ), @@ -1366,6 +1477,7 @@ class FlightScreenState extends State { isCountryLoading ? Center(child: CircularProgressIndicator()) : DropdownSearch( + enabled: !(selectedTripType == "Roundtrip" && index == 2), selectedItem: selectedTo[index] != null ? countryMap[selectedTo[index]] @@ -1385,19 +1497,61 @@ class FlightScreenState extends State { style: TextStyle(fontSize: 12), ), menuProps: MenuProps(backgroundColor: Colors.white), - 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 - ), + 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( @@ -1406,16 +1560,36 @@ class FlightScreenState extends State { contentPadding: EdgeInsets.symmetric(horizontal: 1), ), ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select Country", - style: TextStyle(fontSize: 12), - ), - ), - onChanged: (String? newValue) { + // 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( @@ -1424,6 +1598,13 @@ class FlightScreenState extends State { .key; print(selectedTo[index]); + + if(selectedTripType == "Roundtrip"){ + + print('rounfTo${selectedTo[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedFrom[2]= selectedTo[index]!; + } }); }, ), @@ -1431,7 +1612,7 @@ class FlightScreenState extends State { ), if (errorMessages["to_place_$index"] != null) ...[ SizedBox(height: 5), // Space before error message - Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), + Text( errorMessages["to_place_$index"]! , style: TextStyle(color: Colors.red, fontSize: 12)), ], ], ), diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index e08c86a..7acd3e7 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -1154,7 +1154,7 @@ class _ForexScreenState extends State { showSearchBox: true, // Enables search functionality searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Search Country...", + hintText: "Search ...", contentPadding: EdgeInsets.symmetric(horizontal: 10), ), ), @@ -1171,7 +1171,7 @@ class _ForexScreenState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Country", + selectedItem ?? "Select ", style: TextStyle(fontSize: 12), ), ), diff --git a/lib/Screens/itnerary/insurance.dart b/lib/Screens/itnerary/insurance.dart index d1a903c..0a23644 100644 --- a/lib/Screens/itnerary/insurance.dart +++ b/lib/Screens/itnerary/insurance.dart @@ -1,3 +1,4 @@ +import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; @@ -39,16 +40,18 @@ class _InsuranceScreenState extends State { final FocusNode _fromFocusNode = FocusNode(); final FocusNode _dateFocusNode = FocusNode(); final FocusNode _commentsFocusNode = FocusNode(); + final FocusNode _nomineeFocusNode = FocusNode(); late TextEditingController _tripTypeController = TextEditingController(); late TextEditingController _startdateController = TextEditingController(); late TextEditingController _endDateController = TextEditingController(); - late TextEditingController _insuranceCommentsController = - TextEditingController(); + late TextEditingController _insuranceCommentsController = TextEditingController(); + late TextEditingController _nomineeController = TextEditingController(); bool _isHotelNameFocused = false; bool _dateFocus = false; bool _commentsFocus = false; + bool _nomineeFocus = false; String? selectedTripType; String? selectedInsuranceType; @@ -61,6 +64,7 @@ class _InsuranceScreenState extends State { "start_date": _startdateController.text, "end_date": _endDateController.text, "comments": _insuranceCommentsController.text, + "nominee_name" : _nomineeController.text, "created_by": widget.loginUser, "updated_by": widget.loginUser, }; @@ -98,12 +102,20 @@ class _InsuranceScreenState extends State { }); }); + _nomineeFocusNode.addListener(() { + setState(() { + _nomineeFocus = _nomineeFocusNode.hasFocus; + }); + }); + _insuranceCommentsController = TextEditingController(text: widget.selectedItem?["comments"] ?? ""); _startdateController = TextEditingController(text: widget.selectedItem?["start_date"] ?? ""); _endDateController = TextEditingController(text: widget.selectedItem?['end_date'] ?? ""); + _nomineeController = + TextEditingController(text: widget.selectedItem?['nominee_name'] ?? ""); // Set the selected value if available if (widget.selectedItem != null && @@ -249,6 +261,7 @@ class _InsuranceScreenState extends State { _tripTypeController.dispose(); _startdateController.dispose(); _insuranceCommentsController.dispose(); + _nomineeController.dispose(); super.dispose(); } @@ -311,7 +324,7 @@ class _InsuranceScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Insurance Type", + "Insurance Type", // not in use style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -370,7 +383,7 @@ class _InsuranceScreenState extends State { child: DropdownButtonFormField( focusNode: _tripTypeFocusNode, // Assign the correct focus node value: selectedInsuranceType, - style: TextStyle(fontSize: 12), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), decoration: InputDecoration( border: InputBorder.none, contentPadding: @@ -396,6 +409,93 @@ class _InsuranceScreenState extends State { ]; } + + List _buildInsuranceTypeDropdown(bool isDesktop) { + // List purposeList = widget.apiData?['insurance_type_of_insurance'] ?? []; + List> purposeList = (widget.apiData?['insurance_type_of_insurance'] as List?) + ?.map((e) => Map.from(e as Map)) + .toList() ?? []; + + // Find selected item object based on key + Map? selectedItem = purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedInsuranceType, + orElse: () => {}, + ); + + return [ + CustomTextFieldWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 35, + width: double.infinity, + child: DropdownSearch>( + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 10), + 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, // 👈 Smaller font size + color: Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: const DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, // No underline + + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select Insurance Type", + style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), + ); + }, + selectedItem: selectedItem!.isNotEmpty ? selectedItem : null, + itemAsString: (item) => item['dropdown_value'] ?? '', + onChanged: purposeList.isNotEmpty + ? (Map? newItem) { + if (newItem != null) { + setState(() { + selectedInsuranceType = newItem['dropdown_key']; + errorMessages.remove("type_of_insurance"); + }); + print("Selected Insurance Type: $selectedInsuranceType"); + } + } + : null, + items: purposeList, + ), + ), + ), + ]; + } + + + List _buildSecondRow(bool isDesktop) { List purposeList = widget.apiData?['insurance_type_of_insurance'] ?? []; @@ -524,47 +624,103 @@ class _InsuranceScreenState extends State { } } + return [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Insurance Type", + "Insurance Type *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: const Color(0xFF575A74), + ), + ), + const SizedBox(height: 5), + + // ▼ Dropdown Wrapper ▼ + CustomTextFieldWrapper( + isFocused: _isHotelNameFocused, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.17 : null, + child: SizedBox( + height: 35, + width: double.infinity, + child: DropdownButtonFormField( + focusNode: _tripTypeFocusNode, + value: selectedInsuranceType, + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), + decoration: const InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), + ), + hint: Text( + "Select ", + style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13), + ), + items: purposeList.map>((item) { + return DropdownMenuItem( + value: item['dropdown_key'], + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins(fontSize: 12), + ), + ); + }).toList(), + onChanged: purposeList.isNotEmpty + ? (String? newValue) { + setState(() { + selectedInsuranceType = newValue; + if ((selectedInsuranceType ?? '').isNotEmpty) { + errorMessages.remove("type_of_insurance"); + } + }); + print("Selected Insurance Type: $selectedInsuranceType"); + } + : null, + ), + ), + ), + ], + ), + + if (isDesktop) + Spacer() + else + SizedBox( + height: 8, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Nominee", style: GoogleFonts.poppins( fontSize: 12, - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _isHotelNameFocused, + isFocused: _nomineeFocus, isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, + width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, child: SizedBox( height: 40, - child: DropdownButtonFormField( - focusNode: _tripTypeFocusNode, // Assign the correct focus node - value: selectedInsuranceType, + child: TextField( + focusNode: _nomineeFocusNode, + controller: _nomineeController, style: TextStyle(fontSize: 12), decoration: InputDecoration( + labelText: "Nominee", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, - contentPadding: - EdgeInsets.symmetric(horizontal: 10), // Proper padding + contentPadding: EdgeInsets.symmetric(vertical: 16), + // contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), ), - onChanged: purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedInsuranceType = newValue; - if (selectedInsuranceType!.isNotEmpty) { - errorMessages.remove("type_of_insurance"); - } - }); - - print(selectedInsuranceType); - } - : null, - - items: dropdownItems, ), ), ), @@ -580,7 +736,7 @@ class _InsuranceScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Start Date", + "Start Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -609,7 +765,7 @@ class _InsuranceScreenState extends State { controller: _startdateController, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( - labelText: "Select Date", + labelText: "Select ", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, @@ -641,7 +797,7 @@ class _InsuranceScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "End Date", + "End Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -682,7 +838,7 @@ class _InsuranceScreenState extends State { controller: _endDateController, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( - labelText: "Select Date", + labelText: "Select ", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, diff --git a/lib/Screens/itnerary/miscellaneous.dart b/lib/Screens/itnerary/miscellaneous.dart index 47ec8a8..93029f3 100644 --- a/lib/Screens/itnerary/miscellaneous.dart +++ b/lib/Screens/itnerary/miscellaneous.dart @@ -114,7 +114,7 @@ class _MiscellaneousScreenState extends State { // Check validation for each field for (String field in requiredFields) { if (data[field] == null || data[field].toString().trim().isEmpty) { - errorMessages[field] = "This field is required"; + errorMessages[field] = "Required"; } } @@ -191,7 +191,7 @@ class _MiscellaneousScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Special Type", + "Special Type *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -266,7 +266,7 @@ class _MiscellaneousScreenState extends State { if (errorMessages["special_request"] != null) ...[ SizedBox(height: 5), // Space before error message Text( - "Select Type", + "Required", style: TextStyle(color: Colors.red, fontSize: 12), ), ], @@ -279,7 +279,7 @@ class _MiscellaneousScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Comments", + "Comments *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/Screens/itnerary/taxi.dart b/lib/Screens/itnerary/taxi.dart index 969ba4e..077563b 100644 --- a/lib/Screens/itnerary/taxi.dart +++ b/lib/Screens/itnerary/taxi.dart @@ -524,7 +524,7 @@ class _TaxiScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "City", + "City *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -562,7 +562,7 @@ class _TaxiScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Pickup Location", + "Pickup Location *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -600,7 +600,7 @@ class _TaxiScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Date", + "Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -648,7 +648,7 @@ class _TaxiScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Time", + "Time *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -700,7 +700,7 @@ class _TaxiScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Comments", + "Comments *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/Screens/itnerary/train.dart b/lib/Screens/itnerary/train.dart index 3f2e5d8..3c7c755 100644 --- a/lib/Screens/itnerary/train.dart +++ b/lib/Screens/itnerary/train.dart @@ -369,7 +369,7 @@ class _TrainScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Train Number", + "Train Number *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -584,7 +584,7 @@ class _TrainScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "From", + "From *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -694,7 +694,7 @@ class _TrainScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "To", + "To *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -767,7 +767,7 @@ class _TrainScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Date", + "Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -816,7 +816,7 @@ class _TrainScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Time", + "Time *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/Screens/itnerary/visa.dart b/lib/Screens/itnerary/visa.dart index b8de533..a507456 100644 --- a/lib/Screens/itnerary/visa.dart +++ b/lib/Screens/itnerary/visa.dart @@ -438,68 +438,12 @@ class _VisaScreenState extends State { selectedPurpose ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null; return [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Type of Visa", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF575A74)), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: _tripTypeFocused, - 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 - value: selectedPurpose, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - border: InputBorder.none, - contentPadding: - EdgeInsets.symmetric(horizontal: 10), // Proper padding - ), - onChanged: purposeList.isNotEmpty - ? (newValue) { - setState(() { - selectedPurpose = newValue; - }); - print( - "Updating form data: Flight -> trip_type -> ${newValue ?? ""}"); - } - : null, - items: dropdownItems, - ), - ), - ), - if (errorMessages["type_of_visa"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - "Required", - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Country", + "Country *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, @@ -509,7 +453,10 @@ class _VisaScreenState extends State { CustomTextFieldWrapper( isFocused: _isHotelNameFocused, isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + // width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + width: isDesktop + ? MediaQuery.of(context).size.width * 0.34 + : MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, child: DropdownSearch( @@ -518,7 +465,7 @@ class _VisaScreenState extends State { showSearchBox: true, // Enables search functionality searchFieldProps: TextFieldProps( decoration: InputDecoration( - hintText: "Search Country...", + hintText: "Search ...", contentPadding: EdgeInsets.symmetric(horizontal: 10), ), ), @@ -536,7 +483,7 @@ class _VisaScreenState extends State { // Center-align selected item alignment: Alignment.centerLeft, child: Text( - selectedItem ?? "Select Country", + selectedItem ?? "Select ", style: TextStyle(fontSize: 12), ), ), @@ -564,6 +511,7 @@ class _VisaScreenState extends State { ], ], ), + if (isDesktop) Spacer() else @@ -574,7 +522,65 @@ class _VisaScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Start Date", + "Type of Visa", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74)), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: _tripTypeFocused, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, + // 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 + value: selectedPurpose, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: + EdgeInsets.symmetric(horizontal: 10), // Proper padding + ), + onChanged: purposeList.isNotEmpty + ? (newValue) { + setState(() { + selectedPurpose = newValue; + }); + print( + "Updating form data: Flight -> trip_type -> ${newValue ?? ""}"); + } + : null, + + items: dropdownItems, + ), + ), + ), + if (errorMessages["type_of_visa"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + "Required", + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + if (isDesktop) + Spacer() + else + SizedBox( + height: 8, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Start Date *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/Screens/plans/list_plans.dart b/lib/Screens/plans/list_plans.dart index 39b3e23..1ffebbf 100644 --- a/lib/Screens/plans/list_plans.dart +++ b/lib/Screens/plans/list_plans.dart @@ -968,7 +968,7 @@ class _ListPlansState extends State { height: 15, ), tooltip: - 'Edit Trip/Plans Details', + 'Edit Trip Details', onPressed: () { Navigator.pop( context, @@ -1222,7 +1222,7 @@ class _ListPlansState extends State { height: 15, ), tooltip: - 'Edit Trip/plan Details', + 'Edit Trip Details', onPressed: () { Navigator.pop( context, diff --git a/lib/Screens/policy/policy_list.dart b/lib/Screens/policy/policy_list.dart index 6c69199..8b0a94c 100644 --- a/lib/Screens/policy/policy_list.dart +++ b/lib/Screens/policy/policy_list.dart @@ -322,7 +322,8 @@ class _PolicyListState extends State { controller: searchController, onChanged: filterPolicy, decoration: InputDecoration( - hintText: "Search for a Policy", + hintText: "Search ...", + hintStyle: TextStyle( fontSize: 12, color: Color(0xFF9E9DBD), @@ -383,7 +384,7 @@ class _PolicyListState extends State { MainAxisSize.min, // Ensures content fits nicely children: [ Text( - "Add New Policy", + "Add Policy", style: GoogleFonts.poppins( fontSize: isDesktop ? 13 : 11, ), @@ -413,7 +414,7 @@ class _PolicyListState extends State { controller: searchController, onChanged: filterPolicy, decoration: InputDecoration( - hintText: "Search for a Policy", + hintText: "Search ...", hintStyle: TextStyle( fontSize: 12, color: Color(0xFF9E9DBD), diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index bb0a6de..8a1b59f 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -580,7 +580,8 @@ class _CreateUserFormDetialsState extends State { // travelDetailsData = [travellerDetailsKey.currentState?.travel_Detials]; travelDetailsData = travellerDetailsKey.currentState?.travel_Detials; - errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages; + // errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages; + print("TRAVEL DETAILS FROM CHILD: $travelDetailsData"); @@ -654,10 +655,24 @@ class _CreateUserFormDetialsState extends State { void handleSubmit() async { print("USR Detail Submit"); // printFormData(); - travelDetailsData = travellerDetailsKey.currentState?.travel_Detials; + + bool isValid = travellerDetailsKey.currentState?.boolValidation() ?? false; + + print("isValid- $isValid"); + if (!isValid) { + print("Validation failed. Please check the inputs."); + setState(() {}); + return; // ❌ STOP execution here if not valid + } + + travelDetailsData = travellerDetailsKey.currentState?.travel_Detials; + + print("travelDetailsData - $travelDetailsData"); - errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages; + + print("travelDetailsData - $travelDetailsData"); + // errorMessagesTravel = travellerDetailsKey.currentState!.errorMessages; print("TRAVEL DETAILS FROM CHILD"); // print("TRAVEL DETAILS FROM CHILD: $travelDetailsData"); @@ -673,8 +688,7 @@ class _CreateUserFormDetialsState extends State { // Map data = userDetials; if (!isValidData(data) && - isValidDataTwo(data) && - errorMessagesTravel.isNotEmpty) { + isValidDataTwo(data) ) { print("USERDETAILS : $userDetials"); print("Validation Failed: Required fields are missing."); setState(() {}); @@ -683,7 +697,7 @@ class _CreateUserFormDetialsState extends State { print("USERDETAILS : $userDetials"); orgId = await getOrgId(); - // createUserData(userDetials); + createUserData(userDetials); } } diff --git a/lib/Screens/userManagement/create_user/office_details.dart b/lib/Screens/userManagement/create_user/office_details.dart index 02f80f7..ac72ac4 100644 --- a/lib/Screens/userManagement/create_user/office_details.dart +++ b/lib/Screens/userManagement/create_user/office_details.dart @@ -391,7 +391,7 @@ class _OfficeDetailsState extends State { buildDelegationStartDateField(isDesktop), Spacer(), // Space after Last Name buildDelegationEndDateField(isDesktop), - SizedBox(width: 15), + SizedBox(width: 16), buildReset(isDesktop), ], ) @@ -1475,7 +1475,7 @@ class _OfficeDetailsState extends State { ), SizedBox(height: 5), CustomTextFieldUserWrapper( - width: isDesktop ? MediaQuery.of(context).size.width * 0.18 : null, + width: isDesktop ? MediaQuery.of(context).size.width * 0.2 : null, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( diff --git a/lib/Screens/userManagement/create_user/personal_details.dart b/lib/Screens/userManagement/create_user/personal_details.dart index 3472508..e4ae82b 100644 --- a/lib/Screens/userManagement/create_user/personal_details.dart +++ b/lib/Screens/userManagement/create_user/personal_details.dart @@ -639,7 +639,7 @@ class PersonalDetailsState extends State { children: [ if (!widget.apiselectedUser) ...[ buildPassword(), - SizedBox(width: 15), + SizedBox(width: MediaQuery.of(context).size.width*0.015), buildRole(), ] else ...[ // TextButton( @@ -736,9 +736,11 @@ class PersonalDetailsState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ buildAddress(), - SizedBox(width: 15), + Spacer(), + // SizedBox(width: 15), buildCountryField(), - SizedBox(width: 15), + Spacer(), + // SizedBox(width: 15), buildPostalCodeField(), ], ) diff --git a/lib/Screens/userManagement/create_user/traveller_details.dart b/lib/Screens/userManagement/create_user/traveller_details.dart index 0eb20c1..a52d0c5 100644 --- a/lib/Screens/userManagement/create_user/traveller_details.dart +++ b/lib/Screens/userManagement/create_user/traveller_details.dart @@ -154,6 +154,31 @@ class TravellerDetailsState extends State { }); } + bool boolValidation() { + final passportText = controllers["passportNumber"]?.text ?? ""; + + if (_selectedTripType == "Indian") { + // Match exactly 8 alphanumeric characters + final isValid = RegExp(r'^[a-zA-Z0-9]{8}$').hasMatch(passportText); + + if (!isValid) { + setState(() { + errorMessages["passport_number"] = + "Enter 8 characters"; + }); + return false; + } else { + setState(() { + errorMessages.remove("passport_number"); + }); + } + } + + return true; + } + + + Future apiCheckDuplicate( String label, String field, @@ -708,7 +733,8 @@ class TravellerDetailsState extends State { Future loadCountryList() async { final newTripType = "2"; - final result = await apiService.fetchFlightsCountryList(newTripType); + final result = await apiService.fetchAirlineList(); + // final result = await apiService.fetchFlightsCountryList(newTripType); print("resultFlight: $result "); @@ -1212,6 +1238,7 @@ class TravellerDetailsState extends State { : (String? newValue) { setState(() { _selectedTripType = newValue; + controllers["passportNumber"]?.clear(); print("_selectedTripType - $_selectedTripType"); }); }, @@ -1254,20 +1281,6 @@ class TravellerDetailsState extends State { ], onChanged: (value) { _clearError("passport_number"); - final regex = RegExp(r'^[a-zA-Z0-9]{0,8}$'); - if (!regex.hasMatch(value)) { - setState(() { - if (_selectedTripType == "Indian") { - errorMessages["passport_number"] = - "Only 8 characters allowed (letters & numbers)"; - } - }); - return; - } else { - setState(() { - errorMessages.remove("passport_number"); - }); - } apiCheckDuplicate( "Passport Number", "passport_number", @@ -1438,23 +1451,42 @@ class TravellerDetailsState extends State { DateTime today = DateTime(now.year, now.month, now.day); // DateTime today = DateTime(now.year now.day, now.month,); - // Parse dateOfIssue safely - DateTime firstDate; + DateTime? validFromDate; + try { - firstDate = DateFormat( - "yyyy-MM-dd", - ).parse(controllers["dateOfIssue"]!.text); + String? fromDateText = controllers["dateOfIssue"]?.text.trim(); + print("dateOfIssue From Text: $fromDateText"); + if (fromDateText!.isNotEmpty) { + validFromDate = DateFormat('dd-MM-yyyy').parseStrict(fromDateText); + print("dateOfIssue Valid From: $validFromDate"); + } } catch (e) { - firstDate = today; // fallback if parsing fails + print("Error parsing valid from date: $e"); } + // Use max(today, validFromDate) as firstDate + // DateTime firstDate = today; + DateTime firstDate = validFromDate ?? today; + + // Parse dateOfIssue safely + // DateTime firstDate; + // try { + // firstDate = DateFormat( + // "yyyy-MM-dd", + // ).parse(controllers["dateOfIssue"]!.text); + // } catch (e) { + // firstDate = today; // fallback if parsing fails + // } + DateTime? pickedDate = await showDatePicker( context: context, - initialDate: - _selectedDateOfExpiry != null && - _selectedDateOfExpiry!.isAfter(firstDate) - ? _selectedDateOfExpiry! - : today, + // initialDate: + // _selectedDateOfExpiry != null && + // _selectedDateOfExpiry!.isAfter(firstDate) + // ? _selectedDateOfExpiry! + // : today, + + initialDate:firstDate, firstDate: firstDate, // firstDate: DateTime(1900), lastDate: DateTime(2100), @@ -1857,6 +1889,7 @@ class TravellerDetailsState extends State { dropdownDecoratorProps: const DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, + hintText: "Select Seat", contentPadding: EdgeInsets.symmetric( horizontal: 10, vertical: 5, @@ -1877,7 +1910,7 @@ class TravellerDetailsState extends State { ); } return Text( - selectedItem['dropdown_value'] ?? '', + selectedItem['dropdown_value'] ?? "Select Seat", style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), ); }, @@ -2027,7 +2060,7 @@ class TravellerDetailsState extends State { vertical: 8, ), child: Text( - item['dropdown_value'] ?? '', + item['dropdown_value'] ?? "Select Seat", style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, @@ -2729,9 +2762,14 @@ class TravellerDetailsState extends State { countryList = apiAirlineCountryData!; print("TestcountryList2 - $countryList"); + // countryMap = { + // for (var country in countryList) + // country['Code'] as String: '${country['City']} - ${country['Airport']}', + // }; + countryMap = { for (var country in countryList) - country['Code'] as String: '${country['City']} - ${country['Airport']}', + country['airline'] as String: '${country['airline_name']}', }; countryCodes = countryMap.keys.toList(); @@ -2777,10 +2815,10 @@ class TravellerDetailsState extends State { ), SizedBox(height: 5), CustomTextFieldUserTravellerWrapper( - width: - widget.isDesktop - ? MediaQuery.of(context).size.width * 0.17 - : null, + // width: + // widget.isDesktop + // ? MediaQuery.of(context).size.width * 0.17 + // : null, isFocused: false, isDesktop: widget.isDesktop, child: SizedBox( @@ -3825,21 +3863,45 @@ class TravellerDetailsState extends State { Future _selectValidUpToDate(BuildContext context) async { DateTime now = DateTime.now(); DateTime today = DateTime(now.year, now.month, now.day); + print("buildVisaValidUpTo "); + print("buildVisaValidUpTo - ${entry["controller_valid_from"].text}"); + // Parse date from notifier if available, else use today DateTime initialDate = today; // Use previously selected date if valid - if (_selectedCheckOutDate != null && - _selectedCheckOutDate!.isAfter(today)) { - initialDate = _selectedCheckOutDate!; + // if (_selectedCheckOutDate != null && + // _selectedCheckOutDate!.isAfter(today)) { + // initialDate = _selectedCheckOutDate!; + // } + + DateTime? validFromDate; + + try { + String fromDateText = entry["controller_valid_from"].text.trim(); + print("Valid From Text: $fromDateText"); + if (fromDateText.isNotEmpty) { + validFromDate = DateFormat('dd-MM-yyyy').parseStrict(fromDateText); + print("Parsed Valid From: $validFromDate"); + } + } catch (e) { + print("Error parsing valid from date: $e"); } + // Use max(today, validFromDate) as firstDate + // DateTime firstDate = today; + DateTime firstDate = validFromDate ?? today; + if (validFromDate != null && validFromDate.isAfter(today)) { + firstDate = validFromDate; + } final pickedDate = await showDatePicker( context: context, // initialDate: initialDate, // firstDate: initialDate, - firstDate: DateTime(1900), + // firstDate: DateTime(1900), + initialDate: firstDate, + firstDate: firstDate, lastDate: DateTime(2100), ); diff --git a/lib/Screens/userManagement/user_List.dart b/lib/Screens/userManagement/user_List.dart index c4097ff..ab9b547 100644 --- a/lib/Screens/userManagement/user_List.dart +++ b/lib/Screens/userManagement/user_List.dart @@ -1137,15 +1137,54 @@ class _UserListScreenState extends State { child: Column( // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + // Expanded( + // child: + // isDesktop + // ? SingleChildScrollView( + // scrollDirection: Axis.vertical, + // child: table, // <-- your existing table + // ) + // : buildMobileCardView(paginatedUser), + // ), + Expanded( child: - isDesktop - ? SingleChildScrollView( - scrollDirection: Axis.vertical, - child: table, // <-- your existing table - ) - : buildMobileCardView(paginatedUser), + isDesktop + ? (searchController.text.isNotEmpty && + filteredUsers.isEmpty + ? Center( + child: Text( + "No users found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, + )) + : (searchController.text.isNotEmpty && + filteredUsers.isEmpty + ? Center( + child: Text( + "No users found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : buildMobileCardView(paginatedUser)), + // child: isDesktop + // ? SingleChildScrollView( + // scrollDirection: Axis.vertical, + // child: table, // <-- your existing table + // ) + // : buildMobileCardView(paginatedPlans), ), + PaginationControls( currentPage: currentPage, itemsPerPage: itemsPerPage, diff --git a/lib/services/apiService.dart b/lib/services/apiService.dart index 1b1155f..272aaa5 100644 --- a/lib/services/apiService.dart +++ b/lib/services/apiService.dart @@ -102,6 +102,41 @@ class ApiService { throw Exception('Failed to load country list'); } } + Future> fetchAirlineList() async { + final String apiUrldata = '$apiUrl/api/getAirlineMaster'; + final token = await getToken(); + + if (token == null) { + throw Exception('Token not found. Please log in.'); + } + + final response = await http.get( + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + try { + final data = json.decode(response.body); + print("Airline - $data"); + + if (!data.containsKey('data') || data['data'] is! List) { + throw Exception( + "Invalid response format: 'data' field is missing or not a List", + ); + } + + return data['data']; + } catch (e) { + throw Exception('Error parsing response: $e'); + } + } else { + throw Exception('Failed to load country list'); + } + } Future> fetchUsers() async { String? ordId = await getOrgId(); diff --git a/lib/widgets/popup_userList_action.dart b/lib/widgets/popup_userList_action.dart index aa66b34..5ff7a85 100644 --- a/lib/widgets/popup_userList_action.dart +++ b/lib/widgets/popup_userList_action.dart @@ -42,7 +42,7 @@ class UserActionsMenu extends StatelessWidget { children: [ GestureDetector( child: Tooltip( - message: 'View User Details', + message: 'View Details', child: Icon(Icons.remove_red_eye, color: Color(0xFF475569), size: 18) ), @@ -61,7 +61,7 @@ class UserActionsMenu extends StatelessWidget { SizedBox(width: 8), GestureDetector( child: Tooltip( - message: 'Edit User Details', + message: 'Edit Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, diff --git a/pubspec.lock b/pubspec.lock index e4884cf..94a6c9d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.12.0" bcrypt: dependency: "direct main" description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.2" ffi: dependency: transitive description: @@ -465,18 +465,18 @@ packages: dependency: "direct main" description: name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.20.2" + version: "0.19.0" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: @@ -1014,10 +1014,10 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "14.3.1" vsc_quill_delta_to_html: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 24d8c13..cbf239d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: -# sdk: ^3.6.1 + # sdk: ^3.6.1 sdk: ^3.7.2 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -44,7 +44,7 @@ dependencies: responsive_builder: ^0.7.1 shared_preferences: ^2.5.2 easy_stepper: ^0.8.5+1 - intl: ^0.20.2 + intl: ^0.19.0 dropdown_search: ^5.0.6 file_picker: ^10.0.0 bcrypt: ^1.1.3 @@ -134,4 +134,4 @@ flutter: # weight: 700 # # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package + # see https://flutter.dev/to/font-from-packagej \ No newline at end of file