import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:geolocator/geolocator.dart'; import 'package:marco/helpers/services/api_service.dart'; import 'package:marco/model/attendance_model.dart'; import 'package:marco/model/project_model.dart'; import 'package:marco/model/employee_model.dart'; import 'package:marco/model/attendance_log_model.dart'; import 'package:marco/model/regularization_log_model.dart'; import 'package:marco/model/attendance_log_view_model.dart'; class AttendanceController extends GetxController { List attendances = []; List projects = []; String? selectedProjectId; List employees = []; DateTime? startDateAttendance; DateTime? endDateAttendance; List attendanceLogs = []; List regularizationLogs = []; List attendenceLogsView = []; RxBool isLoading = false.obs; // Added loading flag @override void onInit() { super.onInit(); _initializeDefaults(); } void _initializeDefaults() { _setDefaultDateRange(); fetchProjects(); } void _setDefaultDateRange() { final today = DateTime.now(); startDateAttendance = today.subtract(const Duration(days: 7)); endDateAttendance = today; } Future fetchProjects() async { isLoading.value = true; // Set loading to true before API call final response = await ApiService.getProjects(); isLoading.value = false; // Set loading to false after API call completes if (response != null && response.isNotEmpty) { projects = response.map((json) => ProjectModel.fromJson(json)).toList(); selectedProjectId = projects.first.id.toString(); await fetchProjectData(selectedProjectId); update(['attendance_dashboard_controller']); } else { print("No projects data found or failed to fetch data."); } } Future fetchProjectData(String? projectId) async { if (projectId == null) return; isLoading.value = true; // Set loading to true before API call await Future.wait([ fetchEmployeesByProject(projectId), fetchAttendanceLogs(projectId, dateFrom: startDateAttendance, dateTo: endDateAttendance), fetchRegularizationLogs(projectId), ]); isLoading.value = false; // Set loading to false after data is fetched } Future fetchEmployeesByProject(String? projectId) async { if (projectId == null) return; isLoading.value = true; // Set loading to true before API call final response = await ApiService.getEmployeesByProject(projectId); isLoading.value = false; // Set loading to false after API call completes if (response != null) { employees = response.map((json) => EmployeeModel.fromJson(json)).toList(); update(); } else { print("Failed to fetch employees for project $projectId."); } } Future captureAndUploadAttendance( String id, // Change from int to String String employeeId, // Change from int to String String projectId, { String comment = "Marked via mobile app", required int action, bool imageCapture = true, // <- add this flag }) async { try { XFile? image; if (imageCapture) { image = await ImagePicker().pickImage( source: ImageSource.camera, imageQuality: 80, ); if (image == null) return false; } final position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high, ); final imageName = imageCapture ? ApiService.generateImageName(employeeId, employees.length + 1) : ""; // Empty or null if not capturing image return await ApiService.uploadAttendanceImage( id, employeeId, image, position.latitude, position.longitude, imageName: imageName, projectId: projectId, comment: comment, action: action, imageCapture: imageCapture, // <- pass flag down ); } catch (e) { print("Error capturing or uploading attendance: $e"); return false; } } Future selectDateRangeForAttendance( BuildContext context, AttendanceController controller, ) async { final picked = await showDateRangePicker( context: context, firstDate: DateTime(2022), lastDate: DateTime.now(), initialDateRange: DateTimeRange( start: startDateAttendance ?? DateTime.now().subtract(const Duration(days: 7)), end: endDateAttendance ?? DateTime.now(), ), ); if (picked != null) { startDateAttendance = picked.start; endDateAttendance = picked.end; await controller.fetchAttendanceLogs( controller.selectedProjectId, dateFrom: picked.start, dateTo: picked.end, ); } } Future fetchAttendanceLogs( String? projectId, { DateTime? dateFrom, DateTime? dateTo, }) async { if (projectId == null) return; isLoading.value = true; // Set loading to true before API call final response = await ApiService.getAttendanceLogs( projectId, dateFrom: dateFrom, dateTo: dateTo, ); isLoading.value = false; // Set loading to false after API call completes if (response != null) { attendanceLogs = response.map((json) => AttendanceLogModel.fromJson(json)).toList(); print("Attendance logs fetched: ${response}"); update(); } else { print("Failed to fetch attendance logs for project $projectId."); } } Future fetchRegularizationLogs( String? projectId, { DateTime? dateFrom, DateTime? dateTo, }) async { if (projectId == null) return; isLoading.value = true; final response = await ApiService.getRegularizationLogs(projectId); isLoading.value = false; if (response != null) { regularizationLogs = response .map((json) => RegularizationLogModel.fromJson(json)) .toList(); update(); } else { print("Failed to fetch regularization logs for project $projectId."); } } Future fetchLogsView(String? id) async { if (id == null) return; isLoading.value = true; // Set loading to true before API call final response = await ApiService.getAttendanceLogView(id); isLoading.value = false; // Set loading to false after API call completes if (response != null) { attendenceLogsView = response .map((json) => AttendanceLogViewModel.fromJson(json)) .toList(); update(); } else { print("Failed to fetch regularization logs for project $id."); } } }