diff --git a/src/hooks/useProjects.js b/src/hooks/useProjects.js index 09582880..62641178 100644 --- a/src/hooks/useProjects.js +++ b/src/hooks/useProjects.js @@ -4,6 +4,7 @@ import ProjectRepository from "../repositories/ProjectRepository"; import { useProfile } from "./useProfile"; import { useDispatch, useSelector } from "react-redux"; import { setProjectId } from "../slices/localVariablesSlice"; +import EmployeeList from "../components/Directory/EmployeeList"; export const useProjects = () => { @@ -130,3 +131,48 @@ export const useProjectDetails = (projectId) => { return { projects_Details, loading, error, refetch: fetchData } } + + +export const useProjectsByEmployee = ( employeeId ) => +{ + const [projectList, setProjectList] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const fetchProjects = async (id) => { + try { + setLoading(true); + setError(''); // clear previous error + const res = await ProjectRepository.getProjectsByEmployee(id); + setProjectList(res.data); + cacheData( 'ProjectsByEmployee', {data: res.data, employeeId: id} ); + setLoading(false) + } catch (err) { + setError( err?.message || 'Failed to fetch projects' ); + setLoading(false) + } + }; + + useEffect(() => { + if (!employeeId) return; + + const cache_project = getCachedData('ProjectsByEmployee'); + + if ( + !cache_project?.data || + cache_project?.employeeId !== employeeId + ) { + fetchProjects(employeeId); + } else { + setProjectList(cache_project.data); + } + }, [employeeId]); + + return { + projectList, + loading, + error, + refetch : fetchProjects + } +}; + diff --git a/src/pages/employee/AssignToProject.jsx b/src/pages/employee/AssignToProject.jsx new file mode 100644 index 00000000..891b50df --- /dev/null +++ b/src/pages/employee/AssignToProject.jsx @@ -0,0 +1,182 @@ +import React, { useState, useEffect } from "react"; +import { useProjects, useProjectsByEmployee } from "../../hooks/useProjects"; +import EmployeeList from "./EmployeeList"; +import showToast from "../../services/toastService"; +import ProjectRepository from "../../repositories/ProjectRepository"; + +const AssignToProject = ({ employee, onClose }) => { + const { projects, loading } = useProjects(); + const { projectList,loading:selectedProjectLoding ,refetch} = useProjectsByEmployee(employee?.id); + const [isSubmitting,setSubmitting] = useState(false) + const [searchTerm, setSearchTerm] = useState(""); + const [checkedProjects, setCheckedProjects] = useState({}); + const [selectedEmployees, setSelectedEmployees] = useState([]); + + useEffect(() => { + if (projectList && projectList.length > 0) { + const initialChecked = {}; + const initialSelected = []; + + projectList.forEach((project) => { + initialChecked[project.id] = true; + initialSelected.push({ + jobRoleId: employee.jobRoleId, + projectId: project.id, + status: true, + }); + }); + + setCheckedProjects(initialChecked); + setSelectedEmployees(initialSelected); + } else { + setCheckedProjects({}); + setSelectedEmployees([]); + } + }, [projectList, employee?.id]); + + const handleSearchChange = (e) => { + setSearchTerm(e.target.value.toLowerCase()); + }; + +const handleCheckboxChange = (projectId) => { + const isChecked = !checkedProjects[projectId]; + + setCheckedProjects((prev) => ({ + ...prev, + [projectId]: isChecked, + })); +}; + + +const handleSubmit = async () => { + const initiallyAssigned = new Set(projectList.map((p) => p.id.toString())); + const changes = []; + + Object.entries(checkedProjects).forEach(([projectId, isChecked]) => { + const wasAssigned = initiallyAssigned.has(projectId); + + if (wasAssigned && !isChecked) { + changes.push({ + projectId: projectId, + jobRoleId: employee.jobRoleId, + status: false, + }); + } + + if (!wasAssigned && isChecked) { + changes.push({ + projectId: projectId, + jobRoleId: employee.jobRoleId, + status: true, + }); + } + + }); + + if (changes.length === 0) { + showToast("Make change before.", "info"); + return; + } + + try { + setSubmitting(true) + await ProjectRepository.updateProjectsByEmployee(employee.id, changes) + showToast( "Project assignments updated.", "success" ); + setSubmitting(false) + onClose(); + refetch(employee.id) + } catch (error) { + const msg = error.response?.data?.message || error.message || "Error during API call."; + showToast( msg, "error" ); + setSubmitting(false) + } +}; + + + + + const handleClosedModal = () => { + onClose(); + }; + + const filteredProjects = projects.filter((project) => + project.name.toLowerCase().includes(searchTerm) + ); + + return ( +
Assign to Project
+ +Loading projects...
+Select Project | +
---|
+
+ handleCheckboxChange( project.id )}
+ disabled={selectedProjectLoding}
+
+ />
+
+
+ |
+
No projects found. | +