import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; import 'package:qyuota/config/api_config.dart'; import 'package:qyuota/services/auth_service.dart'; import 'package:qyuota/models/leave.dart'; class ApiService { final AuthService _authService = AuthService(); Future> get(String endpoint) async { try { final token = await _authService.getToken(); if (token == null) { throw Exception('Token not found. Please login again.'); } final response = await http.get( Uri.parse('${ApiConfig.baseUrl}$endpoint'), headers: ApiConfig.authHeaders(token), ); return _handleResponse(response); } catch (e) { throw Exception('Failed to make GET request: $e'); } } Future> post( String endpoint, Map body) async { try { final token = await _authService.getToken(); if (token == null) { throw Exception('Token not found. Please login again.'); } final response = await http.post( Uri.parse('${ApiConfig.baseUrl}$endpoint'), headers: ApiConfig.authHeaders(token), body: jsonEncode(body), ); return _handleResponse(response); } catch (e) { throw Exception('Failed to make POST request: $e'); } } Map _handleResponse(http.Response response) { final responseData = jsonDecode(response.body); if (response.statusCode >= 200 && response.statusCode < 300) { return responseData; } else { throw Exception(responseData['message'] ?? 'Request failed'); } } // Contoh penggunaan untuk fitur cuti Future>> getCutiList() async { final response = await get('${ApiConfig.cuti}/list'); return List>.from(response['data']); } Future> submitCuti(Map cutiData) async { return await post(ApiConfig.cuti, cutiData); } // Contoh penggunaan untuk fitur absensi Future>> getAbsensiList() async { final response = await get('${ApiConfig.absensi}/list'); return List>.from(response['data']); } Future> submitAbsensi( Map absensiData) async { return await post(ApiConfig.absensi, absensiData); } static Future> multipartRequest( String url, String method, Map fields, Map files, String? token, ) async { try { final request = http.MultipartRequest(method, Uri.parse(url)); if (token != null) { request.headers.addAll({ 'Authorization': 'Bearer $token', 'Accept': 'application/json', }); } // Add fields request.fields.addAll(fields); // Add files for (var entry in files.entries) { final file = await http.MultipartFile.fromPath( entry.key, entry.value.path, ); request.files.add(file); } final streamedResponse = await request.send(); final response = await http.Response.fromStream(streamedResponse); if (response.statusCode == 200 || response.statusCode == 201) { return jsonDecode(response.body); } else { throw Exception('Multipart request failed: ${response.statusCode}'); } } catch (e) { throw Exception('Multipart request failed: $e'); } } Future> getLeaves() async { try { final token = await AuthService().getToken(); final userId = await AuthService().getUserId(); if (token == null || userId == null) { throw Exception('Token atau User ID tidak ditemukan'); } final queryParameters = {'user_id': userId}; final uri = Uri.parse(ApiConfig.cuti).replace(queryParameters: queryParameters); // Debug logs print('Fetching leaves for user_id: $userId'); print('Request URL: $uri'); final response = await http.get( uri, headers: ApiConfig.authHeaders(token), ); // Debug response print('Response status code: ${response.statusCode}'); print('Response body: ${response.body}'); if (response.statusCode == 200) { final Map jsonResponse = json.decode(response.body); if (jsonResponse['data'] != null) { List data = jsonResponse['data']; final leaves = data.map((item) => Leave.fromJson(item)).toList(); // Sort leaves by date (newest first) leaves.sort((a, b) { if (a.startDate == null || b.startDate == null) return 0; return DateTime.parse(b.startDate).compareTo(DateTime.parse(a.startDate)); }); return leaves; } else { return []; } } else if (response.statusCode == 401) { throw Exception('Sesi telah berakhir, silakan login kembali'); } else if (response.statusCode == 403) { // Handle forbidden response (no permission to view these leaves) print('Received 403 from server: User doesn\'t have permission to view these leaves'); return []; // Return empty list instead of failing } else { final errorBody = json.decode(response.body); final errorMessage = errorBody['message'] ?? 'Gagal memuat data cuti'; throw Exception(errorMessage); } } catch (e) { if (e is FormatException) { throw Exception('Format data tidak valid'); } rethrow; } } }