2229 lines
64 KiB
Dart
2229 lines
64 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:frontend/utils/auth_utils.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:universal_html/html.dart' as html;
|
|
import 'package:universal_html/js.dart';
|
|
import '../../config/apiUrl.dart';
|
|
import 'dart:convert';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
class ApiService {
|
|
Future<void> storeUserDetails(BuildContext context, String token) async {
|
|
try {
|
|
final parts = token.split('.');
|
|
if (parts.length != 3) throw Exception('Invalid token format');
|
|
|
|
final payload = json.decode(
|
|
utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))),
|
|
);
|
|
|
|
final userData = payload['data'];
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('auth_token', token);
|
|
await prefs.setString(
|
|
'user_data',
|
|
jsonEncode(userData),
|
|
); // Store full user data
|
|
|
|
if (userData != null) {
|
|
final pref = await SharedPreferences.getInstance();
|
|
// await pref.clear();
|
|
// print("Clearing Token--");
|
|
await pref.setString('auth_token', token);
|
|
await pref.setString('user_data', jsonEncode(userData));
|
|
|
|
// userRole = userData['role'];
|
|
|
|
print("store1userData - $userData");
|
|
print("store2userData11 - ${userData['role']}");
|
|
// print("userData12 - $userRole");
|
|
}
|
|
|
|
await getOrganizationData(context);
|
|
} catch (e) {
|
|
print('Error decoding token: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> logout(BuildContext context) async {
|
|
await logoutApi();
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.clear();
|
|
// Optional: clear sessionStorage if used
|
|
// html.window.sessionStorage.clear();
|
|
|
|
// Navigate to login or home page
|
|
context?.go('/');
|
|
}
|
|
|
|
Future<void> logoutApi() async {
|
|
String? userId = await getUserId();
|
|
print('userId - $userId');
|
|
|
|
final String apiUrldata = '$apiUrl/api/auth/logout?user_id=$userId';
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
print("Logout API response: $data");
|
|
} else {
|
|
throw Exception('Failed to logout. Status: ${response.statusCode}');
|
|
}
|
|
}
|
|
|
|
Future<void> storeTripUserDetails(BuildContext context, String token) async {
|
|
try {
|
|
final parts = token.split('.');
|
|
if (parts.length != 3) throw Exception('Invalid token format');
|
|
|
|
print('storeTripUserDetails - $token');
|
|
final payload = json.decode(
|
|
utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))),
|
|
);
|
|
|
|
final userData = payload['data'];
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('trip_auth_token', token);
|
|
await prefs.setString(
|
|
'trip_user_data',
|
|
jsonEncode(userData),
|
|
); // Store full user data
|
|
|
|
if (userData != null) {
|
|
final pref = await SharedPreferences.getInstance();
|
|
await pref.setString('trip_auth_token', token);
|
|
await pref.setString('trip_user_data', jsonEncode(userData));
|
|
|
|
// userRole = userData['role'];
|
|
|
|
print("storetrip_userData - $userData");
|
|
print("storetrip_2userData11 - ${userData['role']}");
|
|
// print("userData12 - $userRole");
|
|
}
|
|
|
|
// await getOrganizationData(context);
|
|
} catch (e) {
|
|
print('Error decoding token: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> getOrganizationData(BuildContext context) async {
|
|
try {
|
|
print("ORG getUpdatedServices");
|
|
final result = await fetchOrganization(context);
|
|
print("UUPdatedServices - $result");
|
|
|
|
// ✅ Save to local storage
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final jsonString = jsonEncode(result);
|
|
await prefs.setString('org_data', jsonString);
|
|
print("✅ Organization data saved to SharedPreferences.");
|
|
|
|
print("selectedOrg - $result");
|
|
} catch (e) {
|
|
print('Error fetching updatedServices list: $e');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchCountryList(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getcountryMaster';
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("Country - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load country list');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchHotelsList(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getHotels';
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("Hotelss - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load country list');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchAirlineList(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getAirlineMaster';
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("Airline - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load country list');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchUsers(BuildContext context) async {
|
|
String? ordId = await getOrgId();
|
|
final String apiUrlData = '$apiUrl/api/users?org_id=$ordId';
|
|
final String? token = await getToken();
|
|
|
|
print("Fetch Users");
|
|
print("TOEKRWE: $token");
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrlData),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
return data['data']; // Returning raw JSON list
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load users');
|
|
}
|
|
}
|
|
|
|
Future<List> fetchCostCenter(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getCostCenterMaster';
|
|
|
|
final token = await getToken();
|
|
|
|
final userId = await getUserId();
|
|
|
|
// print("SUSRTRT- $userId");
|
|
//
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
List<dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
|
// setState(() {
|
|
// apiCostData = plansJson; // Store API response in state
|
|
// if(apiCostData!.isNotEmpty){
|
|
// selectedCostCenterId =apiCostData?.first['department_id'];
|
|
// }
|
|
|
|
// if (apiCostData != null && apiCostData!.isNotEmpty) {
|
|
// selectedCostCenterId ??= apiCostData!.first['department_id']?.toString();
|
|
// }
|
|
// });
|
|
|
|
print('plansJSON');
|
|
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<List> fetchDepartmentCostCenter(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getDepartmentList';
|
|
|
|
final token = await getToken();
|
|
|
|
final userId = await getUserId();
|
|
|
|
// print("SUSRTRT- $userId");
|
|
//
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
List<dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
|
// setState(() {
|
|
// apiCostData = plansJson; // Store API response in state
|
|
// if(apiCostData!.isNotEmpty){
|
|
// selectedCostCenterId =apiCostData?.first['department_id'];
|
|
// }
|
|
|
|
// if (apiCostData != null && apiCostData!.isNotEmpty) {
|
|
// selectedCostCenterId ??= apiCostData!.first['department_id']?.toString();
|
|
// }
|
|
// });
|
|
|
|
print('plansJSON');
|
|
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> fetchMasterDropdown(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getDropdownMaster';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> plansJson =
|
|
data['data']; // 'data' is a Map, not a List
|
|
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchAllServices(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/service';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchAllGroup(BuildContext context) async {
|
|
String? orgId = await getOrgId();
|
|
|
|
final String apiUrldata = '$apiUrl/api/groups?for=table_view&org_id=$orgId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchFindGroup(BuildContext context) async {
|
|
String? orgId = await getOrgId();
|
|
|
|
final String apiUrldata = '$apiUrl/api/groups/find/$orgId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchAllPolicy(BuildContext context) async {
|
|
String? orgId = await getOrgId();
|
|
|
|
final String apiUrldata = '$apiUrl/api/policy?for=table_view&org_id=$orgId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getSinglePolicy(
|
|
int policyId,
|
|
BuildContext context,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/policy/find/${policyId}';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> plansJson =
|
|
data['data']; // 'data' is a Map, not a List
|
|
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> fetchOrganization(BuildContext context) async {
|
|
String? orgId = await getOrgId();
|
|
|
|
// final String apiUrldata = '$apiUrl/api/organizations';
|
|
final String apiUrldata = '$apiUrl/api/organizations/find/$orgId';
|
|
|
|
final token = await getToken();
|
|
print('ORGFindToken - $token');
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
// Make sure each item is a Map<String, dynamic>
|
|
// final List<Map<String, dynamic>> orgList =
|
|
// List<Map<String, dynamic>>.from(data['data']);
|
|
// return orgList;
|
|
|
|
return Map<String, dynamic>.from(data['data']);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load organizations');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getViewPlan(
|
|
String planId,
|
|
userId,
|
|
BuildContext context,
|
|
) async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/plans/cancle_plan?plan_id=$planId&updated_by=$userId';
|
|
|
|
// final String apiUrldata = '$apiUrl/api/plans/find/$planId';
|
|
print("API URL: $apiUrldata");
|
|
// final token = await getToken();
|
|
|
|
final token = await getToken();
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token', // Add token here
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final Map<String, dynamic>? resData = json.decode(response.body);
|
|
|
|
return resData?["data"];
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getViewPlanEdit(
|
|
String planId,
|
|
BuildContext context,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/plans/find/$planId';
|
|
print("API URL: $apiUrldata");
|
|
// final token = await getToken();
|
|
|
|
final token = await getToken();
|
|
|
|
final response = await http.put(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token', // Add token here
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final Map<String, dynamic>? resData = json.decode(response.body);
|
|
|
|
return resData?["data"];
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<void> handleTokenRefresh(BuildContext context, String userId) async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/user/refreshUserToken?user_id=$userId';
|
|
print("API URL: $userId");
|
|
// final token = await getToken();
|
|
|
|
final token = await getToken();
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
print("data- $data");
|
|
|
|
final token = data['token']; // Assuming the token is in response
|
|
// final userId = data['user_id'].toString();
|
|
|
|
print("Token - $token");
|
|
await storeUserDetails(context, token);
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<void> handleTripWiseToken(String userId, BuildContext context) async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/user/refreshUserToken?user_id=$userId';
|
|
print("API URL: $userId");
|
|
// final token = await getToken();
|
|
|
|
final token = await getToken();
|
|
|
|
print('handleTripWiseToken OLd - $token');
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
print("data- $data");
|
|
|
|
final token = data['token']; // Assuming the token is in response
|
|
// final userId = data['user_id'].toString();
|
|
|
|
print('handleTripWiseToken NEW - $token');
|
|
await storeTripUserDetails(context, token);
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<void> viewPlan(
|
|
BuildContext context,
|
|
String planId, {
|
|
bool isViewMode = false,
|
|
bool isMyTrips = false,
|
|
}) async {
|
|
try {
|
|
Map<String, dynamic> planData = await getViewPlanEdit(planId, context);
|
|
print("ViewAAA - $planData");
|
|
|
|
context.go(
|
|
isMyTrips ? '/createPlan' : '/allTrips/trips',
|
|
extra: {'planData': planData, 'isViewMode': isViewMode},
|
|
);
|
|
} catch (e) {
|
|
print("Error fetching plan: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> viewPlanForApprover(
|
|
BuildContext context,
|
|
String planId,
|
|
String? approverId,
|
|
String? delegaterId,
|
|
String? approver_status, {
|
|
bool isViewMode = false,
|
|
bool isApprover = true,
|
|
}) async {
|
|
try {
|
|
Map<String, dynamic> planData = await getViewPlanEdit(planId, context);
|
|
print("ViewAAA - $planData");
|
|
|
|
context.replace(
|
|
'/approver/plans',
|
|
extra: {
|
|
'planData': planData,
|
|
'approver_status': approver_status,
|
|
'approverId': approverId,
|
|
'delegaterId': delegaterId,
|
|
'isViewMode': isViewMode,
|
|
'isApprover': isApprover,
|
|
},
|
|
);
|
|
} catch (e) {
|
|
print("Error fetching plan: $e");
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> fetchUserApprovalList(
|
|
BuildContext context,
|
|
) async {
|
|
String? orgId = await getOrgId();
|
|
String? userId = await getUserId();
|
|
|
|
// final String apiUrldata = '$apiUrl/api/organizations';
|
|
final String apiUrldata =
|
|
'$apiUrl/api/plans/findApprovalList?user_id=$userId&org_id=$orgId';
|
|
|
|
// '$apiUrl/api/findApprovalList?user_id=$userId&org_id=$orgId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
// Make sure each item is a Map<String, dynamic>
|
|
// final List<Map<String, dynamic>> orgList =
|
|
// List<Map<String, dynamic>>.from(data['data']);
|
|
// return orgList;
|
|
|
|
return Map<String, dynamic>.from(data['data']);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load organizations');
|
|
}
|
|
}
|
|
|
|
// Flight From - To
|
|
|
|
Future<List<dynamic>> fetchFlightsCountryList(
|
|
BuildContext context,
|
|
String? tripType,
|
|
) async {
|
|
print("FlightTripType- $tripType");
|
|
|
|
final String apiUrldata =
|
|
'$apiUrl/api/getAirportCodeMaster?trip_type=$tripType';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("Country - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load country list');
|
|
}
|
|
}
|
|
|
|
Future<List<dynamic>> fetchTrainCountryList(BuildContext context) async {
|
|
final String apiUrldata = '$apiUrl/api/getTrainCodeMaster';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("Country - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
return data['data'];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load country list');
|
|
}
|
|
}
|
|
|
|
Future<void> getPdfDownload(BuildContext context, planId) async {
|
|
final String apiUrldata = '$apiUrl/api/plans/download?plan_id=$planId';
|
|
|
|
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
print("PDf Dowloaded");
|
|
|
|
// Create a blob from the response body
|
|
final blob = html.Blob([response.bodyBytes]);
|
|
|
|
// Generate a download URL for the blob
|
|
final url = html.Url.createObjectUrlFromBlob(blob);
|
|
|
|
// Create a link element to trigger the download
|
|
final anchor =
|
|
html.AnchorElement(href: url)
|
|
..setAttribute('download', 'trip_plan_$planId.pdf')
|
|
..click();
|
|
|
|
// Revoke the download URL to free up resources
|
|
html.Url.revokeObjectUrl(url);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else if (response.statusCode == 404) {
|
|
// showDialog(
|
|
// context: context,
|
|
// builder: (BuildContext context) {
|
|
// return AlertDialog(
|
|
// title: Text('File not found.'),
|
|
// // content: Text('File not found.'),
|
|
// actions: [
|
|
// TextButton(
|
|
// child: Text('OK'),
|
|
// onPressed: () {
|
|
// Navigator.of(context).pop(); // Close the dialog
|
|
// },
|
|
// ),
|
|
// ],
|
|
// );
|
|
// },
|
|
// );
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<void> getPassportDocDownload(BuildContext context, userId) async {
|
|
// final String apiUrldata = '$apiUrl/api/plans/download?plan_id=$planId';
|
|
final String apiUrldata = '$apiUrl/api/downloadPassport?user_id=$userId';
|
|
|
|
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
print("PDf Dowloaded");
|
|
final contentType = response.headers['content-type'] ?? '';
|
|
|
|
// print('contentType - $contentType');
|
|
// String fileName = "Document";
|
|
// if (contentType.contains("pdf")) {
|
|
// fileName += ".pdf";
|
|
// } else if (contentType.contains("png")) {
|
|
// fileName += ".png";
|
|
// } else if (contentType.contains("jpeg") ||
|
|
// contentType.contains("jpg")) {
|
|
// fileName += ".jpg";
|
|
// } else {
|
|
// // fallback (unknown type, save as bin)
|
|
// fileName += ".$contentType";
|
|
// }
|
|
|
|
final disposition = response.headers['content-disposition'] ?? '';
|
|
String fileName = "passport_$userId";
|
|
|
|
final regExp = RegExp(
|
|
r'filename[^;=\n]*=((['
|
|
'"]).*?\2|[^;\n]*)',
|
|
);
|
|
final match = regExp.firstMatch(disposition);
|
|
if (match != null) {
|
|
fileName = match.group(1)!.replaceAll('"', '');
|
|
}
|
|
|
|
// Create a blob from the response body
|
|
final blob = html.Blob([response.bodyBytes]);
|
|
|
|
// Generate a download URL for the blob
|
|
final url = html.Url.createObjectUrlFromBlob(blob);
|
|
|
|
// Create a link element to trigger the download
|
|
final anchor =
|
|
html.AnchorElement(href: url)
|
|
..setAttribute('download', fileName)
|
|
..click();
|
|
|
|
// Revoke the download URL to free up resources
|
|
html.Url.revokeObjectUrl(url);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else if (response.statusCode == 404) {
|
|
// showDialog(
|
|
// context: context,
|
|
// builder: (BuildContext context) {
|
|
// return AlertDialog(
|
|
// title: Text('File not found.'),
|
|
// // content: Text('File not found.'),
|
|
// actions: [
|
|
// TextButton(
|
|
// child: Text('OK'),
|
|
// onPressed: () {
|
|
// Navigator.of(context).pop(); // Close the dialog
|
|
// },
|
|
// ),
|
|
// ],
|
|
// );
|
|
// },
|
|
// );
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<void> getForexPdfDownload(BuildContext context, forexId) async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/plans/forexDownload?forex_id=$forexId';
|
|
|
|
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
print("PDf Dowloaded");
|
|
|
|
// Create a blob from the response body
|
|
final blob = html.Blob([response.bodyBytes]);
|
|
|
|
// Generate a download URL for the blob
|
|
final url = html.Url.createObjectUrlFromBlob(blob);
|
|
|
|
// Create a link element to trigger the download
|
|
final anchor =
|
|
html.AnchorElement(href: url)
|
|
..setAttribute('download', 'Forex_$forexId.pdf')
|
|
..click();
|
|
|
|
// Revoke the download URL to free up resources
|
|
html.Url.revokeObjectUrl(url);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else if (response.statusCode == 404) {
|
|
// showDialog(
|
|
// context: context,
|
|
// builder: (BuildContext context) {
|
|
// return AlertDialog(
|
|
// title: Text('File not found.'),
|
|
// // content: Text('File not found.'),
|
|
// actions: [
|
|
// TextButton(
|
|
// child: Text('OK'),
|
|
// onPressed: () {
|
|
// Navigator.of(context).pop(); // Close the dialog
|
|
// },
|
|
// ),
|
|
// ],
|
|
// );
|
|
// },
|
|
// );
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
// download the Template for bulk upload the user
|
|
Future<Map<String, dynamic>> getDownloadUserTemplateForUpload(
|
|
BuildContext context,
|
|
) async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
|
|
|
|
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
print("XL Dowloaded");
|
|
|
|
// Create a blob from the response body
|
|
final blob = html.Blob([response.bodyBytes]);
|
|
|
|
// Generate a download URL for the blob
|
|
final url = html.Url.createObjectUrlFromBlob(blob);
|
|
|
|
// Create a link element to trigger the download
|
|
final anchor =
|
|
html.AnchorElement(href: url)
|
|
..setAttribute('download', 'user_file.xlsx')
|
|
..click();
|
|
|
|
// Revoke the download URL to free up resources
|
|
html.Url.revokeObjectUrl(url);
|
|
return {'status': true, 'message': 'Successfully Downloaded'};
|
|
} catch (e) {
|
|
return {'status': false, 'message': 'Download error: $e'};
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else if (response.statusCode == 404) {
|
|
return {'status': false, 'message': 'File not found (404).'};
|
|
} else {
|
|
return {'status': false, 'message': 'Failed to download. Try again.'};
|
|
}
|
|
}
|
|
|
|
//---------------------------------------User Management-----------------------------------
|
|
|
|
Future<Map<String, dynamic>> getSingleUser(
|
|
BuildContext context,
|
|
int userId,
|
|
) async {
|
|
print('Single USer 1 - $userId');
|
|
|
|
final String apiUrldata = '$apiUrl/api/users/find/$userId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
print('Single USer 1');
|
|
|
|
Map<String, dynamic> plansJson =
|
|
data['data']; // 'data' is a Map, not a List
|
|
|
|
print('Single USer 2');
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getForexDetailsFind(
|
|
BuildContext context,
|
|
int userId,
|
|
) async {
|
|
print('Single Forez 1 - $userId');
|
|
|
|
// final String apiUrldata = '$apiUrl/api/users/find/$userId';
|
|
final String apiUrldata =
|
|
'$apiUrl/api/findForexPerdiem?forex_perdiem_id=$userId';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print("forexDat - $data");
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<dynamic> forexList = data['data'];
|
|
|
|
if (forexList.isEmpty) {
|
|
throw Exception('No forex data found.');
|
|
}
|
|
|
|
return forexList.first as Map<String, dynamic>;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
// ---
|
|
Future<Map<String, dynamic>> getDepartmentDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/findDepartment?id=$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
// print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<Map<String, dynamic>> listData =
|
|
List<Map<String, dynamic>>.from(data['data']);
|
|
|
|
if (listData.isEmpty) {
|
|
throw Exception("No department found with ID $id");
|
|
}
|
|
|
|
return listData[0];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load department details');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getPurposeOfTravelDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/findPurposeOfTravel?id=$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
// print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<Map<String, dynamic>> listData =
|
|
List<Map<String, dynamic>>.from(data['data']);
|
|
|
|
if (listData.isEmpty) {
|
|
throw Exception("No department found with ID $id");
|
|
}
|
|
|
|
return listData[0];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load department details');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getTemplateFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/template/find/$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.put(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
// print(data);
|
|
|
|
// if (!data.containsKey('data') || data['data'] is! List) {
|
|
// throw Exception(
|
|
// "Invalid response format: 'data' field is missing or not a List");
|
|
// }
|
|
//
|
|
// final List<Map<String, dynamic>> listData =
|
|
// List<Map<String, dynamic>>.from(data['data']);
|
|
//
|
|
// if (listData.isEmpty) {
|
|
// throw Exception("No department found with ID $id");
|
|
// }
|
|
//
|
|
// return listData[0];
|
|
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
return Map<String, dynamic>.from(data['data']);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load department details');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getForexTemplate() async {
|
|
final String apiUrldata =
|
|
'$apiUrl/api/getForexTemplate?template_name=forex';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
print(data);
|
|
|
|
// if (!data.containsKey('data') || data['data'] is! List) {
|
|
// throw Exception(
|
|
// "Invalid response format: 'data' field is missing or not a List");
|
|
// }
|
|
//
|
|
// final List<Map<String, dynamic>> listData =
|
|
// List<Map<String, dynamic>>.from(data['data']);
|
|
//
|
|
// if (listData.isEmpty) {
|
|
// throw Exception("No department found with ID $id");
|
|
// }
|
|
//
|
|
// return listData[0];
|
|
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
|
|
return Map<String, dynamic>.from(data['data']);
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else {
|
|
throw Exception('Failed to load department details');
|
|
}
|
|
}
|
|
|
|
Future<bool> showCancelConfirmationDialog(
|
|
BuildContext context,
|
|
Color? layoutColor,
|
|
) async {
|
|
return await showDialog<bool>(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
backgroundColor: Colors.white,
|
|
title: Text(
|
|
'Cancel Confirmation',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
content: Text(
|
|
'Do you want to cancel?',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 14.5,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
actions: [
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
foregroundColor: layoutColor,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
side: BorderSide(
|
|
color: layoutColor ?? Colors.grey,
|
|
width: 2,
|
|
),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
),
|
|
onPressed: () {
|
|
Navigator.of(context).pop(false);
|
|
},
|
|
child: Text(
|
|
"Cancel",
|
|
style: GoogleFonts.poppins(fontSize: 12),
|
|
),
|
|
),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: layoutColor, // Keep original color
|
|
foregroundColor: Colors.white, // Keep original color
|
|
disabledBackgroundColor:
|
|
layoutColor, // Ensure color remains when disabled
|
|
disabledForegroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
side: BorderSide(
|
|
color: layoutColor ?? Colors.grey,
|
|
width: 1,
|
|
),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
),
|
|
onPressed:
|
|
() => Navigator.of(
|
|
context,
|
|
).pop(true), // Disable when in view mode
|
|
child: Text("OK", style: GoogleFonts.poppins(fontSize: 12)),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
) ??
|
|
false; // Default to false if dismissed
|
|
}
|
|
|
|
Future<void> viewPlanTravelAgent(
|
|
BuildContext context,
|
|
String planId, {
|
|
bool isViewMode = false,
|
|
bool isMyTrips = false,
|
|
}) async {
|
|
try {
|
|
Map<String, dynamic> planData = await getViewPlanEdit(planId, context);
|
|
print("ViewAAA - $planData");
|
|
|
|
context.go(
|
|
'/travelagent/trips',
|
|
extra: {'planData': planData, 'isViewMode': isViewMode},
|
|
);
|
|
} catch (e) {
|
|
print("Error fetching plan: $e");
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getCostCenterDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/findCostCenter?cost_center_id=$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
// print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<Map<String, dynamic>> listData =
|
|
List<Map<String, dynamic>>.from(data['data']);
|
|
|
|
if (listData.isEmpty) {
|
|
throw Exception("No CostCenter found with ID $id");
|
|
}
|
|
|
|
return listData[0];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load CostCenter details');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getHotelsDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/findHotels?hotel_id=$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
// print('findout the result');
|
|
// print(data.runtimeType);
|
|
// print(data);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<Map<String, dynamic>> listData =
|
|
List<Map<String, dynamic>>.from(data['data']);
|
|
|
|
if (listData.isEmpty) {
|
|
throw Exception("No Hotel data found with ID $id");
|
|
}
|
|
|
|
return listData[0];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load Hotel details');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getGroupDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/groups/find/$id';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
print(data);
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
print('Single USer 1');
|
|
|
|
Map<String, dynamic> plansJson =
|
|
data['data']; // 'data' is a Map, not a List
|
|
|
|
print('Single USer 2');
|
|
return plansJson;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load plans');
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getTravellerDetailsFind(
|
|
BuildContext context,
|
|
int id,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/travellers/find?traveller_id=$id';
|
|
|
|
//c
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
|
|
if (!data.containsKey('data') || data['data'] is! List) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a List",
|
|
);
|
|
}
|
|
|
|
final List<Map<String, dynamic>> listData =
|
|
List<Map<String, dynamic>>.from(data['data']);
|
|
|
|
if (listData.isEmpty) {
|
|
throw Exception("No Traveller data found with ID $id");
|
|
}
|
|
|
|
return listData[0];
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load Hotel details');
|
|
}
|
|
}
|
|
|
|
// ----------------------- User Management - CheckDuplicate ---------------
|
|
Future<Map<String, dynamic>> CheckDuplicate(
|
|
BuildContext context,
|
|
String label,
|
|
String field,
|
|
String value,
|
|
String? userId,
|
|
) async {
|
|
String apiUrldata;
|
|
if (userId == null || userId.isEmpty) {
|
|
apiUrldata = '$apiUrl/api/checkDuplicate?$field=$value';
|
|
} else {
|
|
apiUrldata = '$apiUrl/api/checkDuplicate?$field=$value&user_id=$userId';
|
|
}
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
|
|
// Updated to match actual response structure
|
|
if (data['status'] == "exists") {
|
|
print("${data['field']} - $value already exists");
|
|
return {"message": "$label already exists", "field": data['field']};
|
|
} else {
|
|
print("$label - $value is a new value");
|
|
return {};
|
|
}
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception(
|
|
'Failed to load checkDuplicate data. Status code: ${response.statusCode}',
|
|
);
|
|
}
|
|
}
|
|
|
|
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
|
// ----------------------- Report -------------------------
|
|
Future<Map<String, dynamic>> CallReports(
|
|
BuildContext context,
|
|
String apiRoute,
|
|
String body,
|
|
) async {
|
|
String apiUrldata = '$apiUrl/api/$apiRoute';
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.post(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
body: body,
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
final data = json.decode(response.body);
|
|
return data;
|
|
} catch (e) {
|
|
throw Exception('Error parsing response: $e');
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception(
|
|
'Failed to load data. Status code: ${response.statusCode}',
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> reportExcelDownload(
|
|
BuildContext context,
|
|
String apiRoute,
|
|
String body,
|
|
String name,
|
|
) async {
|
|
final String apiUrldata = '$apiUrl/api/$apiRoute';
|
|
|
|
// Sanitize name for filename (optional)
|
|
final safeName = name.replaceAll(
|
|
RegExp(r'[^\w\s-]'),
|
|
'',
|
|
); // remove any special chars if needed
|
|
final excelName = '$safeName.xlsx';
|
|
|
|
final token = await getToken();
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.post(
|
|
Uri.parse(apiUrldata),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
body: body,
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
print("report XL Dowloaded");
|
|
print(excelName);
|
|
// Create a blob from the response body
|
|
final blob = html.Blob([response.bodyBytes]);
|
|
|
|
// Generate a download URL for the blob
|
|
final url = html.Url.createObjectUrlFromBlob(blob);
|
|
|
|
// Create a link element to trigger the download
|
|
final anchor =
|
|
html.AnchorElement(href: url)
|
|
..setAttribute('download', excelName)
|
|
..click();
|
|
|
|
// Revoke the download URL to free up resources
|
|
html.Url.revokeObjectUrl(url);
|
|
// throw Exception('Sucessfully Downloaded');
|
|
return {'status': true, 'message': 'Successfully Downloaded'};
|
|
} catch (e) {
|
|
// throw Exception('Error parsing response: $e');
|
|
return {'status': false, 'message': 'Download error: $e'};
|
|
}
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else if (response.statusCode == 404) {
|
|
// throw Exception('File not found.');
|
|
return {'status': false, 'message': 'File not found (404).'};
|
|
} else {
|
|
// throw Exception('Failed to Download');
|
|
return {'status': false, 'message': 'Failed to download. Try again.'};
|
|
}
|
|
}
|
|
|
|
// ----------------------- Report -------------------------
|
|
|
|
Future<List<dynamic>> fetchGetHotels(BuildContext context) async {
|
|
// return [];
|
|
final orgId = await getOrgId();
|
|
final String apiUrlData = '$apiUrl/api/getHotels';
|
|
|
|
final String? token = await getToken();
|
|
|
|
print("Fetch Hotels 2KN : $token");
|
|
|
|
if (token == null) {
|
|
throw Exception('Token not found. Please log in.');
|
|
}
|
|
|
|
final response = await http.get(
|
|
Uri.parse(apiUrlData),
|
|
headers: {
|
|
'Authorization': 'Bearer $token',
|
|
'Content-Type': 'application/json',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
return data['data']; // Returning raw JSON list
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await logout(context);
|
|
return [];
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load users');
|
|
}
|
|
}
|
|
}
|