387 lines
13 KiB
JavaScript

import React, { useState, useEffect, useCallback } from "react";
import MapUsers from "./MapUsers";
import { Link, NavLink, useNavigate } from "react-router-dom";
import showToast from "../../services/toastService";
import Avatar from "../common/Avatar";
import moment from "moment";
import ProjectRepository from "../../repositories/ProjectRepository";
import { useDispatch } from "react-redux";
import { changeMaster } from "../../slices/localVariablesSlice";
import useMaster from "../../hooks/masterHook/useMaster";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { ASSIGN_TO_PROJECT } from "../../utils/constants";
import ConfirmModal from "../common/ConfirmModal";
import eventBus from "../../services/eventBus";
const Teams = ({ project }) => {
const dispatch = useDispatch();
const { data, loading } = useMaster();
const [isModalOpen, setIsModelOpen] = useState(false);
const [error, setError] = useState("");
const [empJobRoles, setEmpJobRoles] = useState(null);
const [employees, setEmployees] = useState([]);
const [filteredEmployees, setFilteredEmployees] = useState([]);
const [removingEmployeeId, setRemovingEmployeeId] = useState(null);
const [assignedLoading, setAssignedLoading] = useState(false);
const [ employeeLodaing, setEmployeeLoading ] = useState( false );
const [ activeEmployee, setActiveEmployee ] = useState( true )
const [deleteEmployee,setDeleteEmplyee] = useState(null)
const navigate = useNavigate();
const HasAssignUserPermission = useHasUserPermission( ASSIGN_TO_PROJECT );
const[IsDeleteModal,setIsDeleteModal] = useState(false)
const fetchEmployees = async () => {
try {
setEmployeeLoading(true);
// if (!empRoles) {
ProjectRepository.getProjectAllocation(project.id)
.then((response) => {
setEmployees(response.data);
setFilteredEmployees( response.data.filter( ( emp ) => emp.isActive ) );
setEmployeeLoading(false);
})
.catch((error) => {
setError("Failed to fetch data.");
setEmployeeLoading(false);
});
} catch (err) {
setError("Failed to fetch activities.");
}
};
const submitAllocations = (items,added) => {
ProjectRepository.manageProjectAllocation(items)
.then((response) => {
fetchEmployees();
if ( added )
{
showToast("Employee Assigned Successfully", "success");
}else{
showToast("Removed Employee Successfully", "success");
}
setRemovingEmployeeId(null);
setAssignedLoading( false );
setDeleteEmplyee( null )
closeDeleteModal()
})
.catch((error) => {
const message = error.response.data.message || error.message || "Error Occured during Api Call";
showToast( message, "error" );
closeDeleteModal()
});
};
const removeAllocation = (item) => {
setRemovingEmployeeId(item.id);
submitAllocations([
{
empID: item.employeeId,
jobRoleId: item.jobRoleId,
projectId: project.id,
status: false,
},
] ,false);
};
const handleEmpAlicationFormSubmit = (allocaionObj) => {
let items = allocaionObj.map((item) => {
return {
empID: item.empID,
jobRoleId: item.jobRoleId,
projectId: project.id,
status: true,
};
});
submitAllocations(items, true);
// Force switch to active view after assignment
setActiveEmployee(true);
setFilteredEmployees(employees.filter((emp) => emp.isActive));
// Also update dropdown select if needed
const dropdown = document.querySelector('select[name="DataTables_Table_0_length"]');
if (dropdown) dropdown.value = "true";
};
const getRole = (jobRoleId) => {
if (loading) return "Loading...";
if (!Array.isArray(empJobRoles)) return "Unassigned";
if (!jobRoleId) return "Unassigned";
const role = empJobRoles.find((b) => b.id == jobRoleId);
return role ? role.name : "Unassigned";
};
const openModel = () => {
setIsModelOpen(true);
};
const onModelClose = () => {
setIsModelOpen(false);
const modalElement = document.getElementById("user-model");
if (modalElement) {
modalElement.classList.remove("show");
modalElement.style.display = "none";
document.body.classList.remove("modal-open");
document.querySelector(".modal-backdrop").remove();
}
const modalBackdropElement = document.querySelector(".modal-backdrop");
if (modalBackdropElement) {
modalBackdropElement.remove();
}
document.body.style.overflow = "auto";
};
useEffect(() => {
dispatch(changeMaster("Job Role"));
}, [dispatch]);
useEffect(() => {
fetchEmployees();
}, []);
useEffect(() => {
if (data) {
setEmpJobRoles(data);
}
}, [data]);
const handleFilterEmployee = (e) => {
const filterValue = e.target.value;
if ( filterValue === "true" )
{
setActiveEmployee(true)
setFilteredEmployees(employees.filter((emp) => emp.isActive));
} else {
setFilteredEmployees( employees.filter( ( emp ) => !emp.isActive ) );
setActiveEmployee(false)
}
};
const deleteModalOpen = (item) =>
{
setDeleteEmplyee(item)
setIsDeleteModal(true)
}
const closeDeleteModal = ()=> setIsDeleteModal(false)
const handler = useCallback(
(msg) => {
if (msg.projectIds.some((item) => item === project.id)) {
fetchEmployees();
}
},
[]
);
useEffect(() => {
eventBus.on("assign_project_all", handler);
return () => eventBus.off("assign_project_all", handler);
}, [handler]);
const employeeHandler = useCallback(
(msg) => {
if(filteredEmployees.some((item) => item.employeeId == msg.employeeId)){
fetchEmployees();
}
},[filteredEmployees]
);
useEffect(() => {
eventBus.on("employee",employeeHandler);
return () => eventBus.off("employee",employeeHandler)
},[employeeHandler])
return (
<>
<div
className="modal fade"
id="user-model"
tabIndex="-1"
aria-labelledby="userModalLabel"
aria-hidden="true"
>
<MapUsers
projectId={project?.id}
onClose={onModelClose}
empJobRoles={empJobRoles}
onSubmit={handleEmpAlicationFormSubmit}
allocation={employees}
assignedLoading={assignedLoading}
setAssignedLoading={setAssignedLoading}
></MapUsers>
</div>
{IsDeleteModal && (
<div
className={`modal fade ${IsDeleteModal ? "show" : ""}`}
tabIndex="-1"
role="dialog"
style={{
display: IsDeleteModal ? "block" : "none",
backgroundColor: IsDeleteModal ? "rgba(0,0,0,0.5)" : "transparent",
}}
aria-hidden="false"
>
<ConfirmModal
type={"delete"}
header={"Removed Employee"}
message={"Are you sure you want delete?"}
onSubmit={removeAllocation}
onClose={closeDeleteModal}
loading={employeeLodaing}
paramData={deleteEmployee}
/>
</div>
)}
<div className="card card-action mb-6">
<div className="card-body">
<div className="row">
<div className="col-12 d-flex justify-content-between mb-1">
<div
className="dataTables_length text-start py-2 px-2"
id="DataTables_Table_0_length"
>
<label>
<select
name="DataTables_Table_0_length"
aria-controls="DataTables_Table_0"
className="form-select form-select-sm"
onChange={handleFilterEmployee}
// value={false}
aria-label=""
defaultValue="true"
>
<option value="true">Active Employee</option>
<option value="false">In-Active Employee</option>
</select>
</label>
</div>
<button
type="button"
className={`link-button btn-sm m-1 ${
HasAssignUserPermission ? "" : "d-none"
}`}
data-bs-toggle="modal"
data-bs-target="#user-model"
>
<i className="bx bx-plus-circle me-2"></i>
Assign Employee
</button>
</div>
</div>
<div className="table-responsive text-nowrap">
{employeeLodaing && <p>Loading..</p>}
{!employeeLodaing && employees && employees.length > 0 && (
<table className="table ">
<thead>
<tr>
<th>Name</th>
<th>Assigned Date</th>
{!activeEmployee && <th>Release Date</th>}
<th>Project Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody className="table-border-bottom-0">
{filteredEmployees &&
filteredEmployees.map((item) => (
<tr key={item.id}>
<td>
<div className="d-flex justify-content-start align-items-center">
<Avatar
firstName={item.firstName}
lastName={item.lastName}
></Avatar>
<div className="d-flex flex-column">
<a
onClick={() =>
navigate(`/employee/${item.employeeId}?for=account`)
}
className="text-heading text-truncate cursor-pointer"
>
<span className="fw-normal">
{item.firstName} {item.middleName}{" "}
{item.lastName}
</span>
</a>
</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">
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 && (
<div className="text-center text-muted py-3">
{activeEmployee
? "No active employees assigned to the project"
: "No inactive employees assigned to the project"}
</div>
)}
</div>
</div>
</div>
</>
);
};
export default Teams;