import 'package:get/get.dart'; import 'package:on_field_work/helpers/services/app_logger.dart'; import 'package:on_field_work/helpers/services/api_service.dart'; import 'package:on_field_work/model/employees/employee_model.dart'; import 'package:on_field_work/model/employees/employee_details_model.dart'; class EmployeesScreenController extends GetxController { /// ✅ Data lists RxList employees = [].obs; RxList filteredEmployees = [].obs; Rxn selectedEmployeeDetails = Rxn(); /// ✅ Loading states RxBool isLoading = true.obs; RxBool isLoadingEmployeeDetails = false.obs; /// ✅ Selection state RxBool isAllEmployeeSelected = false.obs; RxSet selectedEmployeeIds = {}.obs; RxList selectedEmployeePrimaryManagers = [].obs; RxList selectedEmployeeSecondaryManagers = [].obs; @override void onInit() { super.onInit(); fetchAllEmployees(); } /// 🔹 Search/Filter Logic void searchEmployees(String query) { if (query.isEmpty) { filteredEmployees.assignAll(employees); } else { final searchQuery = query.toLowerCase(); final result = employees .where((e) => e.name.toLowerCase().contains(searchQuery) || e.email.toLowerCase().contains(searchQuery) || e.phoneNumber.toLowerCase().contains(searchQuery) || e.jobRole.toLowerCase().contains(searchQuery)) .toList(); // Sort alphabetically result .sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); filteredEmployees.assignAll(result); } } /// 🔹 Fetch all employees Future fetchAllEmployees({String? organizationId}) async { isLoading.value = true; await _handleApiCall( () => ApiService.getAllEmployees(organizationId: organizationId), onSuccess: (data) { final loadedList = data.map((json) => EmployeeModel.fromJson(json)).toList(); employees.assignAll(loadedList); filteredEmployees.assignAll(loadedList); logSafe( "All Employees fetched: ${employees.length} employees loaded.", level: LogLevel.info, ); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; }, onEmpty: () { employees.clear(); filteredEmployees.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; } /// Fetch reporting managers Future fetchReportingManagers(String? employeeId) async { if (employeeId == null || employeeId.isEmpty) return; try { selectedEmployeePrimaryManagers.clear(); selectedEmployeeSecondaryManagers.clear(); final data = await ApiService.getOrganizationHierarchyList(employeeId); if (data == null || data.isEmpty) { update(['employee_screen_controller']); return; } for (final item in data) { try { final reportTo = item['reportTo']; if (reportTo == null) continue; final emp = EmployeeModel.fromJson(reportTo); final isPrimary = item['isPrimary'] == true; if (isPrimary) { if (!selectedEmployeePrimaryManagers.any((e) => e.id == emp.id)) { selectedEmployeePrimaryManagers.add(emp); } } else { if (!selectedEmployeeSecondaryManagers.any((e) => e.id == emp.id)) { selectedEmployeeSecondaryManagers.add(emp); } } } catch (_) {} } update(['employee_screen_controller']); } catch (e) { logSafe("Error fetching reporting managers for $employeeId", level: LogLevel.error, error: e); } } /// 🔹 Clear all employee data void clearEmployees() { employees.clear(); filteredEmployees.clear(); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; logSafe("Employees cleared", level: LogLevel.info); update(['employee_screen_controller']); } 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); } } } 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); } } } }