2025-07-02 01:57:02 +05:30

221 lines
8.5 KiB
JavaScript

import React, { useEffect, useState } from "react";
import WorkItem from "./WorkItem";
import { useProjectDetails, useProjectTasks } from "../../../hooks/useProjects";
import { cacheData } from "../../../slices/apiDataManager";
import { useDispatch, useSelector } from "react-redux";
import { refreshData } from "../../../slices/localVariablesSlice";
import ProjectRepository from "../../../repositories/ProjectRepository";
import showToast from "../../../services/toastService";
import { useHasUserPermission } from "../../../hooks/useHasUserPermission";
import {
ASSIGN_REPORT_TASK,
MANAGE_PROJECT_INFRA,
MANAGE_TASK,
} from "../../../utils/constants";
import { useParams } from "react-router-dom";
import ProgressBar from "../../common/ProgressBar";
const WorkArea = ({ workArea, floor, forBuilding }) => {
const selectedProject = useSelector((store) => store.localVariables.projectId);
const { projects_Details, loading } = useProjectDetails(selectedProject);
const [IsExpandedArea, setIsExpandedArea] = useState(false);
const dispatch = useDispatch();
const [Project, setProject] = useState();
const { projectId } = useParams();
const ManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
const ManageAndAssignTak = useHasUserPermission(ASSIGN_REPORT_TASK);
const { ProjectTaskList, isLoading } = useProjectTasks(workArea.id, IsExpandedArea);
const [workAreaStatus, setWorkAreaStatus] = useState({
completed: 0,
planned: 100,
});
useEffect(() => {
setProject(projects_Details);
}, [projects_Details]);
useEffect(() => {
const totalCompleted = ProjectTaskList?.reduce(
(sum, i) => sum + (i?.workItem?.completedWork || 0),
0
);
const totalPlanned = ProjectTaskList?.reduce(
(sum, i) => sum + (i?.workItem?.plannedWork || 0),
0
);
setWorkAreaStatus({ completed: totalCompleted, planned: totalPlanned });
}, [ProjectTaskList]);
const HanldeDeleteActivity = async (workItemId) => {
try {
const updatedProject = { ...Project.data };
await ProjectRepository.deleteProjectTask(workItemId);
const newProject = {
...updatedProject,
buildings: updatedProject?.buildings.map((building) => ({
...building,
floors: building?.floors.map((floor) => ({
...floor,
workAreas: floor.workAreas.map((wa) =>
wa.id === workArea.id
? {
...wa,
workItems: wa.workItems.filter(
(item) =>
String(item?.workItem?.id ?? item?.id) !==
String(workItemId)
),
}
: wa
),
})),
})),
};
cacheData("projectInfo", {
projectId: newProject.id,
data: newProject,
});
dispatch(refreshData(true));
showToast("Activity Deleted Successfully", "success");
} catch (error) {
const message =
error.response?.data?.message || error.message || "An error occurred";
showToast(message, "error");
}
};
useEffect(() => {
const collapseElement = document.getElementById(`collapse-${workArea.id}`);
const handleShown = () => setIsExpandedArea(true);
const handleHidden = () => setIsExpandedArea(false);
collapseElement?.addEventListener("shown.bs.collapse", handleShown);
collapseElement?.addEventListener("hidden.bs.collapse", handleHidden);
return () => {
collapseElement?.removeEventListener("shown.bs.collapse", handleShown);
collapseElement?.removeEventListener("hidden.bs.collapse", handleHidden);
};
}, [workArea.id]);
return (
<React.Fragment key={workArea.id}>
<tr>
<td colSpan="4" className="p-0">
<div className="accordion border-none" id={`accordion-${workArea.id}`}>
<div className="accordion-item background border-0">
<p className="accordion-header mb-0" id={`heading-${workArea.id}`}>
<button
className="accordion-button text-start px-2 py-2 custom-accordion-btn collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target={`#collapse-${workArea.id}`}
aria-expanded="false"
aria-controls={`collapse-${workArea.id}`}
>
<i
className={`bx me-2 toggle-icon ${
IsExpandedArea ? "bx-minus-circle" : "bx-plus-circle"
}`}
style={{
fontSize: "1.2rem",
color: "black",
}}
></i>
<div className="d-flex justify-content-start row w-100 align-items-center">
<div className="d-flex col-5">
<span className="fw-semibold text-primary small">Floor:</span>
<span className="fw-normal text-darkgreen small px-2">
{floor.floorName}
</span>
</div>
<div className="text-start col-5">
<span className="fw-semibold text-primary small">Work Area:</span>
<span className="fw-normal text-darkgreen small px-2">
{workArea.areaName}
</span>
</div>
{ProjectTaskList?.length > 0 && (
<div className="col-2">
<ProgressBar
completedWork={workAreaStatus.completed}
plannedWork={workAreaStatus.planned}
className="m-0 text-info"
/>
</div>
)}
</div>
</button>
</p>
<div
id={`collapse-${workArea.id}`}
className="accordion-collapse collapse"
aria-labelledby={`heading-${workArea.id}`}
>
<div className="accordion-body px-1">
{isLoading ? (
<div className="text-center py-2 text-muted">Loading activities...</div>
) : ProjectTaskList?.length > 0 ? (
<table className="table table-sm mx-1">
<thead>
<tr>
<th className="infra-activity-table-header-first">Activity</th>
<th className="infra-activity-table-header d-sm-table-cell d-md-none">
Status
</th>
<th className="infra-activity-table-header d-none d-md-table-cell">
Category
</th>
<th className="infra-activity-table-header d-none d-md-table-cell">
Completed/Planned
</th>
<th className="infra-activity-table-header d-none d-md-table-cell">
Today's Planned
</th>
<th className="infra-activity-table-header">Progress</th>
{(ManageInfra || (!projectId && ManageAndAssignTak)) && (
<th className="infra-activity-table-header text-end">
<span className="px-2">Actions</span>
</th>
)}
</tr>
</thead>
<tbody className="table-border-bottom-0">
{ProjectTaskList.map((workItem) => (
<WorkItem
key={workItem.workItemId}
workItem={workItem}
forBuilding={forBuilding}
forFloor={floor}
forWorkArea={workArea}
deleteHandleTask={HanldeDeleteActivity}
/>
))}
</tbody>
</table>
) : (
<div className="text-center text-muted py-3">
No activities available for this work area.
</div>
)}
</div>
</div>
</div>
</div>
</td>
</tr>
</React.Fragment>
);
};
export default WorkArea;