From 1531fbe6f27e688752a8d48e87986296b41a47bd Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Thu, 20 Nov 2025 16:16:20 +0530 Subject: [PATCH 1/2] Implementing Archieve functionality in Jobs. --- src/components/ServiceProject/JobList.jsx | 185 ++++++++++++++-------- src/components/common/ConfirmModal.jsx | 2 +- src/hooks/useServiceProject.jsx | 25 +-- 3 files changed, 132 insertions(+), 80 deletions(-) diff --git a/src/components/ServiceProject/JobList.jsx b/src/components/ServiceProject/JobList.jsx index 8a7f1639..d0ab8695 100644 --- a/src/components/ServiceProject/JobList.jsx +++ b/src/components/ServiceProject/JobList.jsx @@ -4,7 +4,7 @@ import { getJobStatusBadge, getNextBadgeColor, } from "../../utils/appUtils"; -import { useServiceProjectJobs } from "../../hooks/useServiceProject"; +import { useServiceProjectJobs, useUpdateServiceProjectJob } from "../../hooks/useServiceProject"; import { ITEMS_PER_PAGE } from "../../utils/constants"; import EmployeeAvatarGroup from "../common/EmployeeAvatarGroup"; import { formatUTCToLocalTime } from "../../utils/dateUtils"; @@ -12,9 +12,12 @@ import { SpinnerLoader } from "../common/Loader"; import { useParams } from "react-router-dom"; import ProjectPage from "../../pages/project/ProjectPage"; import { useServiceProjectJobContext } from "./Jobs"; +import ConfirmModal from "../common/ConfirmModal"; const JobList = () => { const { setSelectedJob, setManageJob } = useServiceProjectJobContext(); + const { mutate: UpdateJob } = useUpdateServiceProjectJob(() => { + }); const { projectId } = useParams(); const { data, isLoading, isError, error } = useServiceProjectJobs( ITEMS_PER_PAGE, @@ -22,6 +25,29 @@ const JobList = () => { true, projectId ); + const [isArchiveModalOpen, setIsArchiveModalOpen] = useState(false); + const [archiveJobId, setArchiveJobId] = useState(null); + + + const handleArchive = () => { + const payload = [ + { + op: "replace", + path: "/isArchive", + value: true, + }, + ]; + + UpdateJob({ + id: archiveJobId, + payload, + isArchiveAction: true, + }); + + setIsArchiveModalOpen(false); + setArchiveJobId(null); + }; + const jobGrid = [ { @@ -87,64 +113,75 @@ const JobList = () => { ]; return ( -
- - - - {jobGrid.map((col) => ( -
-
{col.label}
+ <> + + {isArchiveModalOpen && ( + setIsArchiveModalOpen(false)} + loading={false} + /> + )} + +
+ + + + {jobGrid.map((col) => ( + + ))} + - ))} - - - + + - - {Array.isArray(data?.data) && data.data.length > 0 ? ( - data.data.map((row, i) => ( - - {jobGrid.map((col) => ( - - ))} - + {jobGrid.map((col) => ( + + ))} + + + )) + ) : ( + + - )) - ) : ( - - - - )} - -
+
{col.label}
+
+ Actions - Actions -
- setSelectedJob({ showCanvas: true, job: row?.id }) - } - > - {col.getValue(row)} - -
-
+ setSelectedJob({ showCanvas: true, job: row?.id }) + } > - - -
+ {col.getValue(row)} +
+
- - <> +
+ - + + +
- +
+ {isLoading ? : "Not Found Jobs."}
- {isLoading ? : "Not Found Jobs."} -
-
+ )} + +
+
+ ); }; diff --git a/src/components/common/ConfirmModal.jsx b/src/components/common/ConfirmModal.jsx index dd0158eb..d2f10213 100644 --- a/src/components/common/ConfirmModal.jsx +++ b/src/components/common/ConfirmModal.jsx @@ -17,7 +17,7 @@ const ConfirmModal = ({ case "delete": return ; case "success": - return ; + return ; case "warning": return ; default: diff --git a/src/hooks/useServiceProject.jsx b/src/hooks/useServiceProject.jsx index 93817800..f93bab4b 100644 --- a/src/hooks/useServiceProject.jsx +++ b/src/hooks/useServiceProject.jsx @@ -255,21 +255,26 @@ export const useCreateServiceProjectJob = (onSuccessCallback) => { }); }; -export const useUpdateServiceProjectJob = (onSuccessCallback) => { +export const useUpdateServiceProjectJob = () => { const queryClient = useQueryClient(); - return useMutation({ - mutationFn: async ({ id, payload }) => { - // Call the repository patch - const resp = await ServiceProjectRepository.UpdateJob(id, payload); - return resp; + return useMutation({ + mutationFn: async ({ id, payload, isArchiveAction = false }) => { + const resp = await ServiceProjectRepository.UpdateJob(id, payload); + return { resp, isArchiveAction }; }, - onSuccess: () => { + + onSuccess: ({ isArchiveAction }, variables) => { queryClient.invalidateQueries({ queryKey: ["serviceProjectJobs"] }); queryClient.invalidateQueries({ queryKey: ["service-job"] }); - if (onSuccessCallback) onSuccessCallback(); - showToast("Job Updated successfully", "success"); + + if (isArchiveAction) { + showToast("Job archived successfully", "success"); + } else { + showToast("Job updated successfully", "success"); + } }, + onError: (error) => { showToast( error?.response?.data?.message || @@ -374,7 +379,7 @@ export const useDeleteBranch = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ id, isActive}) => + mutationFn: async ({ id, isActive }) => await ServiceProjectRepository.DeleteBranch(id, isActive), onSuccess: () => { From caaadc4c084925e32287baa719a4acda1ea7ae12 Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Thu, 20 Nov 2025 16:38:25 +0530 Subject: [PATCH 2/2] Implementing Validation when we status will be done or closed then Archieve button will be shown. --- src/components/ServiceProject/JobList.jsx | 33 ++++++++++++++++------- src/hooks/useServiceProject.jsx | 10 ++++--- src/utils/constants.jsx | 33 ++++++++++++++++++++++- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/components/ServiceProject/JobList.jsx b/src/components/ServiceProject/JobList.jsx index d0ab8695..0cf9b3cc 100644 --- a/src/components/ServiceProject/JobList.jsx +++ b/src/components/ServiceProject/JobList.jsx @@ -5,7 +5,7 @@ import { getNextBadgeColor, } from "../../utils/appUtils"; import { useServiceProjectJobs, useUpdateServiceProjectJob } from "../../hooks/useServiceProject"; -import { ITEMS_PER_PAGE } from "../../utils/constants"; +import { ITEMS_PER_PAGE, JOBS_STATUS_IDS } from "../../utils/constants"; import EmployeeAvatarGroup from "../common/EmployeeAvatarGroup"; import { formatUTCToLocalTime } from "../../utils/dateUtils"; import { SpinnerLoader } from "../common/Loader"; @@ -112,6 +112,14 @@ const JobList = () => { }, ]; + const canArchive = (statusId) => { + const closedId = JOBS_STATUS_IDS.find((s) => s.label === "Closed")?.id; + const workDoneId = JOBS_STATUS_IDS.find((s) => s.label === "Work Done")?.id; + + return statusId === closedId || statusId === workDoneId; + }; + + return ( <> @@ -182,6 +190,7 @@ const JobList = () => { > View + <> + + + {canArchive(row?.status?.id) && ( + + )} - diff --git a/src/hooks/useServiceProject.jsx b/src/hooks/useServiceProject.jsx index f93bab4b..a047a8a0 100644 --- a/src/hooks/useServiceProject.jsx +++ b/src/hooks/useServiceProject.jsx @@ -255,23 +255,26 @@ export const useCreateServiceProjectJob = (onSuccessCallback) => { }); }; -export const useUpdateServiceProjectJob = () => { +export const useUpdateServiceProjectJob = (onSuccessCallback) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, payload, isArchiveAction = false }) => { const resp = await ServiceProjectRepository.UpdateJob(id, payload); + return { resp, isArchiveAction }; }, - onSuccess: ({ isArchiveAction }, variables) => { + onSuccess: ({ isArchiveAction }) => { queryClient.invalidateQueries({ queryKey: ["serviceProjectJobs"] }); queryClient.invalidateQueries({ queryKey: ["service-job"] }); + if (onSuccessCallback) onSuccessCallback(); + if (isArchiveAction) { showToast("Job archived successfully", "success"); } else { - showToast("Job updated successfully", "success"); + showToast("Job Updated successfully", "success"); } }, @@ -286,6 +289,7 @@ export const useUpdateServiceProjectJob = () => { }); }; + //#endregion //#region Branch diff --git a/src/utils/constants.jsx b/src/utils/constants.jsx index 2375b010..1ca271ec 100644 --- a/src/utils/constants.jsx +++ b/src/utils/constants.jsx @@ -210,4 +210,35 @@ export const PAYEE_RECURRING_EXPENSE = [ //#region Service Project and Jobs export const STATUS_JOB_CLOSED = "3ddeefb5-ae3c-4e10-a922-35e0a452bb69" -//#endregion \ No newline at end of file +//#endregion + +export const JOBS_STATUS_IDS = [ + { + id: "32d76a02-8f44-4aa0-9b66-c3716c45a918", + label: "New", + }, + { + id: "cfa1886d-055f-4ded-84c6-42a2a8a14a66", + label: "Assigned", + }, + { + id: "5a6873a5-fed7-4745-a52f-8f61bf3bd72d", + label: "In Progress", + }, + { + id: "aab71020-2fb8-44d9-9430-c9a7e9bf33b0", + label: "Work Done", + }, + { + id: "ed10ab57-dbaa-4ca5-8ecd-56745dcbdbd7", + label: "Review Done", + }, + { + id: "3ddeefb5-ae3c-4e10-a922-35e0a452bb69", + label: "Closed", + }, + { + id: "75a0c8b8-9c6a-41af-80bf-b35bab722eb2", + label: "On Hold", + }, +]; \ No newline at end of file