import React, { useEffect, useState, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; import Breadcrumb from "../../components/common/Breadcrumb"; import { useTaskList } from "../../hooks/useTasks"; import { useProjects } from "../../hooks/useProjects"; import { setProjectId } from "../../slices/localVariablesSlice"; import { ReportTask } from "../../components/Activities/ReportTask"; import ReportTaskComments from "../../components/Activities/ReportTaskComments"; import DateRangePicker from "../../components/common/DateRangePicker"; import { useSearchParams } from "react-router-dom"; import moment from "moment"; import FilterIcon from "../../components/common/FilterIcon"; // Import the FilterIcon component const DailyTask = () => { const [searchParams] = useSearchParams(); const projectIdFromUrl = searchParams.get("project"); const selectedProject = useSelector( (store) => store.localVariables.projectId ); const { projects, loading: project_loading, error: projects_Error, } = useProjects(); const [initialized, setInitialized] = useState(false); const dispatch = useDispatch(); // State for filters (moved to FilterIcon, but we need to receive them here) const [filters, setFilters] = useState({ selectedBuilding: "", selectedFloors: [], selectedActivities: [], }); // Sync projectId (either from URL or pick first accessible one) useEffect(() => { if (!project_loading && projects.length > 0 && !initialized) { if (projectIdFromUrl) { dispatch(setProjectId(projectIdFromUrl)); } else if (selectedProject === 1 || selectedProject === undefined) { // If no project from URL or default/undefined, pick the first project dispatch(setProjectId(projects[0].id)); } setInitialized(true); } }, [ project_loading, projects, projectIdFromUrl, selectedProject, initialized, dispatch, ]); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const { TaskList, loading: task_loading, // This `loading` state indicates if task data is being fetched error: task_error, refetch, } = useTaskList( initialized ? selectedProject : null, initialized ? dateRange.startDate : null, initialized ? dateRange.endDate : null ); const [TaskLists, setTaskLists] = useState([]); // This state holds the *filtered* tasks for display const [dates, setDates] = useState([]); const popoverRefs = useRef([]); // Effect to apply filters to TaskList (from useTaskList) and update TaskLists (filtered display) useEffect(() => { // Only filter if TaskList is available (not null or undefined) 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 { // If TaskList is null (e.g., during initial load or project change before data arrives), // ensure TaskLists is also empty to avoid displaying stale data. setTaskLists([]); } }, [ TaskList, filters.selectedBuilding, filters.selectedFloors, filters.selectedActivities, ]); 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]); const [selectedTask, selectTask] = useState(null); const [comments, setComment] = useState(null); 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 handletask = (task) => { selectTask(task); openModal(); }; useEffect(() => { // Ensure Bootstrap's Popover is initialized correctly popoverRefs.current.forEach((el) => { if ( el && window.bootstrap && typeof window.bootstrap.Popover === "function" ) { // Dispose existing popovers to prevent duplicates if component re-renders const existingPopover = window.bootstrap.Popover.getInstance(el); if (existingPopover) { existingPopover.dispose(); } new window.bootstrap.Popover(el, { trigger: "focus", placement: "left", html: true, content: el.getAttribute("data-bs-content"), }); } }); // Cleanup function for popovers when component unmounts or dependencies change return () => { popoverRefs.current.forEach((el) => { if ( el && window.bootstrap && typeof window.bootstrap.Popover === "function" ) { const existingPopover = window.bootstrap.Popover.getInstance(el); if (existingPopover) { existingPopover.dispose(); } } }); popoverRefs.current = []; // Clear the refs array }; }, [dates, TaskLists]); // Re-initialize popovers when tasks or dates change // Handler for project selection const handleProjectChange = (e) => { const newProjectId = e.target.value; dispatch(setProjectId(newProjectId)); // --- IMPORTANT: Clear old data immediately to show loading state --- setTaskLists([]); // This makes the table empty, allowing the spinner to show // Reset filters when project changes (communicate to FilterIcon to clear) setFilters({ selectedBuilding: "", selectedFloors: [], selectedActivities: [], }); }; return ( <> {/* Report Task Modal */}
{isModalOpen &&
}{" "} {/* Add backdrop */}
{/* Report Task Comments Modal */}
{isModalOpenComment &&
}{" "} {/* Add backdrop */}
{/* FilterIcon component now manages its own filter states and logic */}
{/* --- Spinner when tasks are loading --- */} {(task_loading || project_loading) && ( )} {/* --- "No Reports Found" message only if not loading and no tasks --- */} {!task_loading && !project_loading && TaskLists.length === 0 && ( )} {/* --- Render tasks when not loading and tasks exist --- */} {!task_loading && TaskLists.length > 0 && dates.map((date, i) => { const tasksForDate = TaskLists.filter((task) => task.assignmentDate.includes(date) ); // Only render the date header if there are tasks for that date after filtering if (tasksForDate.length === 0) return null; return ( {tasksForDate.map((task, index) => { const refIndex = `${i}-${index}`; return ( ); })} ); })}
Activity Assigned Completed Assign On Team Actions
{" "} {/* ColSpan set to 6 based on your table headers */}
Loading...

Loading Tasks...

{" "} {/* ColSpan set to 6 */}

No Reports Found

{" "} {/* ColSpan set to 6 */} {moment(date).format("DD-MM-YYYY")}
{task.workItem.activityMaster .activityName || "No Activity Name"}
{task.plannedTask || "NA"} / {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}
)}
); }; export default DailyTask;