import { useCallback, useEffect, useState } from "react"; import { cacheData, getCachedData } from "../slices/apiDataManager"; import ProjectRepository from "../repositories/ProjectRepository"; import { useProfile } from "./useProfile"; import { useDispatch, useSelector } from "react-redux"; import { setProjectId } from "../slices/localVariablesSlice"; import EmployeeList from "../components/Directory/EmployeeList"; import eventBus from "../services/eventBus"; import { Mutation, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query"; import showToast from "../services/toastService"; export const useCurrentService = () => { return useSelector((store) => store.globalVariables.selectedServiceId); }; // ------------------------------Query------------------- export const useProjects = () => { const loggedUser = useSelector((store) => store.globalVariables.loginUser); return useQuery({ queryKey: ["ProjectsList"], queryFn: async () => { const response = await ProjectRepository.getProjectList(); return response.data; }, enabled: !!loggedUser, }); }; export const useEmployeesByProjectAllocated = ( projectId, serviceId, organizationId, emloyeeeStatus ) => { const { data = [], isLoading, refetch, error, } = useQuery({ queryKey: [ "empListByProjectAllocated", projectId, serviceId, organizationId, emloyeeeStatus, ], queryFn: async () => { const res = await ProjectRepository.getProjectAllocation( projectId, serviceId, organizationId, emloyeeeStatus ); return res?.data || res; }, enabled: !!projectId, onError: (error) => { showToast( error.message || "Error while fetching project allocated employees", "error" ); }, }); return { projectEmployees: data, loading: isLoading, error, refetch, }; }; export const useProjectDetails = (projectId, isAuto = true) => { const { data: projects_Details, isLoading, error, refetch, } = useQuery({ queryKey: ["projectInfo", projectId], queryFn: async () => { const res = await ProjectRepository.getProjectByprojectId(projectId); return res.data || res; }, enabled: !!projectId && isAuto, onError: (error) => { showToast( error.message || "Error while Fetching project Details", "error" ); }, }); return { projects_Details, loading: isLoading, error, refetch }; }; export const useProjectsByEmployee = (employeeId) => { const { data: projectList = [], isLoading, error, refetch, } = useQuery({ queryKey: ["ProjectsByEmployee", employeeId], queryFn: async () => { const res = await ProjectRepository.getProjectsByEmployee(employeeId); return res.data || res; }, enabled: !!employeeId, onError: (error) => { showToast( error.message || "Error while Fetching project Employee", "error" ); }, }); return { projectList, loading: isLoading, error, refetch }; }; export const useProjectsAllocationByEmployee = (employeeId) => { const { data: projectList = [], isLoading, error, refetch, } = useQuery({ queryKey: ["ProjectsAllocationByEmployee", employeeId], queryFn: async () => { const res = await ProjectRepository.getProjectsAllocationByEmployee( employeeId ); const sortedProjects = [...res.data].sort((a, b) => a.projectName.localeCompare(b.projectName) ); return sortedProjects || res; //return res.data || res; }, enabled: !!employeeId, onError: (error) => { showToast( error.message || "Error while Fetching project Employee", "error" ); }, }); return { projectList, loading: isLoading, error, refetch }; }; export const useProjectName = (provideAll=false) => { const { data = [], isLoading, error, refetch, isError, } = useQuery({ queryKey: ["basicProjectNameList",provideAll], queryFn: async () => { const res = await ProjectRepository.projectNameList(provideAll); return res.data || res; }, onError: (error) => { showToast(error.message || "Error while Fetching project Name", "error"); }, }); return { projectNames: data, loading: isLoading, Error: error, refetch, isError, }; }; export const useProjectInfra = (projectId, serviceId) => { const { data: projectInfra, isLoading, error, isFetched, } = useQuery({ queryKey: ["ProjectInfra", projectId, serviceId], queryFn: async () => { if (!projectId) return null; const res = await ProjectRepository.getProjectInfraByproject( projectId, serviceId ); return res.data; }, enabled: !!projectId, onError: (error) => { showToast(error.message || "Error while fetching project infra", "error"); }, }); return { projectInfra, isLoading, error, isFetched }; }; export const useProjectTasks = ( workAreaId, serviceId = null, isExpandedArea = false ) => { const { data, isLoading, error } = useQuery({ queryKey: ["WorkItems", workAreaId, serviceId], queryFn: async () => { const res = await ProjectRepository.getProjectTasksByWorkArea( workAreaId, serviceId ); return res.data; // return actual task list }, enabled: !!workAreaId && isExpandedArea, // only fetch if workAreaId exists and area is expanded onError: (err) => { showToast(err.message || "Error while fetching project tasks", "error"); }, }); return { ProjectTaskList: data, isLoading, error }; }; export const useProjectTasksByEmployee = (employeeId, fromDate, toDate) => { return useQuery({ queryKey: ["TasksByEmployee", employeeId], queryFn: async () => { const res = await ProjectRepository.getProjectTasksByEmployee( employeeId, fromDate, toDate ); return res.data; }, enabled: !!employeeId && !!fromDate && !!toDate, onError: (error) => { showToast(error.message || "Error while Fetching project Tasks", "error"); }, }); }; export const useProjectLevelEmployeeList = (ProjectId) => { return useQuery({ queryKey: ["ProjectLevelEmployeeList", ProjectId], queryFn: async () => { const resp = await ProjectRepository.getProjectLevelEmployeeList( ProjectId ); return resp.data; }, enabled: !!ProjectId, }); }; export const useProjectLevelModules = () => { return useQuery({ queryKey: ["ProjectLevelModules"], queryFn: async () => { const resp = await ProjectRepository.getProjectLevelModules(); return resp.data; }, }); }; export const useProjectLevelEmployeePermission = (employeeId, projectId) => { return useQuery({ queryKey: ["ProjectLevelEmployeePermission", employeeId, projectId], queryFn: async () => { const resp = await ProjectRepository.getProjectLevelEmployeePermissions( employeeId, projectId ); return resp.data; }, enabled: !!employeeId && !!projectId, }); }; export const useProjectAssignedOrganizations = (projectId) => { return useQuery({ queryKey: ["projectAssignedOrganiztions", projectId], queryFn: async () => { const resp = await ProjectRepository.getProjectAssignedOrganizations( projectId ); return resp.data; }, enabled: !!projectId, }); }; export const useProjectAssignedOrganizationsName = (projectId) => { return useQuery({ queryKey: ["projectAssignedOrganiztionsName", projectId], queryFn: async () => { const resp = await ProjectRepository.getProjectAssignedOrganizationsName( projectId ); return resp.data; }, enabled: !!projectId, }); }; export const useProjectAssignedServices = (projectId) => { return useQuery({ queryKey: ["projectAssignedServices", projectId], queryFn: async () => { const resp = await ProjectRepository.getProjectAssignedServices( projectId ); return resp.data; }, enabled: !!projectId, }); }; export const useEmployeeForTaskAssign = ( projectId, serviceId, organizationId ) => { return useQuery({ queryKey: ["EmployeeForTaskAssign", projectId, serviceId, organizationId], queryFn: async () => await ProjectRepository.getEmployeeForTaskAssign( projectId, serviceId, organizationId ), }); }; // -- -------------Mutation------------------------------- export const useCreateProject = ( onSuccessCallback ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (payload) => { const res = await ProjectRepository.manageProject(payload); return res.data; }, onSuccess: (data) => { // Invalidate the cache queryClient.invalidateQueries({ queryKey: ["ProjectsList"] }); queryClient.invalidateQueries({ queryKey: ["basicProjectNameList"] }); // Emit event for consumers (like useProjects or others) eventBus.emit("project", { keyword: "Create_Project", response: data, }); showToast("Project Created successfully.", "success"); if (onSuccessCallback) { onSuccessCallback(data); } }, onError: (error) => { showToast(error.message || "Error while creating project", "error"); }, }); }; export const useUpdateProject = ( onSuccessCallback ) => { const queryClient = useQueryClient(); const { mutate, isPending, isSuccess, isError } = useMutation({ mutationFn: async ({ projectId, payload }) => { return await ProjectRepository.updateProject(projectId, payload); }, onSuccess: (data, variables) => { const { projectId } = variables; queryClient.invalidateQueries({ queryKey: ["ProjectsList"] }); queryClient.invalidateQueries({ queryKey: ["projectInfo", projectId] }); queryClient.invalidateQueries({ queryKey: ["basicProjectNameList"] }); eventBus.emit("project", { keyword: "Update_Project", response: data, }); showToast("Project updated successfully.", "success"); if (onSuccessCallback) { onSuccessCallback(data); } }, onError: (error) => { console.log(error); showToast(error?.message || "Error while updating project", "error"); }, }); return { mutate, isPending, isSuccess, isError, }; }; export const useManageProjectInfra = ({ onSuccessCallback }) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ infraObject, projectId }) => { return await ProjectRepository.manageProjectInfra(infraObject); }, onSuccess: (data, variables) => { const { projectId } = variables; queryClient.invalidateQueries({ queryKey: ["ProjectInfra", projectId] }); if (onSuccessCallback) onSuccessCallback(data, variables); }, onError: (error) => { showToast(error.message || "Failed to update Project Infra", "error"); }, }); }; export const useManageProjectAllocation = ({ onSuccessCallback, onErrorCallback, }) => { const queryClient = useQueryClient(); const { mutate, isPending, isSuccess, isError } = useMutation({ mutationFn: async ({ payload }) => { const response = await ProjectRepository.manageProjectAllocation(payload); return response.data; }, onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: ["empListByProjectAllocated"], }); queryClient.removeQueries({ queryKey: ["projectEmployees"] }); queryClient.removeQueries({ queryKey: ["EmployeeForTaskAssign"] }); if (variables.actionType === "assign") { showToast("Employee Assigned Successfully", "success"); } else { showToast("Removed Employee Successfully", "success"); } if (onSuccessCallback) onSuccessCallback(data, context); }, onError: (error) => { const message = error?.response?.data?.message || error.message || "Error occurred during API call"; showToast(message, "error"); if (onErrorCallback) onErrorCallback(error); }, }); return { mutate, isPending, isSuccess, isError, }; }; export const useManageTask = ({ onSuccessCallback }) => { const queryClient = useQueryClient(); const selectedProject = useSelector( (store) => store.localVariables.projectId ); return useMutation({ mutationFn: async ({ payload, PreviousPlannedWork, previousCompletedWork, buildingId, floorId, workAreaId, }) => await ProjectRepository.manageProjectTasks(payload), onSuccess: (data, variables) => { const { workAreaId, buildingId, floorId, PreviousPlannedWork, previousCompletedWork, } = variables; queryClient.invalidateQueries({ queryKey: ["WorkItems"] }); const getPlannedDelta = (previous, current) => current - previous; queryClient.setQueryData(["ProjectInfra", selectedProject], (oldData) => { if (!oldData) return oldData; const { workAreaId, floorId, buildingId } = variables; const updatedData = JSON.parse(JSON.stringify(oldData)); return updatedData.map((building) => { if (building.id !== buildingId) return building; return { ...building, floors: building.floors.map((floor) => { if (floor.id !== floorId) return floor; return { ...floor, workAreas: floor.workAreas.map((area) => { if (area.id !== workAreaId) return area; const previousPlanned = PreviousPlannedWork ?? 0; const currentPlanned = data?.data[0]?.workItem.plannedWork ?? 0; const plannedWorkDelta = getPlannedDelta( previousPlanned, currentPlanned ); const updatedPlannedWork = (area.plannedWork ?? 0) + plannedWorkDelta; const previousCompleted = previousCompletedWork; const currentCompleted = data?.data[0]?.workItem.completedWork ?? 0; const completedWorkDelta = getPlannedDelta( previousCompleted, currentCompleted ); const updatedCompletedWork = (area.completedWork ?? 0) + completedWorkDelta; return { ...area, plannedWork: updatedPlannedWork, completedWork: updatedCompletedWork, }; }), }; }), }; }); }); queryClient.setQueryData(["ProjectsList"], (projects) => { if (!projects) return projects; return projects.map((project) => { if (project.id !== selectedProject) return project; const previousPlanned = PreviousPlannedWork ?? 0; const currentPlanned = data?.data[0]?.workItem.plannedWork ?? 0; const plannedWorkDelta = getPlannedDelta( previousPlanned, currentPlanned ); const updatedPlannedWork = (project.plannedWork ?? 0) + plannedWorkDelta; const previousCompleted = previousCompletedWork; const currentCompleted = data?.data[0]?.workItem.completedWork ?? 0; const completedWorkDelta = getPlannedDelta( previousCompleted, currentCompleted ); const updatedCompletedWork = (project.completedWork ?? 0) + completedWorkDelta; return { ...project, plannedWork: updatedPlannedWork, completedWork: updatedCompletedWork, }; }); }); if (onSuccessCallback) onSuccessCallback(data); }, onError: (error) => { const message = error?.response?.data?.message || error.message || "Error occurred during API call"; showToast(message, "error"); }, }); }; export const useDeleteProjectTask = (onSuccessCallback) => { const queryClient = useQueryClient(); const selectedProject = useSelector( (store) => store.localVariables.projectId ); return useMutation({ mutationFn: async ({ workItemId, workAreaId, completedTask, plannedTask, }) => { return await ProjectRepository.deleteProjectTask(workItemId); }, onSuccess: (_, variables) => { const { completedTask, plannedTask, workAreaId, buildingId, floorId } = variables; queryClient.invalidateQueries({ queryKey: ["WorkItems", variables.workAreaId], }); queryClient.setQueryData(["ProjectInfra", selectedProject], (oldData) => { if (!oldData) return oldData; const { workAreaId, floorId, buildingId, plannedTask, completedTask } = variables; const updatedData = JSON.parse(JSON.stringify(oldData)); return updatedData.map((building) => { if (building.id !== buildingId) return building; return { ...building, floors: building.floors.map((floor) => { if (floor.id !== floorId) return floor; return { ...floor, workAreas: floor.workAreas.map((area) => { if (area.id !== workAreaId) return area; return { ...area, plannedWork: (area.plannedWork ?? 0) - plannedTask, completedWork: (area.completedWork ?? 0) - completedTask, }; }), }; }), }; }); }); queryClient.setQueryData(["ProjectsList"], (projects) => { if (!projects) return projects; return projects.map((project) => { if (project.id !== selectedProject) return project; return { ...project, plannedWork: (project.plannedWork ?? 0) - plannedTask, completedWork: (project.completedWork ?? 0) - completedTask, }; }); }); showToast("Task deleted successfully", "success"); if (onSuccessCallback) onSuccessCallback(); }, onError: (error) => { showToast( error?.response?.data?.message || error.message || "Failed to delete task", "error" ); if (onSuccessCallback) onSuccessCallback(); }, }); }; export const useUpdateProjectLevelEmployeePermission = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (payload) => await ProjectRepository.updateProjectLevelEmployeePermission(payload), onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: ["ProjectLevelEmployeePermission"], }); showToast("Permission Updated successfully", "success"); }, onError: (error) => { showToast( error?.response?.data?.message || error.message || "Failed to delete task", "error" ); if (onSuccessCallback) onSuccessCallback(); }, }); };