From f029c8b9b61bcb8bf564bfb0bda7e5fc1cdc439d Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Sat, 21 Jun 2025 13:44:21 +0530 Subject: [PATCH 1/2] merge with out code --- lib/Screens/costCenter/costCenterDetails.dart | 46 +- lib/Screens/department/departmentDetails.dart | 46 +- lib/Screens/forex/forexDetails.dart | 174 +- lib/Screens/hotels/hotelsDetails.dart | 174 +- lib/Screens/myTemplates/template.dart | 64 +- lib/Screens/myTemplates/templatesList.dart | 30 +- lib/Screens/organization/mailSettings.dart | 41 +- lib/Screens/policy/policy.dart | 22 +- lib/Screens/policy/policyCriteria.dart | 1965 +++++++++++++---- lib/Screens/reports/advancePurchase.dart | 174 +- lib/Screens/reports/guestHouse.dart | 170 +- lib/Screens/reports/misAir.dart | 103 +- lib/Screens/reports/misForex.dart | 103 +- lib/Screens/reports/misHotel.dart | 193 +- lib/Screens/reports/servicesAnalysis.dart | 147 +- lib/Screens/traveller/travellerDetails.dart | 54 +- .../createTravelAgent.dart | 1785 +++++++++++++++ .../listTravelAgent.dart | 1279 +++++++++++ .../personalDetailsTravelAgent.dart | 1833 +++++++++++++++ .../create_user/traveller_details.dart | 2 +- lib/Screens/userManagement/user_List.dart | 108 +- lib/routes/custom_router.dart | 10 + lib/routes/organizationSetting.dart | 6 + lib/services/apiService.dart | 97 +- lib/widgets/custom_text_forex.dart | 28 +- lib/widgets/popup_travelAgentList_action.dart | 88 + 26 files changed, 7896 insertions(+), 846 deletions(-) create mode 100644 lib/Screens/userManagement/create_traveller_agent/createTravelAgent.dart create mode 100644 lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart create mode 100644 lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart create mode 100644 lib/widgets/popup_travelAgentList_action.dart diff --git a/lib/Screens/costCenter/costCenterDetails.dart b/lib/Screens/costCenter/costCenterDetails.dart index 12d24d3..697e3c8 100644 --- a/lib/Screens/costCenter/costCenterDetails.dart +++ b/lib/Screens/costCenter/costCenterDetails.dart @@ -36,11 +36,12 @@ class CostCenterDataState extends State { final ApiService apiService = ApiService(); Map? apiData; - final Map focusNodes = { - "name": FocusNode(), - "description": FocusNode(), - }; - + // final Map focusNodes = { + // "name": FocusNode(), + // "description": FocusNode(), + // }; + Map focusNodes = {}; + Map focusStates = {}; final Map controllers = {}; Map errorMessages = {}; @@ -70,6 +71,15 @@ class CostCenterDataState extends State { apiData = null; for (var field in dataHeader) { controllers[field] = TextEditingController(); + focusNodes["${field}FocusNode"] = FocusNode(); + focusStates["${field}Focused"] = false; + } + for (var key in focusNodes.keys) { + _addFocusListener(focusNodes[key]!, (focus) { + setState(() { + focusStates[key.replaceFirst("FocusNode", "Focused")] = focus; + }); + }); } if (widget.costcenterId != null) { @@ -89,8 +99,18 @@ class CostCenterDataState extends State { for (var controller in controllers.values) { controller.dispose(); } + for (var node in focusNodes.values) { + node.dispose(); + } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { + node.addListener(() { + setState(() { + updateState(node.hasFocus); + }); + }); + } void updateCostCenterDetails() { print("Inside Update Function - ${widget.costcenterData}"); @@ -129,10 +149,10 @@ class CostCenterDataState extends State { if (data[field] == null || data[field]!.trim().isEmpty) { errorMessages[field] = "Required"; - if (!hasFocused) { - focusNodes[field]?.requestFocus(); - hasFocused = true; - } + // if (!hasFocused) { + // focusNodes[field]?.requestFocus(); + // hasFocused = true; + // } } } @@ -258,14 +278,14 @@ class CostCenterDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["nameFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( controller: controllers["name"], - focusNode: focusNodes["name"], + focusNode: focusNodes["nameFocusNode"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( labelText: "Name", @@ -300,14 +320,14 @@ class CostCenterDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["descriptionFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 100, child: TextField( controller: controllers["description"], - focusNode: focusNodes["description"], + focusNode: focusNodes["descriptionFocusNode"], style: const TextStyle(fontSize: 12), maxLines: null, expands: true, diff --git a/lib/Screens/department/departmentDetails.dart b/lib/Screens/department/departmentDetails.dart index 4d461fb..461531f 100644 --- a/lib/Screens/department/departmentDetails.dart +++ b/lib/Screens/department/departmentDetails.dart @@ -36,14 +36,15 @@ class DepartmentDataState extends State { final ApiService apiService = ApiService(); Map? apiData; - final Map focusNodes = { - "name": FocusNode(), - "description": FocusNode(), - }; + // final Map focusNodes = { + // "name": FocusNode(), + // "description": FocusNode(), + // }; final Map controllers = {}; Map errorMessages = {}; - + Map focusNodes = {}; + Map focusStates = {}; String? selectedName; String? selectedDescription; String? userId; @@ -70,6 +71,15 @@ class DepartmentDataState extends State { apiData = null; for (var field in dataHeader) { controllers[field] = TextEditingController(); + focusNodes["${field}FocusNode"] = FocusNode(); + focusStates["${field}Focused"] = false; + } + for (var key in focusNodes.keys) { + _addFocusListener(focusNodes[key]!, (focus) { + setState(() { + focusStates[key.replaceFirst("FocusNode", "Focused")] = focus; + }); + }); } if (widget.departmentId != null) { @@ -89,8 +99,18 @@ class DepartmentDataState extends State { for (var controller in controllers.values) { controller.dispose(); } + for (var node in focusNodes.values) { + node.dispose(); + } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { + node.addListener(() { + setState(() { + updateState(node.hasFocus); + }); + }); + } void updateDepartmentDetails() { print("Inside Update Function - ${widget.departmentData}"); @@ -129,10 +149,10 @@ class DepartmentDataState extends State { if (data[field] == null || data[field]!.trim().isEmpty) { errorMessages[field] = "Required"; - if (!hasFocused) { - focusNodes[field]?.requestFocus(); - hasFocused = true; - } + // if (!hasFocused) { + // focusNodes[field]?.requestFocus(); + // hasFocused = true; + // } } } @@ -261,14 +281,14 @@ class DepartmentDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["nameFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( controller: controllers["name"], - focusNode: focusNodes["name"], + focusNode: focusNodes["nameFocusNode"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( labelText: "Name", @@ -303,14 +323,14 @@ class DepartmentDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["descriptionFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 100, child: TextField( controller: controllers["description"], - focusNode: focusNodes["description"], + focusNode: focusNodes["descriptionFocusNode"], style: const TextStyle(fontSize: 12), maxLines: null, expands: true, diff --git a/lib/Screens/forex/forexDetails.dart b/lib/Screens/forex/forexDetails.dart index a25e338..3415f68 100644 --- a/lib/Screens/forex/forexDetails.dart +++ b/lib/Screens/forex/forexDetails.dart @@ -42,6 +42,8 @@ class ForexDataState extends State { Map? apiData; final Map controllers = {}; Map errorMessages = {}; + Map focusNodes = {}; + Map focusStates = {}; List countryList = []; String? selectedCountry; @@ -89,6 +91,15 @@ class ForexDataState extends State { apiData = null; for (var field in dataHeader) { controllers[field] = TextEditingController(); + focusNodes["${field}FocusNode"] = FocusNode(); + focusStates["${field}Focused"] = false; + } + for (var key in focusNodes.keys) { + _addFocusListener(focusNodes[key]!, (focus) { + setState(() { + focusStates[key.replaceFirst("FocusNode", "Focused")] = focus; + }); + }); } fetchCountries(); @@ -113,8 +124,18 @@ class ForexDataState extends State { for (var controller in controllers.values) { controller.dispose(); } + for (var node in focusNodes.values) { + node.dispose(); + } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { + node.addListener(() { + setState(() { + updateState(node.hasFocus); + }); + }); + } void updateForexDetails() { print("Updateeee - ${widget.forexData}"); @@ -383,62 +404,103 @@ class ForexDataState extends State { SizedBox(height: 5), CustomTextFieldForexWrapper( isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: widget.isDesktop, child: SizedBox( height: 40, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - popupProps: PopupProps.menu( - showSearchBox: true, // Enables search functionality - menuProps: const MenuProps(backgroundColor: Colors.white), - constraints: BoxConstraints(maxHeight: 250), - itemBuilder: - (context, item, isSelected) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, + width: double.infinity, + child: Focus( + focusNode: focusNodes["country_codeFocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["country_codeFocused"] = hasFocus; + }); + }, + child: GestureDetector( + onTap: () { + // Request focus when user taps + focusNodes["country_codeFocusNode"]?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + popupProps: PopupProps.menu( + showSearchBox: true, // Enables search functionality + menuProps: const MenuProps(backgroundColor: Colors.white), + constraints: BoxConstraints(maxHeight: 250), + itemBuilder: + (context, item, isSelected) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric(horizontal: 4), + ), + ), ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["country_codeFocused"] ?? false) + ? widget.layoutColor! + : Colors.white, + // width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["country_codeFocused"] ?? false) + ? widget.layoutColor! + : Colors.white, + // : const Color(0xFFD6D5E6), + // width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: widget.layoutColor!, width: 1), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 10.0, + vertical: 8.0,), + ), ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedCountry = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; + selectedCountryName = newValue; + setCurrencyFromSelectedCountry(selectedCountry!); + }); + }, ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric(horizontal: 4), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - onChanged: (String? newValue) { - setState(() { - // Find the country_code based on selected country_name - selectedCountry = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - selectedCountryName = newValue; - setCurrencyFromSelectedCountry(selectedCountry!); - }); - }, - ), + ) + ) ), ), if (errorMessages["country_code"] != null) ...[ @@ -464,7 +526,7 @@ class ForexDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["currencyFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, @@ -474,6 +536,7 @@ class ForexDataState extends State { child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["currencyFocusNode"], controller: controllers["currency"], style: GoogleFonts.poppins( fontSize: 11, @@ -518,7 +581,7 @@ class ForexDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["cashFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, width: @@ -528,6 +591,7 @@ class ForexDataState extends State { child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["cashFocusNode"], controller: controllers["cash"], keyboardType: TextInputType.number, inputFormatters: [ @@ -570,7 +634,7 @@ class ForexDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["cardFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, width: @@ -580,6 +644,7 @@ class ForexDataState extends State { child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["cardFocusNode"], controller: controllers["card"], keyboardType: TextInputType.number, inputFormatters: [ @@ -624,12 +689,13 @@ class ForexDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["perdiemAmountFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["perdiemAmountFocusNode"], controller: controllers["perdiemAmount"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index a230726..4439c91 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -42,6 +42,8 @@ class HotelsDataState extends State { Map? apiData; final Map controllers = {}; Map errorMessages = {}; + Map focusNodes = {}; + Map focusStates = {}; List countryList = []; String? selectedCountry; @@ -83,6 +85,15 @@ class HotelsDataState extends State { apiData = null; for (var field in dataHeader) { controllers[field] = TextEditingController(); + focusNodes["${field}FocusNode"] = FocusNode(); + focusStates["${field}Focused"] = false; + } + for (var key in focusNodes.keys) { + _addFocusListener(focusNodes[key]!, (focus) { + setState(() { + focusStates[key.replaceFirst("FocusNode", "Focused")] = focus; + }); + }); } fetchCountries(); if (widget.hotelsId != null) { @@ -103,8 +114,18 @@ class HotelsDataState extends State { for (var controller in controllers.values) { controller.dispose(); } + for (var node in focusNodes.values) { + node.dispose(); + } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { + node.addListener(() { + setState(() { + updateState(node.hasFocus); + }); + }); + } void updateHotelsDetails() { print("Update - ${widget.hotelsData}"); @@ -312,12 +333,14 @@ class HotelsDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + // isFocused: false, + isFocused: focusStates["hotel_nameFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["hotel_nameFocusNode"], controller: controllers["hotel_name"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -353,12 +376,13 @@ class HotelsDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["hotel_chainFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["hotel_chainFocusNode"], controller: controllers["hotel_chain"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -394,12 +418,14 @@ class HotelsDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + // isFocused: false, + isFocused: focusStates["categoryFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["categoryFocusNode"], controller: controllers["category"], inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 ]')), @@ -432,61 +458,102 @@ class HotelsDataState extends State { SizedBox(height: 5), CustomTextFieldForexWrapper( isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: widget.isDesktop, child: SizedBox( height: 40, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - popupProps: PopupProps.menu( - showSearchBox: true, // Enables search functionality - menuProps: const MenuProps(backgroundColor: Colors.white), - constraints: BoxConstraints(maxHeight: 250), - itemBuilder: - (context, item, isSelected) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, + width: double.infinity, + child: Focus( + focusNode: focusNodes["country_codeFocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["country_codeFocused"] = hasFocus; + }); + }, + child: GestureDetector( + onTap: () { + // Request focus when user taps + focusNodes["country_codeFocusNode"]?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + popupProps: PopupProps.menu( + showSearchBox: true, // Enables search functionality + menuProps: const MenuProps(backgroundColor: Colors.white), + constraints: BoxConstraints(maxHeight: 200), + itemBuilder: + (context, item, isSelected) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric(horizontal: 4), + ), + ), ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["country_codeFocused"] ?? false) + ? widget.layoutColor! + : Colors.white, + // width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["country_codeFocused"] ?? false) + ? widget.layoutColor! + : Colors.white, + // : const Color(0xFFD6D5E6), + // width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: widget.layoutColor!, width: 1), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 10.0, + vertical: 8.0,), + ), ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedCountry = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; + selectedCountryName = newValue; + }); + }, ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric(horizontal: 4), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select ", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - onChanged: (String? newValue) { - setState(() { - // Find the country_code based on selected country_name - selectedCountry = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - selectedCountryName = newValue; - }); - }, - ), + ) + ) ), ), if (errorMessages["country_code"] != null) ...[ @@ -512,12 +579,13 @@ class HotelsDataState extends State { ), SizedBox(height: 5), CustomTextFieldForexWrapper( - isFocused: false, + isFocused: focusStates["cityFocused"] ?? false, isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( height: 40, child: TextField( + focusNode: focusNodes["cityFocusNode"], controller: controllers["city"], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( diff --git a/lib/Screens/myTemplates/template.dart b/lib/Screens/myTemplates/template.dart index 5e0f4bd..b1eb202 100644 --- a/lib/Screens/myTemplates/template.dart +++ b/lib/Screens/myTemplates/template.dart @@ -33,6 +33,7 @@ import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_user_travel.dart'; import 'dialog_placeholders.dart'; @@ -60,6 +61,8 @@ class TemplateState extends State