integrate React Query for project details and real-time updates
This commit is contained in:
parent
22e65c167e
commit
467d5d4b13
@ -122,18 +122,9 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="modal-dialog modal-lg modal-simple mx-sm-auto mx-1 edit-project-modal"
|
||||
role="document"
|
||||
>
|
||||
<div className="modal-content">
|
||||
<div className="modal-body p-sm-4 p-0">
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={handleCancel}
|
||||
aria-label="Close"
|
||||
></button>
|
||||
|
||||
<div className="p-sm-2 p-2">
|
||||
|
||||
<div className="text-center mb-2">
|
||||
<h5 className="mb-2">
|
||||
{project?.id ? "Edit Project" : "Create Project"}
|
||||
@ -148,7 +139,7 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
className="form-control"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Project Name"
|
||||
{...register("name")}
|
||||
/>
|
||||
@ -169,7 +160,7 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
type="text"
|
||||
id="shortName"
|
||||
name="shortName"
|
||||
className="form-control"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Short Name"
|
||||
{...register("shortName")}
|
||||
/>
|
||||
@ -190,7 +181,7 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
type="text"
|
||||
id="contactPerson"
|
||||
name="contactPerson"
|
||||
className="form-control"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Contact Person"
|
||||
maxLength={50}
|
||||
{...register("contactPerson")}
|
||||
@ -252,7 +243,7 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
<select
|
||||
id="modalEditUserStatus"
|
||||
name="modalEditUserStatus"
|
||||
className="select2 form-select"
|
||||
className="select2 form-select form-select-sm"
|
||||
aria-label="Default select example"
|
||||
{...register("projectStatusId", {
|
||||
required: "Status is required",
|
||||
@ -321,8 +312,6 @@ const ManageProjectInfo = ({ project, handleSubmitForm, onClose }) => {
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
|
||||
import moment from "moment";
|
||||
import { getDateDifferenceInDays } from "../../utils/dateUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useProjectDetails } from "../../hooks/useProjects";
|
||||
import { useProjectDetails, useUpdateProject } from "../../hooks/useProjects";
|
||||
import ManageProjectInfo from "./ManageProjectInfo";
|
||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||
import { cacheData, getCachedData } from "../../slices/apiDataManager";
|
||||
@ -13,29 +13,36 @@ import {
|
||||
getProjectStatusColor,
|
||||
getProjectStatusName,
|
||||
} from "../../utils/projectStatus";
|
||||
import GlobalModel from "../common/GlobalModel";
|
||||
|
||||
const ProjectCard = ({ projectData, recall }) => {
|
||||
const [projectInfo, setProjectInfo] = useState(projectData);
|
||||
const [projectDetails, setProjectDetails] = useState(null);
|
||||
const [ projectInfo, setProjectInfo ] = useState( projectData );
|
||||
const { projects_Details, loading, error, refetch } = useProjectDetails(
|
||||
projectInfo?.id,false
|
||||
);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const ManageProject = useHasUserPermission(MANAGE_PROJECT);
|
||||
const [modifyProjectLoading, setMdifyProjectLoading] = useState(false);
|
||||
const {
|
||||
mutate: updateProject,
|
||||
isPending,
|
||||
isSuccess,
|
||||
isError,
|
||||
} = useUpdateProject({
|
||||
onSuccessCallback: () => {
|
||||
setShowModal(false);
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(()=>{
|
||||
setProjectInfo(projectData);
|
||||
},[projectData])
|
||||
// console.log("in card view",projectInfo);
|
||||
}, [ projectData ] )
|
||||
|
||||
const handleShow = async () => {
|
||||
try {
|
||||
setMdifyProjectLoading(true);
|
||||
const response = await ProjectRepository.getProjectByprojectId(
|
||||
projectInfo.id
|
||||
);
|
||||
setProjectDetails(response.data);
|
||||
setMdifyProjectLoading(false);
|
||||
const { data } = await refetch();
|
||||
setShowModal(true);
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
showToast("Failed to load project details", "error");
|
||||
}
|
||||
};
|
||||
@ -55,63 +62,67 @@ const ProjectCard = ({ projectData, recall }) => {
|
||||
|
||||
const handleFormSubmit = (updatedProject) => {
|
||||
if (projectInfo?.id) {
|
||||
ProjectRepository.updateProject(projectInfo.id, updatedProject)
|
||||
.then((response) => {
|
||||
const updatedProjectData = {
|
||||
...projectInfo,
|
||||
...response.data,
|
||||
building: projectDetails?.building,
|
||||
};
|
||||
|
||||
setProjectInfo(updatedProject);
|
||||
|
||||
if (getCachedData(`projectinfo-${projectInfo.id}`)) {
|
||||
cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData);
|
||||
}
|
||||
|
||||
const projects_list = getCachedData("projectslist");
|
||||
if (projects_list) {
|
||||
const updatedProjectsList = projects_list.map((project) =>
|
||||
project.id === projectInfo.id
|
||||
? {
|
||||
...project,
|
||||
...response.data,
|
||||
// tenant: project.tenant
|
||||
}
|
||||
: project
|
||||
);
|
||||
cacheData("projectslist", updatedProjectsList);
|
||||
}
|
||||
recall(getCachedData("projectslist"));
|
||||
showToast("Project updated successfully.", "success");
|
||||
setShowModal(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
showToast(error.message, "error");
|
||||
updateProject({
|
||||
projectId: projectInfo.id,
|
||||
updatedData: updatedProject,
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// const handleFormSubmit = (updatedProject) => {
|
||||
// if (projectInfo?.id) {
|
||||
// ProjectRepository.updateProject(projectInfo.id, updatedProject)
|
||||
// .then((response) => {
|
||||
// const updatedProjectData = {
|
||||
// ...projectInfo,
|
||||
// ...response.data,
|
||||
// building: projectDetails?.building,
|
||||
// };
|
||||
|
||||
// setProjectInfo(updatedProject);
|
||||
|
||||
// if (getCachedData(`projectinfo-${projectInfo.id}`)) {
|
||||
// cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData);
|
||||
// }
|
||||
|
||||
// const projects_list = getCachedData("projectslist");
|
||||
// if (projects_list) {
|
||||
// const updatedProjectsList = projects_list.map((project) =>
|
||||
// project.id === projectInfo.id
|
||||
// ? {
|
||||
// ...project,
|
||||
// ...response.data,
|
||||
// // tenant: project.tenant
|
||||
// }
|
||||
// : project
|
||||
// );
|
||||
// cacheData("projectslist", updatedProjectsList);
|
||||
// }
|
||||
// recall(getCachedData("projectslist"));
|
||||
// showToast("Project updated successfully.", "success");
|
||||
// setShowModal(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// showToast(error.message, "error");
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
|
||||
return (
|
||||
<>
|
||||
{showModal && projectDetails && (
|
||||
<div
|
||||
className="modal fade show"
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{ display: "block" }}
|
||||
aria-hidden="false"
|
||||
>
|
||||
|
||||
{showModal && projects_Details && (
|
||||
<GlobalModel isOpen={showModal} closeModal={handleClose}>
|
||||
<ManageProjectInfo
|
||||
project={projectDetails}
|
||||
project={projects_Details}
|
||||
handleSubmitForm={handleFormSubmit}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
</div>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
<div className="col-md-6 col-lg-4 col-xl-4 order-0 mb-4">
|
||||
<div className="card cursor-pointer">
|
||||
<div className={`card cursor-pointer ${isPending ? "bg-light opacity-50 pointer-events-none" : ""}`}>
|
||||
<div className="card-header pb-4">
|
||||
<div className="d-flex align-items-start">
|
||||
<div className="d-flex align-items-center">
|
||||
@ -143,7 +154,7 @@ const ProjectCard = ({ projectData, recall }) => {
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{modifyProjectLoading ? (
|
||||
{loading ? (
|
||||
<div
|
||||
className="spinner-border spinner-border-sm text-secondary"
|
||||
role="status"
|
||||
|
@ -14,6 +14,7 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { ASSIGN_TO_PROJECT } from "../../utils/constants";
|
||||
import ConfirmModal from "../common/ConfirmModal";
|
||||
import eventBus from "../../services/eventBus";
|
||||
import {useEmployeesByProjectAllocated, useManageProjectAllocation} from "../../hooks/useProjects";
|
||||
|
||||
const Teams = ({ project }) => {
|
||||
const dispatch = useDispatch();
|
||||
@ -26,69 +27,104 @@ const Teams = ({ project }) => {
|
||||
const [filteredEmployees, setFilteredEmployees] = useState([]);
|
||||
const [removingEmployeeId, setRemovingEmployeeId] = useState(null);
|
||||
const [assignedLoading, setAssignedLoading] = useState(false);
|
||||
const [ employeeLodaing, setEmployeeLoading ] = useState( false );
|
||||
// const [ employeeLodaing, setEmployeeLoading ] = useState( false );
|
||||
const [ activeEmployee, setActiveEmployee ] = useState( true )
|
||||
const [deleteEmployee,setDeleteEmplyee] = useState(null)
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const HasAssignUserPermission = useHasUserPermission( ASSIGN_TO_PROJECT );
|
||||
const[IsDeleteModal,setIsDeleteModal] = useState(false)
|
||||
|
||||
const fetchEmployees = async () => {
|
||||
try {
|
||||
setEmployeeLoading(true);
|
||||
|
||||
// if (!empRoles) {
|
||||
ProjectRepository.getProjectAllocation(project.id)
|
||||
.then((response) => {
|
||||
setEmployees(response.data);
|
||||
setFilteredEmployees( response.data.filter( ( emp ) => emp.isActive ) );
|
||||
setEmployeeLoading(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
setError("Failed to fetch data.");
|
||||
setEmployeeLoading(false);
|
||||
});
|
||||
} catch (err) {
|
||||
setError("Failed to fetch activities.");
|
||||
}
|
||||
};
|
||||
|
||||
const submitAllocations = (items,added) => {
|
||||
ProjectRepository.manageProjectAllocation(items)
|
||||
.then((response) => {
|
||||
fetchEmployees();
|
||||
if ( added )
|
||||
{
|
||||
showToast("Employee Assigned Successfully", "success");
|
||||
}else{
|
||||
showToast("Removed Employee Successfully", "success");
|
||||
}
|
||||
const [ IsDeleteModal, setIsDeleteModal ] = useState( false )
|
||||
const {projectEmployees, loading:employeeLodaing, refetch} = useEmployeesByProjectAllocated( project.id )
|
||||
const {
|
||||
mutate: submitAllocations,
|
||||
isPending,
|
||||
isSuccess,
|
||||
isError,
|
||||
} = useManageProjectAllocation({
|
||||
onSuccessCallback: () => {
|
||||
// Example: UI reset
|
||||
setRemovingEmployeeId(null);
|
||||
setAssignedLoading( false );
|
||||
setDeleteEmplyee( null )
|
||||
closeDeleteModal()
|
||||
})
|
||||
.catch((error) => {
|
||||
const message = error.response.data.message || error.message || "Error Occured during Api Call";
|
||||
showToast( message, "error" );
|
||||
closeDeleteModal()
|
||||
});
|
||||
};
|
||||
setAssignedLoading(false);
|
||||
setDeleteEmplyee(null);
|
||||
closeDeleteModal();
|
||||
},
|
||||
onErrorCallback: () => {
|
||||
closeDeleteModal();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// const fetchEmployees = async () => {
|
||||
// try {
|
||||
// setEmployeeLoading(true);
|
||||
|
||||
// // if (!empRoles) {
|
||||
// ProjectRepository.getProjectAllocation(project.id)
|
||||
// .then((response) => {
|
||||
// setEmployees(response.data);
|
||||
// setFilteredEmployees( response.data.filter( ( emp ) => emp.isActive ) );
|
||||
// setEmployeeLoading(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// setError("Failed to fetch data.");
|
||||
// setEmployeeLoading(false);
|
||||
// });
|
||||
// } catch (err) {
|
||||
// setError("Failed to fetch activities.");
|
||||
// }
|
||||
// };
|
||||
|
||||
// const submitAllocations = (items,added) => {
|
||||
// ProjectRepository.manageProjectAllocation(items)
|
||||
// .then((response) => {
|
||||
// fetchEmployees();
|
||||
// if ( added )
|
||||
// {
|
||||
// showToast("Employee Assigned Successfully", "success");
|
||||
// }else{
|
||||
// showToast("Removed Employee Successfully", "success");
|
||||
// }
|
||||
// setRemovingEmployeeId(null);
|
||||
// setAssignedLoading( false );
|
||||
// setDeleteEmplyee( null )
|
||||
// closeDeleteModal()
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// const message = error.response.data.message || error.message || "Error Occured during Api Call";
|
||||
// showToast( message, "error" );
|
||||
// closeDeleteModal()
|
||||
// });
|
||||
// };
|
||||
|
||||
// const removeAllocation = (item) => {
|
||||
// setRemovingEmployeeId(item.id);
|
||||
// submitAllocations([
|
||||
// {
|
||||
// empID: item.employeeId,
|
||||
// jobRoleId: item.jobRoleId,
|
||||
// projectId: project.id,
|
||||
// status: false,
|
||||
// },
|
||||
// ] ,false);
|
||||
|
||||
// };
|
||||
|
||||
const removeAllocation = (item) => {
|
||||
setRemovingEmployeeId(item.id);
|
||||
submitAllocations([
|
||||
|
||||
submitAllocations({
|
||||
items: [
|
||||
{
|
||||
empID: item.employeeId,
|
||||
jobRoleId: item.jobRoleId,
|
||||
projectId: project.id,
|
||||
status: false,
|
||||
},
|
||||
] ,false);
|
||||
|
||||
};
|
||||
],
|
||||
added: false,
|
||||
});
|
||||
};
|
||||
|
||||
const handleEmpAlicationFormSubmit = (allocaionObj) => {
|
||||
let items = allocaionObj.map((item) => {
|
||||
@ -100,7 +136,7 @@ const Teams = ({ project }) => {
|
||||
};
|
||||
});
|
||||
|
||||
submitAllocations(items, true);
|
||||
submitAllocations({ items, added: true });
|
||||
|
||||
// Force switch to active view after assignment
|
||||
setActiveEmployee(true);
|
||||
@ -146,8 +182,12 @@ const Teams = ({ project }) => {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
fetchEmployees();
|
||||
}, []);
|
||||
if ( projectEmployees )
|
||||
{
|
||||
setEmployees(projectEmployees);
|
||||
setFilteredEmployees( projectEmployees?.filter( ( emp ) => emp.isActive ) );
|
||||
}
|
||||
}, [projectEmployees,employeeLodaing]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@ -177,10 +217,10 @@ const Teams = ({ project }) => {
|
||||
const handler = useCallback(
|
||||
(msg) => {
|
||||
if (msg.projectIds.some((item) => item === project.id)) {
|
||||
fetchEmployees();
|
||||
refetch();
|
||||
}
|
||||
},
|
||||
[]
|
||||
[project.id, refetch]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -191,9 +231,9 @@ const Teams = ({ project }) => {
|
||||
const employeeHandler = useCallback(
|
||||
(msg) => {
|
||||
if(filteredEmployees.some((item) => item.employeeId == msg.employeeId)){
|
||||
fetchEmployees();
|
||||
refetch();
|
||||
}
|
||||
},[filteredEmployees]
|
||||
},[filteredEmployees, refetch]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -240,7 +280,7 @@ const Teams = ({ project }) => {
|
||||
message={"Are you sure you want delete?"}
|
||||
onSubmit={removeAllocation}
|
||||
onClose={closeDeleteModal}
|
||||
loading={employeeLodaing}
|
||||
loading={isPending}
|
||||
paramData={deleteEmployee}
|
||||
/>
|
||||
</div>
|
||||
|
@ -6,194 +6,430 @@ 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 [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 {
|
||||
data: projects = [],
|
||||
isLoading: loading,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ['ProjectsList'],
|
||||
queryFn: async () => {
|
||||
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,
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!loggedUser,
|
||||
});
|
||||
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,
|
||||
projects,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchProjects,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
export const useProjectName = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [projectNames, setProjectName] = useState([]);
|
||||
const [Error, setError] = useState();
|
||||
const dispatch = useDispatch();
|
||||
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
|
||||
} )
|
||||
|
||||
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));
|
||||
return {
|
||||
projectEmployees: data,
|
||||
loading:isLoading,
|
||||
error,
|
||||
refetch
|
||||
}
|
||||
} catch (err) {
|
||||
setError("Failed to fetch data.");
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
}
|
||||
|
||||
return { projectNames, loading, Error, fetchData };
|
||||
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
|
||||
} )
|
||||
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
|
||||
})
|
||||
return {projectList, loading:isLoading,error,refetch }
|
||||
}
|
||||
|
||||
export const useProjectName = () =>
|
||||
{
|
||||
const {data = [],isLoading,error,refetch} = useQuery( {
|
||||
queryFn: [ "basicProjectNameList" ],
|
||||
queryFn: async () =>
|
||||
{
|
||||
const res = await ProjectRepository.projectNameList();
|
||||
return res.data || res;
|
||||
},
|
||||
} )
|
||||
return {projectNames:data,loading:isLoading,Error:error,refetch}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -- 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(['ProjectsList']);
|
||||
|
||||
// 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;
|
||||
|
||||
// Invalidate queries
|
||||
queryClient.invalidateQueries(["ProjectsList"]);
|
||||
queryClient.invalidateQueries(["projectinfo", projectId]);
|
||||
|
||||
// Emit update event
|
||||
eventBus.emit("project", {
|
||||
keyword: "Update_Project",
|
||||
response: data,
|
||||
});
|
||||
|
||||
showToast("Project updated successfully.", "success");
|
||||
|
||||
if (onSuccessCallback) {
|
||||
onSuccessCallback(data);
|
||||
}
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
showToast(error?.message || "Error while updating project", "error");
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
mutate,
|
||||
isPending,
|
||||
isSuccess,
|
||||
isError,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export const useManageProjectInfra = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({infraObject,projectId}) => {
|
||||
return await ProjectRepository.manageProjectInfra(infraObject);
|
||||
},
|
||||
onSuccess: ( response, variables ) =>
|
||||
{
|
||||
const { projectId } = variables;
|
||||
showToast( "Details updated successfully.", "success" );
|
||||
|
||||
queryClient.invalidateQueries(["projectinfo", projectId]);
|
||||
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Failed to update task details", "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(['empListByProjectAllocated']);
|
||||
|
||||
if (context?.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,
|
||||
};
|
||||
};
|
@ -31,34 +31,35 @@ const ProjectDetails = () => {
|
||||
projects_Details,
|
||||
loading: projectLoading,
|
||||
error: ProjectError,
|
||||
refetch
|
||||
} = useProjectDetails(projectId);
|
||||
const dispatch = useDispatch();
|
||||
const [project, setProject] = useState(null);
|
||||
const [projectDetails, setProjectDetails] = useState(null);
|
||||
// const [projectDetails, setProjectDetails] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const fetchData = async () => {
|
||||
const project_cache = getCachedData("projectInfo");
|
||||
if (!project_cache || project_cache?.projectId !== projectId) {
|
||||
ProjectRepository.getProjectByprojectId(projectId)
|
||||
.then((response) => {
|
||||
setProjectDetails(response.data);
|
||||
setProject(response.data);
|
||||
cacheData("projectInfo", { projectId, data: response.data });
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
setError("Failed to fetch data.");
|
||||
setLoading(false);
|
||||
});
|
||||
} else {
|
||||
setProjectDetails(project_cache.data);
|
||||
setProject(project_cache.data);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
// const fetchData = async () => {
|
||||
// const project_cache = getCachedData("projectInfo");
|
||||
// if (!project_cache || project_cache?.projectId !== projectId) {
|
||||
// ProjectRepository.getProjectByprojectId(projectId)
|
||||
// .then((response) => {
|
||||
// setProjectDetails(response.data);
|
||||
// setProject(response.data);
|
||||
// cacheData("projectInfo", { projectId, data: response.data });
|
||||
// setLoading(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error(error);
|
||||
// setError("Failed to fetch data.");
|
||||
// setLoading(false);
|
||||
// });
|
||||
// } else {
|
||||
// setProjectDetails(project_cache.data);
|
||||
// setProject(project_cache.data);
|
||||
// setLoading(false);
|
||||
// }
|
||||
// };
|
||||
|
||||
const [activePill, setActivePill] = useState("profile");
|
||||
|
||||
@ -78,7 +79,7 @@ const ProjectDetails = () => {
|
||||
<div className="row">
|
||||
<div className="col-xl-4 col-lg-5 col-md-5 mt-5">
|
||||
{/* About User */}
|
||||
<AboutProject data={projectDetails}></AboutProject>
|
||||
<AboutProject data={projects_Details}></AboutProject>
|
||||
{/* About User */}
|
||||
</div>
|
||||
<div className="col-xl-4 col-lg-5 col-md-5 mt-5">
|
||||
@ -94,7 +95,7 @@ const ProjectDetails = () => {
|
||||
<div className="row">
|
||||
<div className="col-lg-12 col-xl-12">
|
||||
{/* Teams */}
|
||||
<Teams project={projectDetails}></Teams>
|
||||
<Teams project={projects_Details}></Teams>
|
||||
{/* Teams */}
|
||||
</div>
|
||||
</div>
|
||||
@ -104,7 +105,7 @@ const ProjectDetails = () => {
|
||||
case "infra": {
|
||||
return (
|
||||
<ProjectInfra
|
||||
data={projectDetails}
|
||||
data={projects_Details}
|
||||
onDataChange={handleDataChange}
|
||||
></ProjectInfra>
|
||||
);
|
||||
@ -113,7 +114,7 @@ const ProjectDetails = () => {
|
||||
case "workplan": {
|
||||
return (
|
||||
<WorkPlan
|
||||
data={projectDetails}
|
||||
data={projects_Details}
|
||||
onDataChange={handleDataChange}
|
||||
></WorkPlan>
|
||||
);
|
||||
@ -122,7 +123,7 @@ const ProjectDetails = () => {
|
||||
case "directory": {
|
||||
return (
|
||||
<div className="row">
|
||||
<Directory IsPage={false} prefernceContacts={projectDetails.id} />
|
||||
<Directory IsPage={false} prefernceContacts={projects_Details.id} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -134,26 +135,27 @@ const ProjectDetails = () => {
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setProjectId(projectId));
|
||||
setProject(projects_Details);
|
||||
setProjectDetails(projects_Details);
|
||||
// setProject(projects_Details);
|
||||
// setProjectDetails(projects_Details);
|
||||
}, [projects_Details, projectId]);
|
||||
|
||||
const handler = useCallback(
|
||||
(msg) => {
|
||||
if (msg.keyword === "Update_Project" && project.id === msg.response.id) {
|
||||
clearCacheKey("projectInfo")
|
||||
ProjectRepository.getProjectByprojectId(projectId)
|
||||
.then((response) => {
|
||||
setProjectDetails(response.data);
|
||||
setProject(response.data);
|
||||
cacheData("projectInfo", { projectId, data: response.data });
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
setError("Failed to fetch data.");
|
||||
setLoading(false);
|
||||
});
|
||||
// clearCacheKey("projectInfo")
|
||||
// ProjectRepository.getProjectByprojectId(projectId)
|
||||
// .then((response) => {
|
||||
// setProjectDetails(response.data);
|
||||
// setProject(response.data);
|
||||
// cacheData("projectInfo", { projectId, data: response.data });
|
||||
// setLoading(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error(error);
|
||||
// setError("Failed to fetch data.");
|
||||
// setLoading(false);
|
||||
// });
|
||||
refetch()
|
||||
}
|
||||
},
|
||||
[project,handleDataChange]
|
||||
|
@ -3,10 +3,14 @@ import ProjectCard from "../../components/Project/ProjectCard";
|
||||
import ManageProjectInfo from "../../components/Project/ManageProjectInfo";
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||
import { useProjects } from "../../hooks/useProjects";
|
||||
import { useProjects, useCreateProject } from "../../hooks/useProjects";
|
||||
import { useDispatch } from "react-redux";
|
||||
import showToast from "../../services/toastService";
|
||||
import { getCachedData, cacheData, clearCacheKey } from "../../slices/apiDataManager";
|
||||
// import {
|
||||
// getCachedData,
|
||||
// cacheData,
|
||||
// clearCacheKey,
|
||||
// } from "../../slices/apiDataManager";
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { useProfile } from "../../hooks/useProfile";
|
||||
import { ITEMS_PER_PAGE, MANAGE_PROJECT } from "../../utils/constants";
|
||||
@ -14,6 +18,9 @@ import ProjectListView from "./ProjectListView";
|
||||
import eventBus from "../../services/eventBus";
|
||||
import { clearApiCacheKey } from "../../slices/apiCacheSlice";
|
||||
import { defaultCheckBoxAppearanceProvider } from "pdf-lib";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import usePagination from "../../hooks/usePagination";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
|
||||
const ProjectList = () => {
|
||||
const { profile: loginUser } = useProfile();
|
||||
@ -26,9 +33,12 @@ const ProjectList = () => {
|
||||
HasManageProjectPermission
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
const { mutate: createProject } = useCreateProject({
|
||||
onSuccessCallback: () => {
|
||||
setShowModal(false);
|
||||
},
|
||||
});
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [itemsPerPage] = useState(ITEMS_PER_PAGE);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedStatuses, setSelectedStatuses] = useState([
|
||||
"b74da4c2-d07e-46f2-9919-e75e49b12731",
|
||||
@ -72,31 +82,35 @@ const ProjectList = () => {
|
||||
}
|
||||
}, [loginUser, HasManageProjectPermission]);
|
||||
|
||||
// const handleSubmitForm = (newProject, setloading, reset) => {
|
||||
// ProjectRepository.manageProject(newProject)
|
||||
// .then((response) => {
|
||||
// const cachedProjects = getCachedData("projectslist") || [];
|
||||
// const updatedProjects = [...cachedProjects, response.data];
|
||||
// cacheData("projectslist", updatedProjects);
|
||||
// setProjectList((prev) => [...prev, response.data]);
|
||||
// setloading(false);
|
||||
// reset();
|
||||
// sortingProject(getCachedData("projectslist"));
|
||||
// showToast("Project Created successfully.", "success");
|
||||
// setShowModal(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// showToast(error.message, "error");
|
||||
// setShowModal(false);
|
||||
// });
|
||||
// };
|
||||
|
||||
const handleSubmitForm = (newProject, setloading, reset) => {
|
||||
ProjectRepository.manageProject(newProject)
|
||||
.then((response) => {
|
||||
const cachedProjects = getCachedData("projectslist") || [];
|
||||
const updatedProjects = [...cachedProjects, response.data];
|
||||
cacheData("projectslist", updatedProjects);
|
||||
setProjectList((prev) => [...prev, response.data]);
|
||||
setloading(true);
|
||||
createProject(newProject, {
|
||||
onSettled: () => {
|
||||
setloading(false);
|
||||
reset();
|
||||
sortingProject(getCachedData("projectslist"));
|
||||
showToast("Project Created successfully.", "success");
|
||||
setShowModal(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
showToast(error.message, "error");
|
||||
setShowModal(false);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleReFresh = () => {
|
||||
if (!projects || projects.length === 0) {
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const handleStatusChange = (statusId) => {
|
||||
setCurrentPage(1);
|
||||
setSelectedStatuses((prev) =>
|
||||
@ -118,13 +132,11 @@ const ProjectList = () => {
|
||||
return matchesStatus && matchesSearch;
|
||||
});
|
||||
|
||||
const indexOfLastItem = currentPage * itemsPerPage;
|
||||
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
|
||||
const currentItems = filteredProjects.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
const totalPages = Math.ceil(filteredProjects.length / itemsPerPage);
|
||||
|
||||
const totalPages = Math.ceil( filteredProjects.length / ITEMS_PER_PAGE );
|
||||
|
||||
const {currentItems,currentPage,paginate,setCurrentPage} = usePagination(filteredProjects, ITEMS_PER_PAGE)
|
||||
|
||||
useEffect(() => {
|
||||
const tooltipTriggerList = Array.from(
|
||||
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
@ -132,67 +144,20 @@ const ProjectList = () => {
|
||||
tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el));
|
||||
}, []);
|
||||
|
||||
const handler = useCallback(
|
||||
async (msg) => {
|
||||
if (HasManageProject && msg.keyword === "Create_Project") {
|
||||
const updatedProjects = [...projectList, msg.response];
|
||||
cacheData("projectslist", updatedProjects);
|
||||
setProjectList(updatedProjects);
|
||||
sortingProject(updatedProjects);
|
||||
}
|
||||
if (
|
||||
msg.keyword === "Update_Project" &&
|
||||
projectList.some((item) => item.id === msg.response.id)
|
||||
) {
|
||||
ProjectRepository.getProjectList()
|
||||
.then((response) => {
|
||||
cacheData("projectslist", response?.data);
|
||||
sortingProject(response?.data);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
});
|
||||
}
|
||||
},
|
||||
[HasManageProject, projectList, sortingProject]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
eventBus.on("project", handler);
|
||||
return () => eventBus.off("project", handler);
|
||||
}, [handler]);
|
||||
|
||||
const assignProjectHandler = useCallback(
|
||||
async (data) => {
|
||||
clearCacheKey("projectslist");
|
||||
await refetch();
|
||||
|
||||
sortingProject(projects);
|
||||
},
|
||||
[refetch]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
eventBus.on("assign_project_one", assignProjectHandler);
|
||||
return () => eventBus.off("assign_project_one", assignProjectHandler);
|
||||
}, [handler]);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`modal fade ${showModal ? "show" : ""}`}
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{ display: showModal ? "block" : "none" }}
|
||||
aria-hidden={!showModal}
|
||||
>
|
||||
|
||||
{showModal && (
|
||||
<GlobalModel isOpen={showModal} closeModal={handleClose}>
|
||||
<ManageProjectInfo
|
||||
project={null}
|
||||
handleSubmitForm={handleSubmitForm}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
</div>
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
<div className="container-xxl flex-grow-1 container-p-y">
|
||||
<Breadcrumb
|
||||
|
@ -1,6 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import moment from "moment";
|
||||
import { useProjects } from "../../hooks/useProjects";
|
||||
import {
|
||||
useProjectDetails,
|
||||
useProjects,
|
||||
useUpdateProject,
|
||||
} from "../../hooks/useProjects";
|
||||
import {
|
||||
getProjectStatusName,
|
||||
getProjectStatusColor,
|
||||
@ -14,25 +18,35 @@ import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import ManageProjectInfo from "../../components/Project/ManageProjectInfo";
|
||||
import showToast from "../../services/toastService";
|
||||
import { getCachedData, cacheData } from "../../slices/apiDataManager";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
|
||||
const ProjectListView = ({ projectData, recall }) => {
|
||||
const [projectInfo, setProjectInfo] = useState(projectData);
|
||||
const [projectDetails, setProjectDetails] = useState(null);
|
||||
const { projects_Details, loading, error, refetch } = useProjectDetails(
|
||||
projectInfo?.id,false
|
||||
);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const ManageProject = useHasUserPermission(MANAGE_PROJECT);
|
||||
useEffect(()=>{
|
||||
useEffect(() => {
|
||||
setProjectInfo(projectData);
|
||||
},[projectData])
|
||||
}, [projectData]);
|
||||
const {
|
||||
mutate: updateProject,
|
||||
isPending,
|
||||
isSuccess,
|
||||
isError,
|
||||
} = useUpdateProject({
|
||||
onSuccessCallback: () => {
|
||||
setShowModal(false);
|
||||
},
|
||||
})
|
||||
|
||||
const handleShow = async () => {
|
||||
try {
|
||||
const response = await ProjectRepository.getProjectByprojectId(
|
||||
projectInfo.id
|
||||
);
|
||||
setProjectDetails(response.data);
|
||||
const { data } = await refetch();
|
||||
setShowModal(true);
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
showToast("Failed to load project details", "error");
|
||||
}
|
||||
};
|
||||
@ -52,45 +66,54 @@ const ProjectListView = ({ projectData, recall }) => {
|
||||
|
||||
const handleFormSubmit = (updatedProject) => {
|
||||
if (projectInfo?.id) {
|
||||
ProjectRepository.updateProject(projectInfo.id, updatedProject)
|
||||
.then((response) => {
|
||||
const updatedProjectData = {
|
||||
...projectInfo,
|
||||
...response.data,
|
||||
building: projectDetails?.building,
|
||||
};
|
||||
|
||||
setProjectInfo(updatedProjectData);
|
||||
|
||||
if (getCachedData(`projectinfo-${projectInfo.id}`)) {
|
||||
cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData);
|
||||
}
|
||||
|
||||
const projects_list = getCachedData("projectslist");
|
||||
if (projects_list) {
|
||||
const updatedProjectsList = projects_list.map((project) =>
|
||||
project.id === projectInfo.id
|
||||
? {
|
||||
...project,
|
||||
...response.data,
|
||||
// tenant: project.tenant
|
||||
}
|
||||
: project
|
||||
);
|
||||
cacheData("projectslist", updatedProjectsList);
|
||||
}
|
||||
recall(getCachedData("projectslist"));
|
||||
showToast("Project updated successfully.", "success");
|
||||
setShowModal(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
showToast(error.message, "error");
|
||||
updateProject({
|
||||
projectId: projectInfo.id,
|
||||
updatedData: updatedProject,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// const handleFormSubmit = (updatedProject) => {
|
||||
// if (projectInfo?.id) {
|
||||
// ProjectRepository.updateProject(projectInfo.id, updatedProject)
|
||||
// .then((response) => {
|
||||
// const updatedProjectData = {
|
||||
// ...projectInfo,
|
||||
// ...response.data,
|
||||
// building: projectDetails?.building,
|
||||
// };
|
||||
|
||||
// setProjectInfo(updatedProjectData);
|
||||
|
||||
// if (getCachedData(`projectinfo-${projectInfo.id}`)) {
|
||||
// cacheData(`projectinfo-${projectInfo.id}`, updatedProjectData);
|
||||
// }
|
||||
|
||||
// const projects_list = getCachedData("projectslist");
|
||||
// if (projects_list) {
|
||||
// const updatedProjectsList = projects_list.map((project) =>
|
||||
// project.id === projectInfo.id
|
||||
// ? {
|
||||
// ...project,
|
||||
// ...response.data,
|
||||
// // tenant: project.tenant
|
||||
// }
|
||||
// : project
|
||||
// );
|
||||
// cacheData("projectslist", updatedProjectsList);
|
||||
// }
|
||||
// recall(getCachedData("projectslist"));
|
||||
// showToast("Project updated successfully.", "success");
|
||||
// setShowModal(false);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// showToast(error.message, "error");
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
return (
|
||||
<>
|
||||
{showModal && projectDetails && (
|
||||
{/* {showModal && projects_Details && (
|
||||
<tr>
|
||||
<td
|
||||
className="modal fade show"
|
||||
@ -100,15 +123,22 @@ const ProjectListView = ({ projectData, recall }) => {
|
||||
aria-hidden="false"
|
||||
>
|
||||
<ManageProjectInfo
|
||||
project={projectDetails}
|
||||
project={projects_Details}
|
||||
handleSubmitForm={handleFormSubmit}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)} */}
|
||||
{showModal && projects_Details && (
|
||||
<GlobalModel isOpen={showModal} closeModal={handleClose}> <ManageProjectInfo
|
||||
project={projects_Details}
|
||||
handleSubmitForm={handleFormSubmit}
|
||||
onClose={handleClose}
|
||||
/></GlobalModel>
|
||||
)}
|
||||
|
||||
<tr className="py-8">
|
||||
<tr className={`py-8 ${isPending ? "bg-light opacity-50 pointer-events-none" : ""} `}>
|
||||
<td className="text-start" colSpan={5}>
|
||||
<strong
|
||||
className="text-primary cursor-pointer"
|
||||
@ -162,6 +192,14 @@ const ProjectListView = ({ projectData, recall }) => {
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{loading ? (
|
||||
<div
|
||||
class="spinner-border spinner-border-sm text-secondary"
|
||||
role="status"
|
||||
>
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<i
|
||||
className="bx bx-dots-vertical-rounded bx-sm text-muted"
|
||||
data-bs-toggle="tooltip"
|
||||
@ -170,6 +208,7 @@ const ProjectListView = ({ projectData, recall }) => {
|
||||
data-bs-custom-class="tooltip-dark"
|
||||
title="More Action"
|
||||
></i>
|
||||
)}
|
||||
</button>
|
||||
<ul className="dropdown-menu dropdown-menu-end">
|
||||
<li>
|
||||
|
Loading…
x
Reference in New Issue
Block a user