From bf9a2b12771cc3eec72f28fb90ceff9859d68e51 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 5 Aug 2025 18:32:24 +0530 Subject: [PATCH] UI_HOTEL_NAME --- lib/Screens/itnerary/accomodations.dart | 159 ++++++++++-- lib/routes/custom_appBar.dart | 311 ++++++++++++------------ lib/services/apiService.dart | 40 ++- pubspec.yaml | 3 - 4 files changed, 337 insertions(+), 176 deletions(-) diff --git a/lib/Screens/itnerary/accomodations.dart b/lib/Screens/itnerary/accomodations.dart index a6b2e5c..b49c876 100644 --- a/lib/Screens/itnerary/accomodations.dart +++ b/lib/Screens/itnerary/accomodations.dart @@ -40,7 +40,8 @@ class _AccomodationScreenState extends State { // late Map countryMap; Map countryMap = {}; - + List allItems = []; + List filteredItems = []; String? selectedClass; String? exceptionalClass = "0"; bool hasExceptionalClass = false; @@ -68,6 +69,8 @@ class _AccomodationScreenState extends State { late TextEditingController _checkOutTimeController = TextEditingController(); late TextEditingController _commentsController = TextEditingController(); + List? futureHotels; + bool _destinationFocused = false; bool _isHotelNameFocused = false; bool _CategoryFocused = false; @@ -129,6 +132,7 @@ class _AccomodationScreenState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { loadInitialData(); }); + _addFocusListener( _destinationFocusNode, (focus) => _destinationFocused = focus, @@ -284,11 +288,36 @@ class _AccomodationScreenState extends State { // : Colors.redAccent; // }); + futureHotels = await apiService.fetchGetHotels(); + + print("futureHotels - $futureHotels"); + + // Extract hotel_name and assign to items + allItems = + futureHotels! + .map((hotel) => hotel['hotel_name'].toString()) + .toList(); + setState(() { layoutColor = layoutString != null ? Color(int.parse(layoutString)) : Colors.redAccent; + + filteredItems = List.from(allItems); + + print("items - $allItems"); + _hotelNameController.addListener(_filterItems); + }); + } + + void _filterItems() { + print("Filter iteks"); + String query = _hotelNameController.text.toLowerCase(); + print("Filter iteks - $query"); + setState(() { + filteredItems = + allItems.where((item) => item.toLowerCase().contains(query)).toList(); }); } @@ -587,7 +616,7 @@ class _AccomodationScreenState extends State { ), ); } - final List items = ['Apple', 'Banana', 'Orange', 'Mango']; + // final List items = ['Apple Banana', 'Banana', 'Orange', 'Mango']; // Default selected value // selectedClass ??= // dropdownItems.isNotEmpty ? dropdownItems.first.value : null; @@ -665,26 +694,124 @@ class _AccomodationScreenState extends State { ), SizedBox(height: 5), CustomTextFieldItnerarySubWrapper( - isFocused: _isHotelNameFocused, - + // isFocused: _isHotelNameFocused, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: isDesktop, // width: // isDesktop // ? MediaQuery.of(context).size.width * 0.34 // : MediaQuery.of(context).size.width * 0.66, - child: SizedBox( - height: 40, - child: TextField( - focusNode: _hotelNameFocusNode, // Assign the correct focus node - controller: _hotelNameController, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Hotel Name", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), + child: Focus( + focusNode: _hotelNameFocusNode, + + onFocusChange: (hasFocus) { + setState(() { + _isHotelNameFocused = hasFocus; + }); + }, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () { + _hotelNameFocusNode.requestFocus(); + }, + child: DropdownSearch( + items: allItems, + selectedItem: _hotelNameController.text, + popupProps: PopupProps.menu( + menuProps: const MenuProps(backgroundColor: Colors.white), + showSearchBox: true, + itemBuilder: + (context, item, isSelected) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 2, + ), + child: Text( + item, + + style: GoogleFonts.poppins( + fontSize: 11, + ), // 👈 smaller font size here + ), + ), + searchFieldProps: TextFieldProps( + controller: _hotelNameController, + decoration: InputDecoration( + labelText: "Enter/ Search Hotel Name", + labelStyle: GoogleFonts.poppins(fontSize: 11), + + isDense: true, + floatingLabelBehavior: FloatingLabelBehavior.never, + // contentPadding: EdgeInsets.symmetric( + // vertical: 12, + // horizontal: 10, + // ), + border: OutlineInputBorder(), + ), + ), + fit: FlexFit.loose, + ), + + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + labelText: "Hotel Name", + labelStyle: GoogleFonts.poppins( + fontSize: 11, + color: Colors.grey, + ), + // border: OutlineInputBorder(), + // border: InputBorder.none, + isDense: true, + floatingLabelBehavior: FloatingLabelBehavior.never, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5), + borderSide: BorderSide( + color: + (_isHotelNameFocused ?? false) + ? layoutColor! + : Colors.white, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_CategoryFocused ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 1, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + ), + onChanged: (value) { + _hotelNameController.text = value ?? ''; + }, + ), ), + // TextField( + // focusNode: _hotelNameFocusNode, // Assign the correct focus node + // controller: _hotelNameController, + // style: TextStyle(fontSize: 12), + // decoration: InputDecoration( + // labelText: "Hotel Name", + // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // ), + // ), ), ), ), diff --git a/lib/routes/custom_appBar.dart b/lib/routes/custom_appBar.dart index e0eeb70..77aaeab 100644 --- a/lib/routes/custom_appBar.dart +++ b/lib/routes/custom_appBar.dart @@ -173,7 +173,10 @@ class _CustomAppBarState extends State { // Save to SharedPreferences await prefs.setString('layout_color', selectedOrg?['layout_color']); - await prefs.setString('secondary_color', selectedOrg?['secondary_color']); + await prefs.setString( + 'secondary_color', + selectedOrg?['secondary_color'], + ); await prefs.setString('ternary_color', selectedOrg?['ternary_color']); await prefs.setString('body_color', selectedOrg?['color']); await prefs.setString('body_color', selectedOrg?['plan_action']); @@ -478,167 +481,169 @@ class _CustomAppBarState extends State { children: [ // if (userData?["role"] != "User") ExcludeFocus( - // Focus( - // canRequestFocus: false, - child:Builder( - builder: - (context) => PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: const Offset( - 0, - 50, - ), // 👈 shift it 50 pixels down - onSelected: (String value) { - switch (value) { - case '/OrganizationSettings': - context.go('/OrganizationSettings'); - break; - // case '/OrganizationSetup': - // context.go('/OrganizationSetup'); - // break; - case '/listUser': - context.go('/listUser'); - break; - case '/report': - context.go('/report'); - break; - // case '/department': - // context.go('/department'); - // break; - // case '/PolicyList': - // context.go('/PolicyList'); - // case '/getPerdiem': - // context.go('/getPerdiem'); - // case '/templateList': - // context.go('/templateList'); - // case '/template': - // context.go('/template'); + // Focus( + // canRequestFocus: false, + child: Builder( + builder: + (context) => PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: const Offset( + 0, + 50, + ), // 👈 shift it 50 pixels down + onSelected: (String value) { + switch (value) { + case '/OrganizationSettings': + context.go('/OrganizationSettings'); + break; + // case '/OrganizationSetup': + // context.go('/OrganizationSetup'); + // break; + case '/listUser': + context.go('/listUser'); + break; + case '/report': + context.go('/report'); + break; + // case '/department': + // context.go('/department'); + // break; + // case '/PolicyList': + // context.go('/PolicyList'); + // case '/getPerdiem': + // context.go('/getPerdiem'); + // case '/templateList': + // context.go('/templateList'); + // case '/template': + // context.go('/template'); - case '/CreateUserDetails': - context.go( - "/CreateUserDetails", - extra: { - "selectedUser": profileUserDetails, - "isEditProfile": true, - "isViewMode": false, - }, - ); - case '/logout': - logout(context); - // context.go('/'); - break; - } - }, + case '/CreateUserDetails': + context.go( + "/CreateUserDetails", + extra: { + "selectedUser": profileUserDetails, + "isEditProfile": true, + "isViewMode": false, + }, + ); + case '/logout': + logout(context); + // context.go('/'); + break; + } + }, - // itemBuilder: (BuildContext context) => - // menuItems.map(buildMenuItem).toList(), - itemBuilder: (BuildContext context) { - // final isUser = userData?["role"] == "User"; - final role = userData?["role"]; - List> filteredItems; + // itemBuilder: (BuildContext context) => + // menuItems.map(buildMenuItem).toList(), + itemBuilder: (BuildContext context) { + // final isUser = userData?["role"] == "User"; + final role = userData?["role"]; + List> filteredItems; - if (role == "User") { - filteredItems = - menuItems - .where( - (item) => - item['value'] == - '/CreateUserDetails' || - item['value'] == '/logout', - ) - .toList(); - } else if (role == "Travel Agent") { - filteredItems = - menuItems - .where((item) => item['value'] == '/logout') - .toList(); - } else { - filteredItems = menuItems; - } + if (role == "User") { + filteredItems = + menuItems + .where( + (item) => + item['value'] == + '/CreateUserDetails' || + item['value'] == '/logout', + ) + .toList(); + } else if (role == "Travel Agent") { + filteredItems = + menuItems + .where( + (item) => item['value'] == '/logout', + ) + .toList(); + } else { + filteredItems = menuItems; + } - // Create a new list starting with role display and divider - return [ - PopupMenuItem( - enabled: false, // ❌ Not clickable - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - userData?["role"] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Colors.black, + // Create a new list starting with role display and divider + return [ + PopupMenuItem( + enabled: false, // ❌ Not clickable + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + userData?["role"] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.black, + ), ), - ), - const PopupMenuDivider(), - // const Divider(), // 👈 Divider after role - ], - ), - ), - ...filteredItems - .map(buildMenuItem) - .toList(), // 👈 then normal items - // const PopupMenuDivider(), - PopupMenuItem( - enabled: false, // Not clickable - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Last Login : ", - style: GoogleFonts.poppins( - fontSize: 10, - fontWeight: FontWeight.w500, - color: Colors.grey, - ), - ), - - // SizedBox(width: 10), - Text( - "${userData?["last_login_at"] ?? ''}", - style: GoogleFonts.poppins( - fontSize: 10, - fontWeight: FontWeight.w400, - color: Colors.grey, - ), - ), - ], - ), - ), - ]; - }, - - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - userData?["name"] ?? "N/A", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.black, + const PopupMenuDivider(), + // const Divider(), // 👈 Divider after role + ], ), - // style: const TextStyle( - // fontSize: 14, - // fontWeight: FontWeight.w500, - // fontFamily: "Roboto", - // color: Colors.black, - // ), ), - const Icon( - Icons.arrow_drop_down, - size: 20, - color: Colors.black87, + ...filteredItems + .map(buildMenuItem) + .toList(), // 👈 then normal items + // const PopupMenuDivider(), + PopupMenuItem( + enabled: false, // Not clickable + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Last Login : ", + style: GoogleFonts.poppins( + fontSize: 10, + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + + // SizedBox(width: 10), + Text( + "${userData?["last_login_at"] ?? ''}", + style: GoogleFonts.poppins( + fontSize: 10, + fontWeight: FontWeight.w400, + color: Colors.grey, + ), + ), + ], + ), ), - ], + ]; + }, + + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + userData?["name"] ?? "N/A", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + // style: const TextStyle( + // fontSize: 14, + // fontWeight: FontWeight.w500, + // fontFamily: "Roboto", + // color: Colors.black, + // ), + ), + const Icon( + Icons.arrow_drop_down, + size: 20, + color: Colors.black87, + ), + ], + ), ), ), - ), - ), + ), ), const SizedBox(width: 8), ], @@ -653,7 +658,7 @@ class _CustomAppBarState extends State { color: layoutColor, // Set the color of the bottom border ), ), - ), + ), ); } diff --git a/lib/services/apiService.dart b/lib/services/apiService.dart index 6e20088..c66ecd3 100644 --- a/lib/services/apiService.dart +++ b/lib/services/apiService.dart @@ -898,7 +898,7 @@ class ApiService { } // download the Template for bulk upload the user - Future> getDownloadUserTemplateForUpload() async { + Future> getDownloadUserTemplateForUpload() async { final String apiUrldata = '$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api @@ -1117,7 +1117,7 @@ class ApiService { } final List> listData = - List>.from(data['data']); + List>.from(data['data']); if (listData.isEmpty) { throw Exception("No department found with ID $id"); @@ -1591,7 +1591,11 @@ class ApiService { } } - Future> reportExcelDownload(String apiRoute,String body,String name,) async { + Future> reportExcelDownload( + String apiRoute, + String body, + String name, + ) async { final String apiUrldata = '$apiUrl/api/$apiRoute'; // Sanitize name for filename (optional) @@ -1617,7 +1621,6 @@ class ApiService { ); if (response.statusCode == 200) { - try { print("report XL Dowloaded"); print(excelName); @@ -1651,4 +1654,33 @@ class ApiService { } // ----------------------- Report ------------------------- + + Future> fetchGetHotels() async { + // return []; + final orgId = await getOrgId(); + final String apiUrlData = '$apiUrl/api/getHotels'; + + final String? token = await getToken(); + + print("Fetch Hotels 2KN : $token"); + + 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) { + final data = json.decode(response.body); + return data['data']; // Returning raw JSON list + } else { + throw Exception('Failed to load users'); + } + } } diff --git a/pubspec.yaml b/pubspec.yaml index fe6d555..02e915d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,9 +67,6 @@ dependencies: - - - dev_dependencies: flutter_test: sdk: flutter