179 lines
5.3 KiB
Dart
179 lines
5.3 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:marco/helpers/services/storage/local_storage.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
|
|
class ApiService {
|
|
static const String baseUrl = "https://stageapi.marcoaiot.com/api";
|
|
|
|
// ===== Common Helpers =====
|
|
|
|
static Future<String?> _getToken() async {
|
|
final token = LocalStorage.getJwtToken();
|
|
if (token == null) {
|
|
print("No JWT token found. Please log in.");
|
|
}
|
|
return token;
|
|
}
|
|
|
|
static Map<String, String> _headers(String token) => {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer $token',
|
|
};
|
|
|
|
static Future<http.Response?> _getRequest(String endpoint,
|
|
{Map<String, String>? queryParams}) async {
|
|
final token = await _getToken();
|
|
if (token == null) return null;
|
|
|
|
final uri =
|
|
Uri.parse("$baseUrl$endpoint").replace(queryParameters: queryParams);
|
|
print('GET request: $uri');
|
|
|
|
try {
|
|
return await http.get(uri, headers: _headers(token));
|
|
} catch (e) {
|
|
print("HTTP GET Exception: $e");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static dynamic _parseResponse(http.Response response, {String label = ''}) {
|
|
print("$label Response: ${response.body}");
|
|
if (response.statusCode == 200) {
|
|
final json = jsonDecode(response.body);
|
|
if (json['success'] == true) return json['data'];
|
|
print("API Error: ${json['message']}");
|
|
} else {
|
|
print("HTTP Error [$label]: ${response.statusCode}");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// ===== API Calls =====
|
|
|
|
static Future<List<dynamic>?> getProjects() async {
|
|
final response = await _getRequest("/project/list");
|
|
return response != null
|
|
? _parseResponse(response, label: 'Projects')
|
|
: null;
|
|
}
|
|
|
|
static Future<List<dynamic>?> getEmployeesByProject(int projectId) async {
|
|
final response = await _getRequest("/attendance/project/team",
|
|
queryParams: {"projectId": "$projectId"});
|
|
return response != null
|
|
? _parseResponse(response, label: 'Employees')
|
|
: null;
|
|
}
|
|
|
|
static Future<List<dynamic>?> getAttendanceLogs(
|
|
int projectId, {
|
|
DateTime? dateFrom,
|
|
DateTime? dateTo,
|
|
}) async {
|
|
final query = {
|
|
"projectId": "$projectId",
|
|
if (dateFrom != null)
|
|
"dateFrom": DateFormat('yyyy-MM-dd').format(dateFrom),
|
|
if (dateTo != null) "dateTo": DateFormat('yyyy-MM-dd').format(dateTo),
|
|
};
|
|
|
|
final response =
|
|
await _getRequest("/attendance/project/log", queryParams: query);
|
|
return response != null
|
|
? _parseResponse(response, label: 'Attendance Logs')
|
|
: null;
|
|
}
|
|
|
|
static Future<List<dynamic>?> getAttendanceLogView(int id) async {
|
|
final response = await _getRequest("/attendance/log/attendance/$id");
|
|
return response != null
|
|
? _parseResponse(response, label: 'Attendance Log Details')
|
|
: null;
|
|
}
|
|
|
|
static Future<List<dynamic>?> getRegularizationLogs(int projectId) async {
|
|
final response = await _getRequest("/attendance/regularize",
|
|
queryParams: {"projectId": "$projectId"});
|
|
return response != null
|
|
? _parseResponse(response, label: 'Regularization')
|
|
: null;
|
|
}
|
|
|
|
// ===== Upload Image =====
|
|
|
|
static Future<bool> uploadAttendanceImage(
|
|
int id,
|
|
int employeeId,
|
|
XFile imageFile,
|
|
double latitude,
|
|
double longitude, {
|
|
required String imageName,
|
|
required int projectId,
|
|
String comment = "",
|
|
required int action, // action passed here
|
|
}) async {
|
|
final token = await _getToken();
|
|
if (token == null) return false;
|
|
|
|
try {
|
|
final bytes = await imageFile.readAsBytes();
|
|
final base64Image = base64Encode(bytes);
|
|
final fileSize = await imageFile.length();
|
|
final contentType = "image/${imageFile.path.split('.').last}";
|
|
|
|
final imageObject = {
|
|
"fileName": '$imageName',
|
|
"contentType": '$contentType',
|
|
"fileSize": fileSize,
|
|
"description": "Employee attendance photo",
|
|
"base64Data": '$base64Image',
|
|
};
|
|
|
|
final now = DateTime.now();
|
|
|
|
final body = {
|
|
"id": id,
|
|
"employeeId": employeeId,
|
|
"projectId": projectId,
|
|
"markTime": DateFormat('hh:mm a').format(now),
|
|
"comment": comment,
|
|
"action": action,
|
|
"date": DateFormat('yyyy-MM-dd').format(now),
|
|
"latitude": '$latitude',
|
|
"longitude": '$longitude',
|
|
"image": imageObject
|
|
};
|
|
print("Attendance Image Upload Body: $body");
|
|
final response = await http.post(
|
|
Uri.parse("$baseUrl/attendance/record-image"),
|
|
headers: _headers(token),
|
|
body: jsonEncode(body),
|
|
);
|
|
print("Attendance Image Upload Response: ${response.body}");
|
|
final json = jsonDecode(response.body);
|
|
if (response.statusCode == 200 && json['success'] == true) {
|
|
return true;
|
|
} else {
|
|
print("Failed to upload image. API Error: ${json['message']}");
|
|
}
|
|
} catch (e) {
|
|
print("Exception during image upload: $e");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ===== Utilities =====
|
|
|
|
static String generateImageName(int employeeId, int count) {
|
|
final now = DateTime.now();
|
|
final dateStr = DateFormat('yyyyMMdd_HHmmss').format(now);
|
|
final imageNumber = count.toString().padLeft(3, '0');
|
|
return "${employeeId}_${dateStr}_$imageNumber.jpg";
|
|
}
|
|
}
|