diff --git a/src/components/DailyProgressRport/TaskReportFilterChips.jsx b/src/components/DailyProgressRport/TaskReportFilterChips.jsx new file mode 100644 index 00000000..fb78094f --- /dev/null +++ b/src/components/DailyProgressRport/TaskReportFilterChips.jsx @@ -0,0 +1,95 @@ +import React, { useMemo } from "react"; +import { formatUTCToLocalTime } from "../../utils/dateUtils"; + +const TaskReportFilterChips = ({ filter, filterData, removeFilterChip, clearFilter }) => { + const data = filterData?.data || filterData || {}; + + const filterChips = useMemo(() => { + const chips = []; + + const addGroup = (ids, list, label, key) => { + if (!ids || ids.length === 0) return; + + const items = ids.map((id) => ({ + id, + name: list?.find((i) => i.id === id)?.name || id, + })); + + chips.push({ key, label, items }); + }; + + // Building + addGroup(filter?.buildingIds, data?.buildings, "Building", "buildingIds"); + + // Floor + addGroup(filter?.floorIds, data?.floors, "Floor", "floorIds"); + + // Activities + addGroup(filter?.activityIds, data?.activities, "Activity", "activityIds"); + + // Date Range Chips + if (filter?.dateFrom || filter?.dateTo) { + chips.push({ + key: "date", + label: "Date Range", + items: [ + { + id: "date-range", + name: `${filter?.dateFrom ? formatUTCToLocalTime(filter.dateFrom) : ""} + ${filter?.dateTo ? " to " + formatUTCToLocalTime(filter.dateTo) : ""}`, + }, + ], + }); + } + + return chips; + }, [filter, filterData]); + + if (!filterChips.length) return null; + + return ( +
+ {filterChips.map((chipGroup) => ( +
+ {chipGroup.label}: + + {chipGroup.items.map((item) => ( + + {item.name} + + {/* If date chip → remove whole date range */} + {chipGroup.key === "date" ? ( +
+ ))} +
+ ); +}; + +export default TaskReportFilterChips; diff --git a/src/components/DailyProgressRport/TaskReportFilterPanel.jsx b/src/components/DailyProgressRport/TaskReportFilterPanel.jsx index e682ad14..c5f833bb 100644 --- a/src/components/DailyProgressRport/TaskReportFilterPanel.jsx +++ b/src/components/DailyProgressRport/TaskReportFilterPanel.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useCurrentService } from "../../hooks/useProjects"; import { useSelectedProject } from "../../slices/apiDataManager"; import { FormProvider, useForm } from "react-hook-form"; @@ -11,8 +11,9 @@ import { DateRangePicker1 } from "../common/DateRangePicker"; import SelectMultiple from "../common/SelectMultiple"; import { localToUtc } from "../../utils/appUtils"; import { useTaskFilter } from "../../hooks/useTasks"; +import { set } from "date-fns"; -const TaskReportFilterPanel = ({ handleFilter }) => { +const TaskReportFilterPanel = forwardRef(({ handleFilter, setFilterdata, clearFilter }, ref) => { const [resetKey, setResetKey] = useState(0); const selectedProject = useSelectedProject(); const selectedService = useCurrentService(); @@ -23,10 +24,39 @@ const TaskReportFilterPanel = ({ handleFilter }) => { defaultValues: TaskReportDefaultValue, }); + const dynamicDefaultFilter = useMemo(() => { + return { + ...TaskReportDefaultValue, + buildingIds: TaskReportDefaultValue.buildingIds || [], + floorIds: TaskReportDefaultValue.floorIds || [], + activityIds: TaskReportDefaultValue.activityIds || [], + dateFrom: TaskReportDefaultValue.startDate, + dateTo: TaskReportDefaultValue.endDate, + }; + }, [selectedProject]); + + useImperativeHandle(ref, () => ({ + resetFieldValue: (name, value) => { + // Reset specific field + if (value !== undefined) { + setValue(name, value); + } else { + reset({ ...methods.getValues(), [name]: defaultFilter[name] }); + } + }, + getValues: methods.getValues, // optional, to read current filter state + })); + + useEffect(() => { + if (data && setFilterdata) { + setFilterdata(data); + } + }, [data, setFilterdata]); const { register, reset, handleSubmit, + setValue, formState: { errors }, } = methods; const closePanel = () => { @@ -52,7 +82,7 @@ const TaskReportFilterPanel = ({ handleFilter }) => {
{ ); -}; +}); export default TaskReportFilterPanel; diff --git a/src/components/DailyProgressRport/TaskReportList.jsx b/src/components/DailyProgressRport/TaskReportList.jsx index 5e9cf12d..a991a1d3 100644 --- a/src/components/DailyProgressRport/TaskReportList.jsx +++ b/src/components/DailyProgressRport/TaskReportList.jsx @@ -17,8 +17,9 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import Pagination from "../common/Pagination"; import { TaskReportListSkeleton } from "./TaskRepprtListSkeleton"; import HoverPopup from "../common/HoverPopup"; +import TaskReportFilterChips from "./TaskReportFilterChips"; -const TaskReportList = () => { +const TaskReportList = ({ filter, filterData, removeFilterChip, clearFilter }) => { const [currentPage, setCurrentPage] = useState(1); const [filters, setFilters] = useState({ selectedBuilding: "", @@ -29,7 +30,7 @@ const TaskReportList = () => { const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK); const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK); - const { service, openModal, closeModal, filter } = useDailyProgrssContext(); + const { service, openModal, closeModal, filter: contextFilter } = useDailyProgrssContext(); const selectedProject = useSelectedProject(); const { projectNames } = useProjectName(); @@ -37,7 +38,7 @@ const TaskReportList = () => { selectedProject, ITEMS_PER_PAGE, currentPage, - service, filter + service, contextFilter ); const ProgrssReportColumn = [ @@ -193,124 +194,136 @@ const TaskReportList = () => { if (isError) return
Loading....
; return (
-
- - - - - - +
+
+ -
- - - - - - {groupedTasks.length === 0 && ( + +
+
Activity - - Total Pending{" "} - - This shows the total pending tasks for each activity on that date. - - } - > - - - - - - Reported/Planned{" "} - - This shows the reported versus planned tasks for each activity on that date. - - } - > - - - - Assign DateTeamActions
+ - - - )} + + - {groupedTasks.map(({ date, tasks }) => ( - - - + + + + + + + + {groupedTasks.length === 0 && ( + + - {tasks.map((task, idx) => ( - - - - - - - + - ))} - - ))} - -
- No reports available -
Activity + + Total Pending{" "} + + This shows the total pending tasks for each activity on that date. + + } + > + + + +
- {formatUTCToLocalTime(date)} + + + Reported/Planned{" "} + + This shows the reported versus planned tasks for each activity on that date. + + } + > + + + + Assign DateTeamActions
+ No reports available
-
- {task.workItem.activityMaster?.activityName || "No Activity Name"} -
-
- {task.workItem.workArea?.floor?.building?.name} ›{" "} - {task.workItem.workArea?.floor?.floorName} ›{" "} - {task.workItem.workArea?.areaName} -
-
- {formatNumber(task.workItem.plannedWork)} - {`${formatNumber(task.completedTask)} / ${formatNumber(task.plannedTask)}`}{formatUTCToLocalTime(task.assignmentDate)}{renderTeamMembers(task, idx)} -
- {ReportTaskRights && !task.reportedDate && ( - - )} - {ApprovedTaskRights && task.reportedDate && !task.approvedBy && ( - - )} - -
+ )} + + {groupedTasks.map(({ date, tasks }) => ( + +
+ {formatUTCToLocalTime(date)}
+ {tasks.map((task, idx) => ( + + +
+ {task.workItem.activityMaster?.activityName || "No Activity Name"} +
+
+ {task.workItem.workArea?.floor?.building?.name} ›{" "} + {task.workItem.workArea?.floor?.floorName} ›{" "} + {task.workItem.workArea?.areaName} +
+ + + {formatNumber(task.workItem.plannedWork)} + + {`${formatNumber(task.completedTask)} / ${formatNumber(task.plannedTask)}`} + {formatUTCToLocalTime(task.assignmentDate)} + {renderTeamMembers(task, idx)} + +
+ {ReportTaskRights && !task.reportedDate && ( + + )} + {ApprovedTaskRights && task.reportedDate && !task.approvedBy && ( + + )} + +
+ + + ))} + + ))} + + -
- { - data?.data?.length > 0 && ( - - ) - } +
+ { + data?.data?.length > 0 && ( + + ) + } +
); }; diff --git a/src/pages/DailyProgressReport/DailyProgrssReport.jsx b/src/pages/DailyProgressReport/DailyProgrssReport.jsx index e543895e..da63e491 100644 --- a/src/pages/DailyProgressReport/DailyProgrssReport.jsx +++ b/src/pages/DailyProgressReport/DailyProgrssReport.jsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useEffect, useState } from "react"; +import React, { createContext, useContext, useEffect, useRef, useState } from "react"; import Breadcrumb from "../../components/common/Breadcrumb"; import { useServices } from "../../hooks/masterHook/useMaster"; import TaskReportList from "../../components/DailyProgressRport/TaskReportList"; @@ -13,6 +13,7 @@ import { useSelectedProject } from "../../slices/apiDataManager"; import SelectField from "../../components/common/Forms/SelectField"; import { AppFormController } from "../../hooks/appHooks/useAppForm"; import { useForm } from "react-hook-form"; +import { TaskReportDefaultValue } from "../../components/DailyProgressRport/TaskRportScheam"; const DailyProgrssContext = createContext(); export const useDailyProgrssContext = () => { @@ -30,8 +31,9 @@ const DailyProgrssReport = () => { const [service, setService] = useState(""); const [filter, setFilter] = useState('') const { setOffcanvasContent, setShowTrigger } = useFab(); + const updatedRef = useRef(); const { data, isLoading, isError, error } = useProjectAssignedServices(selectedProject); - + const [filterData, setFilterdata] = useState(null); const [modal, setModal] = useState({ type: null, data: null }); const openModal = (type, data = null) => setModal({ type, data }); @@ -49,20 +51,38 @@ const DailyProgrssReport = () => { serviceFilter: "" } }); - + const clearFilter = () => setFilter(TaskReportDefaultValue); const handleFilter = (filterObj) => { setFilter(filterObj) } useEffect(() => { setShowTrigger(true); - setOffcanvasContent("Report Filter", ); + setOffcanvasContent("Report Filter", ); return () => { setShowTrigger(false); setOffcanvasContent("", null); }; }, []); + + const handleRemoveChip = (key, id) => { + setFilter((prev) => { + const updated = { ...prev }; + + if (Array.isArray(updated[key])) { + updated[key] = updated[key].filter((v) => v !== id); + setTimeout(() => updatedRef.current?.resetFieldValue(key, updated[key]), 0); + } else { + updated[key] = null; + setTimeout(() => updatedRef.current?.resetFieldValue(key, null), 0); + } + + return updated; + }); + }; return (
@@ -97,7 +117,7 @@ const DailyProgrssReport = () => { ]} /> -
+
{data?.length > 0 && (
{ render={({ field }) => ( { - field.onChange(val); - setService(val); + field.onChange(val); + setService(val); }} className="m-0" /> @@ -125,7 +145,10 @@ const DailyProgrssReport = () => { )}
- +