marco.pms.mobileapp/lib/controller/employee/employees_screen_controller.dart

211 lines
6.3 KiB
Dart

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<EmployeeModel> employees = <EmployeeModel>[].obs;
RxList<EmployeeModel> filteredEmployees = <EmployeeModel>[].obs;
Rxn<EmployeeDetailsModel> selectedEmployeeDetails =
Rxn<EmployeeDetailsModel>();
/// ✅ Loading states
RxBool isLoading = true.obs;
RxBool isLoadingEmployeeDetails = false.obs;
/// ✅ Selection state
RxBool isAllEmployeeSelected = false.obs;
RxSet<String> selectedEmployeeIds = <String>{}.obs;
RxList<EmployeeModel> selectedEmployeePrimaryManagers = <EmployeeModel>[].obs;
RxList<EmployeeModel> selectedEmployeeSecondaryManagers =
<EmployeeModel>[].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<void> 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<void> 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<void> 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<void> _handleApiCall(
Future<List<dynamic>?> Function() apiCall, {
required Function(List<dynamic>) 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<void> _handleSingleApiCall(
Future<Map<String, dynamic>?> Function() apiCall, {
required Function(Map<String, dynamic>) 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);
}
}
}
}