diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index cedf96b..fb4d67f 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -221,6 +221,7 @@ class _ListAllPlansState extends State { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -253,6 +254,7 @@ class _ListAllPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(planData), // Convert map to JSON ); @@ -308,6 +310,7 @@ class _ListAllPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); diff --git a/lib/Screens/allTrips/remarks_list.dart b/lib/Screens/allTrips/remarks_list.dart index 3bf5e3c..6a32f1d 100644 --- a/lib/Screens/allTrips/remarks_list.dart +++ b/lib/Screens/allTrips/remarks_list.dart @@ -29,7 +29,8 @@ class _CommentModalListState extends State { Future>> fetchComments1() async { final response = await http.get( Uri.parse( - '$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}'), + '$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}', + ), ); if (response.statusCode == 200) { @@ -58,6 +59,7 @@ class _CommentModalListState extends State { Uri.parse(apiUrldata), headers: { 'Authorization': 'Bearer $token', + 'app-signature': 'ts-traveltool-2025-signature-123456', 'Content-Type': 'application/json', }, ); @@ -81,10 +83,7 @@ class _CommentModalListState extends State { Widget build(BuildContext context) { return AlertDialog( backgroundColor: Colors.white, - title: Text( - 'Comments', - style: GoogleFonts.poppins(color: Colors.black), - ), + title: Text('Comments', style: GoogleFonts.poppins(color: Colors.black)), content: ConstrainedBox( constraints: const BoxConstraints( maxWidth: 500, // ✅ You can adjust this width @@ -119,64 +118,86 @@ class _CommentModalListState extends State { child: DataTable( columns: [ DataColumn( - label: Text( - 'Name', - style: - GoogleFonts.poppins(fontSize: 11, color: Colors.black), - )), + label: Text( + 'Name', + style: GoogleFonts.poppins( + fontSize: 11, + color: Colors.black, + ), + ), + ), DataColumn( - label: Text( - 'Comment', - style: - GoogleFonts.poppins(fontSize: 11, color: Colors.black), - )), + label: Text( + 'Comment', + style: GoogleFonts.poppins( + fontSize: 11, + color: Colors.black, + ), + ), + ), DataColumn( - label: Text( - 'Updated On', - style: - GoogleFonts.poppins(fontSize: 11, color: Colors.black), - )), + label: Text( + 'Updated On', + style: GoogleFonts.poppins( + fontSize: 11, + color: Colors.black, + ), + ), + ), ], - rows: comments.map((comment) { - final name = comment['created_by_name'] ?? 'Unknown'; - final remark = comment['remarks'] ?? ''; - final rawDateStr = comment['updated_on']; - String updatedOn = ''; + rows: + comments.map((comment) { + final name = comment['created_by_name'] ?? 'Unknown'; + final remark = comment['remarks'] ?? ''; + final rawDateStr = comment['updated_on']; + String updatedOn = ''; - if (rawDateStr != null && rawDateStr.isNotEmpty) { - try { - final parsedDate = DateTime.parse(rawDateStr); - updatedOn = DateFormat('d MMM yyyy') - .format(parsedDate); // e.g., 15 May 2025 - } catch (e) { - updatedOn = rawDateStr.split(' ').first; // fallback - } - } + if (rawDateStr != null && rawDateStr.isNotEmpty) { + try { + final parsedDate = DateTime.parse(rawDateStr); + updatedOn = DateFormat( + 'd MMM yyyy', + ).format(parsedDate); // e.g., 15 May 2025 + } catch (e) { + updatedOn = rawDateStr.split(' ').first; // fallback + } + } - return DataRow(cells: [ - DataCell(Text( - name, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - fontWeight: FontWeight.w500), - )), - DataCell(Text( - remark, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - fontWeight: FontWeight.w500), - )), - DataCell(Text( - updatedOn, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - fontWeight: FontWeight.w500), - )), - ]); - }).toList(), + return DataRow( + cells: [ + DataCell( + Text( + name, + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ), + DataCell( + Text( + remark, + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ), + DataCell( + Text( + updatedOn, + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ); + }).toList(), ), ); }, @@ -185,11 +206,14 @@ class _CommentModalListState extends State { actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: Text('Close', - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: widget.layoutColorForUser)), + child: Text( + 'Close', + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + color: widget.layoutColorForUser, + ), + ), ), ], ); diff --git a/lib/Screens/allTrips/travel_agent_list.dart b/lib/Screens/allTrips/travel_agent_list.dart index acfb6f0..72da57b 100644 --- a/lib/Screens/allTrips/travel_agent_list.dart +++ b/lib/Screens/allTrips/travel_agent_list.dart @@ -211,6 +211,7 @@ class _TravelAgentListPlansState extends State { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -243,6 +244,7 @@ class _TravelAgentListPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(planData), // Convert map to JSON ); diff --git a/lib/Screens/approvals/approval_list.dart b/lib/Screens/approvals/approval_list.dart index 09e509b..f8fa76d 100644 --- a/lib/Screens/approvals/approval_list.dart +++ b/lib/Screens/approvals/approval_list.dart @@ -200,6 +200,7 @@ class _ApprovalListState extends State { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -233,6 +234,7 @@ class _ApprovalListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(planData), // Convert map to JSON ); @@ -293,6 +295,7 @@ class _ApprovalListState extends State { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -525,6 +528,7 @@ class _ApprovalListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index 400c647..9b9b8b9 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -117,6 +117,7 @@ class _LoginWidgetState extends State { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode({ 'email': _emailController.text.trim(), @@ -214,11 +215,14 @@ class _LoginWidgetState extends State { if (_isForgotPassword && !_showOtpResetFields) { print('11'); // Step 1: Send OTP - final url = '$apiUrl/forgotPassword/verifyUser'; + final url = '$apiUrl/api/forgotPassword/verifyUser'; try { final response = await http.post( Uri.parse(url), - headers: {'Content-Type': 'application/json'}, + headers: { + 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', + }, body: jsonEncode({'email': _emailController.text.trim()}), ); @@ -273,12 +277,15 @@ class _LoginWidgetState extends State { } else if (!_isForgotPassword && _showOtpResetFields) { print('22'); // Step 2: Verify OTP & Reset Password - final url = '$apiUrl/forgotPassword/changePassword'; + final url = '$apiUrl/api/forgotPassword/changePassword'; try { print('21'); final response = await http.post( Uri.parse(url), - headers: {'Content-Type': 'application/json'}, + headers: { + 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', + }, body: jsonEncode({ 'email': _emailController.text.trim(), 'otp': _otpController.text.trim(), @@ -1111,12 +1118,15 @@ class _LoginWidgetState extends State { } Future handleMS() async { - final url = '$apiUrl/auth/mslogin'; + final url = '$apiUrl/api/auth/mslogin'; print(url); try { final response = await http.get( Uri.parse(url), - headers: {'Content-Type': 'application/json'}, + headers: { + 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', + }, ); print("inside try method"); if (response.statusCode == 200) { diff --git a/lib/Screens/costCenter/costCenterDetails.dart b/lib/Screens/costCenter/costCenterDetails.dart index 9286603..327e279 100644 --- a/lib/Screens/costCenter/costCenterDetails.dart +++ b/lib/Screens/costCenter/costCenterDetails.dart @@ -105,6 +105,7 @@ class CostCenterDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -168,7 +169,7 @@ class CostCenterDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postCostCenterData(); - }else{ + } else { isDisable = false; } }); @@ -212,6 +213,7 @@ class CostCenterDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(costcenterData); @@ -426,22 +428,23 @@ class CostCenterDataState extends State { // ), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, // onPressed: () { // handleSubmit(); // // You can get text from commentController.text diff --git a/lib/Screens/costCenter/costCenter_list.dart b/lib/Screens/costCenter/costCenter_list.dart index 6450262..5e47127 100644 --- a/lib/Screens/costCenter/costCenter_list.dart +++ b/lib/Screens/costCenter/costCenter_list.dart @@ -149,6 +149,7 @@ class CostCenterListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); print("called api : $apiUrlData"); @@ -286,15 +287,13 @@ class CostCenterListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Cost Center Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Cost Center Details'), ], ), ), @@ -310,8 +309,8 @@ class CostCenterListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.08), - // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -458,7 +457,7 @@ class CostCenterListState extends State { builder: (context, snapshot) { final adjHgt = MediaQuery.of(context).size.height; if (futureCostCenter == null) { - return CircularProgressIndicator(); + return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { diff --git a/lib/Screens/dashboard/status_dashboard.dart b/lib/Screens/dashboard/status_dashboard.dart index 7e26f2d..507a56d 100644 --- a/lib/Screens/dashboard/status_dashboard.dart +++ b/lib/Screens/dashboard/status_dashboard.dart @@ -205,6 +205,7 @@ class StatusDashboardState extends State { Uri.parse(apiUrlData), headers: { 'Authorization': 'Bearer $token', + 'app-signature': 'ts-traveltool-2025-signature-123456', 'Content-Type': 'application/json', }, ); diff --git a/lib/Screens/department/departmentDetails.dart b/lib/Screens/department/departmentDetails.dart index 0f69ca3..940020c 100644 --- a/lib/Screens/department/departmentDetails.dart +++ b/lib/Screens/department/departmentDetails.dart @@ -105,6 +105,7 @@ class DepartmentDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -168,7 +169,7 @@ class DepartmentDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postDepartmentData(); - }else{ + } else { isDisable = false; } }); @@ -212,6 +213,7 @@ class DepartmentDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(departmentData); @@ -428,22 +430,23 @@ class DepartmentDataState extends State { // ), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/department/department_list.dart b/lib/Screens/department/department_list.dart index 215defd..802fdb0 100644 --- a/lib/Screens/department/department_list.dart +++ b/lib/Screens/department/department_list.dart @@ -149,6 +149,7 @@ class DepartmentListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); print("called api : $apiUrlData"); @@ -181,11 +182,10 @@ class DepartmentListState extends State { allDepartment.where((object) { final isActiveStatus = object['is_active'] == "1" ? "active" : "inactive"; - return (object['id']?.toLowerCase().contains( - lowerQuery, - ) ?? + return (object['id']?.toLowerCase().contains(lowerQuery) ?? + false) || + (object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) || - (object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) || // (object['description']?.toLowerCase().contains(lowerQuery) ?? // false) || (isActiveStatus.contains(lowerQuery)); @@ -285,15 +285,13 @@ class DepartmentListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Department Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Department Details'), ], ), ), @@ -309,8 +307,8 @@ class DepartmentListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.08), - // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -584,8 +582,7 @@ class DepartmentListState extends State { rows: paginatedDepartment.map((tableObject) { String departmentId = - tableObject['id'] - .toString(); // Get user ID + tableObject['id'].toString(); // Get user ID bool isSelected = selectedDepartmentId == departmentId; @@ -648,8 +645,7 @@ class DepartmentListState extends State { // final usersData = await getUserDetails(userId); // final departmentId = int.tryParse( - tableObject['id'] - .toString(), + tableObject['id'].toString(), ); if (departmentId != null) { @@ -741,8 +737,7 @@ class DepartmentListState extends State { // final usersData = await getUserDetails(userId); // final departmentId = int.tryParse( - cardObject['id'] - .toString(), + cardObject['id'].toString(), ); if (departmentId != null) { diff --git a/lib/Screens/dialog/user_selection_dialog.dart b/lib/Screens/dialog/user_selection_dialog.dart index 6a90111..90542bb 100644 --- a/lib/Screens/dialog/user_selection_dialog.dart +++ b/lib/Screens/dialog/user_selection_dialog.dart @@ -71,6 +71,7 @@ class _UserSelectionDialogState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -95,7 +96,6 @@ class _UserSelectionDialogState extends State { _users = userList.map((user) => SearchUser.fromJson(user)).toList(); _filteredUsers = List.from(_users); _filterUsers(""); - }); print("filtered user === ${_filteredUsers.length}"); print("Users fetched: ${_users.length}"); @@ -132,6 +132,7 @@ class _UserSelectionDialogState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -211,10 +212,15 @@ class _UserSelectionDialogState extends State { if (query.isEmpty) { // ✅ Return all users excluding self and roleId == 5 - _filteredList = _users.where((user) => - user.userId.toString() != excludedUserId && user.roleId.toString() != "5") - .map((user) => {"type": "user", "data": user}) - .toList(); + _filteredList = + _users + .where( + (user) => + user.userId.toString() != excludedUserId && + user.roleId.toString() != "5", + ) + .map((user) => {"type": "user", "data": user}) + .toList(); // _filteredList = [ // // ..._users.map((user) => {"type": "user", "data": user}), @@ -277,9 +283,10 @@ class _UserSelectionDialogState extends State { setState(() { _filteredList.clear(); // Reset the list before filtering if (query.isEmpty) { - _filteredList = _traveller - .map((traveller) => {"type": "traveller", "data": traveller}) - .toList(); + _filteredList = + _traveller + .map((traveller) => {"type": "traveller", "data": traveller}) + .toList(); // _filteredList = [ // ..._users.map((user) => {"type": "user", "data": user}), // ]; @@ -377,19 +384,21 @@ class _UserSelectionDialogState extends State { @override void initState() { super.initState(); - if (widget.title == "Others (Non Employee)"){ fetchTraveller(); } - else{ fetchUsers(); } + if (widget.title == "Others (Non Employee)") { + fetchTraveller(); + } else { + fetchUsers(); + } print("SelffsdfcurrentUser - ${widget.currentUser}"); _filterByTitle(""); } @override Widget build(BuildContext context) { - - final isValid = _searchController.text.trim().isNotEmpty && + final isValid = + _searchController.text.trim().isNotEmpty && userIdSelected.trim().isNotEmpty; - return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Container( @@ -482,81 +491,100 @@ class _UserSelectionDialogState extends State { // _searchController.text.isNotEmpty // ? if (!_showTravellerForm) - SizedBox( - height: 300, // Limit height to avoid overflow - // child: _filteredUsers.isEmpty - child: - _filteredList.isEmpty - ? Center( - child: Text( - "No users found", - style: GoogleFonts.poppins( - fontSize: 14, - color: Colors.grey, - ), + SizedBox( + height: 300, // Limit height to avoid overflow + // child: _filteredUsers.isEmpty + child: + _filteredList.isEmpty + ? Center( + child: Text( + "No users found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, ), - ) - : ListView.builder( - // itemCount: _filteredUsers.length, - itemCount: _filteredList.length, - itemBuilder: (context, index) { - // final user = _filteredUsers[index]; - - final item = _filteredList[index]; - final user = item["data"]; // Extract user object - final userType = - item["type"]; // "user" or "traveller" - if (user is Map) { - print("userLsirer - ${jsonEncode(user)}"); // pretty JSON-like string - } else { - print("userLsirer - $user"); // fallback - } - final isSelected = userIdSelected == (userType == "user" ? user.userId : user.travellerId); - return ListTile( - // hoverColor: , - title: Text( - "${user.firstName ?? "Unknown"}" "${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}", - style: GoogleFonts.poppins(fontSize: 11 , color: isSelected ? widget.layoutColorForUser : Colors.black), - ), - subtitle: - userType == "user" - ? Text( - "Employee ID: ${user.empCode ?? "-"} ", - // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", - style: GoogleFonts.poppins( - fontSize: 10, - color: isSelected ? widget.layoutColorForUser : Colors.black, - ), - ) - : Text( - "Mobile : ${user.mobileNo ?? "-"} ", - // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", - style: GoogleFonts.poppins( - fontSize: 10, - color: isSelected ? widget.layoutColorForUser : Colors.black, - ), - ), - onTap: () { - String selectedUser = - "${user.firstName ?? "Unknown"} ${user.lastName ?? ""}"; - setState(() { - _searchController.text = selectedUser; - userIdSelected = - userType == "user" - ? user.userId - : user.travellerId; - isTraveller = userType == "traveller"; - }); - print( - "Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId}," - " isTraveller: $userIdSelected", - ); - }, - ); - }, ), - ), - // : SizedBox.shrink(), + ) + : ListView.builder( + // itemCount: _filteredUsers.length, + itemCount: _filteredList.length, + itemBuilder: (context, index) { + // final user = _filteredUsers[index]; + + final item = _filteredList[index]; + final user = item["data"]; // Extract user object + final userType = + item["type"]; // "user" or "traveller" + if (user is Map) { + print( + "userLsirer - ${jsonEncode(user)}", + ); // pretty JSON-like string + } else { + print("userLsirer - $user"); // fallback + } + final isSelected = + userIdSelected == + (userType == "user" + ? user.userId + : user.travellerId); + return ListTile( + // hoverColor: , + title: Text( + "${user.firstName ?? "Unknown"}" + "${(user.lastName?.isNotEmpty ?? false) ? " ${user.lastName}" : ""}", + style: GoogleFonts.poppins( + fontSize: 11, + color: + isSelected + ? widget.layoutColorForUser + : Colors.black, + ), + ), + subtitle: + userType == "user" + ? Text( + "Employee ID: ${user.empCode ?? "-"} ", + // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", + style: GoogleFonts.poppins( + fontSize: 10, + color: + isSelected + ? widget.layoutColorForUser + : Colors.black, + ), + ) + : Text( + "Mobile : ${user.mobileNo ?? "-"} ", + // "Employee ID: ${userType == "user" ? user.userId : user.travellerId}", + style: GoogleFonts.poppins( + fontSize: 10, + color: + isSelected + ? widget.layoutColorForUser + : Colors.black, + ), + ), + onTap: () { + String selectedUser = + "${user.firstName ?? "Unknown"} ${user.lastName ?? ""}"; + setState(() { + _searchController.text = selectedUser; + userIdSelected = + userType == "user" + ? user.userId + : user.travellerId; + isTraveller = userType == "traveller"; + }); + print( + "Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId}," + " isTraveller: $userIdSelected", + ); + }, + ); + }, + ), + ), + // : SizedBox.shrink(), // Traveler Form if (_showTravellerForm) @@ -616,32 +644,35 @@ class _UserSelectionDialogState extends State { SizedBox(width: 10), ElevatedButton( style: ElevatedButton.styleFrom( - backgroundColor: isValid ? widget.layoutColorForUser : Colors.grey, + backgroundColor: + isValid ? widget.layoutColorForUser : Colors.grey, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( // color: widget.layoutColorForUser, - color: isValid ? widget.layoutColorForUser : Colors.grey, + color: + isValid ? widget.layoutColorForUser : Colors.grey, width: isValid ? 2 : 0, ), ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), - onPressed: isValid ? () { - print("Submitting: ${_searchController.text}, ID: $userIdSelected"); - widget.onSubmit( - _searchController.text, - userIdSelected, - isTraveller, - ); - Navigator.pop(context); - } - : null, - child: Text( - "Save", - style: GoogleFonts.poppins(fontSize: 11), - ), + onPressed: + isValid + ? () { + print( + "Submitting: ${_searchController.text}, ID: $userIdSelected", + ); + widget.onSubmit( + _searchController.text, + userIdSelected, + isTraveller, + ); + Navigator.pop(context); + } + : null, + child: Text("Save", style: GoogleFonts.poppins(fontSize: 11)), ), ], ), @@ -745,6 +776,7 @@ class _TravelerFormState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(requestBody), ); diff --git a/lib/Screens/group/group.dart b/lib/Screens/group/group.dart index 88a28f6..a309647 100644 --- a/lib/Screens/group/group.dart +++ b/lib/Screens/group/group.dart @@ -247,6 +247,7 @@ class _groupState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(groupData), ) @@ -255,6 +256,7 @@ class _groupState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(groupData), )); diff --git a/lib/Screens/group/groupDetails.dart b/lib/Screens/group/groupDetails.dart index 0107aaf..738b5cb 100644 --- a/lib/Screens/group/groupDetails.dart +++ b/lib/Screens/group/groupDetails.dart @@ -232,7 +232,7 @@ class GroupDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postGroupData(); - }else{ + } else { isDisable = false; } }); @@ -270,6 +270,7 @@ class GroupDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(groupData); @@ -308,12 +309,12 @@ class GroupDataState extends State { behavior: SnackBarBehavior.floating, ), ); - } - else { + } else { print("Failed to submit plan. Status: ${response.statusCode}"); print("Error: ${response.body}"); final message = jsonDecode(response.body); - final errorMessage = message['messages']?['error'] ?? 'Unknown error occurred'; + final errorMessage = + message['messages']?['error'] ?? 'Unknown error occurred'; if (errorMessage.contains("Duplicate entry")) { _clearError(); @@ -464,7 +465,11 @@ class GroupDataState extends State { ), ), IconButton( - icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent), + icon: Icon( + Icons.remove_circle_sharp, + size: 12, + color: Colors.redAccent, + ), tooltip: "Reset", onPressed: () { setState(() { @@ -506,15 +511,15 @@ class GroupDataState extends State { 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), - ), - ), + 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 ...", @@ -533,40 +538,47 @@ class GroupDataState extends State { borderRadius: BorderRadius.circular(8), borderSide: BorderSide( color: - (focusStates["domestic_policy_nameFocused"] ?? false) - ? widget.layoutColor! - : Colors.white, + (focusStates["domestic_policy_nameFocused"] ?? + false) + ? widget.layoutColor! + : Colors.white, // width: 0.5, ), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: - (focusStates["domestic_policy_nameFocused"] ?? false) - ? widget.layoutColor! - : Colors.white, + (focusStates["domestic_policy_nameFocused"] ?? + false) + ? widget.layoutColor! + : Colors.white, // : const Color(0xFFD6D5E6), // width: 0.5, // const Color(0xFFD6D5E6), ), ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: widget.layoutColor!, width: 1), + borderSide: BorderSide( + color: widget.layoutColor!, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, - vertical: 8.0,), // 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), - ), - ), + // 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 @@ -574,7 +586,7 @@ class GroupDataState extends State { DomesticMap.entries .firstWhere( (entry) => entry.value == newValue, - ) + ) .key; selectedDomesticPolicyName = newValue; }); @@ -602,7 +614,11 @@ class GroupDataState extends State { ), ), IconButton( - icon: Icon(Icons.remove_circle_sharp, size: 12, color: Colors.redAccent), + icon: Icon( + Icons.remove_circle_sharp, + size: 12, + color: Colors.redAccent, + ), tooltip: "Reset", onPressed: () { setState(() { @@ -673,28 +689,35 @@ class GroupDataState extends State { borderRadius: BorderRadius.circular(8), borderSide: BorderSide( color: - (focusStates["international_policy_nameFocused"] ?? false) - ? widget.layoutColor! - : Colors.white, + (focusStates["international_policy_nameFocused"] ?? + false) + ? widget.layoutColor! + : Colors.white, width: 0.5, ), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: - (focusStates["international_policy_nameFocused"] ?? false) - ? widget.layoutColor! - : Colors.white, + (focusStates["international_policy_nameFocused"] ?? + false) + ? widget.layoutColor! + : Colors.white, // : const Color(0xFFD6D5E6), width: 0.5, // const Color(0xFFD6D5E6), ), ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: widget.layoutColor!, width: 1), + borderSide: BorderSide( + color: widget.layoutColor!, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, - vertical: 8.0,), // contentPadding: EdgeInsets.symmetric(horizontal: 1), ), ), @@ -833,21 +856,22 @@ class GroupDataState extends State { // // You can get text from commentController.text // // Navigator.of(context).pop(); // Close the modal // }, - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/group/groupList.dart b/lib/Screens/group/groupList.dart index f67f303..ac164c5 100644 --- a/lib/Screens/group/groupList.dart +++ b/lib/Screens/group/groupList.dart @@ -190,6 +190,7 @@ class _GroupListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode({ "is_active": newStatus, // Set new status dynamically @@ -304,18 +305,17 @@ class _GroupListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Group ', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Group '), ], ), ), + // Text( // 'Group', // style: GoogleFonts.poppins( @@ -324,13 +324,12 @@ class _GroupListState extends State { // color: Colors.black, // ), // ), - ], ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.145), - // SizedBox(width: MediaQuery.of(context).size.width * 0.28), + // SizedBox(width: MediaQuery.of(context).size.width * 0.28), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -625,7 +624,9 @@ class _GroupListState extends State { // ), DataCell( ConstrainedBox( - constraints: BoxConstraints(maxWidth: 200), // limit description width + constraints: BoxConstraints( + maxWidth: 200, + ), // limit description width child: Text( "${group['name'] ?? ''}", style: TextStyle( @@ -633,7 +634,8 @@ class _GroupListState extends State { fontFamily: "Inter", ), overflow: TextOverflow.ellipsis, - maxLines: 1, // optional: show only 1 line + maxLines: + 1, // optional: show only 1 line softWrap: false, ), ), @@ -667,7 +669,9 @@ class _GroupListState extends State { // ), DataCell( ConstrainedBox( - constraints: BoxConstraints(maxWidth: 200), // limit description width + constraints: BoxConstraints( + maxWidth: 200, + ), // limit description width child: Text( "${group['description'] ?? 'N/A'}", style: TextStyle( diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index e876093..b4f1602 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -120,6 +120,7 @@ class HotelsDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -201,7 +202,7 @@ class HotelsDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postHotelsData(); - }else{ + } else { isDisable = false; } }); @@ -247,6 +248,7 @@ class HotelsDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(hotelsData); @@ -282,7 +284,6 @@ class HotelsDataState extends State { setState(() { isDisable = false; }); - } else { print("Failed to submit plan. Status: ${response.statusCode}"); print("Error: ${response.body}"); @@ -291,14 +292,12 @@ class HotelsDataState extends State { isDisable = false; }); } - } - catch (e) { + } catch (e) { print("Error submitting plan: $e"); setState(() { isDisable = false; }); } - } @override @@ -318,7 +317,7 @@ class HotelsDataState extends State { countryMap = { for (var country in countryList) (country['country_code'] ?? ''): - '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', + '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', }; // Extract only country codes for processing @@ -455,7 +454,9 @@ class HotelsDataState extends State { focusNode: focusNodes["categoryFocusNode"], controller: controllers["category"], inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 ]')), + FilteringTextInputFormatter.allow( + RegExp(r'[a-zA-Z0-9 ]'), + ), ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -489,119 +490,144 @@ class HotelsDataState extends State { isDesktop: widget.isDesktop, child: SizedBox( height: 40, - width: double.infinity, - child: Focus( - focusNode: focusNodes["country_codeFocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["country_codeFocused"] = hasFocus; - }); + 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: 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) { - print("contryItem - $item"); - final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); - final countryName = match?.group(1) ?? ''; - final countryCode = match?.group(2) ?? ''; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 0.02, - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - countryName, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - Text( - countryCode, - style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), - - ), - ], - ), - ), - );}, - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric(horizontal: 1,vertical: 1), - ), - ), - ), - 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; - final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); - final countryName = match?.group(1) ?? newValue; // --> "Ascension Islands" - // final countryCode = match?.group(2) ?? ""; - selectedCountryName = countryName; - }); - }, + 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) { + print("contryItem - $item"); + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 0.02, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + Text( + countryCode, + style: GoogleFonts.poppins( + fontSize: 11.5, + color: Colors.grey, + ), + ), + ], + ), + ), + ); + }, + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + vertical: 1, + ), + ), + ), + ), + 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; + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(newValue!); + final countryName = + match?.group(1) ?? + newValue; // --> "Ascension Islands" + // final countryCode = match?.group(2) ?? ""; + selectedCountryName = countryName; + }); + }, + ), + ), + ), ), ), if (errorMessages["country_code"] != null) ...[ @@ -712,22 +738,23 @@ class HotelsDataState extends State { // ), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/hotels/hotels_list.dart b/lib/Screens/hotels/hotels_list.dart index 058e148..43f0601 100644 --- a/lib/Screens/hotels/hotels_list.dart +++ b/lib/Screens/hotels/hotels_list.dart @@ -152,6 +152,7 @@ class HotelsDataListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -177,6 +178,7 @@ class HotelsDataListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -338,15 +340,13 @@ class HotelsDataListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Hotel Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Hotel Details'), ], ), ), @@ -508,7 +508,7 @@ class HotelsDataListState extends State { builder: (context, snapshot) { final adjHgt = MediaQuery.of(context).size.height; if (futureHotels == null) { - return CircularProgressIndicator(); + return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { @@ -892,7 +892,7 @@ class HotelsDataListState extends State { children: [ Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Text( "${hotels['category'] ?? ''} ", diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index 05e1ca1..0f8cdd9 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -207,6 +207,7 @@ class _ForexScreenState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(forexData), // Convert map to JSON ); diff --git a/lib/Screens/myTemplates/templateForex.dart b/lib/Screens/myTemplates/templateForex.dart index 9fa8287..764c0ba 100644 --- a/lib/Screens/myTemplates/templateForex.dart +++ b/lib/Screens/myTemplates/templateForex.dart @@ -1,4 +1,6 @@ import 'dart:convert'; +import 'dart:html' as html; +import 'dart:async'; import 'dart:io' as io show Directory, File; import 'package:delta_to_html/delta_to_html.dart'; import 'package:flutter/cupertino.dart' as dom; @@ -15,6 +17,9 @@ import 'package:frontend/Screens/myTemplates/templateForex.dart' as _editorScrollController; import 'package:frontend/Screens/myTemplates/templateForex.dart' as _controller; import 'package:html2md/html2md.dart' as html2md; +import 'package:http_parser/http_parser.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:mime/mime.dart'; import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart'; import 'package:flutter_quill/flutter_quill.dart' as quill; @@ -59,6 +64,8 @@ class TemplateForex extends StatefulWidget { class TemplateForexState extends State { final ApiService apiService = ApiService(); + Uint8List? _imageBytes; + String? selectedOrglogo; // final QuillController _controller = QuillController.basic(); String? orgId; String? userId; @@ -91,11 +98,6 @@ class TemplateForexState extends State { "body_html": DeltaToHTML.encodeJson( _controller.document.toDelta().toJson(), ), - // "body_html": jsonEncode(_controller.document.toDelta().toJson()), - - // "body_html": _controller, - // "body_html": convertQuillDocToHtml(_controller.document), - // ✅ convert delta to HTML "placeholder": jsonEncode(placeholderList), // "created_by": userId }; @@ -363,7 +365,7 @@ class TemplateForexState extends State { print( "API Selected User Has - ${widget.templateData?["templateData"]?["subject"]}", ); - setState(() { + setState(() async { // ✅ Wrap in setState to update the UI controllers["templateName"]?.text = widget.templateData?["templateData"]?["template_name"] ?? ""; @@ -432,7 +434,7 @@ class TemplateForexState extends State { ) ?? 0; print("Fetched template_id: $templateId"); - + fetchSignature(); // if (widget.group?["international_policy_id"] != null) { // selectedInternational = // widget.group!["international_policy_id"].toString(); @@ -443,6 +445,34 @@ class TemplateForexState extends State { } } + Future fetchSignature() async { + final uri = Uri.parse('$apiUrl/api/getForexSignaturePath'); + final token = await getToken(); + + final response = await http.get( + uri, + headers: {'Authorization': 'Bearer $token'}, + ); + + if (response.statusCode == 200) { + print("ERS - $response"); + final json = jsonDecode(response.body); + + print("ERSjson - $json"); + + String? rawLogoPath = json['url']?.toString(); + + if (rawLogoPath != null && rawLogoPath.isNotEmpty) { + print("ERSrawLogoPath - $rawLogoPath"); + setState(() { + selectedOrglogo = rawLogoPath; + }); + } + } else { + print("❌ Failed to fetch signature: ${response.statusCode}"); + } + } + Future handleSubmit() async { Map data = TemplateData; @@ -492,6 +522,7 @@ class TemplateForexState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(policyData), // Convert map to JSON ); @@ -519,6 +550,70 @@ class TemplateForexState extends State { } } + Future _pickImage() async { + final picker = ImagePicker(); + final XFile? pickedFile = await picker.pickImage( + source: ImageSource.gallery, + ); + + if (pickedFile != null && kIsWeb) { + try { + final bytes = await pickedFile.readAsBytes(); + print('✅ Image loaded, size: ${bytes.length} bytes'); + setState(() { + _imageBytes = bytes; + }); + await uploadSignature(); + } catch (e) { + print('❌ Error reading image bytes: $e'); + } + } else { + print('⚠️ Image picking canceled or not on web.'); + } + } + + Future uploadSignature() async { + if (_imageBytes == null) { + print('⚠️ No image selected'); + return; + } + + final token = await getToken(); // Fetch token + + if (token == null) { + throw Exception('Token not found. Please log in.'); + } + + final uri = Uri.parse('$apiUrl/api/forex_signature_upload'); + final request = http.MultipartRequest('POST', uri); + + // Add auth header + request.headers['Authorization'] = 'Bearer $token'; + + // Add the image as multipart with the key "signature" + request.files.add( + http.MultipartFile.fromBytes( + 'signature', // <-- key name + _imageBytes!, // <-- image bytes + filename: 'signature.png', // <-- filename (can be png/jpg) + contentType: MediaType('image', 'png'), + ), + ); + + try { + final response = await request.send(); + final respStr = await response.stream.bytesToString(); + + if (response.statusCode == 200 || response.statusCode == 201) { + print('✅ Upload successful: $respStr'); + } else { + print('❌ Upload failed (${response.statusCode}): $respStr'); + } + } catch (e) { + print('❌ Error uploading signature: $e'); + } + } + @override Widget build(BuildContext context) { return ResponsiveBuilder( @@ -683,56 +778,65 @@ class TemplateForexState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null, child: IconTheme( data: IconThemeData(size: 18), // Set icon size here - child: QuillSimpleToolbar( - controller: _controller, - config: QuillSimpleToolbarConfig( - embedButtons: FlutterQuillEmbeds.toolbarButtons(), - showClipboardPaste: true, - customButtons: [ - QuillToolbarCustomButtonOptions( - icon: const Icon(Icons.add_alarm_rounded), - onPressed: () { - _controller.document.insert( - _controller.selection.extentOffset, - TimeStampEmbed(DateTime.now().toString()), - ); - _controller.updateSelection( - TextSelection.collapsed( - offset: _controller.selection.extentOffset + 1, - ), - ChangeSource.local, - ); - }, - ), - ], - buttonOptions: QuillSimpleToolbarButtonOptions( - base: QuillToolbarBaseButtonOptions( - afterButtonPressed: () { - final isDesktop = { - TargetPlatform.linux, - TargetPlatform.windows, - TargetPlatform.macOS, - }.contains(defaultTargetPlatform); - // if (isDesktop) { - // _editorFocusNode.requestFocus(); - // } - }, - ), - linkStyle: QuillToolbarLinkStyleButtonOptions( - validateLink: (link) { - // Treats all links as valid. When launching the URL, - // `https://` is prefixed if the link is incomplete (e.g., `google.com` → `https://google.com`) - // however this happens only within the editor. - return true; - }, - ), - ), + child: Container( + color: Color(0xFFFFFEF0), + width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null, + child: IconTheme( + data: IconThemeData(size: 18), // Set icon size here + child: QuillSimpleToolbar(controller: _controller), ), ), + // child: QuillSimpleToolbar( + // controller: _controller, + // config: QuillSimpleToolbarConfig( + // embedButtons: FlutterQuillEmbeds.toolbarButtons(), + // showClipboardPaste: true, + // customButtons: [ + // QuillToolbarCustomButtonOptions( + // icon: const Icon(Icons.add_alarm_rounded), + // onPressed: () { + // _controller.document.insert( + // _controller.selection.extentOffset, + // TimeStampEmbed(DateTime.now().toString()), + // ); + // + // _controller.updateSelection( + // TextSelection.collapsed( + // offset: _controller.selection.extentOffset + 1, + // ), + // ChangeSource.local, + // ); + // }, + // ), + // ], + // buttonOptions: QuillSimpleToolbarButtonOptions( + // base: QuillToolbarBaseButtonOptions( + // afterButtonPressed: () { + // final isDesktop = { + // TargetPlatform.linux, + // TargetPlatform.windows, + // TargetPlatform.macOS, + // }.contains(defaultTargetPlatform); + // // if (isDesktop) { + // // _editorFocusNode.requestFocus(); + // // } + // }, + // ), + // linkStyle: QuillToolbarLinkStyleButtonOptions( + // validateLink: (link) { + // // Treats all links as valid. When launching the URL, + // // `https://` is prefixed if the link is incomplete (e.g., `google.com` → `https://google.com`) + // // however this happens only within the editor. + // return true; + // }, + // ), + // ), + // ), + // ), ), ), - + SizedBox(height: 2), Container( child: Row( mainAxisAlignment: MainAxisAlignment.end, @@ -782,9 +886,10 @@ class TemplateForexState extends State { ], ), ), + Container( padding: const EdgeInsets.all(16), - height: MediaQuery.of(context).size.height * 0.45, + height: MediaQuery.of(context).size.height * 0.38, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xFFD6D5E6), width: 0.5), @@ -799,15 +904,16 @@ class TemplateForexState extends State { padding: const EdgeInsets.all(16), embedBuilders: [ ...FlutterQuillEmbeds.editorBuilders( - imageEmbedConfig: QuillEditorImageEmbedConfig( - imageProviderBuilder: (context, imageUrl) { - // https://pub.dev/packages/flutter_quill_extensions#-image-assets - if (imageUrl.startsWith('assets/')) { - return AssetImage(imageUrl); - } - return null; - }, - ), + // imageEmbedConfig: QuillEditorImageEmbedConfig( + // imageProviderBuilder: (context, imageUrl) { + // if (imageUrl.startsWith('data:image')) { + // return MemoryImage( + // base64Decode(imageUrl.split(',').last), + // ); + // } + // return null; + // }, + // ), videoEmbedConfig: QuillEditorVideoEmbedConfig( customVideoBuilder: (videoUrl, readOnly) { // To load YouTube videos https://github.com/singerdmx/flutter-quill/releases/tag/v10.8.0 @@ -820,6 +926,58 @@ class TemplateForexState extends State { ), ), ), + SizedBox(height: 4), + Container( + child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "Upload Signature", + style: GoogleFonts.poppins(fontSize: 11.5), + ), + SizedBox(width: 5), + GestureDetector( + onTap: _pickImage, + + child: + _imageBytes != null + ? ClipOval( + child: Image.memory( + _imageBytes!, + // width: 50, + // height: 50, + width: 50, // Use responsive width + height: 50, + fit: BoxFit.cover, + ), + ) + : selectedOrglogo != null + ? ClipRect( + child: Image.network( + selectedOrglogo!, + width: 50, // Use responsive width + height: 50, + // width: 250, + // height: 55, + fit: BoxFit.contain, + errorBuilder: (context, error, stackTrace) { + return const CircleAvatar( + radius: 20, + backgroundColor: Colors.redAccent, + child: Icon(Icons.error, size: 10), + ); + }, + ), + ) + : const CircleAvatar( + radius: 20, + backgroundColor: Colors.amber, + child: Icon(Icons.add_a_photo, size: 10), + ), + ), + ], + ), + ), ], ); } diff --git a/lib/Screens/myTemplates/templatesList.dart b/lib/Screens/myTemplates/templatesList.dart index cf184c8..9c77250 100644 --- a/lib/Screens/myTemplates/templatesList.dart +++ b/lib/Screens/myTemplates/templatesList.dart @@ -178,6 +178,7 @@ class TemplatesListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -210,6 +211,7 @@ class TemplatesListState extends State { // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456'; // If updating, spoof the method Laravel-style @@ -447,24 +449,22 @@ class TemplatesListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Templates', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Templates'), ], ), ), ], ), if (isDesktop) - SizedBox(width: MediaQuery.of(context).size.width * 0.13), - // SizedBox(width: MediaQuery.of(context).size.width * 0.23), + SizedBox(width: MediaQuery.of(context).size.width * 0.13), + // SizedBox(width: MediaQuery.of(context).size.width * 0.23), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -597,7 +597,7 @@ class TemplatesListState extends State { builder: (context, snapshot) { final adjHgt = MediaQuery.of(context).size.height; if (futureTemplates == null) { - return CircularProgressIndicator(); + return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); diff --git a/lib/Screens/organization/mailSettings.dart b/lib/Screens/organization/mailSettings.dart index 0821e76..7bfcd41 100644 --- a/lib/Screens/organization/mailSettings.dart +++ b/lib/Screens/organization/mailSettings.dart @@ -50,6 +50,7 @@ class _MailSettingState extends State { super.dispose(); } + Map getMailData() => mailData; Map get mailData { @@ -169,6 +170,7 @@ class _MailSettingState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(mailData), // Convert map to JSON ); @@ -353,7 +355,7 @@ class _MailSettingState extends State { ], ], ), - if(isDesktop) SizedBox(width:20), + if (isDesktop) SizedBox(width: 20), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works crossAxisAlignment: CrossAxisAlignment.start, @@ -447,9 +449,9 @@ class _MailSettingState extends State { isFocused: focusStates["senderEmailFocused"] ?? false, isDesktop: widget.isDesktop, width: - widget.isDesktop - ? MediaQuery.of(context).size.width * 0.23 - : MediaQuery.of(context).size.width * 0.85, + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.23 + : MediaQuery.of(context).size.width * 0.85, child: SizedBox( height: 40, child: TextField( @@ -465,8 +467,7 @@ class _MailSettingState extends State { } else if (!RegExp( r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", ).hasMatch(value)) { - errorMessages["sender_email"] = - "Invalid email format"; + errorMessages["sender_email"] = "Invalid email format"; } }, style: GoogleFonts.poppins(fontSize: 12), @@ -492,7 +493,7 @@ class _MailSettingState extends State { ], ], ), - if(isDesktop) SizedBox(width:20), + if (isDesktop) SizedBox(width: 20), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works crossAxisAlignment: CrossAxisAlignment.start, @@ -545,7 +546,7 @@ class _MailSettingState extends State { ], ], ), - if(isDesktop) SizedBox(width:20), + if (isDesktop) SizedBox(width: 20), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, // ✅ This works crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/Screens/organization/orgSetup.dart b/lib/Screens/organization/orgSetup.dart index 096d91f..97d7aa5 100644 --- a/lib/Screens/organization/orgSetup.dart +++ b/lib/Screens/organization/orgSetup.dart @@ -333,6 +333,7 @@ class _OrgSetUpState extends State { // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456'; // If updating, spoof the method Laravel-style if (isUpdating) { diff --git a/lib/Screens/perdiem_amount/forexDetails.dart b/lib/Screens/perdiem_amount/forexDetails.dart index 732f0f4..fc82083 100644 --- a/lib/Screens/perdiem_amount/forexDetails.dart +++ b/lib/Screens/perdiem_amount/forexDetails.dart @@ -130,6 +130,7 @@ class ForexDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -247,7 +248,7 @@ class ForexDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postForexData(); - }else{ + } else { isDisable = false; } }); @@ -256,7 +257,6 @@ class ForexDataState extends State { print("ForexDAta - $forexData1"); } - Future postForexData({int isActive = 1}) async { // final remarksData = getData(); @@ -296,6 +296,7 @@ class ForexDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(forexData); @@ -375,7 +376,7 @@ class ForexDataState extends State { countryMap = { for (var country in countryList) (country['country_code'] ?? ''): - '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', + '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', }; // Extract only country codes for processing @@ -435,105 +436,130 @@ class ForexDataState extends State { isDesktop: widget.isDesktop, child: SizedBox( height: 40, - 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) { - print("contryItem - $item"); - final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); - final countryName = match?.group(1) ?? ''; - final countryCode = match?.group(2) ?? ''; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 0.02, - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - countryName, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - Text( - countryCode, - style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), - ), - ], + 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) { + print("contryItem - $item"); + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 0.02, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), ), - ), - );}, - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search ...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric(horizontal: 3,vertical: 3), + Text( + countryCode, + style: GoogleFonts.poppins( + fontSize: 11.5, + color: Colors.grey, + ), + ), + ], ), ), - ), - items: countryMap.values.toList(), - filterFn: (item, filter) { - final lowerFilter = filter.toLowerCase(); - - final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item); - final countryName = match?.group(1)?.toLowerCase() ?? ''; - final countryCode = match?.group(2)?.toLowerCase() ?? ''; - - // Prioritize country code match, fallback to country name - return countryCode.contains(lowerFilter) || countryName.contains(lowerFilter); - }, - 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,), + ); + }, + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric( + horizontal: 3, + vertical: 3, ), ), - dropdownBuilder: - (context, selectedItem) => Align( + ), + ), + items: countryMap.values.toList(), + filterFn: (item, filter) { + final lowerFilter = filter.toLowerCase(); + + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(item); + final countryName = + match?.group(1)?.toLowerCase() ?? ''; + final countryCode = + match?.group(2)?.toLowerCase() ?? ''; + + // Prioritize country code match, fallback to country name + return countryCode.contains(lowerFilter) || + countryName.contains(lowerFilter); + }, + 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( @@ -541,100 +567,105 @@ class ForexDataState extends State { 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; - final setMatch = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(newValue!); - final setCountryName = setMatch?.group(1)?.toLowerCase() ?? ''; - selectedCountryName = setCountryName; - setCurrencyFromSelectedCountry(selectedCountry!); - }); - }, - ), - // 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), - // ), - // ), - // ), - // 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!); - // }); - // }, - // ), - ) - ) + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedCountry = + countryMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + final setMatch = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(newValue!); + final setCountryName = + setMatch?.group(1)?.toLowerCase() ?? ''; + selectedCountryName = setCountryName; + setCurrencyFromSelectedCountry(selectedCountry!); + }); + }, + ), + // 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), + // ), + // ), + // ), + // 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!); + // }); + // }, + // ), + ), + ), ), ), if (errorMessages["country_code"] != null) ...[ @@ -913,22 +944,23 @@ class ForexDataState extends State { // // You can get text from commentController.text // // Navigator.of(context).pop(); // Close the modal // }, - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/perdiem_amount/forex_list.dart b/lib/Screens/perdiem_amount/forex_list.dart index 20a1571..f47a7ab 100644 --- a/lib/Screens/perdiem_amount/forex_list.dart +++ b/lib/Screens/perdiem_amount/forex_list.dart @@ -168,6 +168,7 @@ class ForexDataListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -193,6 +194,7 @@ class ForexDataListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -368,9 +370,10 @@ class ForexDataListState extends State { return input .toLowerCase() .split(' ') - .map((word) => word.isNotEmpty - ? word[0].toUpperCase() + word.substring(1) - : '') + .map( + (word) => + word.isNotEmpty ? word[0].toUpperCase() + word.substring(1) : '', + ) .join(' '); } @@ -464,15 +467,13 @@ class ForexDataListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Perdiem Amount Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Perdiem Amount Details'), ], ), ), @@ -488,8 +489,8 @@ class ForexDataListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.1), - // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -634,7 +635,7 @@ class ForexDataListState extends State { future: futureForex, builder: (context, snapshot) { if (futureForex == null) { - return const CircularProgressIndicator(); + return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); @@ -790,7 +791,8 @@ class ForexDataListState extends State { ), DataCell( Text( - toTitleCase(forex['country_name']) ?? '', + toTitleCase(forex['country_name']) ?? + '', style: TextStyle( fontSize: 13, fontFamily: "Inter", @@ -921,7 +923,8 @@ class ForexDataListState extends State { MainAxisAlignment.spaceBetween, children: [ Text( - toTitleCase(forex['country_name']) ?? 'N/A', + toTitleCase(forex['country_name']) ?? + 'N/A', style: GoogleFonts.poppins( fontSize: 10, color: Colors.black87, diff --git a/lib/Screens/plans/create_plans.dart b/lib/Screens/plans/create_plans.dart index 35b6cb5..c0f7fb8 100644 --- a/lib/Screens/plans/create_plans.dart +++ b/lib/Screens/plans/create_plans.dart @@ -824,6 +824,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -964,6 +965,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1010,6 +1012,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1081,6 +1084,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1139,6 +1143,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1289,6 +1294,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(data), ); @@ -1500,6 +1506,7 @@ class CreateNewPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(planData), // Convert map to JSON ); diff --git a/lib/Screens/plans/list_plans.dart b/lib/Screens/plans/list_plans.dart index f537169..19b26f1 100644 --- a/lib/Screens/plans/list_plans.dart +++ b/lib/Screens/plans/list_plans.dart @@ -300,6 +300,7 @@ class _ListPlansState extends State { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -332,6 +333,7 @@ class _ListPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(planData), // Convert map to JSON ); @@ -446,6 +448,7 @@ class _ListPlansState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); diff --git a/lib/Screens/policy/policy.dart b/lib/Screens/policy/policy.dart index ca3524d..5b6ebc3 100644 --- a/lib/Screens/policy/policy.dart +++ b/lib/Screens/policy/policy.dart @@ -595,6 +595,7 @@ class _PolicyState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(policyData), // Convert map to JSON ); diff --git a/lib/Screens/policy/policy_list.dart b/lib/Screens/policy/policy_list.dart index cdaae27..e6fb525 100644 --- a/lib/Screens/policy/policy_list.dart +++ b/lib/Screens/policy/policy_list.dart @@ -139,10 +139,12 @@ class _PolicyListState extends State { filteredPolicy = allPolicy.where((object) { final isActiveStatus = - object['is_active'] == "1" ? "active" : "inactive"; - return (object['policy_id']?.toLowerCase().contains(lowerQuery) ?? false) || + object['is_active'] == "1" ? "active" : "inactive"; + return (object['policy_id']?.toLowerCase().contains(lowerQuery) ?? + false) || (object['name']?.toLowerCase().contains(lowerQuery) ?? false) || - (object['policy_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['policy_type']?.toLowerCase().contains(lowerQuery) ?? + false) || (isActiveStatus.contains(lowerQuery)); }).toList(); currentPage = 0; @@ -185,6 +187,7 @@ class _PolicyListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(policyData), // Convert map to JSON ); @@ -339,15 +342,13 @@ class _PolicyListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Policy', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Policy'), ], ), ), @@ -363,8 +364,8 @@ class _PolicyListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.145), - // SizedBox(width: MediaQuery.of(context).size.width * 0.28), + // SizedBox(width: MediaQuery.of(context).size.width * 0.28), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -1029,32 +1030,34 @@ class _PolicyListState extends State { children: [ Expanded( child: - isDesktop - ? (searchController.text.isNotEmpty && filteredPolicy.isEmpty - ? Center( - child: Text( "No Matches Found", - style: GoogleFonts.poppins( - fontSize: 14, - color: Colors.grey, - ),), - ) - : SingleChildScrollView( - scrollDirection: Axis.vertical, - child: table, - ) - ) - : (searchController.text.isNotEmpty && filteredPolicy.isEmpty - ? Center( - child: Text( + isDesktop + ? (searchController.text.isNotEmpty && + filteredPolicy.isEmpty + ? Center( + child: Text( "No Matches Found", style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey, ), - ), - ) - : buildMobileCardView(paginatedUser) - ), + ), + ) + : SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, + )) + : (searchController.text.isNotEmpty && + filteredPolicy.isEmpty + ? Center( + child: Text( + "No Matches Found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : buildMobileCardView(paginatedUser)), ), PaginationControls( currentPage: currentPage, diff --git a/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart b/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart index f883c7f..79731ca 100644 --- a/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart +++ b/lib/Screens/purposeOfTravel/purpose_of_travel_details.dart @@ -105,6 +105,7 @@ class PurposeOfTravelDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -168,7 +169,7 @@ class PurposeOfTravelDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postPurposeOfTravelData(); - }else{ + } else { isDisable = false; } }); @@ -212,6 +213,7 @@ class PurposeOfTravelDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(purposeOfTravelData); @@ -429,22 +431,23 @@ class PurposeOfTravelDataState extends State { // ), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart b/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart index 7e46b64..9a3c0a5 100644 --- a/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart +++ b/lib/Screens/purposeOfTravel/purpose_of_travel_list.dart @@ -132,7 +132,8 @@ class PurposeOfTravelListState extends State { } Future> fetchGetPurposeOfTravel() async { - final String apiUrlData = '$apiUrl/api/getPurposeOfTravelList?for=table_view'; + final String apiUrlData = + '$apiUrl/api/getPurposeOfTravelList?for=table_view'; final String? token = await getToken(); @@ -148,6 +149,7 @@ class PurposeOfTravelListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); print("called api : $apiUrlData"); @@ -180,11 +182,10 @@ class PurposeOfTravelListState extends State { allPurposeOfTravel.where((object) { final isActiveStatus = object['is_active'] == "1" ? "active" : "inactive"; - return (object['id']?.toLowerCase().contains( - lowerQuery, - ) ?? + return (object['id']?.toLowerCase().contains(lowerQuery) ?? + false) || + (object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) || - (object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) || // (object['description']?.toLowerCase().contains(lowerQuery) ?? // false) || (isActiveStatus.contains(lowerQuery)); @@ -284,15 +285,13 @@ class PurposeOfTravelListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Purpose Of Travel Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Purpose Of Travel Details'), ], ), ), @@ -308,8 +307,8 @@ class PurposeOfTravelListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.08), - // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -583,10 +582,10 @@ class PurposeOfTravelListState extends State { rows: paginatedPurposeOfTravel.map((tableObject) { String purposeOfTravelId = - tableObject['id'] - .toString(); // Get user ID + tableObject['id'].toString(); // Get user ID bool isSelected = - selectedPurposeOfTravelId == purposeOfTravelId; + selectedPurposeOfTravelId == + purposeOfTravelId; return DataRow( cells: [ @@ -635,7 +634,8 @@ class PurposeOfTravelListState extends State { // ), GestureDetector( child: Tooltip( - message: 'Edit Purpose Of Travel Details', + message: + 'Edit Purpose Of Travel Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, @@ -646,10 +646,10 @@ class PurposeOfTravelListState extends State { // final userId = getUserId(user['user_id']); // final usersData = await getUserDetails(userId); // - final purposeOfTravelId = int.tryParse( - tableObject['id'] - .toString(), - ); + final purposeOfTravelId = + int.tryParse( + tableObject['id'].toString(), + ); if (purposeOfTravelId != null) { print( @@ -664,7 +664,9 @@ class PurposeOfTravelListState extends State { showDialog( context: context, builder: - (context) => PurposeOfTravelData( + ( + context, + ) => PurposeOfTravelData( isDesktop: isDesktop, purposeOfTravelId: purposeOfTravelId, // Pass the ID @@ -728,7 +730,8 @@ class PurposeOfTravelListState extends State { GestureDetector( child: Tooltip( - message: 'Edit Purpose Of Travel Details', + message: + 'Edit Purpose Of Travel Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, @@ -740,8 +743,7 @@ class PurposeOfTravelListState extends State { // final usersData = await getUserDetails(userId); // final purposeOfTravelId = int.tryParse( - cardObject['id'] - .toString(), + cardObject['id'].toString(), ); if (purposeOfTravelId != null) { @@ -757,7 +759,9 @@ class PurposeOfTravelListState extends State { showDialog( context: context, builder: - (context) => PurposeOfTravelData( + ( + context, + ) => PurposeOfTravelData( isDesktop: isDesktop, purposeOfTravelId: purposeOfTravelId, // Pass the ID diff --git a/lib/Screens/traveller/travellerDetails.dart b/lib/Screens/traveller/travellerDetails.dart index 8325f70..9302e58 100644 --- a/lib/Screens/traveller/travellerDetails.dart +++ b/lib/Screens/traveller/travellerDetails.dart @@ -106,6 +106,7 @@ class TravellerDataState extends State { } super.dispose(); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -188,7 +189,7 @@ class TravellerDataState extends State { // This triggers UI rebuild with error messages if (validateData()) { postTravellerData(); - }else{ + } else { isDisable = false; } }); @@ -235,6 +236,7 @@ class TravellerDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode(travellerData); @@ -550,22 +552,23 @@ class TravellerDataState extends State { // ), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal - // Optional: re-enable only on error - // setState(() { - // isDisable = false; - // }); - }, + // Optional: re-enable only on error + // setState(() { + // isDisable = false; + // }); + }, style: ElevatedButton.styleFrom( backgroundColor: widget.layoutColor, shape: RoundedRectangleBorder( diff --git a/lib/Screens/traveller/travellerList.dart b/lib/Screens/traveller/travellerList.dart index 6c9fde7..316b4a3 100644 --- a/lib/Screens/traveller/travellerList.dart +++ b/lib/Screens/traveller/travellerList.dart @@ -151,6 +151,7 @@ class TravellerListState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); print("called api : $apiUrlData"); @@ -294,15 +295,13 @@ class TravellerListState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Traveller Details', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Traveller Details'), ], ), ), @@ -318,8 +317,8 @@ class TravellerListState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.10), - // SizedBox(width: MediaQuery.of(context).size.width * 0.16), + // SizedBox(width: MediaQuery.of(context).size.width * 0.16), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -466,7 +465,7 @@ class TravellerListState extends State { builder: (context, snapshot) { final adjHgt = MediaQuery.of(context).size.height; if (futureTraveller == null) { - return CircularProgressIndicator(); + return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { diff --git a/lib/Screens/userManagement/create_traveller_agent/createTravelAgent.dart b/lib/Screens/userManagement/create_traveller_agent/createTravelAgent.dart index 9dc2198..90670fe 100644 --- a/lib/Screens/userManagement/create_traveller_agent/createTravelAgent.dart +++ b/lib/Screens/userManagement/create_traveller_agent/createTravelAgent.dart @@ -990,6 +990,7 @@ class _CreateTravelAgentFormDetialsState // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456'; // If updating, spoof the method Laravel-style if (isUpdating) { diff --git a/lib/Screens/userManagement/create_user/change_password.dart b/lib/Screens/userManagement/create_user/change_password.dart index 3ecc927..6e9a675 100644 --- a/lib/Screens/userManagement/create_user/change_password.dart +++ b/lib/Screens/userManagement/create_user/change_password.dart @@ -12,43 +12,35 @@ import '../../../services/apiService.dart'; import '../../../utils/auth_utils.dart'; import '../../../widgets/custom_user_form.dart'; - class ChangePasswordDialogData extends StatefulWidget { - final dynamic isDesktop; final dynamic layoutColor; final dynamic updaterUserId; final dynamic updaterEmail; const ChangePasswordDialogData({ - super.key, - this.isDesktop, - this.layoutColor, - this.updaterUserId, - this.updaterEmail + super.key, + this.isDesktop, + this.layoutColor, + this.updaterUserId, + this.updaterEmail, }); - - @override - ChangePasswordDialogDataState createState() => ChangePasswordDialogDataState(); - } + @override + ChangePasswordDialogDataState createState() => + ChangePasswordDialogDataState(); +} class ChangePasswordDialogDataState extends State { - final ApiService apiService = ApiService(); final Map controllers = {}; Map errorMessages = {}; - String? loggeduserId; String? updaterUserIdForAPI; - List dataHeader = [ - "email", - "changePassword", - "confirmPassword" - ]; + List dataHeader = ["email", "changePassword", "confirmPassword"]; // @override // void initState() { @@ -75,15 +67,13 @@ class ChangePasswordDialogDataState extends State { } setState(() { - controllers['email']?.text = widget.updaterEmail ; + controllers['email']?.text = widget.updaterEmail; controllers['changePassword']?.text = ''; controllers['confirmPassword']?.text = ''; updaterUserIdForAPI = widget.updaterUserId; }); } - - void _clearError() { setState(() { errorMessages.clear(); @@ -98,40 +88,37 @@ class ChangePasswordDialogDataState extends State { super.dispose(); } - - bool validateData() { errorMessages.clear(); - final String? email = controllers["email"]?.text; - final String? changePassword = controllers["changePassword"]?.text; - final String? confirmPassword = controllers["confirmPassword"]?.text; + final String? email = controllers["email"]?.text; + final String? changePassword = controllers["changePassword"]?.text; + final String? confirmPassword = controllers["confirmPassword"]?.text; - // Required fields check - if (email == null || email.trim().isEmpty) { - errorMessages["email"] = "Required"; - } - - if (changePassword == null || changePassword.trim().isEmpty) { - errorMessages["changePassword"] = "Required"; - } - - if (confirmPassword == null || confirmPassword.trim().isEmpty) { - errorMessages["confirmPassword"] = "Required"; - } - - // Password match check - if ((changePassword?.isNotEmpty ?? false) && - (confirmPassword?.isNotEmpty ?? false) && - changePassword != confirmPassword) { - errorMessages["changePassword"] = "Passwords do not match"; - errorMessages["confirmPassword"] = "Passwords do not match"; - } - - // setState(() {}); // Update UI with any error messages - return errorMessages.isEmpty; + // Required fields check + if (email == null || email.trim().isEmpty) { + errorMessages["email"] = "Required"; } + if (changePassword == null || changePassword.trim().isEmpty) { + errorMessages["changePassword"] = "Required"; + } + + if (confirmPassword == null || confirmPassword.trim().isEmpty) { + errorMessages["confirmPassword"] = "Required"; + } + + // Password match check + if ((changePassword?.isNotEmpty ?? false) && + (confirmPassword?.isNotEmpty ?? false) && + changePassword != confirmPassword) { + errorMessages["changePassword"] = "Passwords do not match"; + errorMessages["confirmPassword"] = "Passwords do not match"; + } + + // setState(() {}); // Update UI with any error messages + return errorMessages.isEmpty; + } Future handleSubmit() async { loggeduserId = await getUserId(); @@ -142,7 +129,6 @@ class ChangePasswordDialogDataState extends State { postData(); } }); - } Future postData() async { @@ -152,12 +138,14 @@ class ChangePasswordDialogDataState extends State { final password = controllers["changePassword"]?.text ?? ''; final confirmPassword = controllers["confirmPassword"]?.text ?? ''; - final String apiUrldata = '$apiUrl/api/user/user-password/$updaterUserIdForAPI'; + final String apiUrldata = + '$apiUrl/api/user/user-password/$updaterUserIdForAPI'; final token = await getToken(); final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; try { @@ -165,6 +153,7 @@ class ChangePasswordDialogDataState extends State { final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }; final body = jsonEncode({ "password": password, @@ -200,7 +189,6 @@ class ChangePasswordDialogDataState extends State { @override Widget build(BuildContext context) { - return AlertDialog( backgroundColor: Colors.white, contentPadding: const EdgeInsets.fromLTRB(34, 30, 34, 30), @@ -220,10 +208,7 @@ class ChangePasswordDialogDataState extends State { ], ), const SizedBox(height: 2), - Divider( - thickness: 0.2, - color: Colors.blueGrey.shade100, - ), + Divider(thickness: 0.2, color: Colors.blueGrey.shade100), const SizedBox(height: 5), Column( @@ -232,9 +217,10 @@ class ChangePasswordDialogDataState extends State { Text( "Email", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldUserWrapper( @@ -245,18 +231,19 @@ class ChangePasswordDialogDataState extends State { // ? MediaQuery.of(context).size.width * 0.330 // : MediaQuery.of(context).size.width * 0.66, child: SizedBox( - height: 40, - child: TextField( - controller: controllers["email"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Email", - labelStyle: TextStyle(fontSize: 11, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), - )), + height: 40, + child: TextField( + controller: controllers["email"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Email", + labelStyle: TextStyle(fontSize: 11, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), ), if (errorMessages["email"] != null) ...[ SizedBox(height: 5), // Space before error message @@ -267,18 +254,17 @@ class ChangePasswordDialogDataState extends State { ], ], ), - SizedBox( - height: 10, - ), + SizedBox(height: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Change Password", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldUserWrapper( @@ -286,18 +272,19 @@ class ChangePasswordDialogDataState extends State { isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( - height: 40, - child: TextField( - controller: controllers["changePassword"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Change Password", - labelStyle: TextStyle(fontSize: 11, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), - )), + height: 40, + child: TextField( + controller: controllers["changePassword"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Change Password", + labelStyle: TextStyle(fontSize: 11, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), ), if (errorMessages["changePassword"] != null) ...[ SizedBox(height: 5), // Space before error message @@ -308,18 +295,17 @@ class ChangePasswordDialogDataState extends State { ], ], ), - SizedBox( - height: 15, - ), + SizedBox(height: 15), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Confirm Password", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldUserWrapper( @@ -327,18 +313,19 @@ class ChangePasswordDialogDataState extends State { isDesktop: widget.isDesktop, color: Colors.transparent, child: SizedBox( - height: 40, - child: TextField( - controller: controllers["confirmPassword"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Confirm Password", - labelStyle: TextStyle(fontSize: 11, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), - )), + height: 40, + child: TextField( + controller: controllers["confirmPassword"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Confirm Password", + labelStyle: TextStyle(fontSize: 11, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), ), if (errorMessages["confirmPassword"] != null) ...[ SizedBox(height: 5), // Space before error message @@ -349,10 +336,8 @@ class ChangePasswordDialogDataState extends State { ], ], ), - SizedBox( - height: 15, - ), - + SizedBox(height: 15), + Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -367,17 +352,20 @@ class ChangePasswordDialogDataState extends State { borderRadius: BorderRadius.circular(8), ), ), - child: Text('Save', - style: GoogleFonts.poppins( - fontSize: 11, color: Colors.white)), + child: Text( + 'Save', + style: GoogleFonts.poppins( + fontSize: 11, + color: Colors.white, + ), + ), ), ), ], - ) + ), // : SizedBox.shrink(), ], ), ); } } - diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index 56798a4..4132c5b 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -1259,6 +1259,7 @@ class _CreateUserFormDetialsState extends State { // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456'; // If updating, spoof the method Laravel-style if (isUpdating) { diff --git a/lib/Screens/userManagement/user_List.dart b/lib/Screens/userManagement/user_List.dart index 2712a67..0cbaaa3 100644 --- a/lib/Screens/userManagement/user_List.dart +++ b/lib/Screens/userManagement/user_List.dart @@ -161,6 +161,7 @@ class _UserListScreenState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -186,6 +187,7 @@ class _UserListScreenState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -587,6 +589,9 @@ class _UserListScreenState extends State { // Attach the file to the request // Set authorization token in headers request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = + 'ts-traveltool-2025-signature-123456'; + // request.files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: fileName)); request.files.add( @@ -718,6 +723,7 @@ class _UserListScreenState extends State { // Use MultipartRequest (POST only) final request = http.MultipartRequest('POST', uri); request.headers['Authorization'] = 'Bearer $token'; + request.headers['app-signature'] = 'ts-traveltool-2025-signature-123456'; // If updating, spoof the method Laravel-style diff --git a/lib/app.dart b/lib/app.dart index 7235458..1f05d7d 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -34,8 +34,8 @@ class _MyAppState extends State { @override void initState() { super.initState(); - SemanticsBinding.instance - .ensureSemantics(); // -only for testing uncomment, Otherwise Email Template wont allow to type + // SemanticsBinding.instance + // .ensureSemantics(); // -only for testing uncomment, Otherwise Email Template wont allow to type if (kIsWeb) { final uri = Uri.parse(html.window.location.href); print("URI - $uri"); @@ -87,7 +87,7 @@ class _MyAppState extends State { print("handleTokenUsingMS- $authCode"); try { // final url = 'http://localhost:43627/tstat/auth/verifyMSAuthUser?code=$authCode'; - final url = '$apiUrl/auth/verifyMSAuthUser?code=$authCode'; + final url = '$apiUrl/api/auth/verifyMSAuthUser?code=$authCode'; print("Microsoft BE URL - $url"); final response = await http.get( Uri.parse(url), diff --git a/lib/services/apiService.dart b/lib/services/apiService.dart index c66ecd3..317ca4e 100644 --- a/lib/services/apiService.dart +++ b/lib/services/apiService.dart @@ -44,6 +44,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -80,6 +81,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -116,6 +118,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -156,6 +159,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -185,6 +189,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -240,6 +245,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -291,6 +297,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -330,6 +337,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -367,6 +375,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -404,6 +413,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -441,6 +451,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -476,6 +487,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -518,6 +530,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -559,6 +572,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -583,6 +597,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', // Add token here 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -664,6 +679,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -710,6 +726,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -747,6 +764,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -786,6 +804,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -850,6 +869,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -915,6 +935,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + // 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -965,6 +986,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1010,6 +1032,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1054,6 +1077,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1100,6 +1124,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1146,6 +1171,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1200,6 +1226,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1346,6 +1373,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1392,6 +1420,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1438,6 +1467,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1480,6 +1510,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -1534,6 +1565,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); if (response.statusCode == 200) { @@ -1573,6 +1605,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: body, ); @@ -1616,6 +1649,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: body, ); @@ -1673,6 +1707,7 @@ class ApiService { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); diff --git a/lib/utils/travelAgent_remarks.dart b/lib/utils/travelAgent_remarks.dart index 192c868..5133399 100644 --- a/lib/utils/travelAgent_remarks.dart +++ b/lib/utils/travelAgent_remarks.dart @@ -122,6 +122,7 @@ class CommentModalState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, ); @@ -143,7 +144,8 @@ class CommentModalState extends State { print("Res1 - $data"); if (!data.containsKey('data') || data['data'] is! Map) { throw Exception( - "Invalid response format: 'data' field is missing or not a Map"); + "Invalid response format: 'data' field is missing or not a Map", + ); } return data['data']; } else { @@ -186,6 +188,7 @@ class CommentModalState extends State { headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', + 'app-signature': 'ts-traveltool-2025-signature-123456', }, body: jsonEncode(remarksData), // Convert map to JSON ); @@ -255,7 +258,8 @@ class CommentModalState extends State { icon: const Icon(Icons.delete, size: 20), onPressed: () async { await postRemarksData( - isActive: 0); // Marks the remark as deleted + isActive: 0, + ); // Marks the remark as deleted Navigator.of(context).pop(); }, ), @@ -280,27 +284,30 @@ class CommentModalState extends State { const SizedBox(height: 20), // Row 3: OK button - editRemarks ? SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () { - postRemarksData(); - // You can get text from commentController.text - Navigator.of(context).pop(); // Close the modal - }, - style: ElevatedButton.styleFrom( - backgroundColor: widget.layoutColorForUser, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + width: double.infinity, + child: ElevatedButton( + onPressed: () { + postRemarksData(); + // You can get text from commentController.text + Navigator.of(context).pop(); // Close the modal + }, + style: ElevatedButton.styleFrom( + backgroundColor: widget.layoutColorForUser, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), ), - child: Text('OK', - style: GoogleFonts.poppins( - fontSize: 13, color: Colors.white)), ), - ) + child: Text( + 'OK', + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.white, + ), + ), + ), + ) : SizedBox.shrink(), ], ), diff --git a/pubspec.lock b/pubspec.lock index dd87d19..0c5d513 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -609,10 +609,10 @@ packages: dependency: transitive description: name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "1.0.6" nested: dependency: transitive description: