fixed high level changes

This commit is contained in:
pramod mahajan 2025-09-18 12:38:39 +05:30
parent 09bb58e50e
commit 9311f41f56
6 changed files with 123 additions and 126 deletions

View File

@ -19,54 +19,60 @@ import { useSelectedProject } from "../../slices/apiDataManager";
import Loader from "../common/Loader"; import Loader from "../common/Loader";
const InfraPlanning = () =>
{
const {profile: LoggedUser, refetch : fetchData} = useProfile() const InfraPlanning = () => {
const dispatch = useDispatch() const { profile: LoggedUser, refetch: fetchData } = useProfile();
// const selectedProject = useSelector((store)=>store.localVariables.projectId) const dispatch = useDispatch();
const selectedProject = useSelectedProject(); const selectedProject = useSelectedProject();
const {projectInfra, isLoading, error} = useProjectInfra( selectedProject )
const { projectInfra, isLoading, isError, error, isFetched } = useProjectInfra(selectedProject);
const canManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA ) const canApproveTask = useHasUserPermission(APPROVE_TASK);
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK) const canReportTask = useHasUserPermission(ASSIGN_REPORT_TASK);
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK)
const reloadedData = useSelector( ( store ) => store.localVariables.reload )
const reloadedData = useSelector((store) => store.localVariables.reload);
// useEffect( () =>
// {
// if (reloadedData)
// {
// refetch()
// dispatch( refreshData( false ) )
// }
// },[reloadedData]) const hasAccess = canManageInfra || canApproveTask || canReportTask;
if (isError) {
return <div>{error?.response?.data?.message || error?.message}</div>;
}
if (!hasAccess && !isLoading) {
return (
<div className="text-center">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>Access Denied: You don't have permission to perform this action.</p>
</div>
);
}
if (isLoading) {
return <Loader />;
}
if (isFetched && (!projectInfra || projectInfra.length === 0)) {
return (
<div className="card text-center">
<p className="my-3">No Result Found</p>
</div>
);
}
return ( return (
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4"> <div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
<div className="card"> <div className="card">
<div className="card-body" style={{ padding: "0.5rem" }}> <div className="card-body" style={{ padding: "0.5rem" }}>
{(ApprovedTaskRights || ReportTaskRights) ? ( <div className="row">
<div className="align-items-center"> <InfraTable buildings={projectInfra} projectId={selectedProject} />
<div className="row ">
{isLoading && (<Loader/> )}
{( !isLoading && projectInfra?.length === 0 ) && ( <p>No Result Found</p> )}
{(!isLoading && projectInfra?.length > 0) && (<InfraTable buildings={projectInfra} projectId={selectedProject}/>)}
</div> </div>
</div> </div>
) : (
<div className="text-center">
<i className="fa-solid fa-triangle-exclamation fs-5"></i>
<p>Access Denied: You don't have permission to perform this action. !</p>
</div>
)}
</div> </div>
</div> </div>
</div>
); );
}; };
export default InfraPlanning; export default InfraPlanning;

View File

@ -1,16 +1,26 @@
import { useSelectedProject } from "../slices/apiDataManager"; import { useSelectedProject } from "../slices/apiDataManager";
import { useAllProjectLevelPermissions, useProfile } from "./useProfile"; import { useAllProjectLevelPermissions, useProfile } from "./useProfile";
export const useHasUserPermission = (permission) => { export const useHasUserPermission = (permission) => {
const selectedProject = useSelectedProject(); const selectedProject = useSelectedProject();
const { profile } = useProfile(); const { profile } = useProfile();
const { data: projectPermissions = [], isLoading, isError } = useAllProjectLevelPermissions(selectedProject); const {
data: projectPermissions = [],
isLoading,
isError,
} = useAllProjectLevelPermissions(selectedProject);
if (isLoading || !permission) return false; if (isLoading || !permission) return false;
const globalPerms = profile?.featurePermissions ?? []; const globalPerms = profile?.featurePermissions ?? [];
const projectPerms = projectPermissions ?? []; const projectPerms = projectPermissions ?? [];
if (selectedProject) {
return globalPerms.includes(permission) || projectPerms.includes(permission); if (projectPerms.length === 0) {
return projectPerms.includes(permission);
} else {
return projectPerms.includes(permission);
}
} else {
return globalPerms.includes(permission);
}
}; };

View File

@ -0,0 +1,26 @@
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";
import { useHasUserPermission } from "./useHasUserPermission";
import { useAllProjectLevelPermissions } from "./useProfile";
import { VIEW_PROJECTS } from "../utils/constants";
import showToast from "../services/toastService";
export const useProjectAccess = (projectId) => {
const { data: projectPermissions, isLoading, isFetched } =
useAllProjectLevelPermissions(projectId);
const canView = useHasUserPermission(VIEW_PROJECTS);
const navigate = useNavigate();
useEffect(() => {
if (projectId && isFetched && !isLoading && !canView) {
showToast("You don't have permission to view project details", "warning");
navigate("/projects");
}
}, [projectId, isFetched, isLoading, canView, navigate]);
return {
canView,
loading: isLoading || !isFetched,
};
};

View File

@ -177,6 +177,7 @@ export const useProjectInfra = (projectId) => {
data: projectInfra, data: projectInfra,
isLoading, isLoading,
error, error,
isFetched
} = useQuery({ } = useQuery({
queryKey: ["ProjectInfra", projectId], queryKey: ["ProjectInfra", projectId],
queryFn: async () => { queryFn: async () => {
@ -190,7 +191,7 @@ export const useProjectInfra = (projectId) => {
}, },
}); });
return { projectInfra, isLoading, error }; return { projectInfra, isLoading, error, isFetched };
}; };
export const useProjectTasks = (workAreaId, IsExpandedArea = false) => { export const useProjectTasks = (workAreaId, IsExpandedArea = false) => {

View File

@ -21,6 +21,7 @@ import ContactProfile from "../../components/Directory/ContactProfile";
import GlobalModel from "../../components/common/GlobalModel"; import GlobalModel from "../../components/common/GlobalModel";
import { exportToCSV } from "../../utils/exportUtils"; import { exportToCSV } from "../../utils/exportUtils";
import ConfirmModal from "../../components/common/ConfirmModal"; import ConfirmModal from "../../components/common/ConfirmModal";
import { useSelectedProject } from "../../slices/apiDataManager";
const NotesPage = lazy(() => import("./NotesPage")); const NotesPage = lazy(() => import("./NotesPage"));
const ContactsPage = lazy(() => import("./ContactsPage")); const ContactsPage = lazy(() => import("./ContactsPage"));

View File

@ -1,5 +1,6 @@
import { useSelector, useDispatch } from "react-redux"; // Import useSelector
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect, useCallback } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import ProjectOverview from "../../components/Project/ProjectOverview"; import ProjectOverview from "../../components/Project/ProjectOverview";
import AboutProject from "../../components/Project/AboutProject"; import AboutProject from "../../components/Project/AboutProject";
@ -9,63 +10,43 @@ import ProjectInfra from "../../components/Project/ProjectInfra";
import Loader from "../../components/common/Loader"; import Loader from "../../components/common/Loader";
import WorkPlan from "../../components/Project/WorkPlan"; import WorkPlan from "../../components/Project/WorkPlan";
import Breadcrumb from "../../components/common/Breadcrumb"; import Breadcrumb from "../../components/common/Breadcrumb";
import { import { useSelectedProject } from "../../slices/apiDataManager";
cacheData, import { useProjectDetails, useProjectName } from "../../hooks/useProjects";
clearCacheKey,
getCachedData,
useSelectedProject,
} from "../../slices/apiDataManager";
import "./ProjectDetails.css";
import { useProjectDetails } from "../../hooks/useProjects";
import { ComingSoonPage } from "../Misc/ComingSoonPage"; import { ComingSoonPage } from "../Misc/ComingSoonPage";
import eventBus from "../../services/eventBus"; import eventBus from "../../services/eventBus";
import ProjectProgressChart from "../../components/Dashboard/ProjectProgressChart"; import ProjectProgressChart from "../../components/Dashboard/ProjectProgressChart";
import { useProjectName } from "../../hooks/useProjects";
import AttendanceOverview from "../../components/Dashboard/AttendanceChart"; import AttendanceOverview from "../../components/Dashboard/AttendanceChart";
import { setProjectId } from "../../slices/localVariablesSlice"; import { setProjectId } from "../../slices/localVariablesSlice";
import ProjectDocument from "../../components/Project/ProjectDocuments";
import ProjectDocuments from "../../components/Project/ProjectDocuments"; import ProjectDocuments from "../../components/Project/ProjectDocuments";
import ProjectSetting from "../../components/Project/ProjectSetting"; import ProjectSetting from "../../components/Project/ProjectSetting";
import DirectoryPage from "../Directory/DirectoryPage"; import DirectoryPage from "../Directory/DirectoryPage";
import { useHasAnyPermission } from "../../hooks/useExpense"; import { useProjectAccess } from "../../hooks/useProjectAccess"; // new
import { VIEW_PROJECTS } from "../../utils/constants";
import { useNavigate, useRoutes } from "react-router-dom"; import "./ProjectDetails.css";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
const ProjectDetails = () => { const ProjectDetails = () => {
const projectId = useSelectedProject(); const projectId = useSelectedProject();
const CanViewProject = useHasUserPermission(VIEW_PROJECTS);
const navigate = useNavigate();
const { projectNames, fetchData } = useProjectName();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { projectNames } = useProjectName();
const { projects_Details, loading: projectLoading, refetch } =
useProjectDetails(projectId);
const { canView, loading: permsLoading } = useProjectAccess(projectId);
useEffect(() => { useEffect(() => {
if (!CanViewProject) { if (!projectId && projectNames.length > 0) {
navigate("/dashboard"); dispatch(setProjectId(projectNames[0].id));
} }
if (projectId == null) { }, [projectId, projectNames, dispatch]);
dispatch(setProjectId(projectNames[0]?.id));
}
}, [projectNames]);
const { const [activePill, setActivePill] = useState(
projects_Details, localStorage.getItem("lastActiveProjectTab") || "profile"
loading: projectLoading, );
error: projectError,
refetch,
} = useProjectDetails(projectId);
const [activePill, setActivePill] = useState(() => {
return localStorage.getItem("lastActiveProjectTab") || "profile";
});
const handler = useCallback( const handler = useCallback(
(msg) => { (msg) => {
if ( if (msg.keyword === "Update_Project" && projects_Details?.id === msg.response.id) {
msg.keyword === "Update_Project" &&
projects_Details?.id === msg.response.id
) {
refetch(); refetch();
} }
}, },
@ -79,69 +60,42 @@ const ProjectDetails = () => {
const handlePillClick = (pillKey) => { const handlePillClick = (pillKey) => {
setActivePill(pillKey); setActivePill(pillKey);
localStorage.setItem("lastActiveProjectTab", pillKey); localStorage.setItem("lastActiveProjectTab", pillKey);
}; };
const renderContent = () => { if (projectLoading || permsLoading || !projects_Details) {
if (projectLoading || !projects_Details) return <Loader />; return <Loader />;
}
const renderContent = () => {
switch (activePill) { switch (activePill) {
case "profile": case "profile":
return (
<>
<div className="row">
<div className="col-lg-4 col-md-5 mt-2">
<AboutProject></AboutProject>
<ProjectOverview project={projectId} />
</div>
<div className="col-lg-8 col-md-7 mt-5">
<ProjectProgressChart
ShowAllProject="false"
DefaultRange="1M"
/>
<div className="mt-5">
{" "}
<AttendanceOverview />
</div>
</div>
</div>
</>
);
case "teams":
return ( return (
<div className="row"> <div className="row">
<div className="col-lg-12"> <div className="col-lg-4 col-md-5 mt-2">
<Teams /> <AboutProject />
<ProjectOverview project={projectId} />
</div>
<div className="col-lg-8 col-md-7 mt-5">
<ProjectProgressChart ShowAllProject="false" DefaultRange="1M" />
<div className="mt-5">
<AttendanceOverview />
</div>
</div> </div>
</div> </div>
); );
case "teams":
return <Teams />;
case "infra": case "infra":
return <ProjectInfra data={projects_Details} onDataChange={refetch} />; return <ProjectInfra data={projects_Details} onDataChange={refetch} />;
case "workplan": case "workplan":
return <WorkPlan data={projects_Details} onDataChange={refetch} />; return <WorkPlan data={projects_Details} onDataChange={refetch} />;
case "directory": case "directory":
return ( return <DirectoryPage IsPage={false} projectId={projects_Details.id} />;
<div className="row mt-2">
<DirectoryPage IsPage={false} projectId={projects_Details.id} />
</div>
);
case "documents": case "documents":
return ( return <ProjectDocuments />;
<div className="row">
<ProjectDocuments />
</div>
);
case "setting": case "setting":
return ( return <ProjectSetting />;
<div className="row">
<ProjectSetting />
</div>
);
default: default:
return <ComingSoonPage />; return <ComingSoonPage />;
} }
@ -156,7 +110,6 @@ const ProjectDetails = () => {
{ label: projects_Details?.name || "Project", link: null }, { label: projects_Details?.name || "Project", link: null },
]} ]}
/> />
<div className="row"> <div className="row">
<ProjectNav onPillClick={handlePillClick} activePill={activePill} /> <ProjectNav onPillClick={handlePillClick} activePill={activePill} />
</div> </div>