183 lines
5.6 KiB
Dart
183 lines
5.6 KiB
Dart
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<Map<String, dynamic>> 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<Map<String, dynamic>> post(
|
|
String endpoint, Map<String, dynamic> 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<String, dynamic> _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<List<Map<String, dynamic>>> getCutiList() async {
|
|
final response = await get('${ApiConfig.cuti}/list');
|
|
return List<Map<String, dynamic>>.from(response['data']);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> submitCuti(Map<String, dynamic> cutiData) async {
|
|
return await post(ApiConfig.cuti, cutiData);
|
|
}
|
|
|
|
// Contoh penggunaan untuk fitur absensi
|
|
Future<List<Map<String, dynamic>>> getAbsensiList() async {
|
|
final response = await get('${ApiConfig.absensi}/list');
|
|
return List<Map<String, dynamic>>.from(response['data']);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> submitAbsensi(
|
|
Map<String, dynamic> absensiData) async {
|
|
return await post(ApiConfig.absensi, absensiData);
|
|
}
|
|
|
|
static Future<Map<String, dynamic>> multipartRequest(
|
|
String url,
|
|
String method,
|
|
Map<String, String> fields,
|
|
Map<String, File> 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<List<Leave>> 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<String, dynamic> jsonResponse = json.decode(response.body);
|
|
|
|
if (jsonResponse['data'] != null) {
|
|
List<dynamic> 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;
|
|
}
|
|
}
|
|
}
|