From e33af3cd8a50095a3970c137164832bed86887fa Mon Sep 17 00:00:00 2001 From: venbaittech Date: Fri, 20 Jun 2025 14:44:50 +0530 Subject: [PATCH] travelAgentLst --- lib/Screens/allTrips/travel_agent_list.dart | 4 +- .../authentication/login/login_widget.dart | 64 +- lib/Screens/itnerary/accomodations.dart | 16 +- lib/Screens/itnerary/flights.dart | 780 ++++++++++++------ lib/Screens/itnerary/forex.dart | 131 +-- lib/Screens/itnerary/insurance.dart | 151 +++- .../forexDetails.dart | 0 .../{forex => perdiem_amount}/forex_list.dart | 0 lib/Screens/plans/create_plans.dart | 260 +++++- lib/app.dart | 4 +- lib/config/apiUrl.dart | 4 +- lib/routes/custom_router.dart | 12 +- lib/widgets/custom_text_field.dart | 27 +- 13 files changed, 1013 insertions(+), 440 deletions(-) rename lib/Screens/{forex => perdiem_amount}/forexDetails.dart (100%) rename lib/Screens/{forex => perdiem_amount}/forex_list.dart (100%) diff --git a/lib/Screens/allTrips/travel_agent_list.dart b/lib/Screens/allTrips/travel_agent_list.dart index ef90d8e..66243f3 100644 --- a/lib/Screens/allTrips/travel_agent_list.dart +++ b/lib/Screens/allTrips/travel_agent_list.dart @@ -216,8 +216,8 @@ class _TravelAgentListPlansState extends State { if (response.statusCode == 200) { final data = json.decode(response.body); - List plansJson = []; - // List plansJson = data['data']; + // List plansJson = []; + List plansJson = data['data']; return plansJson.map((json) => Plan.fromJson(json)).toList(); } else { throw Exception('Failed to load plans'); diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index 783cbc8..400c647 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -30,6 +30,8 @@ class _LoginWidgetState extends State { final ApiService apiService = ApiService(); bool _moved = false; + bool _isLoading = false; + final _formKey = GlobalKey(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); @@ -103,6 +105,10 @@ class _LoginWidgetState extends State { Future _login(BuildContext context) async { if (_formKey.currentState!.validate()) { + setState(() { + _isLoading = true; + }); + const String url = '$apiUrl/auth/login'; try { @@ -193,6 +199,10 @@ class _LoginWidgetState extends State { fontSize: 16.0, webBgColor: "linear-gradient(to right, #dc1c13, #dc1c13)", ); + } finally { + setState(() { + _isLoading = false; + }); } } } @@ -619,7 +629,13 @@ class _LoginWidgetState extends State { children: [ Expanded( child: ElevatedButton( - onPressed: () => _login(context), + // onPressed: () => _login(context), + onPressed: + _isLoading + ? null + : () => _login( + context, + ), // disable when loading style: ElevatedButton.styleFrom( backgroundColor: Color( 0xFF12B24B, @@ -639,23 +655,35 @@ class _LoginWidgetState extends State { horizontal: 24, vertical: 5, ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Sign In", - style: GoogleFonts.poppins( - fontWeight: FontWeight.w800, - fontSize: 13.5, - ), - ), - SizedBox(width: 3), - Icon( - Icons.arrow_forward_sharp, - color: Colors.white, - ), - ], - ), + child: + _isLoading + ? SizedBox( + height: 20, + width: 20, + child: + CircularProgressIndicator( + color: Colors.white, + strokeWidth: 2, + ), + ) + : Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Sign In", + style: GoogleFonts.poppins( + fontWeight: + FontWeight.w800, + fontSize: 13.5, + ), + ), + SizedBox(width: 3), + Icon( + Icons.arrow_forward_sharp, + color: Colors.white, + ), + ], + ), ), ), ), diff --git a/lib/Screens/itnerary/accomodations.dart b/lib/Screens/itnerary/accomodations.dart index 0cc5201..6187eb9 100644 --- a/lib/Screens/itnerary/accomodations.dart +++ b/lib/Screens/itnerary/accomodations.dart @@ -763,7 +763,10 @@ class _AccomodationScreenState extends State { child: SizedBox( height: 40, child: GestureDetector( - onTap: () => _selectCheckInDate(context), + onTap: () { + _checkInFocusNode.requestFocus(); + _selectCheckInDate(context); + }, child: AbsorbPointer( child: TextField( focusNode: _checkInFocusNode, @@ -816,6 +819,7 @@ class _AccomodationScreenState extends State { height: 40, child: GestureDetector( onTap: () { + _checkInTimeFocusNode.requestFocus(); _checkInTimeController.text = ""; _selectCheckInTime(context); }, @@ -870,7 +874,10 @@ class _AccomodationScreenState extends State { child: SizedBox( height: 40, child: GestureDetector( - onTap: () => _selectCheckOutDate(context), + onTap: () { + _checkOutFocusNode.requestFocus(); + _selectCheckOutDate(context); + }, child: AbsorbPointer( child: TextField( focusNode: _checkOutFocusNode, @@ -922,7 +929,10 @@ class _AccomodationScreenState extends State { child: SizedBox( height: 40, child: GestureDetector( - onTap: () => _selectCheckOutTime(context), + onTap: () { + _checkOutTimeFocusNode.requestFocus(); + _selectCheckOutTime(context); + }, child: AbsorbPointer( child: TextField( focusNode: _checkOutTimeFocusNode, diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index 12ec138..7e9d9b6 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -5,6 +5,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; +import '../../utils/auth_utils.dart'; import '../../widgets/custom_radio_button.dart'; import '../../widgets/custom_text_field.dart'; import '../../widgets/custom_text_itnerary_sub.dart'; @@ -64,6 +65,9 @@ class FlightScreenState extends State { String? selectedvisa_available; int multiTripRowCount = 1; + // Color? layoutColor; + Color layoutColor = Colors.grey; + List dataHeader = [ "_tripType", "_class", @@ -89,7 +93,9 @@ class FlightScreenState extends State { @override void initState() { super.initState(); - + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); print("TripType - ${widget.tripType}"); // final newTripType = widget.tripTypeNotifier.value; @@ -280,6 +286,24 @@ class FlightScreenState extends State { return 1; // Default for Oneway } + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + + // setState(() { + // layoutColor = + // layoutString != null + // ? Color(int.parse(layoutString)) + // : Colors.redAccent; + // }); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + }); + } + void _initializeFields() { print("_initializeFields-----------------"); @@ -982,7 +1006,9 @@ class FlightScreenState extends State { return [ CustomTextFieldWrapper( // isFocused: _tripTypeFocused, - isFocused: focusStates["_tripType1Focused"] ?? false, + // isFocused: focusStates["_tripType1Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, child: SizedBox( @@ -1008,8 +1034,35 @@ class FlightScreenState extends State { .toList(), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1), + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_tripType1Focused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_tripType1Focused"] ?? 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, + ), ), ), onChanged: (newValue) { @@ -1427,7 +1480,9 @@ class FlightScreenState extends State { SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( // isFocused: _fromFocus, - isFocused: focusStates["_from${index}Focused"] ?? false, + // isFocused: focusStates["_from${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, isDesktop: isDesktop, child: SizedBox( @@ -1548,9 +1603,38 @@ class FlightScreenState extends State { items: countryMap.values.toList(), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, + 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: 1, + horizontal: 10, + vertical: 5, ), ), ), @@ -1652,160 +1736,214 @@ class FlightScreenState extends State { ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_to${index}Focused"] ?? false, + // 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()) - : 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, + : 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), ), - ), - 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, + menuProps: MenuProps( + backgroundColor: Colors.white, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + 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: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), + 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( - code, + airport, style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, ), ), ], ), - 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, + ), ), - ); - }, - // 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: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1), + ), + + // 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]!; + } + }); + }, ), ), - - // 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]!; - } - }); - }, ), ), ), @@ -1885,74 +2023,119 @@ class FlightScreenState extends State { ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_class${index}Focused"] ?? false, + // isFocused: focusStates["_class${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, child: SizedBox( - height: 35, + height: 40, width: double.infinity, - child: DropdownSearch>( - items: purposeList.cast>(), - selectedItem: purposeList.firstWhere( - (item) => item['dropdown_key'] == selectedClasses[index], - 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: 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>(), + selectedItem: purposeList.firstWhere( + (item) => item['dropdown_key'] == selectedClasses[index], + 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["_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, + ), ), - child: Text( - item['dropdown_value'] ?? '', + ), + 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, ), - ), - ); - }, - ), - dropdownDecoratorProps: const DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + ); + }, + onChanged: + purposeList.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedClasses[index] = + newValue?['dropdown_key']; + print( + "Selected Class: ${selectedClasses[index]}", + ); + }); + } + : null, ), ), - 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) { - setState(() { - selectedClasses[index] = newValue?['dropdown_key']; - print("Selected Class: ${selectedClasses[index]}"); - }); - } - : null, ), ), ), @@ -1987,7 +2170,10 @@ class FlightScreenState extends State { child: SizedBox( height: 40, child: GestureDetector( - onTap: () => _selectCheckOutDate(context), + onTap: () { + focusNodes["_date${index}FocusNode"]?.requestFocus(); + _selectCheckOutDate(context); + }, child: AbsorbPointer( child: TextField( focusNode: focusNodes["_date${index}FocusNode"], @@ -1995,13 +2181,44 @@ class FlightScreenState extends State { controller: textControllers["_date${index}Controller"], readOnly: true, style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( + decoration: InputDecoration( labelText: "Select Date", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + labelStyle: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon( + // 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, @@ -2042,6 +2259,7 @@ class FlightScreenState extends State { height: 40, child: GestureDetector( onTap: () { + focusNodes["_time${index}FocusNode"]?.requestFocus(); textControllers["_time${index}Controller"]?.text = ""; _clearError("time_$index"); // validateTimeDifference(index); @@ -2214,74 +2432,116 @@ class FlightScreenState extends State { SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( // use same wrapper as class - isFocused: focusStates["_visa1Focused"] ?? false, + // isFocused: focusStates["_visa1Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, child: SizedBox( height: 35, width: double.infinity, - 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: 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, + ), ), - child: Text( - item['dropdown_value'] ?? '', + ), + 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, ), - ), - ); - }, - ), - dropdownDecoratorProps: const DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + ); + }, + onChanged: + visa_available.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedvisa_available = + newValue?['dropdown_key']; + print("Selected Visa: $selectedvisa_available"); + }); + } + : null, ), ), - 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, ), ), ), diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index b880436..5a8c4f7 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -135,7 +135,6 @@ class _ForexScreenState extends State { String? selectedQuotedAmount; int? selectedCashPercent; int? selectedCardPercent; - bool userEdited = false; Map get forexData { @@ -399,7 +398,10 @@ class _ForexScreenState extends State { focusStates[field] = false; } } - print("textControllers - $textControllers"); + + print("Focus States KeysII: ${focusStates.keys.toList()}"); + print("Focus Nodes KeysII: ${focusNodes.keys.toList()}"); + print("Text Controllers KeysII: ${textControllers.keys.toList()}"); // Add focus listeners focusNodes.forEach((key, focusNode) { @@ -1347,64 +1349,85 @@ class _ForexScreenState extends State { // ), // ), CustomTextFieldForexWrapper( - isFocused: focusStates["_countries"] ?? false, + isFocused: focusStates["_countriesFocused"] ?? false, isDesktop: isDesktop, child: SizedBox( height: 40, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250), - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: - (context, item, isSelected) => Container( - color: Colors.white, - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ), - onChanged: (String? newValue) { + child: Focus( + focusNode: focusNodes["_countriesFocusNode"], + onFocusChange: (hasFocus) { setState(() { - // Find the country_code based on selected country_name - selectedCountry = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - _onCountryChanged(selectedCountry); + focusStates["_countriesFocused"] = hasFocus; }); }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_countriesFocusNode"]?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250), + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => Container( + color: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + ), + ), + ), + ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(horizontal: 1), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedCountry = + countryMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + _onCountryChanged(selectedCountry); + }); + }, + ), + ), ), ), ), diff --git a/lib/Screens/itnerary/insurance.dart b/lib/Screens/itnerary/insurance.dart index 3784e7a..3e19de0 100644 --- a/lib/Screens/itnerary/insurance.dart +++ b/lib/Screens/itnerary/insurance.dart @@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; +import '../../utils/auth_utils.dart'; import '../../widgets/custom_text_field.dart'; import '../../widgets/custom_text_itnerary_sub.dart'; @@ -53,6 +54,8 @@ class _InsuranceScreenState extends State { late TextEditingController _nomineerelationController = TextEditingController(); + Color layoutColor = Colors.grey; + bool _isHotelNameFocused = false; bool _startDateFocus = false; bool _endDateFocus = false; @@ -63,6 +66,18 @@ class _InsuranceScreenState extends State { String? selectedInsuranceType; Map errorMessages = {}; + Map focusNodes = {}; + Map focusStates = {}; + + List dataHeader = [ + "type_of_insurance", + "start_date", + "end_date", + "comments", + "nominee_name", + "nominee_dob", + "nominee_relationship", + ]; Map get InsuranceData { Map data = { @@ -94,33 +109,27 @@ class _InsuranceScreenState extends State { @override void initState() { super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); + focusNodes.clear(); + focusStates.clear(); - _hotelNameFocusNode.addListener(() { - setState(() { - _isHotelNameFocused = _hotelNameFocusNode.hasFocus; - }); - }); - _endDateFocusNode.addListener(() { - setState(() { - _endDateFocus = _endDateFocusNode.hasFocus; - }); - }); - _startDateFocusNode.addListener(() { - setState(() { - _startDateFocus = _startDateFocusNode.hasFocus; - }); - }); - _commentsFocusNode.addListener(() { - setState(() { - _commentsFocus = _commentsFocusNode.hasFocus; - }); - }); + // Initialize fields dynamically + for (var field in dataHeader) { + focusNodes["${field}FocusNode"] = FocusNode(); + focusStates["${field}Focused"] = false; + } - _nomineeFocusNode.addListener(() { - setState(() { - _nomineeFocus = _nomineeFocusNode.hasFocus; + for (var key in focusNodes.keys) { + _addFocusListener(focusNodes[key]!, (focus) { + setState(() { + focusStates[key.replaceFirst("FocusNode", "Focused")] = focus; + }); }); - }); + } + print("Focus Nodes Keys: ${focusNodes.keys.toList()}"); + print("Focus States Keys: ${focusStates.keys.toList()}"); _insuranceCommentsController = TextEditingController( text: widget.selectedItem?["comments"] ?? "", @@ -181,6 +190,16 @@ class _InsuranceScreenState extends State { }); } + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + }); + } + Map getFlightTripDateRange( List> flightData, ) { @@ -285,6 +304,11 @@ class _InsuranceScreenState extends State { @override void dispose() { + // Dispose all dynamically created FocusNodes + for (var node in focusNodes.values) { + node.dispose(); + } + _tripTypeFocusNode.dispose(); _tripTypeController.dispose(); _startDateController.dispose(); @@ -769,7 +793,9 @@ class _InsuranceScreenState extends State { // ), // ▼ Dropdown Wrapper ▼ CustomTextFieldWrapper( - isFocused: _isHotelNameFocused, + // isFocused: _isHotelNameFocused, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null, child: SizedBox( @@ -802,14 +828,45 @@ class _InsuranceScreenState extends State { ); }, ), - dropdownDecoratorProps: const DropDownDecoratorProps( + dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( + // border: InputBorder.none, // No underline + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["type_of_insuranceFocusNode"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["type_of_insuranceFocusNode"] ?? 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: 10, + vertical: 5, ), ), + // dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 10, + // ), + // ), ), dropdownBuilder: (context, selectedItem) { if (selectedItem == null || selectedItem.isEmpty) { @@ -897,13 +954,15 @@ class _InsuranceScreenState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _startDateFocus, + // isFocused: _startDateFocus, + isFocused: focusStates["start_dateFocused"] ?? false, isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, child: SizedBox( height: 40, child: GestureDetector( onTap: () async { + focusNodes["start_dateFocusNode"]?.requestFocus(); await _selectCheckOutDate(context); if (_startDateController.text.isNotEmpty) { setState(() { @@ -915,7 +974,8 @@ class _InsuranceScreenState extends State { }, child: AbsorbPointer( child: TextField( - focusNode: _startDateFocusNode, + // focusNode: _startDateFocusNode, + focusNode: focusNodes["start_dateFocusNode"], controller: _startDateController, readOnly: true, style: const TextStyle(fontSize: 12), @@ -956,13 +1016,14 @@ class _InsuranceScreenState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _endDateFocus, + isFocused: focusStates["end_dateFocused"] ?? false, isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, child: SizedBox( height: 40, child: GestureDetector( onTap: () async { + focusNodes["end_dateFocusNode"]?.requestFocus(); await _selectEndCheckOutDate(context); if (_endDateController.text.isNotEmpty) { @@ -985,7 +1046,8 @@ class _InsuranceScreenState extends State { }, child: AbsorbPointer( child: TextField( - focusNode: _endDateFocusNode, + // focusNode: _endDateFocusNode, + focusNode: focusNodes["end_dateFocusNode"], controller: _endDateController, readOnly: true, style: const TextStyle(fontSize: 12), @@ -1108,7 +1170,8 @@ class _InsuranceScreenState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _nomineeFocus, + // isFocused: _nomineeFocus, + isFocused: focusStates["nominee_nameFocused"] ?? false, isDesktop: isDesktop, // width: isDesktop ? MediaQuery.of(context).size.width * 0.15 : null, width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null, @@ -1116,7 +1179,9 @@ class _InsuranceScreenState extends State { child: SizedBox( height: 40, child: TextField( - focusNode: _nomineeFocusNode, + focusNode: focusNodes["nominee_nameFocusNode"], + + // focusNode: _nomineeFocusNode, controller: _nomineeController, style: TextStyle(fontSize: 12), decoration: InputDecoration( @@ -1150,7 +1215,7 @@ class _InsuranceScreenState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _startDateFocus, + isFocused: focusStates["nominee_dobFocused"] ?? false, isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, // width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, @@ -1158,6 +1223,7 @@ class _InsuranceScreenState extends State { height: 40, child: GestureDetector( onTap: () async { + focusNodes["nominee_dobFocusNode"]?.requestFocus(); await _selectCheckDOBOutDate(context); // await _selectDateOfBirth(context); if (_dateOfBirthController.text.isNotEmpty) { @@ -1170,7 +1236,7 @@ class _InsuranceScreenState extends State { }, child: AbsorbPointer( child: TextField( - focusNode: _startDateFocusNode, + focusNode: focusNodes["nominee_dobFocusNode"], controller: _dateOfBirthController, readOnly: true, style: const TextStyle(fontSize: 12), @@ -1213,7 +1279,7 @@ class _InsuranceScreenState extends State { // CustomTextFieldWrapper( - isFocused: false, + isFocused: focusStates["nominee_relationshipFocused"] ?? false, isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.16 : null, // width: isDesktop ? MediaQuery.of(context).size.width * 0.31 : null, @@ -1221,7 +1287,7 @@ class _InsuranceScreenState extends State { child: SizedBox( height: 40, child: TextField( - // focusNode: _nomineeFocusNode, + focusNode: focusNodes["nominee_relationshipFocusNode"], controller: _nomineerelationController, style: TextStyle(fontSize: 12), decoration: InputDecoration( @@ -1260,7 +1326,9 @@ class _InsuranceScreenState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: _commentsFocus, // Dropdown doesn't use focus + isFocused: + focusStates["commentsFocused"] ?? + false, // Dropdown doesn't use focus isDesktop: isDesktop, width: isDesktop @@ -1269,7 +1337,8 @@ class _InsuranceScreenState extends State { child: SizedBox( height: 40, child: TextField( - focusNode: _commentsFocusNode, + // focusNode: _commentsFocusNode, + focusNode: focusNodes["commentsFocusNode"], controller: _insuranceCommentsController, style: TextStyle(fontSize: 12), decoration: InputDecoration( diff --git a/lib/Screens/forex/forexDetails.dart b/lib/Screens/perdiem_amount/forexDetails.dart similarity index 100% rename from lib/Screens/forex/forexDetails.dart rename to lib/Screens/perdiem_amount/forexDetails.dart diff --git a/lib/Screens/forex/forex_list.dart b/lib/Screens/perdiem_amount/forex_list.dart similarity index 100% rename from lib/Screens/forex/forex_list.dart rename to lib/Screens/perdiem_amount/forex_list.dart diff --git a/lib/Screens/plans/create_plans.dart b/lib/Screens/plans/create_plans.dart index 5e23763..8218b5d 100644 --- a/lib/Screens/plans/create_plans.dart +++ b/lib/Screens/plans/create_plans.dart @@ -389,6 +389,8 @@ class CreateNewPlansState extends State { // bool _isdescriptionFocused = false; // bool _isTripTitleFocused = false; + Color? layoutColor; + late String _selectedOption = "Option 1"; // late String? _selectedIsBillable = "Billable"; @@ -537,6 +539,9 @@ class CreateNewPlansState extends State { void initState() { super.initState(); print("approverStatus - ${widget.approverStatus}"); + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); if (widget.approverStatus == "Approval pending") { print("Status approver - Approval Pending"); @@ -580,6 +585,17 @@ class CreateNewPlansState extends State { handleUpdateData(); } + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + }); + } + @override void dispose() { for (var node in focusNodes.values) { @@ -1332,22 +1348,22 @@ class CreateNewPlansState extends State { if (response.statusCode == 200) { print("Plan submitted successfully!"); print("Response: ${response.body}"); - - final currentUri = - GoRouterState.of( - context, - ).uri.toString(); // ✅ safer than `.location` - print("currentUri - $currentUri"); - - if (currentUri == "/allTrips/trips") { - context.go('/listAllPlan'); - } else if (currentUri == "/createPlan") { - context.go('/listPlan'); - } else { - widget.isApprover - ? context.go('/approvallist') - : context.go('/listPlan'); - } + // + // final currentUri = + // GoRouterState.of( + // context, + // ).uri.toString(); // ✅ safer than `.location` + // print("currentUri - $currentUri"); + // + // if (currentUri == "/allTrips/trips") { + // context.go('/listAllPlan'); + // } else if (currentUri == "/createPlan") { + // context.go('/listPlan'); + // } else { + // widget.isApprover + // ? context.go('/approvallist') + // : context.go('/listPlan'); + // } } else { print("Failed to submit plan. Status: ${response.statusCode}"); print("Error: ${response.body}"); @@ -1804,10 +1820,13 @@ class CreateNewPlansState extends State { SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: focusStates["trip_typeFocused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + // isFocused: focusStates["trip_typeFocused"] ?? false, isDesktop: widget.isDesktop, child: SizedBox( height: 35, + // width: double.infinity, width: double.infinity, child: Focus( focusNode: focusNodes["trip_typeFocusNode"], @@ -1825,7 +1844,9 @@ class CreateNewPlansState extends State { popupProps: PopupProps.menu( showSearchBox: false, // Optionally enable search fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { return Padding( padding: const EdgeInsets.symmetric( @@ -1842,16 +1863,42 @@ class CreateNewPlansState extends State { ); }, ), - dropdownDecoratorProps: const DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, // No underline - contentPadding: EdgeInsets.symmetric( + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, // No underline + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["trip_typeFocused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["trip_typeFocused"] ?? 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( @@ -1951,7 +1998,9 @@ class CreateNewPlansState extends State { SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: focusStates["is_billableFocused"] ?? false, + // isFocused: focusStates["is_billableFocused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), width: widget.isDesktop ? MediaQuery.of(context).size.width * 0.2 @@ -1994,10 +2043,33 @@ class CreateNewPlansState extends State { ); }, ), - dropdownDecoratorProps: const DropDownDecoratorProps( + dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["is_billableFocused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["is_billableFocused"] ?? 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, ), @@ -2225,9 +2297,10 @@ class CreateNewPlansState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: - focusStates["cost_center_idFocused"] ?? - false, // Dropdown doesn't use focus + // isFocused: focusStates["cost_center_idFocused"] ?? + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: widget.isDesktop, child: SizedBox( height: 35, @@ -2242,6 +2315,7 @@ class CreateNewPlansState extends State { ) : Focus( focusNode: focusNodes["cost_center_idFocusNode"], + onFocusChange: (hasFocus) { setState(() { focusStates["cost_center_idFocused"] = hasFocus; @@ -2295,7 +2369,35 @@ class CreateNewPlansState extends State { items: costCenterMap.values.toList(), // just names dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["cost_center_idFocused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["cost_center_idFocused"] ?? + 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: 1), contentPadding: EdgeInsets.symmetric( horizontal: 10, @@ -2400,7 +2502,9 @@ class CreateNewPlansState extends State { isDesktop ? MediaQuery.of(context).size.width * 0.2 : MediaQuery.of(context).size.width * 0.88, - isFocused: focusStates["purpose_of_travelFocused"] ?? false, + // isFocused: focusStates["purpose_of_travelFocused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: widget.isDesktop, child: SizedBox( @@ -2472,11 +2576,39 @@ class CreateNewPlansState extends State { ), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["purpose_of_travelFocused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["purpose_of_travelFocused"] ?? + 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, ), - border: InputBorder.none, ), ), onChanged: @@ -2582,7 +2714,9 @@ class CreateNewPlansState extends State { ), SizedBox(height: 5), CustomTextFieldWrapper( - isFocused: focusStates["functional_departmentFocused"] ?? false, + // isFocused: focusStates["functional_departmentFocused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: widget.isDesktop, width: isDesktop @@ -2666,7 +2800,35 @@ class CreateNewPlansState extends State { horizontal: 10, vertical: 5, ), - border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["functional_departmentFocused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["functional_departmentFocused"] ?? + false) + ? layoutColor! + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor!, + width: 1, + ), + ), ), ), onChanged: @@ -2737,8 +2899,9 @@ class CreateNewPlansState extends State { return [ CustomTextFieldWrapper( - isFocused: focusStates["trip_plannedFocused"] ?? false, - + // isFocused: focusStates["trip_plannedFocused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, layoutColor: widget.layoutColor, child: SizedBox( @@ -2766,6 +2929,7 @@ class CreateNewPlansState extends State { popupProps: PopupProps.menu( showSearchBox: false, menuProps: const MenuProps(backgroundColor: Colors.white), + constraints: BoxConstraints(maxHeight: 100), itemBuilder: (context, item, isSelected) => Padding( @@ -2781,7 +2945,31 @@ class CreateNewPlansState extends State { ), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["trip_typeFocused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["trip_plannedFocused"] ?? 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, diff --git a/lib/app.dart b/lib/app.dart index f89ee60..3839acd 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; +// import 'package:flutter/rendering.dart'; import 'dart:html' as html; import 'package:frontend/config/apiUrl.dart'; // 1 newly added import 'package:frontend/services/apiService.dart'; @@ -31,7 +31,7 @@ class _MyAppState extends State { @override void initState() { super.initState(); - SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here + // SemanticsBinding.instance.ensureSemantics(); // ✅ Safe here if (kIsWeb) { final uri = Uri.parse(html.window.location.href); print("URI - $uri"); diff --git a/lib/config/apiUrl.dart b/lib/config/apiUrl.dart index eb751b8..7139bea 100644 --- a/lib/config/apiUrl.dart +++ b/lib/config/apiUrl.dart @@ -1,3 +1,3 @@ //api url -const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be'; -// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be'; +// const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be'; +const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be'; diff --git a/lib/routes/custom_router.dart b/lib/routes/custom_router.dart index 5e72184..6bc6568 100644 --- a/lib/routes/custom_router.dart +++ b/lib/routes/custom_router.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:frontend/Screens/authentication/login/login_page.dart'; import 'package:frontend/Screens/authentication/loginPage1.dart'; import 'package:frontend/Screens/dashboard/home_page.dart'; -import 'package:frontend/Screens/forex/forex_list.dart'; import 'package:frontend/Screens/myTemplates/templatesList.dart'; import 'package:frontend/Screens/organization/orgSetup.dart'; import 'package:frontend/Screens/organization/org_List.dart'; @@ -26,6 +25,7 @@ import '../Screens/group/groupList.dart'; import '../Screens/myTemplates/template.dart'; import '../Screens/myTemplates/templateForex.dart'; import '../Screens/myTemplates/templateTest.dart'; +import '../Screens/perdiem_amount/forex_list.dart'; import '../Screens/userManagement/create_user/create_user.dart'; import '../Screens/department/department_list.dart'; import '../Screens/costCenter/costCenter_list.dart'; @@ -150,10 +150,7 @@ final GoRouter router = GoRouter( pageBuilder: (context, state) => MaterialPage(child: Group.fromState(state)), ), - GoRoute( - path: '/report', - builder: (context, state) => ReportList(), - ), + GoRoute(path: '/report', builder: (context, state) => ReportList()), GoRoute( path: '/advancePurchase', builder: (context, state) => AdvancePurchase(), @@ -162,10 +159,7 @@ final GoRouter router = GoRouter( path: '/misservicesAnalysis', builder: (context, state) => ServicesAnalysis(), ), - GoRoute( - path: '/misAirReport', - builder: (context, state) => MISair(), - ), + GoRoute(path: '/misAirReport', builder: (context, state) => MISair()), GoRoute( path: '/misHotelReport', builder: (context, state) => MIShotel(), diff --git a/lib/widgets/custom_text_field.dart b/lib/widgets/custom_text_field.dart index 1aeed1c..eebc4c7 100644 --- a/lib/widgets/custom_text_field.dart +++ b/lib/widgets/custom_text_field.dart @@ -85,19 +85,20 @@ class _CustomTextFieldWrapperState extends State { // color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6), width: widget.isFocused ? 1.0 : 0.5, ), - // boxShadow: widget.isFocused - // ? [ - // BoxShadow( - // // color: Color.fromRGBO(120, 180, 252, 0.3), - // // color: widget.isFocused - // // ? (widget.layoutColor ?? Colors.red).withAlpha(204) - // // : Color(0xFFF5F5F5), - // blurRadius: 10, - // spreadRadius: 1, - // offset: Offset(0, 4), - // ), - // ] - // : [], + // boxShadow: + // widget.isFocused + // ? [ + // BoxShadow( + // color: widget.isFocused ? layoutColor! : Color(0xFFD6D5E6), + // // color: widget.isFocused + // // ? (widget.layoutColor ?? Colors.red).withAlpha(204) + // // : Color(0xFFF5F5F5), + // blurRadius: 10, + // spreadRadius: 1, + // offset: Offset(0, 4), + // ), + // ] + // : [], ), child: widget.child, );