diff --git a/src/components/Activities/ReportTask.jsx b/src/components/Activities/ReportTask.jsx index a3550683..b0e650de 100644 --- a/src/components/Activities/ReportTask.jsx +++ b/src/components/Activities/ReportTask.jsx @@ -202,3 +202,4 @@ export const ReportTask = ({ report, closeModal }) => { ); }; + export default ReportTask; \ No newline at end of file diff --git a/src/hooks/useProjects.js b/src/hooks/useProjects.js index 554af77e..3a887d60 100644 --- a/src/hooks/useProjects.js +++ b/src/hooks/useProjects.js @@ -175,6 +175,7 @@ export const useProjectInfra = (projectId) => { } = useQuery({ queryKey: ["ProjectInfra", projectId], queryFn: async () => { + if(!projectId) return null; const res = await ProjectRepository.getProjectInfraByproject(projectId); return res.data; }, diff --git a/src/pages/Activities/DailyTask.jsx b/src/pages/Activities/DailyTask.jsx index be432a0f..7008ec78 100644 --- a/src/pages/Activities/DailyTask.jsx +++ b/src/pages/Activities/DailyTask.jsx @@ -1,31 +1,29 @@ -import React, { useEffect, useState, useRef } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import Breadcrumb from "../../components/common/Breadcrumb"; +import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useDispatch } from "react-redux"; import { useTaskList } from "../../hooks/useTasks"; -import { useProjectName, useProjects } from "../../hooks/useProjects"; +import { useProjectName } from "../../hooks/useProjects"; import { setProjectId } from "../../slices/localVariablesSlice"; -import { ReportTask } from "../../components/Activities/ReportTask"; -import ReportTaskComments from "../../components/Activities/ReportTaskComments"; +import Breadcrumb from "../../components/common/Breadcrumb"; import DateRangePicker from "../../components/common/DateRangePicker"; -import { useSearchParams } from "react-router-dom"; -import moment from "moment"; -import FilterIcon from "../../components/common/FilterIcon"; +import FilterIcon from "../../components/common/FilterIcon"; import GlobalModel from "../../components/common/GlobalModel"; -import AssignTask from "../../components/Project/AssignTask"; +import ReportTask from "../../components/Activities/ReportTask"; +import ReportTaskComments from "../../components/Activities/ReportTaskComments"; import SubTask from "../../components/Activities/SubTask"; -import {formatNumber} from "../../utils/dateUtils"; +import { formatNumber, formatUTCToLocalTime } from "../../utils/dateUtils"; import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { APPROVE_TASK, ASSIGN_REPORT_TASK } from "../../utils/constants"; import { useSelectedproject } from "../../slices/apiDataManager"; +import moment from "moment"; +import Loader from "../../components/common/Loader"; const DailyTask = () => { - // const selectedProject = useSelector( - // (store) => store.localVariables.projectId - // ); + const dispatch = useDispatch(); const selectedProject = useSelectedproject(); - const dispatch = useDispatch() - const { projectNames, loading: projectLoading, fetchData } = useProjectName(); - + const { projectNames } = useProjectName(); +console.log(selectedProject) + const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK); + const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK); const [filters, setFilters] = useState({ selectedBuilding: "", @@ -33,429 +31,201 @@ const DailyTask = () => { selectedActivities: [], }); - - const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); - const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK) - const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK) - const { - TaskList, - loading: task_loading, - error: task_error, - refetch, - } = useTaskList( - selectedProject || null, - dateRange?.startDate || null, + const { TaskList, loading: taskLoading } = useTaskList( + selectedProject || null, + dateRange?.startDate || null, dateRange?.endDate || null - ); - - useEffect(() => { - if (!selectedProject?.id && projectNames.length > 0) { - dispatch(setProjectId(projectNames[0].id)); -} - -}, [selectedProject, projectNames, dispatch]); - - const [TaskLists, setTaskLists] = useState([]); - const [dates, setDates] = useState([]); - const popoverRefs = useRef([]); + ); + // Ensure project is set useEffect(() => { - if (TaskList) { - let filteredTasks = TaskList; - - if (filters.selectedBuilding) { - filteredTasks = filteredTasks.filter( - (task) => - task?.workItem?.workArea?.floor?.building?.name === - filters.selectedBuilding - ); - } - - if (filters.selectedFloors.length > 0) { - filteredTasks = filteredTasks?.filter((task) => - filters.selectedFloors?.includes( - task?.workItem?.workArea?.floor?.floorName - ) - ); - } - - if (filters.selectedActivities.length > 0) { - filteredTasks = filteredTasks.filter((task) => - filters.selectedActivities.includes( - task?.workItem?.activityMaster?.activityName - ) - ); - } - setTaskLists(filteredTasks); - } else { - setTaskLists([]); + if (!selectedProject && projectNames.length > 0) { + dispatch(setProjectId(projectNames[0].id)); } - }, [ - TaskList, - filters?.selectedBuilding, - filters?.selectedFloors, - filters?.selectedActivities, - ]); + }, [selectedProject, projectNames, dispatch]); - useEffect(() => { - const AssignmentDates = [ - ...new Set(TaskLists.map((task) => task.assignmentDate.split("T")[0])), - ].sort((a, b) => new Date(b) - new Date(a)); - setDates(AssignmentDates); - }, [TaskLists]); + // Memoized filtering + const filteredTasks = useMemo(() => { + if (!TaskList) return []; + return TaskList.filter((task) => { + const { selectedBuilding, selectedFloors, selectedActivities } = filters; - const [selectedTask, selectTask] = useState(null); - const [comments, setComment] = useState({ task: null, isActionAllow: false }); + if (selectedBuilding && task?.workItem?.workArea?.floor?.building?.name !== selectedBuilding) return false; + if (selectedFloors.length > 0 && !selectedFloors.includes(task?.workItem?.workArea?.floor?.floorName)) return false; + if (selectedActivities.length > 0 && !selectedActivities.includes(task?.workItem?.activityMaster?.activityName)) return false; - const [isModalOpen, setIsModalOpen] = useState(false); - const [isModalOpenComment, setIsModalOpenComment] = useState(false); - - const openModal = () => setIsModalOpen(true); - const closeModal = () => setIsModalOpen(false); - - const openComment = () => setIsModalOpenComment(true); - const closeCommentModal = () => setIsModalOpenComment(false); - const [IsSubTaskNeeded, setIsSubTaskNeeded] = useState(false); - const [SubTaskData, setSubTaskData] = useState(); - const handletask = (task) => { - selectTask(task); - openModal(); - }; - - useEffect(() => { - popoverRefs.current.forEach((el) => { - if (el) { - new bootstrap.Popover(el, { - trigger: "focus", - placement: "left", - html: true, - content: el.getAttribute("data-bs-content"), - }); - } + return true; }); - }, [dates, TaskLists]); + }, [TaskList, filters]); + // Memoized dates + const groupedTasks = useMemo(() => { + const groups = {}; + filteredTasks.forEach((task) => { + const date = task.assignmentDate.split("T")[0]; + if (!groups[date]) groups[date] = []; + groups[date].push(task); + }); + return Object.keys(groups) + .sort((a, b) => new Date(b) - new Date(a)) + .map((date) => ({ date, tasks: groups[date] })); + }, [filteredTasks]); - const handlecloseModal = () => - { - setIsModalOpen( false ) - // refetch(); - } + // --- Modal State + const [modal, setModal] = useState({ type: null, data: null }); - const handleCloseAction = (IsSubTask) => { - if (IsSubTask) { - setIsSubTaskNeeded(true); - setIsModalOpenComment(false); - } else { - // refetch(); - setIsModalOpenComment(false); - } - }; - const hanleCloseSubTask = () => { - setIsSubTaskNeeded(false); - setComment( null ); - // refetch(); - }; + const openModal = (type, data = null) => setModal({ type, data }); + const closeModal = () => setModal({ type: null, data: null }); + // --- Render helpers + const renderTeamMembers = (task, refIndex) => ( +
+ ${task.teamMembers + .map( + (m) => ` +
+
+ + ${m?.firstName?.charAt(0) || ""}${m?.lastName?.charAt(0) || ""} + +
+ ${m.firstName} ${m.lastName} +
` + ) + .join("")} +
+ `} + > + {task.teamMembers.slice(0, 3).map((m) => ( +
+ + {m?.firstName.slice(0, 1)} + +
+ ))} + {task.teamMembers.length > 3 && ( +
+ +{task.teamMembers.length - 3} +
+ )} + + ); return ( <> - {isModalOpen && - - } - - {isModalOpenComment && ( - setIsModalOpenComment(false)} - > + {/* --- Modals --- */} + {modal.type === "report" && ( + + + + )} + {modal.type === "comments" && ( + { + if (isSubTask) openModal("subtask", modal.data.task); + else closeModal(); + }} + closeModal={closeModal} /> )} - - {IsSubTaskNeeded && ( - - + {modal.type === "subtask" && ( + + )}
- -
+ + +
-
-
- - -
+ {!selectedProject && (
Please Select Project
)} + {/* --- Filters --- */} +
+ +
+ + {/* --- Table --- */}
- + - - {/* --- Spinner when tasks are loading --- */} - {task_loading && ( + + {taskLoading && ( )} - {!task_loading && - TaskLists.length === 0 && ( - - - - )} - {!task_loading && - TaskLists.length > 0 && - dates.map((date, i) => { - const tasksForDate = TaskLists.filter((task) => - task.assignmentDate.includes(date) - ); - if (tasksForDate.length === 0) return null; - - return ( - - - + + + )} + {!taskLoading && + groupedTasks.map(({ date, tasks }) => ( + + + + + {tasks.map((task, idx) => ( + + + + + + + - {tasksForDate.map((task, index) => { - const refIndex = index * 10 + i; - return ( - - - - - - - - - - - ); - })} - - ); - })} + ))} + + ))}
ActivityAssigned Assigned Completed Assign On Team Actions
- {" "} -
-
- Loading... -
-

Loading Tasks...

-
+
-
- {" "} -

No Reports Found

-
-
- {" "} - - {moment(date).format("DD-MM-YYYY")} - + {!taskLoading && groupedTasks.length === 0 && ( +
No Reports Found
{formatUTCToLocalTime(date)}
+
{task.workItem.activityMaster?.activityName || "No Activity Name"}
+
+ {task.workItem.workArea?.floor?.building?.name} › {task.workItem.workArea?.floor?.floorName} › {task.workItem.workArea?.areaName} +
+
{formatNumber(task.plannedTask)} / {formatNumber(task.workItem.plannedWork - task.workItem.completedWork)}{task.completedTask}{formatUTCToLocalTime(task.assignmentDate)}{renderTeamMembers(task, idx)} +
+ {ReportTaskRights && !task.reportedDate && ( + + )} + {ApprovedTaskRights && task.reportedDate && !task.approvedBy && ( + + )} + +
-
- {task.workItem.activityMaster - .activityName || "No Activity Name"} -
-
- -
-
- {formatNumber(task.plannedTask)} / {formatNumber(task.workItem.plannedWork - task.workItem.completedWork)} - {task.completedTask} - {moment(task.assignmentDate).format( - "DD-MM-YYYY" - )} - -
- (popoverRefs.current[refIndex] = el) - } - tabIndex="0" - className="d-flex align-items-center avatar-group justify-content-center" - data-bs-toggle="popover" - data-bs-trigger="focus" - data-bs-placement="left" - data-bs-html="true" - data-bs-content={` -
- ${task.teamMembers - .map( - (member) => ` -
-
- - ${ - member?.firstName?.charAt( - 0 - ) || "" - }${ - member?.lastName?.charAt(0) || "" - } - -
- ${member.firstName} ${ - member.lastName - } -
- ` - ) - .join("")} -
- `} - > - {task.teamMembers - .slice(0, 3) - .map((member) => ( -
- - {member?.firstName.slice(0, 1)} - -
- ))} - {task.teamMembers.length > 3 && ( -
- - + {task.teamMembers.length - 3} - -
- )} -
-
-
- { ReportTaskRights && - - } - {(ApprovedTaskRights && task.reportedDate ) && ( - - )} - - -
-
diff --git a/src/pages/Activities/TaskPlannng.jsx b/src/pages/Activities/TaskPlannng.jsx index 4ced1b42..ed51490c 100644 --- a/src/pages/Activities/TaskPlannng.jsx +++ b/src/pages/Activities/TaskPlannng.jsx @@ -1,4 +1,4 @@ -import React,{useEffect} from "react"; +import React,{useEffect,useRef} from "react"; import Breadcrumb from "../../components/common/Breadcrumb"; import InfraPlanning from "../../components/Activities/InfraPlanning"; import { useProjectName } from "../../hooks/useProjects"; @@ -6,33 +6,34 @@ import { useDispatch, useSelector } from "react-redux"; import { setProjectId } from "../../slices/localVariablesSlice"; import { useSelectedproject } from "../../slices/apiDataManager"; - const TaskPlannng = () => { - // const selectedProject = useSelector( - // (store) => store.localVariables.projectId - // ); const selectedProject = useSelectedproject(); + const dispatch = useDispatch(); + const { projectNames, loading: projectLoading } = useProjectName(); + + const initialized = useRef(false); - const dispatch = useDispatch() - const { projectNames, loading: projectLoading, fetchData } = useProjectName(); useEffect(() => { - if(selectedProject == null){ - dispatch(setProjectId(projectNames[0]?.id)); - } - },[]) + if (!initialized.current && projectNames.length > 0 && !selectedProject?.id) { + dispatch(setProjectId(projectNames[0].id)); + initialized.current = true; + } + }, [projectNames, selectedProject, dispatch]); return ( - <> -
- - -
- +
+ + {selectedProject ? ( + + ) : ( +
Please Select Project
+ )} +
); };