diff --git a/lib/Screens/group/groupDetails.dart b/lib/Screens/group/groupDetails.dart index 916b54e..d185fc6 100644 --- a/lib/Screens/group/groupDetails.dart +++ b/lib/Screens/group/groupDetails.dart @@ -410,14 +410,148 @@ class GroupDataState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Select Policy For International", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), + // Text( + // "Select Policy For Domestic", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Select Policy For Domestic", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + IconButton( + icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent), + tooltip: "Reset", + onPressed: () { + setState(() { + selectedDomesticPolicyID = null; + selectedDomesticPolicyName = null; + }); + }, + ), + ], + ), + SizedBox(height: 5), + CustomTextFieldForexWrapper( + isFocused: focusStates["domestic_policy_nameFocused"] ?? false, + isDesktop: widget.isDesktop, + child: SizedBox( + height: 40, + child: Focus( + focusNode: focusNodes["domestic_policy_nameFocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["domestic_policy_nameFocused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["domestic_policy_nameFocusNode"] + ?.requestFocus(); + }, + child: DropdownSearch( + selectedItem: DomesticMap[selectedDomesticPolicyID], + popupProps: PopupProps.menu( + showSearchBox: true, // Enables search functionality + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + constraints: BoxConstraints(maxHeight: 250), + itemBuilder: + (context, object, isSelected) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Text( + object, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric( + horizontal: 4, + ), + ), + ), + ), + items: DomesticMap.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 + selectedDomesticPolicyID = + DomesticMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + selectedDomesticPolicyName = newValue; + }); + }, + ), + ), + ), ), ), + ], + ), + const SizedBox(height: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Select Policy For International", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + IconButton( + icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent), + tooltip: "Reset", + onPressed: () { + setState(() { + selectedInternationalPolicyID = null; + selectedInternationalPolicyName = null; + }); + }, + ), + ], + ), SizedBox(height: 5), CustomTextFieldForexWrapper( isFocused: @@ -507,102 +641,6 @@ class GroupDataState extends State { ], ), const SizedBox(height: 10), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Select Policy For Domestic", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldForexWrapper( - isFocused: focusStates["domestic_policy_nameFocused"] ?? false, - isDesktop: widget.isDesktop, - child: SizedBox( - height: 40, - child: Focus( - focusNode: focusNodes["domestic_policy_nameFocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["domestic_policy_nameFocused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["domestic_policy_nameFocusNode"] - ?.requestFocus(); - }, - child: DropdownSearch( - selectedItem: DomesticMap[selectedDomesticPolicyID], - popupProps: PopupProps.menu( - showSearchBox: true, // Enables search functionality - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - constraints: BoxConstraints(maxHeight: 250), - itemBuilder: - (context, object, isSelected) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, - ), - child: Text( - object, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric( - horizontal: 4, - ), - ), - ), - ), - items: DomesticMap.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 - selectedDomesticPolicyID = - DomesticMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; - selectedDomesticPolicyName = newValue; - }); - }, - ), - ), - ), - ), - ), - ], - ), - const SizedBox(height: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index 80182f5..feb40b1 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -496,7 +496,7 @@ class HotelsDataState extends State { return Padding( padding: const EdgeInsets.symmetric( horizontal: 8.0, - vertical: 6.0, + vertical: 0.02, ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -572,7 +572,10 @@ class HotelsDataState extends State { countryMap.entries .firstWhere((entry) => entry.value == newValue) .key; - selectedCountryName = newValue; + final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); + final countryName = match?.group(1) ?? newValue; // --> "Ascension Islands" + // final countryCode = match?.group(2) ?? ""; + selectedCountryName = countryName; }); }, ), diff --git a/lib/Screens/organization/themeColor.dart b/lib/Screens/organization/themeColor.dart index e2f4052..d2b44fb 100644 --- a/lib/Screens/organization/themeColor.dart +++ b/lib/Screens/organization/themeColor.dart @@ -26,21 +26,16 @@ class _ColorThemePickerWidgetState extends State { // Layout colors final List layoutThemeColors = [ Color(0xFF448AFF), // BlueAccent - Color(0xFFF44336), // Red + Color(0xFF027E87), // Blue Shade Color(0xFF12B24B), // Green Color(0xFF2ECC71), // Emerald Green Color(0xFFFF9800), // Orange Color(0xFFE67E22), // Orange 2 Color(0xFFBF4C0D), // Orange dark orange 3 - Color(0xFFAA9941), // Husk Color(0xFFD9067A), // rose Color(0xFFc94b92), // rose light Color(0xFF9C27B0), // Purple Color(0xFF9B59B6), // Purple 2 - Color(0xFF027E87), // Blue Shade - Color(0xFF810D26), // Merun Shade - Color(0xFFd1b795), - Color(0xFF7F8C8D) // Slate Gray Neutral and soft ]; // Body colors diff --git a/lib/Screens/perdiem_amount/forexDetails.dart b/lib/Screens/perdiem_amount/forexDetails.dart index d3458de..b6695a4 100644 --- a/lib/Screens/perdiem_amount/forexDetails.dart +++ b/lib/Screens/perdiem_amount/forexDetails.dart @@ -442,7 +442,7 @@ class ForexDataState extends State { return Padding( padding: const EdgeInsets.symmetric( horizontal: 8.0, - vertical: 6.0, + vertical: 0.02, ), child: Padding( padding: const EdgeInsets.all(8.0), @@ -527,7 +527,10 @@ class ForexDataState extends State { countryMap.entries .firstWhere((entry) => entry.value == newValue) .key; - selectedCountryName = newValue; + final setMatch = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); + final setCountryName = setMatch?.group(1)?.toLowerCase() ?? ''; + selectedCountryName = setCountryName; + setCurrencyFromSelectedCountry(selectedCountry!); }); }, ), diff --git a/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart b/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart new file mode 100644 index 0000000..7d4726d --- /dev/null +++ b/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart @@ -0,0 +1,439 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; + +import '../../config/apiUrl.dart'; +import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; +import '../../widgets/custom_text_forex.dart'; +import 'purpose_of_travel_list.dart'; + +class PurposeOfTravelData extends StatefulWidget { + final Future> Function() fetchGetPurposeOfTravel; + final bool isDesktop; + final Color? layoutColor; + + final int? purposeOfTravelId; // <-- Add this + final Map? purposeOfTravelData; + + const PurposeOfTravelData({ + super.key, + required this.isDesktop, + this.layoutColor, + required this.fetchGetPurposeOfTravel, + this.purposeOfTravelId, + this.purposeOfTravelData, + }); + + @override + PurposeOfTravelDataState createState() => PurposeOfTravelDataState(); +} + +class PurposeOfTravelDataState extends State { + final ApiService apiService = ApiService(); + Map? apiData; + + // final Map focusNodes = { + // "name": FocusNode(), + // "description": FocusNode(), + // }; + + final Map controllers = {}; + Map errorMessages = {}; + Map focusNodes = {}; + Map focusStates = {}; + String? selectedName; + String? selectedDescription; + String? userId; + int? purposeOfTravelDataId; + late String isActive = "1"; + + List dataHeader = ["dropdown_value", "description"]; + + Map purposeOfTravelDetails() { + final data = { + // "purposeOfTravel_id": int.parse(purposeOfTravelId), + "dropdown_value": controllers["dropdown_value"]?.text, + "description": controllers["description"]?.text, + "created_by": userId, + "is_active": isActive, + }; + return data; + } + + @override + void initState() { + super.initState(); + + 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.purposeOfTravelId != null) { + print('Editing D ID: ${widget.purposeOfTravelId}'); + updateDepartmentDetails(); + } + } + + void _clearError() { + setState(() { + errorMessages.clear(); + }); + } + + @override + void dispose() { + 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.purposeOfTravelData}"); + + final data = widget.purposeOfTravelData; + + if (data == null) return; + setState(() { + controllers['dropdown_value']?.text = data['dropdown_value'] ?? ''; + // controllers['description']?.text = data['description'].toString(); + isActive = data["is_active"]; + final purposeOfTravelId = int.tryParse(data['id'].toString()); + purposeOfTravelDataId = purposeOfTravelId; + }); + } + + void toggleStatus() { + setState(() { + isActive = isActive == "1" ? "0" : "1"; + }); + } + + bool validateData() { + errorMessages.clear(); + + final data = { + "dropdown_value": controllers["dropdown_value"]?.text, + // "description": controllers["description"]?.text, + }; + + final requiredFields = ["dropdown_value"]; + bool hasFocused = false; + + // Check validation for each field + for (String field in requiredFields) { + if (data[field] == null || data[field]!.trim().isEmpty) { + errorMessages[field] = "Required"; + + // if (!hasFocused) { + // focusNodes[field]?.requestFocus(); + // hasFocused = true; + // } + } + } + + return errorMessages.isEmpty; + } + + Future handleSubmit() async { + userId = await getUserId(); + + setState(() { + // This triggers UI rebuild with error messages + if (validateData()) { + postPurposeOfTravelData(); + } + }); + + final purposeOfTravelData1 = purposeOfTravelDetails(); + print("submit data - $purposeOfTravelData1"); + } + + Future postPurposeOfTravelData({int isActive = 1}) async { + // final remarksData = getData(); + + final purposeOfTravelData = purposeOfTravelDetails(); + + print("initially value of the Department - $purposeOfTravelData"); + + final String apiUrldata; + + if (purposeOfTravelDataId != null) { + print("for edit purposeOfTravel id - $purposeOfTravelDataId"); + apiUrldata = '$apiUrl/api/updatePurposeOfTravel/$purposeOfTravelDataId'; + purposeOfTravelData["id"] = purposeOfTravelDataId.toString(); + purposeOfTravelData["updated_by"] = userId; + (purposeOfTravelData.containsKey("created_by")) + ? purposeOfTravelData.remove("created_by") + : ''; + } else { + print("for add PurposeOfTravel id - null"); + apiUrldata = '$apiUrl/api/createPurposeOfTravel'; + print("called apiUrl - $apiUrldata"); + purposeOfTravelData["created_by"] = userId; + } + print("recently PurposeOfTravel data - $purposeOfTravelData"); + final token = await getToken(); // Fetch token + + if (token == null) { + throw Exception('Token not found. Please log in.'); + } + + try { + final uri = Uri.parse(apiUrldata); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + final body = jsonEncode(purposeOfTravelData); + + final response = + purposeOfTravelDataId != null + ? await http.put(uri, headers: headers, body: body) + : await http.post(uri, headers: headers, body: body); + + if (response.statusCode == 200 || response.statusCode == 201) { + print("successfully!"); + print("Response: ${response.body}"); + _clearError(); + widget.fetchGetPurposeOfTravel(); + // dispose(); + Navigator.of(context).pop(); + } else if (response.statusCode == 404) { + Navigator.of(context).pop(); + final message = jsonDecode(response.body)['message'] ?? 'Unknown error'; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + backgroundColor: Colors.redAccent, + behavior: SnackBarBehavior.floating, + ), + ); + } else { + print("Failed to submit. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + } + } catch (e) { + print(" Error submitting plan: $e"); + } + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + backgroundColor: Colors.white, + contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30), + // contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Row 1: Title + Edit + Delete buttons + Row( + children: [ + Text( + (purposeOfTravelDataId != null) + ? 'Edit Purpose Of Travel' + : 'Create Purpose Of Travel', + style: GoogleFonts.poppins(fontSize: 15, color: Colors.black), + ), + const Spacer(), + ], + ), + const SizedBox(height: 2), + Divider(thickness: 0.2, color: Colors.blueGrey.shade100), + const SizedBox(height: 5), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Name *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldForexWrapper( + isFocused: focusStates["dropdown_valueFocused"] ?? false, + isDesktop: widget.isDesktop, + color: Colors.transparent, + child: SizedBox( + height: 40, + child: TextField( + controller: controllers["dropdown_value"], + focusNode: focusNodes["dropdown_valueFocusNode"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Name", + labelStyle: TextStyle(fontSize: 11, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), + ), + if (errorMessages["dropdown_value"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["dropdown_value"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + SizedBox(height: 15), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Description *", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // SizedBox(height: 5), + // CustomTextFieldForexWrapper( + // isFocused: focusStates["descriptionFocused"] ?? false, + // isDesktop: widget.isDesktop, + // color: Colors.transparent, + // child: SizedBox( + // height: 100, + // child: TextField( + // controller: controllers["description"], + // focusNode: focusNodes["descriptionFocusNode"], + // style: const TextStyle(fontSize: 12), + // maxLines: null, + // expands: true, + // decoration: const InputDecoration( + // labelText: "Description", + // labelStyle: TextStyle(fontSize: 11, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // ), + // ), + // ), + // ), + // if (errorMessages["description"] != null) ...[ + // SizedBox(height: 5), // Space before error message + // Text( + // errorMessages["description"]!, + // style: TextStyle(color: Colors.red, fontSize: 12), + // ), + // ], + // ], + // ), + // SizedBox(height: 15), + if (purposeOfTravelDataId != null) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Change Status ", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + Tooltip( + message: + isActive == "1" ? "Tap to deactivate" : "Tap to activate", + child: GestureDetector( + onTap: toggleStatus, + child: Text( + isActive == "1" ? "Active" : "Inactive", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + color: isActive == "1" ? Colors.green : Colors.red, + ), + ), + ), + ), + ], + ), + if (purposeOfTravelDataId != null) SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + // SizedBox( + // child: ElevatedButton( + // onPressed: () { + // // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal + // }, + // style: ElevatedButton.styleFrom( + // backgroundColor: widget.layoutColor, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // child: Text('Cancel', + // style: GoogleFonts.poppins( + // fontSize: 13, color: Colors.white)), + // ), + // ), + // SizedBox( + // width: 10, + // ), + SizedBox( + child: ElevatedButton( + onPressed: () { + handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal + }, + style: ElevatedButton.styleFrom( + backgroundColor: widget.layoutColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + 'Save', + style: GoogleFonts.poppins( + fontSize: 11, + color: Colors.white, + ), + ), + ), + ), + ], + ), + // : SizedBox.shrink(), + ], + ), + ); + } +} diff --git a/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart b/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart new file mode 100644 index 0000000..402abce --- /dev/null +++ b/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart @@ -0,0 +1,854 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:responsive_builder/responsive_builder.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../config/apiUrl.dart'; +import '../../routes/custom_appBar.dart'; +import '../../routes/custom_drawer.dart'; +import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; +import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; +import 'purpose_of_travel_details.dart'; + +class PurposeOfTravelList extends StatefulWidget { + const PurposeOfTravelList({super.key}); + + @override + PurposeOfTravelListState createState() => PurposeOfTravelListState(); +} + +class PurposeOfTravelListState extends State { + final GlobalKey purposeOfTravelListKey = + GlobalKey(); + + final ApiService apiService = ApiService(); + // late Future> futurePurposeOfTravel; + Future>? futurePurposeOfTravel; + + late Map depSingleData; + String? selectedPurposeOfTravelId; + String? orgId; + + Color? layoutColor; + Color? bodyColor; + + List allPurposeOfTravel = []; + List filteredPurposeOfTravel = []; + TextEditingController searchController = TextEditingController(); + + int currentPage = 0; + int itemsPerPage = 10; + + @override + void initState() { + super.initState(); + _checkAuthAndLoadData(); + // futurePurposeOfTravel = fetchGetPurposeOfTravel(); + // + // futurePurposeOfTravel.then((object) { + // setState(() { + // allPurposeOfTravel = object; + // }); + // }); + // + // WidgetsBinding.instance.addPostFrameCallback((_) { + // loadInitialData(); + // }); + + // futurePlans = fetchPlans(); + } + + void _checkAuthAndLoadData() async { + final String? token = await getToken(); // Your async function to get token + + if (token == null || token.isEmpty) { + // Token doesn't exist → redirect to login + context.go( + "/", + ); // or use: router.go("/") if you're using `GoRouter` directly + return; + } + if (!mounted) return; + try { + futurePurposeOfTravel = fetchGetPurposeOfTravel(); + + futurePurposeOfTravel?.then((object) { + setState(() { + allPurposeOfTravel = object; + }); + }); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadInitialData(); + }); + } catch (e) { + print("group : $e"); + } + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + bodyColor = + bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; + }); + } + + Future getToken() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString('auth_token'); + } + + Future> refreshData() { + print("Calling Refresh Data"); + + futurePurposeOfTravel = fetchGetPurposeOfTravel(); + + return futurePurposeOfTravel!.then((object) { + print("Calling Refresh Data $object"); + setState(() { + allPurposeOfTravel = object; + filteredPurposeOfTravel = object; + searchController.text = ""; + }); + return object; + }); + } + + Future> fetchGetPurposeOfTravel() async { + final String apiUrlData = '$apiUrl/api/getPurposeOfTravelList?for=table_view'; + + final String? token = await getToken(); + + print("Fetch PurposeOfTravel"); + print("2KN Here : $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', + }, + ); + print("called api : $apiUrlData"); + if (response.statusCode == 200) { + final data = json.decode(response.body); + return data['data']; // Returning raw JSON list + } else { + throw Exception('Failed to load users'); + } + } + + void filterPurposeOfTravel(String query) { + // print("all before filtering: $query"); + // final lowerQuery = query.toLowerCase(); + // setState(() { + // filteredPurposeOfTravel = allPurposeOfTravel.where((object) { + // return (object['purposeOfTravel_id']?.toLowerCase().contains(lowerQuery) ?? + // false) || + // (object['description']?.toLowerCase().contains(lowerQuery) ?? false) || + // (object['user']?.toLowerCase().contains(lowerQuery) ?? false) || + // (object['is_active']?.toLowerCase().contains(lowerQuery) ?? false); + // }).toList(); + // }); + // print("filteredPlans: $filteredPurposeOfTravel"); + + print("all before filtering: $query"); + final lowerQuery = query.toLowerCase(); + setState(() { + filteredPurposeOfTravel = + allPurposeOfTravel.where((object) { + final isActiveStatus = + object['is_active'] == "1" ? "active" : "inactive"; + return (object['id']?.toLowerCase().contains( + lowerQuery, + ) ?? + false) || + (object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) || + // (object['description']?.toLowerCase().contains(lowerQuery) ?? + // false) || + (isActiveStatus.contains(lowerQuery)); + }).toList(); + currentPage = 0; + }); + print("filteredPurposeOfTravel: $filteredPurposeOfTravel"); + } + + @override + Widget build(BuildContext context) { + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; + + return Scaffold( + backgroundColor: Color(0xFFf5f5f5), + // appBar: isDesktop ? null : const CustomAppBar(title: 'User Management'), + // drawer: isDesktop ? null : CustomDrawer(isDesktop: false), + appBar: CustomAppBar(isDesktop: isDesktop), + drawer: CustomDrawer(isDesktop: false), + body: Padding( + padding: + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: + MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(0), + child: Row( + children: [ + // if (isDesktop) CustomDrawer(isDesktop: true), + // const Expanded(child: Center(child: Text("User Page Content"))), + Expanded(child: buildGroupList(isDesktop)), + ], + ), + ), + ); + }, + ); + } + + Widget buildGroupList(bool isDesktop) { + return Container( + margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null, + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: isDesktop ? Colors.white : Color(0xFFFCFCFC), + ), + // decoration: BoxDecoration( + // // color: Colors.amber, + // // color: bodyColor, + // color: Color(0xFFE1F5FE), + // border: Border.all( + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // width: 3.5)), + child: buildUserTable(isDesktop), + ); + } + + Widget buildUserTable(bool isDesktop) { + return Container( + // margin: isDesktop + // ? EdgeInsets.all(10.0) + // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), + // padding: const EdgeInsets.all(10), + height: + isDesktop + ? MediaQuery.of(context).size.height * 0.98 + : MediaQuery.of(context).size.height, + + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Container( + color: Colors.white, + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Divider( + // thickness: 0.2, // how "thick" the line is + // color: Colors.grey, // optional + // ), + Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Purpose Of Travel Details', + ), + ], + ), + ), + // Text( + // 'PurposeOfTravel Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), + ], + ), + if (isDesktop) + SizedBox(width: MediaQuery.of(context).size.width * 0.08), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + + if (isDesktop) + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchController, + onChanged: filterPurposeOfTravel, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + // SizedBox(width: 16), + Spacer(), + + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + foregroundColor: Colors.white, + disabledBackgroundColor: Color(0xFF114D8B), + disabledForegroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () async { + showDialog( + context: context, + builder: + (context) => PurposeOfTravelData( + isDesktop: isDesktop, + layoutColor: layoutColor!, + fetchGetPurposeOfTravel: refreshData, + + // role: + // "Travel Agent" + ), + ); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Add Purpose Of Travel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon( + Icons.add_circle_outline_rounded, + size: 15, + color: Colors.white, + ), + ], + ), + ), + ], + ), + + if (!isDesktop) SizedBox(height: 5), + isDesktop + ? SizedBox.shrink() + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.8, + height: 35, + child: TextField( + controller: searchController, + onChanged: filterPurposeOfTravel, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + // SizedBox(width: 16), + ], + ), + const SizedBox(height: 10), + FutureBuilder>( + future: futurePurposeOfTravel, + builder: (context, snapshot) { + if (futurePurposeOfTravel == null) { + CircularProgressIndicator(); + } + + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || + !snapshot.hasData || + snapshot.data!.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // const Icon(Icons.error_outline, + // color: Colors.redAccent, size: 60), + // const SizedBox(height: 16), + // Text( + // "Oops!", + // style: GoogleFonts.poppins( + // fontSize: 20, + // fontWeight: FontWeight.bold, + // color: Colors.redAccent), + // ), + const SizedBox(height: 8), + Text( + "No Purpose Of Travel Available ", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + Text( + "Please Create Purpose Of Travel Details", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 16, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } + /* Here collect the list to displayed the data in table or card Used */ + List object = + filteredPurposeOfTravel.isNotEmpty + ? filteredPurposeOfTravel + : allPurposeOfTravel; + + /* List is Sorting here */ + object.sort((a, b) { + DateTime dateA = DateTime.parse(a['created_on']); + DateTime dateB = DateTime.parse(b['created_on']); + + return dateB.compareTo(dateA); // Descending: newest first + }); + + /* For pagination for list ... */ + List paginatedPurposeOfTravel = + object + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) + .toList(); + + /* Table ... */ + Widget table = LayoutBuilder( + builder: (context, constraints) { + double minWidth = isDesktop ? constraints.maxWidth : 1300; + + return ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, + ), + ), + columns: [ + DataColumn( + label: Text( + 'Name', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + // DataColumn( + // label: Text( + // 'Description', + // style: GoogleFonts.poppins( + // fontSize: 13, + // fontWeight: FontWeight.w600, + // ), + // ), + // ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + rows: + paginatedPurposeOfTravel.map((tableObject) { + String purposeOfTravelId = + tableObject['id'] + .toString(); // Get user ID + bool isSelected = + selectedPurposeOfTravelId == purposeOfTravelId; + + return DataRow( + cells: [ + DataCell( + Text( + tableObject['dropdown_value'] ?? '', + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + // DataCell( + // Text( + // tableObject['description'] ?? 'N/A', + // style: TextStyle( + // fontSize: 13, + // fontFamily: "Inter", + // ), + // softWrap: true, + // overflow: TextOverflow.ellipsis, + // ), + // ), + DataCell( + Text( + tableObject['is_active'] == "1" + ? 'Active' + : 'Inactive', + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + color: + tableObject['is_active'] == "1" + ? Colors.green + : Colors.grey, + ), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + DataCell( + // UserActionsMenu( + // user: forex, + // getUserDetails: (id) => + // apiService.getSingleUser(id), + // ), + GestureDetector( + child: Tooltip( + message: 'Edit Purpose Of Travel Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + onTap: () async { + // final userId = getUserId(user['user_id']); + // final usersData = await getUserDetails(userId); + // + final purposeOfTravelId = int.tryParse( + tableObject['id'] + .toString(), + ); + + if (purposeOfTravelId != null) { + print( + "Table cell - purposeOfTravel Id -- $purposeOfTravelId", + ); + final data = await apiService + .getPurposeOfTravelDetailsFind( + purposeOfTravelId, + ); + print("PurposeOfTravelId -- $data"); + + showDialog( + context: context, + builder: + (context) => PurposeOfTravelData( + isDesktop: isDesktop, + purposeOfTravelId: + purposeOfTravelId, // Pass the ID + purposeOfTravelData: data, + layoutColor: layoutColor!, + // fetchGetForex: fetchGetForex, + fetchGetPurposeOfTravel: + refreshData, + // role: + // "Travel Agent" + ), + ); + } else { + print("Invalid ID"); + } + }, + ), + ), + ], + ); + }).toList(), + ), + ); + }, + ); + + /* Card ... */ + Widget buildMobileCardView(List paginatedUser) { + return ListView.builder( + itemCount: paginatedUser.length, + itemBuilder: (context, index) { + final cardObject = paginatedUser[index]; + return Card( + color: Colors.white, + margin: EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 3, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Status and Employee Code + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + cardObject['dropdown_value'] ?? 'N/A', + style: GoogleFonts.poppins( + fontSize: 10, + color: Colors.black87, + fontWeight: FontWeight.w700, + ), + ), + + GestureDetector( + child: Tooltip( + message: 'Edit Purpose Of Travel Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + onTap: () async { + // final userId = getUserId(user['user_id']); + // final usersData = await getUserDetails(userId); + // + final purposeOfTravelId = int.tryParse( + cardObject['id'] + .toString(), + ); + + if (purposeOfTravelId != null) { + print( + "purposeOfTravelId -- $purposeOfTravelId", + ); + final data = await apiService + .getPurposeOfTravelDetailsFind( + purposeOfTravelId, + ); + print("PurposeOfTravelId -- $data"); + + showDialog( + context: context, + builder: + (context) => PurposeOfTravelData( + isDesktop: isDesktop, + purposeOfTravelId: + purposeOfTravelId, // Pass the ID + purposeOfTravelData: data, + layoutColor: layoutColor!, + // fetchGetPurposeOfTravel: fetchGetPurposeOfTravel, + fetchGetPurposeOfTravel: + refreshData, + // role: + // "Travel Agent" + ), + ); + } else { + print("Invalid ID"); + } + }, + ), + ], + ), + + SizedBox(height: 2), + ], + ), + ), + ); + }, + ); + } + + return Expanded( + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: + isDesktop + ? (searchController.text.isNotEmpty && + filteredPurposeOfTravel.isEmpty + ? Center( + child: Text( + "No matches found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, + )) + : (searchController.text.isNotEmpty && + filteredPurposeOfTravel.isEmpty + ? Center( + child: Text( + "No matches found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : buildMobileCardView( + paginatedPurposeOfTravel, + )), + ), + PaginationControls( + currentPage: currentPage, + itemsPerPage: itemsPerPage, + totalItems: object.length, + activeColor: layoutColor, // your theme color + onPageChanged: (page) { + setState(() { + currentPage = page; + }); + }, + onItemsPerPageChanged: (items) { + setState(() { + itemsPerPage = items; + currentPage = 0; + }); + }, + ), + ], + ), + ); + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart b/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart index 82869db..7f814b1 100644 --- a/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart +++ b/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart @@ -811,188 +811,34 @@ class _TravelAgentListScreenState extends State { ), ), ), + // DataCell( Text("10") ), DataCell( - UserActionsMenu( - user: user, - getUserDetails: - (id) => - apiService.getSingleUser(id), + Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + GestureDetector( + child: Tooltip( + message: 'Edit Travel Agent Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = user['user_id']; + final userId = int.parse(user['user_id'].toString()); + final usersData = await apiService.getSingleUser(userId); + context.go("/CreateTravelAgent", extra: { + "selectedUser": usersData, + "isViewMode": false, + }); + }, + ), + ], ), - // PopupMenuButton( - // color: Colors.white, - // padding: EdgeInsets.zero, - // offset: Offset(0, 30), - // icon: Icon( - // Icons.more_vert, - // color: Color(0xFF475569), - // size: 14, - // ), - // itemBuilder: (context) => [ - // CustomPopupMenuEntry( - // child: Container( - // padding: EdgeInsets.symmetric( - // horizontal: 8, vertical: 8), - // child: Row( - // mainAxisSize: MainAxisSize.min, - // mainAxisAlignment: - // MainAxisAlignment.center, - // children: [ - // IconButton( - // icon: Icon( - // Icons.remove_red_eye, - // color: - // Color(0xFF475569), - // size: 18), - // onPressed: () async { - // print( - // "USerDAta1 - $user"); - // // Fetch the user data properly with await - // Map - // usersData = - // await apiService - // .getSingleUser(user[ - // 'user_id'] - // is String - // ? int.parse(user[ - // 'user_id']) - // : user[ - // 'user_id']); - // - // print( - // "USerDAta2 - $usersData"); - // - // // userSingleData = - // // await apiService - // // .getSingleUser(user[ - // // 'user_id']); - // - // context.go( - // "/CreateTravelAgent", - // extra: { - // "selectedUser": - // usersData, - // "isViewMode": true - // }, - // ); - // }), - // IconButton( - // icon: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 20, - // height: 15), - // onPressed: () async { - // // Fetch the user data properly with await - // Map - // usersData = - // await apiService - // .getSingleUser(user[ - // 'user_id'] - // is String - // ? int.parse(user[ - // 'user_id']) - // : user[ - // 'user_id']); - // - // print( - // "USerDAta2 - $usersData"); - // context.go( - // "/CreateTravelAgent", - // extra: { - // "selectedUser": - // usersData, - // "isViewMode": false - // }, - // ); - // }, - // ), - // ], - // ), - // ), - // ), - // ], - // ), - // Row( - // children: [ - // MouseRegion( - // cursor: user['is_active'] == "0" - // ? SystemMouseCursors.forbidden - // : SystemMouseCursors.click, - // child: IconButton( - // icon: Icon(Icons.remove_red_eye, - // size: 18, - // color: user['is_active'] == "0" - // ? Colors.grey - // : Color(0xFF475569)), - // onPressed: user['is_active'] == "0" - // ? null - // : () { - // context.go( - // "/CreateTravelAgent", - // extra: { - // "selectedUser": user, - // "isViewMode": true - // }, - // ); - // }, - // ), - // ), - // - // MouseRegion( - // cursor: user['is_active'] == "0" - // ? SystemMouseCursors.forbidden - // : SystemMouseCursors.click, - // child: GestureDetector( - // onTap: user['is_active'] == "0" - // ? null - // : () { - // - // }, - // child: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 20, - // height: 15), - // ), - // ), - // - // // MouseRegion( - // // cursor: user['is_active'] == "0" - // // ? SystemMouseCursors - // // .forbidden - // // : SystemMouseCursors.click, - // // child: IconButton( - // // icon: Icon(Icons.edit, - // // color: - // // user['is_active'] == - // // "0" - // // ? Colors.grey - // // : Colors.green), - // // onPressed: - // // user['is_active'] == "0" - // // ? null - // // : () { - // // print( - // // "USER: $user"); - // // - // // // final userJson = jsonEncode( - // // // user); // Convert user map to string - // // // final encodedUser = - // // // Uri.encodeComponent( - // // // userJson); - // // - // // context.go( - // // "/CreateTravelAgent", - // // extra: { - // // "selectedUser": - // // user, - // // "isViewMode": - // // false - // // }, - // // ); - // // }, - // // ), - // // ), - // ], - // ), ), ], ); @@ -1036,11 +882,37 @@ class _TravelAgentListScreenState extends State { ), ), - UserActionsMenu( - user: user, - getUserDetails: - (id) => apiService.getSingleUser(id), - ), + + Row( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + GestureDetector( + child: Tooltip( + message: 'Edit Travel Agent Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + onTap: () async { + Navigator.pop(context); // Close the menu + final userId = int.parse(user['user_id'].toString()); + final usersData = await apiService.getSingleUser(userId); + context.go("/CreateTravelAgent", extra: { + "selectedUser": usersData, + "isViewMode": false, + }); + }, + ), + ], + ), + // UserActionsMenu( + // user: user, + // getUserDetails: + // (id) => apiService.getSingleUser(id), + // ), // PopupMenuButton( // color: Colors.white, // padding: EdgeInsets.zero, diff --git a/lib/routes/custom_router.dart b/lib/routes/custom_router.dart index 4d797b0..62c9f94 100644 --- a/lib/routes/custom_router.dart +++ b/lib/routes/custom_router.dart @@ -29,6 +29,7 @@ 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/purposeOfTravel/purpose_of_travel_list.dart'; import '../Screens/costCenter/costCenter_list.dart'; import '../Screens/dashboard/status_dashboard.dart'; import '../Screens/hotels/hotels_list.dart'; @@ -186,6 +187,10 @@ final GoRouter router = GoRouter( path: '/CreateTravelAgent', builder: (context, state) => CreateTravelAgentFormDetials(), ), + GoRoute( + path: '/PurposeOfTravel', + builder: (context, state) => PurposeOfTravelList(), + ), ], ), ], diff --git a/lib/routes/organizationSetting.dart b/lib/routes/organizationSetting.dart index 95663ad..0d24272 100644 --- a/lib/routes/organizationSetting.dart +++ b/lib/routes/organizationSetting.dart @@ -123,18 +123,25 @@ class OrganizationSettingState extends State { 'label': 'Email Templates', 'description': ' Edit Email Template', }, - { - 'value': '/department', - 'icon': Icons.group_add_outlined, - 'label': 'Departments', - 'description': 'Create and Edit Department', - }, { 'value': '/costcenter', 'icon': Icons.account_balance_wallet, 'label': 'Cost Center', 'description': 'Create and Edit Cost Center', }, + { + 'value': '/PurposeOfTravel', + 'icon': Icons.mode_of_travel_sharp, + 'label': 'Purpose Of Travel', + 'description': 'Create and Edit Purpose Of Travel', + }, + { + 'value': '/department', + // 'icon': Icons.group_add_outlined, + 'icon': Icons.account_tree_rounded, + 'label': 'Functional Department', + 'description': 'Create and Edit Department', + }, { 'value': '/hotels', 'icon': Icons.add_business, diff --git a/lib/services/apiService.dart b/lib/services/apiService.dart index 64f034d..98317fb 100644 --- a/lib/services/apiService.dart +++ b/lib/services/apiService.dart @@ -1086,6 +1086,52 @@ class ApiService { } } + Future> getPurposeOfTravelDetailsFind(int id) async { + final String apiUrldata = '$apiUrl/api/findPurposeOfTravel?id=$id'; + + final token = await getToken(); + + if (token == null) { + throw Exception('Token not found. Please log in.'); + } + + final response = await http.get( + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + try { + final data = json.decode(response.body); + // print('findout the result'); + // print(data.runtimeType); + // print(data); + + if (!data.containsKey('data') || data['data'] is! List) { + throw Exception( + "Invalid response format: 'data' field is missing or not a List", + ); + } + + final List> listData = + List>.from(data['data']); + + if (listData.isEmpty) { + throw Exception("No department found with ID $id"); + } + + return listData[0]; + } catch (e) { + throw Exception('Error parsing response: $e'); + } + } else { + throw Exception('Failed to load department details'); + } + } + Future> getTemplateFind(int id) async { final String apiUrldata = '$apiUrl/api/template/find/$id';