marco.pms.web/src/hooks/useProjects.js

696 lines
20 KiB
JavaScript

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 useProjects = () => {
// const loggedUser = useSelector((store) => store.globalVariables.loginUser);
// const [projects, setProjects] = useState([]);
// const [loading, setLoading] = useState(true);
// const [error, setError] = useState("");
// const fetchData = async () => {
// const projectIds = loggedUser?.projects || [];
// const filterProjects = (projectsList) => {
// return projectsList
// .filter((proj) => projectIds.includes(String(proj.id)))
// .sort((a, b) => a?.name?.localeCompare(b.name));
// };
// const projects_cache = getCachedData("projectslist");
// if (!projects_cache) {
// setLoading(true);
// try {
// const response = await ProjectRepository.getProjectList();
// const allProjects = response.data;
// const filtered = filterProjects(allProjects);
// setProjects(filtered);
// cacheData("projectslist", allProjects);
// } catch (err) {
// setError("Failed to fetch data.");
// } finally {
// setLoading(false);
// }
// } else {
// if (!projects.length) {
// const filtered = filterProjects(projects_cache);
// setProjects(filtered);
// setLoading(false);
// }
// }
// };
// useEffect(() => {
// if (loggedUser) {
// fetchData();
// }
// }, [loggedUser]);
// return { projects, loading, error, refetch: fetchData };
// };
// export const useEmployeesByProjectAllocated = (selectedProject) => {
// const [projectEmployees, setEmployeeList] = useState([]);
// const [loading, setLoading] = useState(true);
// const [projects, setProjects] = useState([]);
// const fetchData = async (projectid) => {
// try {
// let EmployeeByProject_Cache = getCachedData("empListByProjectAllocated");
// if (
// !EmployeeByProject_Cache ||
// !EmployeeByProject_Cache.projectId === projectid
// ) {
// let response = await ProjectRepository.getProjectAllocation(projectid);
// setEmployeeList(response.data);
// cacheData("empListByProjectAllocated", {
// data: response.data,
// projectId: projectid,
// });
// setLoading(false);
// } else {
// setEmployeeList(EmployeeByProject_Cache.data);
// setLoading(false);
// }
// } catch (err) {
// setError("Failed to fetch data.");
// setLoading(false);
// }
// };
// useEffect(() => {
// if (selectedProject) {
// fetchData(selectedProject);
// }
// }, [selectedProject]);
// return { projectEmployees, loading, projects };
// };
// export const useProjectDetails = (projectId) => {
// const { profile } = useProfile();
// const [projects_Details, setProject_Details] = useState(null);
// const [loading, setLoading] = useState(true);
// const [error, setError] = useState("");
// const fetchData = async () => {
// setLoading(true);
// const project_cache = getCachedData("projectInfo");
// if (!project_cache || project_cache?.projectId != projectId) {
// ProjectRepository.getProjectByprojectId(projectId)
// .then((response) => {
// setProject_Details(response.data);
// cacheData("projectInfo", {
// projectId: projectId,
// data: response.data,
// });
// setLoading(false);
// })
// .catch((error) => {
// console.error(error);
// setError("Failed to fetch data.");
// setLoading(false);
// });
// } else {
// setProject_Details(project_cache.data);
// setLoading(false);
// }
// };
// useEffect(() => {
// if (profile && projectId != undefined) {
// fetchData();
// }
// }, [projectId, profile]);
// return { projects_Details, loading, error, refetch: fetchData };
// };
// export const useProjectsByEmployee = (employeeId) => {
// const [projectList, setProjectList] = useState([]);
// const [loading, setLoading] = useState(false);
// const [error, setError] = useState("");
// const fetchProjects = async (id) => {
// try {
// setLoading(true);
// setError(""); // clear previous error
// const res = await ProjectRepository.getProjectsByEmployee(id);
// setProjectList(res.data);
// cacheData("ProjectsByEmployee", { data: res.data, employeeId: id });
// setLoading(false);
// } catch (err) {
// setError(err?.message || "Failed to fetch projects");
// setLoading(false);
// }
// };
// useEffect(() => {
// if (!employeeId) return;
// const cache_project = getCachedData("ProjectsByEmployee");
// if (!cache_project?.data || cache_project?.employeeId !== employeeId) {
// fetchProjects(employeeId);
// } else {
// setProjectList(cache_project.data);
// }
// }, [employeeId]);
// return {
// projectList,
// loading,
// error,
// refetch: fetchProjects,
// };
// };
// export const useProjectName = () => {
// const [loading, setLoading] = useState(true);
// const [projectNames, setProjectName] = useState([]);
// const [Error, setError] = useState();
// const dispatch = useDispatch();
// const fetchData = async () => {
// try {
// let response = await ProjectRepository.projectNameList();
// setProjectName(response.data);
// cacheData("basicProjectNameList", response.data);
// setLoading(false);
// if(response.data.length === 1){
// dispatch(setProjectId(response.data[0]?.id));
// }
// } catch (err) {
// setError("Failed to fetch data.");
// setLoading(false);
// }
// };
// useEffect(() => {
// fetchData();
// }, []);
// return { projectNames, loading, Error, fetchData };
// };
// ------------------------------Query-------------------
export const useProjects = () => {
const loggedUser = useSelector((store) => store.globalVariables.loginUser);
const {
data: projects = [],
isLoading: loading,
error,
refetch,
} = useQuery({
queryKey: ["ProjectsList"],
queryFn: async () => {
const response = await ProjectRepository.getProjectList();
return response.data;
},
enabled: !!loggedUser,
});
return {
projects,
loading,
error,
refetch,
};
};
export const useEmployeesByProjectAllocated = (selectedProject) => {
const {
data = [],
isLoading,
refetch,
error,
} = useQuery({
queryKey: ["empListByProjectAllocated", selectedProject],
queryFn: async () => {
const res = await ProjectRepository.getProjectAllocation(selectedProject);
return res.data || res;
},
enabled: !!selectedProject,
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: projectNameList = [],
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 useProjectName = () => {
const {
data = [],
isLoading,
error,
refetch,
} = useQuery({
queryKey: ["basicProjectNameList"],
queryFn: async () => {
const res = await ProjectRepository.projectNameList();
return res.data || res;
},
onError: (error) => {
showToast(error.message || "Error while Fetching project Name", "error");
},
});
return { projectNames: data, loading: isLoading, Error: error, refetch };
};
export const useProjectInfra = (projectId) => {
const {
data: projectInfra,
isLoading,
error,
} = useQuery({
queryKey: ["ProjectInfra", projectId],
queryFn: async () => {
const res = await ProjectRepository.getProjectInfraByproject(projectId);
return res.data;
},
enabled: !!projectId,
onError: (error) => {
showToast(error.message || "Error while fetching project infra", "error");
},
});
return { projectInfra, isLoading, error };
};
export const useProjectTasks = (workAreaId, IsExpandedArea = false) => {
const {
data: ProjectTaskList,
isLoading,
error,
} = useQuery({
queryKey: ["WorkItems", workAreaId],
queryFn: async () => {
const res = await ProjectRepository.getProjectTasksByWorkArea(workAreaId);
return res.data;
},
enabled: !!workAreaId && !!IsExpandedArea,
onError: (error) => {
showToast(error.message || "Error while Fetching project Tasks", "error");
},
});
return { ProjectTaskList, isLoading, error };
};
// -- -------------Mutation-------------------------------
export const useCreateProject = ({ onSuccessCallback }) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (newProject) => {
const res = await ProjectRepository.manageProject(newProject);
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, updatedData }) => {
return await ProjectRepository.updateProject(projectId, updatedData);
},
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 ({ items }) => {
const response = await ProjectRepository.manageProjectAllocation(items);
return response.data;
},
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({
queryKey: ["empListByProjectAllocated"],
});
queryClient.removeQueries({ queryKey: ["projectEmployees"] });
if (variables?.added) {
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();
},
});
};