- 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(),
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| }
 |