From f848f97d874feece582f7fb9f899ffa04286a3d8 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Mon, 30 Jun 2025 20:20:52 +0530 Subject: [PATCH] implement partial react-query in task assignment flow --- src/components/Activities/InfraPlanning.jsx | 26 +- src/components/Activities/ReportTask.jsx | 70 ++-- .../Activities/ReportTaskComments.jsx | 296 ++++++++------- src/components/Layout/Header.jsx | 27 +- src/components/Project/AssignTask.jsx | 63 ++-- src/hooks/useTasks.js | 347 +++++++++++++----- src/pages/Activities/DailyTask.jsx | 104 +++--- src/pages/Activities/TaskPlannng.jsx | 117 +----- src/services/signalRService.js | 23 +- 9 files changed, 601 insertions(+), 472 deletions(-) diff --git a/src/components/Activities/InfraPlanning.jsx b/src/components/Activities/InfraPlanning.jsx index 47c4dba9..49f00567 100644 --- a/src/components/Activities/InfraPlanning.jsx +++ b/src/components/Activities/InfraPlanning.jsx @@ -21,17 +21,13 @@ const InfraPlanning = () => { const {profile: LoggedUser, refetch : fetchData} = useProfile() const dispatch = useDispatch() - const {projects,loading:project_listLoader,error:projects_error} = useProjects() + // const {projects,loading:project_listLoader,error:projects_error} = useProjects() const selectedProject = useSelector((store)=>store.localVariables.projectId) const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA ) const {projects_Details, loading: project_deatilsLoader, error: project_error,refetch} = useProjectDetails( selectedProject ) const reloadedData = useSelector( ( store ) => store.localVariables.reload ) - - // useEffect( () => - // { - // dispatch(setProjectId(projects[0]?.id)) - // }, [ projects ] ) + useEffect( () => { @@ -48,24 +44,6 @@ const InfraPlanning = () =>
- {/*
-
- -
- -
*/}
{project_deatilsLoader && (

Loading...

)} {( !project_deatilsLoader && projects_Details?.buildings.length === 0 ) && (

No Result Found

)} diff --git a/src/components/Activities/ReportTask.jsx b/src/components/Activities/ReportTask.jsx index 13b7228a..e376433f 100644 --- a/src/components/Activities/ReportTask.jsx +++ b/src/components/Activities/ReportTask.jsx @@ -5,9 +5,21 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import showToast from "../../services/toastService"; import { TasksRepository } from "../../repositories/TaskRepository"; +import {useReportTask} from "../../hooks/useTasks"; -export const ReportTask = ({ report, closeModal, refetch }) => { - const [loading, setloading] = useState(false); +export const ReportTask = ({ report, closeModal }) => { + const [ loading, setloading ] = useState( false ); + const { mutate: reportTask, isPending } = useReportTask({ + onSuccessCallback: () => { + // refetch(); + reset(); + setloading(false); + closeModal(); + }, + onErrorCallback: () => { + setloading(false); + }, + } ); const maxPending = report?.workItem?.plannedWork - report?.workItem?.completedWork; @@ -43,33 +55,45 @@ export const ReportTask = ({ report, closeModal, refetch }) => { useEffect(() => { if (report) { - reset({ completedTask: 0, comment: "" }); // optional: customize default if needed + reset({ completedTask: 0, comment: "" }); } }, [report, reset]); - const onSubmit = async (data) => { - try { - setloading(true); - const reportData = { - ...data, - id: report?.id, - reportedDate: new Date().toISOString(), - checkList: [], - }; + // const onSubmit = async (data) => { + // try { + // setloading(true); + // const reportData = { + // ...data, + // id: report?.id, + // reportedDate: new Date().toISOString(), + // checkList: [], + // }; - let response = await TasksRepository.reportTask(reportData); - showToast("Task Reported Successfully.", "success"); - refetch(); - reset() - setloading(false); - closeModal(); - } catch ( error ) - { - const msg = error.response.data.message || error.message || "Error Occur During Api Call" - showToast(msg, "error"); - } + // let response = await TasksRepository.reportTask(reportData); + // showToast("Task Reported Successfully.", "success"); + // refetch(); + // reset() + // setloading(false); + // closeModal(); + // } catch ( error ) + // { + // const msg = error.response.data.message || error.message || "Error Occur During Api Call" + // showToast(msg, "error"); + // } + // } + + const onSubmit = (data) => { + setloading(true); + const reportData = { + ...data, + id: report?.id, + reportedDate: new Date().toISOString(), + checkList: [], }; + + reportTask(reportData); +}; const handleClose = () => { closeModal(); reset(); diff --git a/src/components/Activities/ReportTaskComments.jsx b/src/components/Activities/ReportTaskComments.jsx index f5db9434..22e69306 100644 --- a/src/components/Activities/ReportTaskComments.jsx +++ b/src/components/Activities/ReportTaskComments.jsx @@ -9,7 +9,7 @@ import Avatar from "../common/Avatar"; import { getBgClassFromHash } from "../../utils/projectStatus"; import { cacheData, getCachedData } from "../../slices/apiDataManager"; import ImagePreview from "../common/ImagePreview"; -import { useAuditStatus } from "../../hooks/useTasks"; +import { useAuditStatus, useSubmitTaskComment } from "../../hooks/useTasks"; const ReportTaskComments = ({ commentsData, @@ -48,7 +48,18 @@ const ReportTaskComments = ({ const [loading, setloading] = useState(false); const [comments, setComment] = useState([]); const { status, loading: auditStatusLoading } = useAuditStatus(); - const [IsNeededSubTask, setIsNeededSubTask] = useState(false); + const [ IsNeededSubTask, setIsNeededSubTask ] = useState( false ); + const { submitComment, isPending } = useSubmitTaskComment({ + actionAllow, + onSuccessCallback: (data) => { + setComment((prev) => [...prev, data]); + reset(); + if ( actionAllow ) + { + handleCloseAction(IsNeededSubTask); + } + }, + }); const { watch, @@ -88,70 +99,73 @@ const ReportTaskComments = ({ } }, [comments]); - const onSubmit = async (data) => { - let payload = { - ...data, - [actionAllow ? "id" : "taskAllocationId"]: commentsData?.id, - ...(actionAllow ? {} : { commentDate: new Date().toISOString() }), - }; + // const onSubmit = async (data) => { + // let payload = { + // ...data, + // [actionAllow ? "id" : "taskAllocationId"]: commentsData?.id, + // ...(actionAllow ? {} : { commentDate: new Date().toISOString() }), + // }; - try { - setloading(true); - const resp = actionAllow - ? await TasksRepository.auditTask(payload) - : await TasksRepository.taskComments(payload); + // try { + // setloading(true); + // const resp = actionAllow + // ? await TasksRepository.auditTask(payload) + // : await TasksRepository.taskComments(payload); - setComment((prevItems) => [...prevItems, resp.data]); + // setComment((prevItems) => [...prevItems, resp.data]); - const taskList = getCachedData("taskList"); + // const taskList = getCachedData("taskList"); - if (actionAllow) { - handleCloseAction(IsNeededSubTask); - showToast( - "Review submitted successfully. Record has been updated.", - "success" - ); - } else { - if (taskList && taskList.data) { - const updatedTaskList = taskList.data.map((task) => { - if (task.id === resp.data.taskAllocationId) { - const existingComments = Array.isArray(task.comments) - ? task.comments - : []; - return { - ...task, - comments: [...existingComments, resp.data], - }; - } - return task; - }); + // if (actionAllow) { + // handleCloseAction(IsNeededSubTask); + // showToast( + // "Review submitted successfully. Record has been updated.", + // "success" + // ); + // } else { + // if (taskList && taskList.data) { + // const updatedTaskList = taskList.data.map((task) => { + // if (task.id === resp.data.taskAllocationId) { + // const existingComments = Array.isArray(task.comments) + // ? task.comments + // : []; + // return { + // ...task, + // comments: [...existingComments, resp.data], + // }; + // } + // return task; + // }); - cacheData("taskList", { - data: updatedTaskList, - projectId: taskList.projectId, - }); - } - showToast("Successfully Sent", "success"); - } + // cacheData("taskList", { + // data: updatedTaskList, + // projectId: taskList.projectId, + // }); + // } + // showToast("Successfully Sent", "success"); + // } - reset(); - setloading(false); - } catch (error) { - setloading(false); - showToast( - error.response.data?.message || "Something went wrong", - "error" - ); - } + // reset(); + // setloading(false); + // } catch (error) { + // setloading(false); + // showToast( + // error.response.data?.message || "Something went wrong", + // "error" + // ); + // } + // }; + + const onSubmit = (formData) => { + submitComment({ data: formData, commentsData }); }; - const selectedAuditStatus = watch("workStatus"); useEffect(() => { reset({ approvedTask: defaultCompletedTask || 0, }); - }, [ defaultCompletedTask ] ); + }, [defaultCompletedTask]); return (
@@ -233,7 +247,6 @@ const ReportTaskComments = ({ )}
-

@@ -260,50 +273,50 @@ const ReportTaskComments = ({

{commentsData?.description}
- {commentsData?.approvedBy && ( <> -
-
- -
- {commentsData.approvedBy && ( -
- - Approved By: -
- - {commentsData.approvedBy.firstName + - " " + - commentsData.approvedBy.lastName} -
+
+
+
+ {commentsData.approvedBy && ( +
+ + Approved By: +
+ + {commentsData.approvedBy.firstName + + " " + + commentsData.approvedBy.lastName} +
+
+ )}
- )} -
-
- {commentsData?.workStatus != null && ( -
- - Work Status : - - {commentsData?.workStatus.name} - {/* {commentsData?.} */} - +
+ {commentsData?.workStatus != null && ( +
+ + Work Status : + + {commentsData?.workStatus.name} + {/* {commentsData?.} */} + +
+ )}
- )} -
-
- Total Approved : {commentsData?.completedTask } -
- )} - +
+ Total Approved : + {commentsData?.completedTask} +
+ + )} + {commentsData?.reportedPreSignedUrls?.length > 0 && ( <>

@@ -319,54 +332,53 @@ const ReportTaskComments = ({ )}

- {( actionAllow && !commentsData.approvedBy ) && ( + {actionAllow && !commentsData.approvedBy && ( <> -
-
- - - {errors.approvedTask && ( -

- {errors.approvedTask.message} -

- )} -
-
- - + {errors.approvedTask && ( +

+ {errors.approvedTask.message} +

)} - - {errors.workStatus && ( -
- {errors.workStatus.message} -
- )} +
+
+ + + {errors.workStatus && ( +
+ {errors.workStatus.message} +
+ )} +
-
- )} @@ -382,10 +394,16 @@ const ReportTaskComments = ({ )}
-
+
{ [fetchData,projectNames,selectedProject] ); - useEffect(() => { - eventBus.on("assign_project_one", handler); - return () => eventBus.off("assign_project_one", handler); - }, [handler]); + // useEffect(() => { + // eventBus.on("assign_project_one", handler); + // return () => eventBus.off("assign_project_one", handler); + // }, [handler]); const newProjectHandler = useCallback( async (msg) => { @@ -139,10 +139,23 @@ const Header = () => { [HasManageProjectPermission,projectNames] ); + // useEffect(() => { + // eventBus.on("project", newProjectHandler); + // return () => eventBus.off("project", newProjectHandler); + // }, [handler]); + + useEffect(() => { - eventBus.on("project", newProjectHandler); - return () => eventBus.off("project", newProjectHandler); - }, [handler]); + eventBus.on("assign_project_one", handler); + eventBus.on("project", newProjectHandler); + + return () => { + eventBus.off("assign_project_one", handler); + eventBus.off("project", newProjectHandler); + }; +}, [handler, newProjectHandler]); + + return (
)} diff --git a/src/pages/Activities/TaskPlannng.jsx b/src/pages/Activities/TaskPlannng.jsx index 71598315..e8a03c6e 100644 --- a/src/pages/Activities/TaskPlannng.jsx +++ b/src/pages/Activities/TaskPlannng.jsx @@ -1,110 +1,9 @@ -import React, { useState, useEffect } from "react"; -import "../../components/Project/ProjectInfra.css"; - -import ProjectRepository from "../../repositories/ProjectRepository"; +import React from "react"; import Breadcrumb from "../../components/common/Breadcrumb"; import InfraPlanning from "../../components/Activities/InfraPlanning"; -import { cacheData, getCachedData } from "../../slices/apiDataManager"; -import { useProfile } from "../../hooks/useProfile"; -import { useDispatch, useSelector } from "react-redux"; -import { useProjectDetails, useProjects } from "../../hooks/useProjects"; -import { setProjectId } from "../../slices/localVariablesSlice"; -import showToast from "../../services/toastService"; + const TaskPlannng = () => { - const { profile } = useProfile(); - const { - projects, - loading: project_listLoader, - error: projects_error, - } = useProjects(); - const dispatch = useDispatch(); - const selectedProject = useSelector( - (store) => store.localVariables.projectId - ); - - - const [project, setProject] = useState(null); - const [projectDetails, setProjectDetails] = useState(null); - const [activities, setActivities] = useState(null); - - const [loading, setLoading] = useState(true); - const [error, setError] = useState(""); - - const fetchActivities = async () => { - try { - const activities_cache = getCachedData("activitiesMaster"); - - if (!activities_cache) { - ActivityeRepository.getActivities() - .then((response) => { - setActivities(response.data); - cacheData("activitiesMaster", response.data); - }) - .catch((error) => { - setError("Failed to fetch data."); - }); - } else { - setActivities(activities_cache); - } - } catch (err) { - setError("Failed to fetch activities."); - } finally { - // setLoading(false); - } - }; - - const fetchData = async () => { - try { - const project_cache = getCachedData("projectInfo"); - if (!project_cache || !project_cache.projectId == selectedProject) { - ProjectRepository.getProjectByprojectId(selectedProject) - .then((response) => { - setProjectDetails(response); - setProject(response); - cacheData("projectInfo", { - data: response.data, - projectId: selectedProject, - }); - }) - .catch((error) => { - const message = - error.response?.data?.message || - error.message || - "An unexpected error occurred"; - showToast( message, "error" ); - }); - } else { - setProjectDetails(project_cache); - } - } catch (err) { - setError( "Failed to fetch data." ); - const message = - error.response?.data?.message || - error.message || - "An unexpected error occurred"; - showToast( message, "error" ); - } finally { - setLoading(false); - } - }; - - const [activePill, setActivePill] = useState("profile"); - - const handlePillClick = (pillKey) => { - setActivePill(pillKey); - }; - - const handleDataChange = (data) => { - fetchData(); - }; - - useEffect(() => { - if (projects.length != 0 && selectedProject) { - fetchData(); - fetchActivities(); - } - }, [selectedProject]); return ( <> @@ -115,17 +14,7 @@ const TaskPlannng = () => { { label: "Daily Task Planning", link: "/activities/task" }, ]} > - {project_listLoader &&

Loading..

} - {!project_listLoader && projects.length === 0 && ( -

No Project Found.

- )} - {!project_listLoader && projects.length > 0 && ( - - )} +
); diff --git a/src/services/signalRService.js b/src/services/signalRService.js index 49ad0cc8..cb9603e8 100644 --- a/src/services/signalRService.js +++ b/src/services/signalRService.js @@ -8,7 +8,8 @@ import showToast from "./toastService"; import eventBus from "./eventBus"; import { useSelector } from "react-redux"; import { clearApiCacheKey } from "../slices/apiCacheSlice"; -import { BASE_URL } from "../utils/constants"; +import {BASE_URL} from "../utils/constants"; +import { queryClient } from "../layouts/AuthLayout"; const base_Url = BASE_URL; let connection = null; @@ -57,7 +58,8 @@ export function startSignalR(loggedUser) { data.keyword == "Create_Project" || data.keyword == "Update_Project" ) { - clearCacheKey("projectslist"); + // clearCacheKey("projectslist"); + queryClient.invalidateQueries(['projectslist']); eventBus.emit("project", data); } @@ -83,13 +85,22 @@ export function startSignalR(loggedUser) { // if created or updated Employee if (data.keyword == "Employee") { - clearCacheKey("employeeListByProject"); - clearCacheKey("allEmployeeList"); - clearCacheKey("allInactiveEmployeeList"); - clearCacheKey("employeeProfile"); + // clearCacheKey("employeeListByProject"); + // clearCacheKey("allEmployeeList"); + // clearCacheKey("allInactiveEmployeeList"); + // clearCacheKey("employeeProfile"); clearCacheKey("Attendance"); clearCacheKey("regularizedList") clearCacheKey("AttendanceLogs") + + // ---we can do also---- + // queryClient.removeQueries(['allEmployee', true]); + // but best practies is refetch + queryClient.invalidateQueries(['allEmployee', true]); + queryClient.invalidateQueries(['allEmployee', false]); + queryClient.invalidateQueries(['employeeProfile', data.response?.employeeId]); + queryClient.invalidateQueries(['employeeListByProject']); // optional if scope + queryClient eventBus.emit("employee", data); } }