- Implemented employee skeleton card for loading states in the UI. - Created AssignedProjectsResponse and AssignedProject models for handling project assignments. - Enhanced EmployeeDetailBottomSheet to include project assignment button. - Developed AssignProjectBottomSheet for selecting projects to assign to employees. - Introduced EmployeeDetailPage for displaying detailed employee information. - Updated EmployeesScreen to support searching and filtering employees. - Improved layout and UI elements for better user experience.
146 lines
4.3 KiB
Dart
146 lines
4.3 KiB
Dart
import 'package:flutter/widgets.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:marco/helpers/services/api_service.dart';
|
|
import 'package:marco/helpers/services/app_logger.dart';
|
|
import 'package:marco/model/global_project_model.dart';
|
|
import 'package:marco/model/employees/assigned_projects_model.dart';
|
|
import 'package:marco/controller/project_controller.dart';
|
|
|
|
class AssignProjectController extends GetxController {
|
|
final String employeeId;
|
|
final String jobRoleId;
|
|
|
|
AssignProjectController({
|
|
required this.employeeId,
|
|
required this.jobRoleId,
|
|
});
|
|
|
|
final ProjectController projectController = Get.put(ProjectController());
|
|
|
|
RxBool isLoading = false.obs;
|
|
RxBool isAssigning = false.obs;
|
|
|
|
RxList<String> assignedProjectIds = <String>[].obs;
|
|
RxList<String> selectedProjects = <String>[].obs;
|
|
RxList<GlobalProjectModel> allProjects = <GlobalProjectModel>[].obs;
|
|
RxList<GlobalProjectModel> filteredProjects = <GlobalProjectModel>[].obs;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
fetchAllProjectsAndAssignments();
|
|
});
|
|
}
|
|
|
|
/// Fetch all projects and assigned projects
|
|
Future<void> fetchAllProjectsAndAssignments() async {
|
|
isLoading.value = true;
|
|
try {
|
|
await projectController.fetchProjects();
|
|
allProjects.assignAll(projectController.projects);
|
|
filteredProjects.assignAll(allProjects); // initially show all
|
|
|
|
final responseList = await ApiService.getAssignedProjects(employeeId);
|
|
if (responseList != null) {
|
|
final assignedProjects =
|
|
responseList.map((e) => AssignedProject.fromJson(e)).toList();
|
|
|
|
assignedProjectIds.assignAll(
|
|
assignedProjects.map((p) => p.id).toList(),
|
|
);
|
|
selectedProjects.assignAll(assignedProjectIds);
|
|
}
|
|
|
|
logSafe("All Projects: ${allProjects.map((e) => e.id)}");
|
|
logSafe("Assigned Project IDs: $assignedProjectIds");
|
|
} catch (e, stack) {
|
|
logSafe("Error fetching projects or assignments: $e",
|
|
level: LogLevel.error);
|
|
logSafe("StackTrace: $stack", level: LogLevel.debug);
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
}
|
|
|
|
/// Assign selected projects
|
|
Future<bool> assignProjectsToEmployee() async {
|
|
if (selectedProjects.isEmpty) {
|
|
logSafe("No projects selected for assignment.", level: LogLevel.warning);
|
|
return false;
|
|
}
|
|
|
|
final List<Map<String, dynamic>> projectPayload =
|
|
selectedProjects.map((id) {
|
|
return {"projectId": id, "jobRoleId": jobRoleId, "status": true};
|
|
}).toList();
|
|
|
|
isAssigning.value = true;
|
|
try {
|
|
final success = await ApiService.assignProjects(
|
|
employeeId: employeeId,
|
|
projects: projectPayload,
|
|
);
|
|
|
|
if (success) {
|
|
logSafe("Projects assigned successfully.");
|
|
assignedProjectIds.assignAll(selectedProjects);
|
|
return true;
|
|
} else {
|
|
logSafe("Failed to assign projects.", level: LogLevel.error);
|
|
return false;
|
|
}
|
|
} catch (e, stack) {
|
|
logSafe("Error assigning projects: $e", level: LogLevel.error);
|
|
logSafe("StackTrace: $stack", level: LogLevel.debug);
|
|
return false;
|
|
} finally {
|
|
isAssigning.value = false;
|
|
}
|
|
}
|
|
|
|
/// Toggle project selection
|
|
void toggleProjectSelection(String projectId, bool isSelected) {
|
|
if (isSelected) {
|
|
if (!selectedProjects.contains(projectId)) {
|
|
selectedProjects.add(projectId);
|
|
}
|
|
} else {
|
|
selectedProjects.remove(projectId);
|
|
}
|
|
}
|
|
|
|
/// Check if project is selected
|
|
bool isProjectSelected(String projectId) {
|
|
return selectedProjects.contains(projectId);
|
|
}
|
|
|
|
/// Select all / deselect all
|
|
void toggleSelectAll() {
|
|
if (areAllSelected()) {
|
|
selectedProjects.clear();
|
|
} else {
|
|
selectedProjects.assignAll(allProjects.map((p) => p.id.toString()));
|
|
}
|
|
}
|
|
|
|
/// Are all selected?
|
|
bool areAllSelected() {
|
|
return selectedProjects.length == allProjects.length &&
|
|
allProjects.isNotEmpty;
|
|
}
|
|
|
|
/// Filter projects by search text
|
|
void filterProjects(String query) {
|
|
if (query.isEmpty) {
|
|
filteredProjects.assignAll(allProjects);
|
|
} else {
|
|
filteredProjects.assignAll(
|
|
allProjects
|
|
.where((p) => p.name.toLowerCase().contains(query.toLowerCase()))
|
|
.toList(),
|
|
);
|
|
}
|
|
}
|
|
}
|