import 'package:get/get.dart'; import 'package:marco/helpers/services/app_logger.dart'; import 'package:marco/helpers/services/api_service.dart'; import 'package:marco/model/employees/employee_model.dart'; import 'package:marco/model/employees/employee_details_model.dart'; class EmployeesScreenController extends GetxController { /// ✅ Data lists RxList employees = [].obs; Rxn selectedEmployeeDetails = Rxn(); /// ✅ Loading states RxBool isLoading = false.obs; RxBool isLoadingEmployeeDetails = false.obs; /// ✅ Selection state RxBool isAllEmployeeSelected = false.obs; RxSet selectedEmployeeIds = {}.obs; /// ✅ Upload state tracking (if needed later) RxMap uploadingStates = {}.obs; @override void onInit() { super.onInit(); fetchAllEmployees(); } /// 🔹 Fetch all employees (no project filter) Future fetchAllEmployees({String? organizationId}) async { isLoading.value = true; update(['employee_screen_controller']); await _handleApiCall( () => ApiService.getAllEmployees(organizationId: organizationId), onSuccess: (data) { employees.assignAll(data.map((json) => EmployeeModel.fromJson(json))); logSafe( "All Employees fetched: ${employees.length} employees loaded.", level: LogLevel.info, ); // Reset selection states when new data arrives selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; }, onEmpty: () { employees.clear(); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; logSafe("No Employee data found or API call failed", level: LogLevel.warning); }, ); isLoading.value = false; update(['employee_screen_controller']); } /// 🔹 Fetch details for a specific employee Future fetchEmployeeDetails(String? employeeId) async { if (employeeId == null || employeeId.isEmpty) return; isLoadingEmployeeDetails.value = true; await _handleSingleApiCall( () => ApiService.getEmployeeDetails(employeeId), onSuccess: (data) { selectedEmployeeDetails.value = EmployeeDetailsModel.fromJson(data); logSafe("Employee details loaded for $employeeId", level: LogLevel.info); }, onEmpty: () { selectedEmployeeDetails.value = null; logSafe("No employee details found for $employeeId", level: LogLevel.warning); }, onError: (e) { selectedEmployeeDetails.value = null; logSafe("Error fetching employee details for $employeeId", level: LogLevel.error, error: e); }, ); isLoadingEmployeeDetails.value = false; } /// 🔹 Clear all employee data void clearEmployees() { employees.clear(); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; logSafe("Employees cleared", level: LogLevel.info); update(['employee_screen_controller']); } /// 🔹 Generic handler for list API responses Future _handleApiCall( Future?> Function() apiCall, { required Function(List) onSuccess, required Function() onEmpty, Function(dynamic error)? onError, }) async { try { final response = await apiCall(); if (response != null && response.isNotEmpty) { onSuccess(response); } else { onEmpty(); } } catch (e) { if (onError != null) { onError(e); } else { logSafe("API call error", level: LogLevel.error, error: e); } } } /// 🔹 Generic handler for single-object API responses Future _handleSingleApiCall( Future?> Function() apiCall, { required Function(Map) onSuccess, required Function() onEmpty, Function(dynamic error)? onError, }) async { try { final response = await apiCall(); if (response != null && response.isNotEmpty) { onSuccess(response); } else { onEmpty(); } } catch (e) { if (onError != null) { onError(e); } else { logSafe("API call error", level: LogLevel.error, error: e); } } } }