UI_HOTEL_NAME

This commit is contained in:
venbaittech 2025-08-05 18:32:24 +05:30
parent a7310238c0
commit bf9a2b1277
4 changed files with 337 additions and 176 deletions

View File

@ -40,7 +40,8 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
// late Map<String, String> countryMap; // late Map<String, String> countryMap;
Map<String, String> countryMap = {}; Map<String, String> countryMap = {};
List<String> allItems = [];
List<String> filteredItems = [];
String? selectedClass; String? selectedClass;
String? exceptionalClass = "0"; String? exceptionalClass = "0";
bool hasExceptionalClass = false; bool hasExceptionalClass = false;
@ -68,6 +69,8 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
late TextEditingController _checkOutTimeController = TextEditingController(); late TextEditingController _checkOutTimeController = TextEditingController();
late TextEditingController _commentsController = TextEditingController(); late TextEditingController _commentsController = TextEditingController();
List<dynamic>? futureHotels;
bool _destinationFocused = false; bool _destinationFocused = false;
bool _isHotelNameFocused = false; bool _isHotelNameFocused = false;
bool _CategoryFocused = false; bool _CategoryFocused = false;
@ -129,6 +132,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
loadInitialData(); loadInitialData();
}); });
_addFocusListener( _addFocusListener(
_destinationFocusNode, _destinationFocusNode,
(focus) => _destinationFocused = focus, (focus) => _destinationFocused = focus,
@ -284,11 +288,36 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
// : Colors.redAccent; // : Colors.redAccent;
// }); // });
futureHotels = await apiService.fetchGetHotels();
print("futureHotels - $futureHotels");
// Extract hotel_name and assign to items
allItems =
futureHotels!
.map<String>((hotel) => hotel['hotel_name'].toString())
.toList();
setState(() { setState(() {
layoutColor = layoutColor =
layoutString != null layoutString != null
? Color(int.parse(layoutString)) ? Color(int.parse(layoutString))
: Colors.redAccent; : 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<AccomodationScreen> {
), ),
); );
} }
final List<String> items = ['Apple', 'Banana', 'Orange', 'Mango']; // final List<String> items = ['Apple Banana', 'Banana', 'Orange', 'Mango'];
// Default selected value // Default selected value
// selectedClass ??= // selectedClass ??=
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null; // dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
@ -665,26 +694,124 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
), ),
SizedBox(height: 5), SizedBox(height: 5),
CustomTextFieldItnerarySubWrapper( CustomTextFieldItnerarySubWrapper(
isFocused: _isHotelNameFocused, // isFocused: _isHotelNameFocused,
isFocused: false,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop, isDesktop: isDesktop,
// width: // width:
// isDesktop // isDesktop
// ? MediaQuery.of(context).size.width * 0.34 // ? MediaQuery.of(context).size.width * 0.34
// : MediaQuery.of(context).size.width * 0.66, // : MediaQuery.of(context).size.width * 0.66,
child: SizedBox( child: Focus(
height: 40, focusNode: _hotelNameFocusNode,
child: TextField(
focusNode: _hotelNameFocusNode, // Assign the correct focus node onFocusChange: (hasFocus) {
controller: _hotelNameController, setState(() {
style: TextStyle(fontSize: 12), _isHotelNameFocused = hasFocus;
decoration: InputDecoration( });
labelText: "Hotel Name", },
labelStyle: TextStyle(fontSize: 12, color: Colors.grey), child: SizedBox(
floatingLabelBehavior: FloatingLabelBehavior.never, height: 40,
border: InputBorder.none, child: GestureDetector(
contentPadding: EdgeInsets.symmetric(vertical: 16), onTap: () {
_hotelNameFocusNode.requestFocus();
},
child: DropdownSearch<String>(
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),
// ),
// ),
), ),
), ),
), ),

View File

@ -173,7 +173,10 @@ class _CustomAppBarState extends State<CustomAppBar> {
// Save to SharedPreferences // Save to SharedPreferences
await prefs.setString('layout_color', selectedOrg?['layout_color']); 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('ternary_color', selectedOrg?['ternary_color']);
await prefs.setString('body_color', selectedOrg?['color']); await prefs.setString('body_color', selectedOrg?['color']);
await prefs.setString('body_color', selectedOrg?['plan_action']); await prefs.setString('body_color', selectedOrg?['plan_action']);
@ -478,167 +481,169 @@ class _CustomAppBarState extends State<CustomAppBar> {
children: [ children: [
// if (userData?["role"] != "User") // if (userData?["role"] != "User")
ExcludeFocus( ExcludeFocus(
// Focus( // Focus(
// canRequestFocus: false, // canRequestFocus: false,
child:Builder( child: Builder(
builder: builder:
(context) => PopupMenuButton<String>( (context) => PopupMenuButton<String>(
color: Colors.white, color: Colors.white,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
offset: const Offset( offset: const Offset(
0, 0,
50, 50,
), // 👈 shift it 50 pixels down ), // 👈 shift it 50 pixels down
onSelected: (String value) { onSelected: (String value) {
switch (value) { switch (value) {
case '/OrganizationSettings': case '/OrganizationSettings':
context.go('/OrganizationSettings'); context.go('/OrganizationSettings');
break; break;
// case '/OrganizationSetup': // case '/OrganizationSetup':
// context.go('/OrganizationSetup'); // context.go('/OrganizationSetup');
// break; // break;
case '/listUser': case '/listUser':
context.go('/listUser'); context.go('/listUser');
break; break;
case '/report': case '/report':
context.go('/report'); context.go('/report');
break; break;
// case '/department': // case '/department':
// context.go('/department'); // context.go('/department');
// break; // break;
// case '/PolicyList': // case '/PolicyList':
// context.go('/PolicyList'); // context.go('/PolicyList');
// case '/getPerdiem': // case '/getPerdiem':
// context.go('/getPerdiem'); // context.go('/getPerdiem');
// case '/templateList': // case '/templateList':
// context.go('/templateList'); // context.go('/templateList');
// case '/template': // case '/template':
// context.go('/template'); // context.go('/template');
case '/CreateUserDetails': case '/CreateUserDetails':
context.go( context.go(
"/CreateUserDetails", "/CreateUserDetails",
extra: { extra: {
"selectedUser": profileUserDetails, "selectedUser": profileUserDetails,
"isEditProfile": true, "isEditProfile": true,
"isViewMode": false, "isViewMode": false,
}, },
); );
case '/logout': case '/logout':
logout(context); logout(context);
// context.go('/'); // context.go('/');
break; break;
} }
}, },
// itemBuilder: (BuildContext context) => // itemBuilder: (BuildContext context) =>
// menuItems.map(buildMenuItem).toList(), // menuItems.map(buildMenuItem).toList(),
itemBuilder: (BuildContext context) { itemBuilder: (BuildContext context) {
// final isUser = userData?["role"] == "User"; // final isUser = userData?["role"] == "User";
final role = userData?["role"]; final role = userData?["role"];
List<Map<String, dynamic>> filteredItems; List<Map<String, dynamic>> filteredItems;
if (role == "User") { if (role == "User") {
filteredItems = filteredItems =
menuItems menuItems
.where( .where(
(item) => (item) =>
item['value'] == item['value'] ==
'/CreateUserDetails' || '/CreateUserDetails' ||
item['value'] == '/logout', item['value'] == '/logout',
) )
.toList(); .toList();
} else if (role == "Travel Agent") { } else if (role == "Travel Agent") {
filteredItems = filteredItems =
menuItems menuItems
.where((item) => item['value'] == '/logout') .where(
.toList(); (item) => item['value'] == '/logout',
} else { )
filteredItems = menuItems; .toList();
} } else {
filteredItems = menuItems;
}
// Create a new list starting with role display and divider // Create a new list starting with role display and divider
return [ return [
PopupMenuItem<String>( PopupMenuItem<String>(
enabled: false, // Not clickable enabled: false, // Not clickable
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
userData?["role"] ?? '', userData?["role"] ?? '',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black, color: Colors.black,
),
), ),
), const PopupMenuDivider(),
const PopupMenuDivider(), // const Divider(), // 👈 Divider after role
// const Divider(), // 👈 Divider after role ],
],
),
),
...filteredItems
.map(buildMenuItem)
.toList(), // 👈 then normal items
// const PopupMenuDivider(),
PopupMenuItem<String>(
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( ...filteredItems
Icons.arrow_drop_down, .map(buildMenuItem)
size: 20, .toList(), // 👈 then normal items
color: Colors.black87, // const PopupMenuDivider(),
PopupMenuItem<String>(
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), const SizedBox(width: 8),
], ],
@ -653,7 +658,7 @@ class _CustomAppBarState extends State<CustomAppBar> {
color: layoutColor, // Set the color of the bottom border color: layoutColor, // Set the color of the bottom border
), ),
), ),
), ),
); );
} }

View File

@ -898,7 +898,7 @@ class ApiService {
} }
// download the Template for bulk upload the user // download the Template for bulk upload the user
Future<Map<String, dynamic>> getDownloadUserTemplateForUpload() async { Future<Map<String, dynamic>> getDownloadUserTemplateForUpload() async {
final String apiUrldata = final String apiUrldata =
'$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api '$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
@ -1117,7 +1117,7 @@ class ApiService {
} }
final List<Map<String, dynamic>> listData = final List<Map<String, dynamic>> listData =
List<Map<String, dynamic>>.from(data['data']); List<Map<String, dynamic>>.from(data['data']);
if (listData.isEmpty) { if (listData.isEmpty) {
throw Exception("No department found with ID $id"); throw Exception("No department found with ID $id");
@ -1591,7 +1591,11 @@ class ApiService {
} }
} }
Future<Map<String, dynamic>> reportExcelDownload(String apiRoute,String body,String name,) async { Future<Map<String, dynamic>> reportExcelDownload(
String apiRoute,
String body,
String name,
) async {
final String apiUrldata = '$apiUrl/api/$apiRoute'; final String apiUrldata = '$apiUrl/api/$apiRoute';
// Sanitize name for filename (optional) // Sanitize name for filename (optional)
@ -1617,7 +1621,6 @@ class ApiService {
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
try { try {
print("report XL Dowloaded"); print("report XL Dowloaded");
print(excelName); print(excelName);
@ -1651,4 +1654,33 @@ class ApiService {
} }
// ----------------------- Report ------------------------- // ----------------------- Report -------------------------
Future<List<dynamic>> 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');
}
}
} }

View File

@ -67,9 +67,6 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter