missing changes from PR : Add Search Bar in Assigned Employee Popup under Project > Teams #324

#324
This commit is contained in:
Vikas Nale 2025-08-16 13:34:54 +05:30
parent dd0c7e95bf
commit 1e9db47144

View File

@ -14,11 +14,13 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { ASSIGN_TO_PROJECT } from "../../utils/constants"; import { ASSIGN_TO_PROJECT } from "../../utils/constants";
import ConfirmModal from "../common/ConfirmModal"; import ConfirmModal from "../common/ConfirmModal";
import eventBus from "../../services/eventBus"; import eventBus from "../../services/eventBus";
import {useEmployeesByProjectAllocated, useManageProjectAllocation} from "../../hooks/useProjects"; import {
useEmployeesByProjectAllocated,
useManageProjectAllocation,
} from "../../hooks/useProjects";
import { useSelectedproject } from "../../slices/apiDataManager"; import { useSelectedproject } from "../../slices/apiDataManager";
const Teams = () => const Teams = () => {
{
// const {projectId} = useParams() // const {projectId} = useParams()
// const projectId = useSelector((store)=>store.localVariables.projectId) // const projectId = useSelector((store)=>store.localVariables.projectId)
const projectId = useSelectedproject(); const projectId = useSelectedproject();
@ -32,68 +34,72 @@ const Teams = () =>
const [filteredEmployees, setFilteredEmployees] = useState([]); const [filteredEmployees, setFilteredEmployees] = useState([]);
const [removingEmployeeId, setRemovingEmployeeId] = useState(null); const [removingEmployeeId, setRemovingEmployeeId] = useState(null);
const [assignedLoading, setAssignedLoading] = useState(false); const [assignedLoading, setAssignedLoading] = useState(false);
const [ activeEmployee, setActiveEmployee ] = useState( true ) const [activeEmployee, setActiveEmployee] = useState(true);
const [deleteEmployee,setDeleteEmplyee] = useState(null) const [deleteEmployee, setDeleteEmplyee] = useState(null);
const [searchTerm, setSearchTerm] = useState(""); // State for search term
const navigate = useNavigate(); const navigate = useNavigate();
const HasAssignUserPermission = useHasUserPermission( ASSIGN_TO_PROJECT ); const HasAssignUserPermission = useHasUserPermission(ASSIGN_TO_PROJECT);
const [ IsDeleteModal, setIsDeleteModal ] = useState( false ) const [IsDeleteModal, setIsDeleteModal] = useState(false);
const {projectEmployees, loading:employeeLodaing, refetch} = useEmployeesByProjectAllocated( projectId ) const {
const { projectEmployees,
mutate: submitAllocations, loading: employeeLodaing,
isPending, refetch,
isSuccess, } = useEmployeesByProjectAllocated(projectId);
isError, const {
} = useManageProjectAllocation({ mutate: submitAllocations,
onSuccessCallback: () => { isPending,
setRemovingEmployeeId(null); isSuccess,
setAssignedLoading(false); isError,
setDeleteEmplyee(null); } = useManageProjectAllocation({
closeDeleteModal(); onSuccessCallback: () => {
}, setRemovingEmployeeId(null);
onErrorCallback: () => { setAssignedLoading(false);
closeDeleteModal(); setDeleteEmplyee(null);
}, closeDeleteModal();
}); },
onErrorCallback: () => {
closeDeleteModal();
},
const removeAllocation = (item) => {
setRemovingEmployeeId(item.id);
submitAllocations({
items: [
{
empID: item.employeeId,
jobRoleId: item.jobRoleId,
projectId: projectId,
status: false,
},
],
added: false,
}); });
};
const removeAllocation = (item) => {
setRemovingEmployeeId(item.id);
submitAllocations({
items: [
{
empID: item.employeeId,
jobRoleId: item.jobRoleId,
projectId: projectId,
status: false,
},
],
added: false,
});
};
const handleEmpAlicationFormSubmit = (allocaionObj) => { const handleEmpAlicationFormSubmit = (allocaionObj) => {
let items = allocaionObj.map((item) => { let items = allocaionObj.map((item) => {
return { return {
empID: item.empID, empID: item.empID,
jobRoleId: item.jobRoleId, jobRoleId: item.jobRoleId,
projectId: projectId, projectId: projectId,
status: true, status: true,
}; };
}); });
submitAllocations({ items, added: true }); submitAllocations({ items, added: true });
setActiveEmployee(true); setActiveEmployee(true);
setFilteredEmployees(employees.filter((emp) => emp.isActive)); setFilteredEmployees(employees.filter((emp) => emp.isActive));
const dropdown = document.querySelector('select[name="DataTables_Table_0_length"]');
if (dropdown) dropdown.value = "true";
};
const dropdown = document.querySelector(
'select[name="DataTables_Table_0_length"]'
);
if (dropdown) dropdown.value = "true";
};
const getRole = (jobRoleId) => { const getRole = (jobRoleId) => {
if (loading) return "Loading..."; if (loading) return "Loading...";
@ -124,17 +130,17 @@ const {
}; };
useEffect(() => { useEffect(() => {
dispatch(changeMaster("Job Role")); dispatch(changeMaster("Job Role"));
}, [dispatch]); }, [dispatch]);
useEffect(() => { useEffect(() => {
if ( projectEmployees ) if (projectEmployees) {
{
setEmployees(projectEmployees); setEmployees(projectEmployees);
setFilteredEmployees( projectEmployees?.filter( ( emp ) => emp.isActive ) ); //setFilteredEmployees(projectEmployees?.filter((emp) => emp.isActive));
const filtered = projectEmployees.filter((emp) => emp.isActive);
setFilteredEmployees(filtered);
} }
}, [projectEmployees,employeeLodaing]); }, [projectEmployees, employeeLodaing]);
useEffect(() => { useEffect(() => {
if (data) { if (data) {
@ -142,24 +148,57 @@ const {
} }
}, [data]); }, [data]);
const filterAndSearchEmployees = useCallback(() => {
const statusFiltered = employees.filter((emp) =>
activeEmployee ? emp.isActive : !emp.isActive
);
if (searchTerm === "") {
setFilteredEmployees(statusFiltered);
return;
}
const lowercasedSearchTerm = searchTerm.toLowerCase();
const searchedAndFiltered = statusFiltered.filter((item) => {
const fullName =
`${item.firstName} ${item.middleName} ${item.lastName}`.toLowerCase();
const roleName = getRole(item.jobRoleId).toLowerCase();
return (
fullName.includes(lowercasedSearchTerm) ||
roleName.includes(lowercasedSearchTerm)
);
});
setFilteredEmployees(searchedAndFiltered);
}, [employees, activeEmployee, searchTerm, getRole]);
useEffect(() => {
filterAndSearchEmployees();
}, [employees, activeEmployee, searchTerm, filterAndSearchEmployees]);
const handleFilterEmployee = (e) => { const handleFilterEmployee = (e) => {
const filterValue = e.target.value; const filterValue = e.target.value;
if ( filterValue === "true" ) // if (filterValue === "true") {
{ // setActiveEmployee(true);
setActiveEmployee(true) // setFilteredEmployees(employees.filter((emp) => emp.isActive));
setFilteredEmployees(employees.filter((emp) => emp.isActive)); // } else {
} else { // setFilteredEmployees(employees.filter((emp) => !emp.isActive));
setFilteredEmployees( employees.filter( ( emp ) => !emp.isActive ) ); // setActiveEmployee(false);
setActiveEmployee(false) // }
} setActiveEmployee(filterValue === "true");
setSearchTerm("");
}; };
const deleteModalOpen = (item) => const handleSearch = (e) => {
{ setSearchTerm(e.target.value);
setDeleteEmplyee(item) };
setIsDeleteModal(true)
} const deleteModalOpen = (item) => {
const closeDeleteModal = ()=> setIsDeleteModal(false) setDeleteEmplyee(item);
setIsDeleteModal(true);
};
const closeDeleteModal = () => setIsDeleteModal(false);
const handler = useCallback( const handler = useCallback(
(msg) => { (msg) => {
@ -167,7 +206,7 @@ const {
refetch(); refetch();
} }
}, },
[projectId, refetch] [projectId, refetch]
); );
useEffect(() => { useEffect(() => {
@ -175,18 +214,19 @@ const {
return () => eventBus.off("assign_project_all", handler); return () => eventBus.off("assign_project_all", handler);
}, [handler]); }, [handler]);
const employeeHandler = useCallback( const employeeHandler = useCallback(
(msg) => { (msg) => {
if(filteredEmployees.some((item) => item.employeeId == msg.employeeId)){ if (filteredEmployees.some((item) => item.employeeId == msg.employeeId)) {
refetch(); refetch();
} }
},[filteredEmployees, refetch] },
[filteredEmployees, refetch]
); );
useEffect(() => { useEffect(() => {
eventBus.on("employee",employeeHandler); eventBus.on("employee", employeeHandler);
return () => eventBus.off("employee",employeeHandler) return () => eventBus.off("employee", employeeHandler);
},[employeeHandler]) }, [employeeHandler]);
return ( return (
<> <>
@ -208,8 +248,7 @@ const {
></MapUsers> ></MapUsers>
</div> </div>
{IsDeleteModal && (
{IsDeleteModal && (
<div <div
className={`modal fade ${IsDeleteModal ? "show" : ""}`} className={`modal fade ${IsDeleteModal ? "show" : ""}`}
tabIndex="-1" tabIndex="-1"
@ -220,7 +259,6 @@ const {
}} }}
aria-hidden="false" aria-hidden="false"
> >
<ConfirmModal <ConfirmModal
type={"delete"} type={"delete"}
header={"Removed Employee"} header={"Removed Employee"}
@ -235,8 +273,20 @@ const {
<div className="card card-action mb-6"> <div className="card card-action mb-6">
<div className="card-body"> <div className="card-body">
<div className="row"> <div className="row d-flex justify-content-between mb-4">
<div className="col-12 d-flex justify-content-between mb-1"> <div className="col-md-6 col-12 d-flex align-items-center">
<div className="dataTables_filter d-inline-flex align-items-center ms-2">
<input
type="search"
className="form-control form-control-sm me-4"
placeholder="Search by Name or Role"
aria-controls="DataTables_Table_0"
value={searchTerm}
onChange={handleSearch}
/>
</div>
</div>
<div className="col-md-6 col-12 d-flex justify-content-end align-items-center">
<div <div
className="dataTables_length text-start py-2 px-2" className="dataTables_length text-start py-2 px-2"
id="DataTables_Table_0_length" id="DataTables_Table_0_length"
@ -258,7 +308,7 @@ const {
</div> </div>
<button <button
type="button" type="button"
className={`link-button btn-sm m-1 ${ className={`link-button btn-primary btn-sm ${
HasAssignUserPermission ? "" : "d-none" HasAssignUserPermission ? "" : "d-none"
}`} }`}
data-bs-toggle="modal" data-bs-toggle="modal"
@ -271,91 +321,99 @@ const {
</div> </div>
<div className="table-responsive text-nowrap"> <div className="table-responsive text-nowrap">
{employeeLodaing && <p>Loading..</p>} {employeeLodaing && <p>Loading..</p>}
{!employeeLodaing && employees && employees.length > 0 && ( {!employeeLodaing &&
<table className="table "> filteredEmployees &&
<thead> filteredEmployees.length > 0 && (
<tr> <table className="table ">
<th>Name</th> <thead>
<th>Assigned Date</th> <tr>
{!activeEmployee && <th>Release Date</th>} <th>
<th>Project Role</th> <div className="text-start ms-5">Name</div>
<th>Actions</th> </th>
</tr> <th>Assigned Date</th>
</thead> {!activeEmployee && <th>Release Date</th>}
<tbody className="table-border-bottom-0"> <th>Project Role</th>
{filteredEmployees && <th>Actions</th>
filteredEmployees.map((item) => ( </tr>
<tr key={item.id}> </thead>
<td> <tbody className="table-border-bottom-0">
<div className="d-flex justify-content-start align-items-center"> {filteredEmployees &&
<Avatar filteredEmployees.map((item) => (
firstName={item.firstName} <tr key={item.id}>
lastName={item.lastName} <td>
></Avatar> <div className="d-flex justify-content-start align-items-center">
<div className="d-flex flex-column"> <Avatar
<a firstName={item.firstName}
onClick={() => lastName={item.lastName}
navigate(`/employee/${item.employeeId}?for=attendance`) ></Avatar>
} <div className="d-flex flex-column">
className="text-heading text-truncate cursor-pointer" <a
> onClick={() =>
<span className="fw-normal"> navigate(
{item.firstName} {item.middleName}{" "} `/employee/${item.employeeId}?for=attendance`
{item.lastName} )
</span> }
</a> className="text-heading text-truncate cursor-pointer"
</div>
</div>
</td>
<td>
{" "}
{moment(item.allocationDate).format(
"DD-MMM-YYYY"
)}{" "}
</td>
{!activeEmployee && <td>
{item.reAllocationDate
? moment(item.reAllocationDate).format(
"DD-MMM-YYYY"
)
: "Present"}
</td>}
<td>
<span className="badge bg-label-primary me-1">
{getRole(item.jobRoleId)}
</span>
</td>
<td>
{item.isActive && (
<button
aria-label="Delete"
type="button"
title="Remove from project"
className="btn p-0 dropdown-toggle hide-arrow"
onClick={() => deleteModalOpen(item)}
>
{" "}
{removingEmployeeId === item.id ? (
<div
className="spinner-border spinner-border-sm text-primary"
role="status"
> >
<span className="visually-hidden"> <span className="fw-normal">
Loading... {item.firstName} {item.middleName}{" "}
{item.lastName}
</span> </span>
</div> </a>
) : ( </div>
<i className="bx bx-trash me-1 text-danger"></i> </div>
)} </td>
</button> <td>
{" "}
{moment(item.allocationDate).format(
"DD-MMM-YYYY"
)}{" "}
</td>
{!activeEmployee && (
<td>
{item.reAllocationDate
? moment(item.reAllocationDate).format(
"DD-MMM-YYYY"
)
: "Present"}
</td>
)} )}
{!item.isActive && <span>Not in project</span>} <td>
</td> <span className="badge bg-label-primary me-1">
</tr> {getRole(item.jobRoleId)}
))} </span>
</tbody> </td>
</table> <td>
)} {item.isActive && (
<button
aria-label="Delete"
type="button"
title="Remove from project"
className="btn p-0 dropdown-toggle hide-arrow"
onClick={() => deleteModalOpen(item)}
>
{" "}
{removingEmployeeId === item.id ? (
<div
className="spinner-border spinner-border-sm text-primary"
role="status"
>
<span className="visually-hidden">
Loading...
</span>
</div>
) : (
<i className="bx bx-trash me-1 text-danger"></i>
)}
</button>
)}
{!item.isActive && <span>Not in project</span>}
</td>
</tr>
))}
</tbody>
</table>
)}
{!employeeLodaing && filteredEmployees.length === 0 && ( {!employeeLodaing && filteredEmployees.length === 0 && (
<div className="text-center text-muted py-3"> <div className="text-center text-muted py-3">
{activeEmployee {activeEmployee