268 lines
8.3 KiB
JavaScript
268 lines
8.3 KiB
JavaScript
import React, { useEffect, useState } from "react";
|
|
import { useModal } from "../../../hooks/useAuth";
|
|
import Modal from "../../common/Modal";
|
|
import Label from "../../common/Label";
|
|
import { useTeamRole } from "../../../hooks/masterHook/useMaster";
|
|
import SelectField from "../../common/Forms/SelectField";
|
|
import SelectFieldServerSide from "../../common/Forms/SelectFieldServerSide";
|
|
import SelectEmployeeServerSide from "../../common/Forms/SelectFieldServerSide";
|
|
import Avatar from "../../common/Avatar";
|
|
import { useParams } from "react-router-dom";
|
|
import { EmployeeChip } from "../../common/Chips";
|
|
import {
|
|
useAllocationServiceProjectTeam,
|
|
useServiceProjectTeam,
|
|
} from "../../../hooks/useServiceProject";
|
|
import { SpinnerLoader } from "../../common/Loader";
|
|
import showToast from "../../../services/toastService";
|
|
import ConfirmModal from "../../common/ConfirmModal";
|
|
|
|
const ServiceProjectTeamAllocation = () => {
|
|
const { isOpen, onClose, data: Project } = useModal("ServiceTeamAllocation");
|
|
const [deletingEmp, setSeletingEmp] = useState({
|
|
employee: null,
|
|
isOpen: false,
|
|
});
|
|
const {
|
|
data: Team,
|
|
isLoading: isTeamLoading,
|
|
isError: isTeamError,
|
|
error: teamError,
|
|
} = useServiceProjectTeam(Project?.projectId, true);
|
|
const [isAddEmployee, setIsAddEmployee] = useState(false);
|
|
const [nonDuplicateEmployee, setNonDuplicateEmployee] = useState([]);
|
|
const [selectedTeam, setSelectTeam] = useState(null);
|
|
const [selectedEmployees, setSelectedEmployees] = useState([]);
|
|
const { data, isLoading } = useTeamRole();
|
|
|
|
const TeamAllocationColumns = [
|
|
{
|
|
key: "team",
|
|
label: "Role",
|
|
getValue: (e) => e?.teamName || "-",
|
|
},
|
|
];
|
|
const handleRemove = (id) => {
|
|
setSelectedEmployees((prev) => prev.filter((e) => e.id !== id));
|
|
};
|
|
const { mutate: AllocationTeam, isPending } = useAllocationServiceProjectTeam(
|
|
() => {
|
|
setSelectedEmployees([]);
|
|
setSeletingEmp({
|
|
employee: null,
|
|
isOpen: false,
|
|
});
|
|
}
|
|
);
|
|
|
|
const AssignEmployee = () => {
|
|
let payload = selectedEmployees.map((e) => {
|
|
return {
|
|
projectId: Project?.projectId,
|
|
employeeId: e.id,
|
|
teamRoleId: selectedTeam,
|
|
isActive: true,
|
|
};
|
|
});
|
|
AllocationTeam({ payload, isActive: true });
|
|
};
|
|
|
|
const handleDeAllocation = (emp) => {
|
|
let payload = [
|
|
{
|
|
projectId: Project?.projectId,
|
|
employeeId: emp.employee.id,
|
|
teamRoleId: emp.teamRole.id,
|
|
isActive: false,
|
|
},
|
|
];
|
|
|
|
AllocationTeam({ payload: payload, isActive: false });
|
|
};
|
|
useEffect(() => {
|
|
if (selectedEmployees?.length > 0 && !selectedTeam) {
|
|
handleRemove(selectedEmployees[0]?.id);
|
|
showToast(`Please select a role`, "warning");
|
|
}
|
|
if (Team?.length > 0 && selectedEmployees?.length > 0) {
|
|
setNonDuplicateEmployee((prev) => {
|
|
let updated = [...prev];
|
|
|
|
selectedEmployees.forEach((selectedEmployee) => {
|
|
const alreadyAllocated = Team.some(
|
|
(e) =>
|
|
e?.employee?.id === selectedEmployee?.id &&
|
|
e?.teamRole?.id === selectedTeam
|
|
);
|
|
if (alreadyAllocated) {
|
|
handleRemove(selectedEmployee?.id);
|
|
showToast(
|
|
`${selectedEmployee.firstName} ${selectedEmployee.lastName} already allocated with same role`,
|
|
"warning"
|
|
);
|
|
}
|
|
});
|
|
|
|
return updated;
|
|
});
|
|
}
|
|
}, [Team, selectedEmployees, selectedTeam]);
|
|
|
|
const TeamAllocationBody = (
|
|
<>
|
|
<ConfirmModal
|
|
type="delete"
|
|
header="Remove Employee"
|
|
message="Are you sure you want remove?"
|
|
onSubmit={handleDeAllocation}
|
|
onClose={() => setSeletingEmp({ employee: null, isOpen: false })}
|
|
loading={isPending}
|
|
paramData={deletingEmp.employee}
|
|
isOpen={deletingEmp.isOpen}
|
|
/>
|
|
<div className=" text-start">
|
|
<div className="row">
|
|
<div className="d-flex justify-content-end">
|
|
{!isAddEmployee && (
|
|
<button
|
|
className="btn btn-sm btn-primary"
|
|
onClick={() => setIsAddEmployee(!isAddEmployee)}
|
|
>
|
|
<i className="bx bx-plus-circle me-2"></i>Add Employee
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{isAddEmployee && (
|
|
<>
|
|
<div className="col-12 col-md-6 mb-3">
|
|
<SelectField
|
|
label="Select Role"
|
|
required
|
|
options={data}
|
|
value={selectedTeam}
|
|
labelKey="name"
|
|
valueKey="id"
|
|
onChange={(e) => {
|
|
setSelectedEmployees([]);
|
|
setSelectTeam(e);
|
|
}}
|
|
isLoading={isLoading}
|
|
/>
|
|
</div>
|
|
|
|
<div className="col-12 col-md-6 mb-3">
|
|
<SelectEmployeeServerSide
|
|
label="Select Employee"
|
|
isMultiple={true}
|
|
isFullObject={true}
|
|
value={selectedEmployees}
|
|
onChange={setSelectedEmployees}
|
|
/>
|
|
</div>
|
|
<div className="col-12 d-flex flex-row gap-2 flex-wrap">
|
|
{selectedEmployees.map((e) => (
|
|
<EmployeeChip handleRemove={handleRemove} employee={e} />
|
|
))}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
{isAddEmployee && (
|
|
<div className="d-flex justify-content-end my-2">
|
|
{" "}
|
|
<button
|
|
type="button"
|
|
className="btn btn-label-secondary btn-sm me-2"
|
|
onClick={() => setIsAddEmployee(false)}
|
|
aria-label="Close"
|
|
disabled={isPending}
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
className="btn btn-sm btn-primary"
|
|
disabled={isPending}
|
|
onClick={AssignEmployee}
|
|
>
|
|
{isPending && !deletingEmp.employee ? "Please wait..." : "Save"}
|
|
</button>
|
|
</div>
|
|
)}
|
|
<div className="col-12">
|
|
<table className="table text-center">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Role</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
{Team?.length > 0 ? (
|
|
Team?.map((emp) => (
|
|
<tr key={emp?.id}>
|
|
<td className="w-min">
|
|
<div className="d-flex align-items-center gap-2">
|
|
<Avatar
|
|
size="xs"
|
|
firstName={emp?.employee?.firstName}
|
|
lastName={emp?.employee?.lastName}
|
|
/>
|
|
<span className="fw-medium">
|
|
{emp?.employee?.firstName} {emp?.employee?.lastName}
|
|
</span>
|
|
</div>
|
|
</td>
|
|
|
|
<td>{emp?.teamRole?.name}</td>
|
|
|
|
<td>
|
|
{deletingEmp?.employee?.id === emp.id && isPending ? (
|
|
<div className="spinner-border spinner-border-sm"></div>
|
|
) : (
|
|
<i
|
|
className="bx bx-trash bx-sm text-danger cursor-pointer"
|
|
onClick={() =>
|
|
setSeletingEmp({ employee: emp, isOpen: true })
|
|
}
|
|
></i>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr>
|
|
<td
|
|
colSpan={3}
|
|
className="text-center text-muted py-4 border-0"
|
|
>
|
|
{isTeamLoading ? (
|
|
<SpinnerLoader />
|
|
) : (
|
|
<p className="m-0 py-4">No Records Found</p>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
|
|
return (
|
|
<Modal
|
|
size="lg"
|
|
title={"Team Allocation"}
|
|
isOpen={isOpen}
|
|
onClose={onClose}
|
|
body={TeamAllocationBody}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default ServiceProjectTeamAllocation;
|