When a project is selected, the last selected project will be displayed.
This commit is contained in:
parent
4512c11a60
commit
5399fa1f17
@ -3,6 +3,7 @@ import {
|
|||||||
cacheData,
|
cacheData,
|
||||||
clearAllCache,
|
clearAllCache,
|
||||||
getCachedData,
|
getCachedData,
|
||||||
|
useSelectedproject,
|
||||||
} from "../../slices/apiDataManager";
|
} from "../../slices/apiDataManager";
|
||||||
import AuthRepository from "../../repositories/AuthRepository";
|
import AuthRepository from "../../repositories/AuthRepository";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
@ -12,18 +13,18 @@ import { useProfile } from "../../hooks/useProfile";
|
|||||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
||||||
import Avatar from "../../components/common/Avatar";
|
import Avatar from "../../components/common/Avatar";
|
||||||
import { useChangePassword } from "../Context/ChangePasswordContext";
|
import { useChangePassword } from "../Context/ChangePasswordContext";
|
||||||
import { useProjects } from "../../hooks/useProjects";
|
import { useProjects, useProjectName } from "../../hooks/useProjects"; // Make sure useProjects is imported if needed elsewhere
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useProjectName } from "../../hooks/useProjects";
|
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||||
import { MANAGE_PROJECT } from "../../utils/constants";
|
import { MANAGE_PROJECT } from "../../utils/constants";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const { profile } = useProfile();
|
const { profile } = useProfile();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { data, loading } = useMaster();
|
const { data, loading: masterLoading } = useMaster(); // Renamed loading to masterLoading for clarity
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const HasManageProjectPermission = useHasUserPermission(MANAGE_PROJECT);
|
const HasManageProjectPermission = useHasUserPermission(MANAGE_PROJECT);
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ const Header = () => {
|
|||||||
/^\/dashboard$/.test(location.pathname) || /^\/$/.test(location.pathname);
|
/^\/dashboard$/.test(location.pathname) || /^\/$/.test(location.pathname);
|
||||||
|
|
||||||
// Define the specific project status IDs you want to filter by
|
// Define the specific project status IDs you want to filter by
|
||||||
// Changed to explicitly include only 'Active', 'On Hold', 'In Progress'
|
|
||||||
const allowedProjectStatusIds = [
|
const allowedProjectStatusIds = [
|
||||||
"603e994b-a27f-4e5d-a251-f3d69b0498ba", // On Hold
|
"603e994b-a27f-4e5d-a251-f3d69b0498ba", // On Hold
|
||||||
"cdad86aa-8a56-4ff4-b633-9c629057dfef", // In Progress
|
"cdad86aa-8a56-4ff4-b633-9c629057dfef", // In Progress
|
||||||
@ -67,7 +67,6 @@ const Header = () => {
|
|||||||
window.location.href = "/auth/login";
|
window.location.href = "/auth/login";
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
// Even if logout API fails, clear local storage and redirect
|
|
||||||
localStorage.removeItem("jwtToken");
|
localStorage.removeItem("jwtToken");
|
||||||
localStorage.removeItem("refreshToken");
|
localStorage.removeItem("refreshToken");
|
||||||
localStorage.removeItem("user");
|
localStorage.removeItem("user");
|
||||||
@ -86,63 +85,52 @@ const Header = () => {
|
|||||||
navigate(`/employee/${profile?.employeeInfo?.id}?for=attendance`);
|
navigate(`/employee/${profile?.employeeInfo?.id}?for=attendance`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { projectNames, loading: projectLoading, fetchData } = useProjectName();
|
const { projectNames, loading: projectLoading, fetchData } = useProjectName(); // Renamed loading to projectLoading
|
||||||
|
|
||||||
const selectedProject = useSelector(
|
const selectedProject = useSelectedproject();
|
||||||
(store) => store.localVariables.projectId
|
|
||||||
);
|
|
||||||
|
|
||||||
const projectsForDropdown = isDashboard
|
// Filter projects for the dropdown based on the current path and allowed statuses
|
||||||
? projectNames // On dashboard, show all projects
|
const projectsForDropdown = useMemo(() => {
|
||||||
: projectNames?.filter(project =>
|
if (!projectNames) return []; // Return empty array if projectNames is not yet fetched
|
||||||
allowedProjectStatusIds.includes(project.projectStatusId)
|
|
||||||
|
return isDashboard
|
||||||
|
? projectNames
|
||||||
|
: projectNames?.filter(project => allowedProjectStatusIds.includes(project.projectStatusId));
|
||||||
|
}, [projectNames, isDashboard, allowedProjectStatusIds]);
|
||||||
|
|
||||||
|
|
||||||
|
// Determine the display text for the project dropdown
|
||||||
|
let displayText = "Loading..."; // Default to loading
|
||||||
|
if (!projectLoading && projectNames) { // Only update if not loading and projectNames is available
|
||||||
|
if (selectedProject === null) {
|
||||||
|
displayText = "All Projects";
|
||||||
|
} else {
|
||||||
|
// Find the selected project from the full projectNames list
|
||||||
|
const selectedProjectObj = projectNames.find( // Use projectNames directly here
|
||||||
|
(p) => p?.id === selectedProject
|
||||||
);
|
);
|
||||||
|
displayText = selectedProjectObj ? selectedProjectObj.name : "All Projects"; // Fallback to "All Projects" if selected project is not found
|
||||||
// Determine the display text for the project section
|
|
||||||
let currentProjectDisplayName = "Loading...";
|
|
||||||
if (!projectLoading && projectNames) {
|
|
||||||
if (projectNames.length === 0) {
|
|
||||||
// If no projects are assigned at all
|
|
||||||
currentProjectDisplayName = "No Projects Assigned";
|
|
||||||
} else if (projectNames.length === 1) {
|
|
||||||
// If there's exactly one project overall (unfiltered list)
|
|
||||||
currentProjectDisplayName = projectNames[0].name;
|
|
||||||
} else { // projectNames.length > 1 (multiple projects)
|
|
||||||
if (selectedProject === null) {
|
|
||||||
currentProjectDisplayName = "All Projects";
|
|
||||||
} else {
|
|
||||||
const selectedProjectObj = projectNames.find(
|
|
||||||
(p) => p?.id === selectedProject
|
|
||||||
);
|
|
||||||
currentProjectDisplayName = selectedProjectObj ? selectedProjectObj.name : "Unknown Project";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const { openChangePassword } = useChangePassword();
|
const { openChangePassword } = useChangePassword();
|
||||||
|
|
||||||
// Effect to set initial projectId based on scenarios
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
projectNames &&
|
projectNames &&
|
||||||
projectNames.length > 0 &&
|
projectNames.length > 0 &&
|
||||||
selectedProject === undefined && // Only set if no project is explicitly selected yet
|
selectedProject === undefined && // Only set default if no project is currently selected
|
||||||
!getCachedData("hasReceived") // To avoid re-setting on every render
|
!getCachedData("hasReceived") // Check if this flag is still relevant for your caching strategy
|
||||||
) {
|
) {
|
||||||
if (projectNames.length === 1) {
|
if (isDashboard) {
|
||||||
// If only one project exists, automatically select it
|
dispatch(setProjectId(null)); // Always set to null for "All Projects" on Dashboard initial load
|
||||||
dispatch(setProjectId(projectNames[0]?.id || null));
|
|
||||||
} else {
|
} else {
|
||||||
// If multiple projects, default to "All Projects" on dashboard, or first allowed for others
|
const firstAllowedProject = projectNames.find(project => allowedProjectStatusIds.includes(project.projectStatusId));
|
||||||
if (isDashboard) {
|
dispatch(setProjectId(firstAllowedProject?.id || null)); // Fallback to null if no allowed projects
|
||||||
dispatch(setProjectId(null)); // Default to "All Projects" for dashboard when multiple projects
|
|
||||||
} else {
|
|
||||||
const firstAllowedProject = projectNames.find(project => allowedProjectStatusIds.includes(project.projectStatusId));
|
|
||||||
dispatch(setProjectId(firstAllowedProject?.id || null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [projectNames, selectedProject, dispatch, isDashboard]);
|
}, [projectNames, selectedProject, dispatch, isDashboard, allowedProjectStatusIds]);
|
||||||
|
|
||||||
|
|
||||||
const handler = useCallback(
|
const handler = useCallback(
|
||||||
@ -163,7 +151,7 @@ const Header = () => {
|
|||||||
const newProjectHandler = useCallback(
|
const newProjectHandler = useCallback(
|
||||||
async (msg) => {
|
async (msg) => {
|
||||||
if (HasManageProjectPermission && msg.keyword === "Create_Project") {
|
if (HasManageProjectPermission && msg.keyword === "Create_Project") {
|
||||||
await fetchData();
|
await fetchData();
|
||||||
} else if (projectNames?.some((item) => item.id === msg.response.id)) {
|
} else if (projectNames?.some((item) => item.id === msg.response.id)) {
|
||||||
await fetchData();
|
await fetchData();
|
||||||
}
|
}
|
||||||
@ -186,16 +174,19 @@ const Header = () => {
|
|||||||
};
|
};
|
||||||
}, [handler, newProjectHandler]);
|
}, [handler, newProjectHandler]);
|
||||||
|
|
||||||
const handleProjectChange = (project) => {
|
|
||||||
dispatch(setProjectId(project)); // Always set the projectId
|
|
||||||
|
|
||||||
if (isProjectPath && project !== null) {
|
const handleProjectChange = (projectId) => {
|
||||||
navigate("/projects/details"); // Navigate only if on /projects and a specific project is selected
|
dispatch(setProjectId(projectId));
|
||||||
|
if (isProjectPath && projectId !== null) {
|
||||||
|
navigate(`/projects/details?resetDates=true`);
|
||||||
|
} else if (isProjectPath && projectId === null) {
|
||||||
|
navigate("/projects");
|
||||||
|
} else if (isDashboard) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine if the dropdown should be shown: Only if there are genuinely multiple projects
|
const shouldShowDropdown =
|
||||||
const shouldShowDropdown = projectNames && projectNames.length > 1;
|
isDashboard || (projectsForDropdown && projectsForDropdown.length > 1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
@ -218,30 +209,35 @@ const Header = () => {
|
|||||||
<div className="align-items-center">
|
<div className="align-items-center">
|
||||||
<i className="rounded-circle bx bx-building-house bx-sm-lg bx-md me-2"></i>
|
<i className="rounded-circle bx bx-building-house bx-sm-lg bx-md me-2"></i>
|
||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
{/* Conditionally render as a dropdown toggle button or a plain span */}
|
{/* Conditionally render the button based on shouldShowDropdown */}
|
||||||
{shouldShowDropdown ? (
|
{shouldShowDropdown ? (
|
||||||
<button
|
<button
|
||||||
className={`btn btn-sm-sm btn-xl dropdown-toggle px-1`}
|
className={`btn btn-sm-sm btn-xl ${projectsForDropdown && projectsForDropdown.length > 0 ? "dropdown-toggle" : ""
|
||||||
|
} px-1`}
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
>
|
>
|
||||||
{currentProjectDisplayName}
|
{displayText}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
// If no dropdown (single or zero projects), just display the text
|
// If only one project or no projects (and not dashboard), just display its name/message without a dropdown
|
||||||
<span className="btn btn-sm-sm btn-xl px-1">
|
<span className="btn btn-sm-sm btn-xl px-1">
|
||||||
{currentProjectDisplayName}
|
{projectLoading ? "Loading..." :
|
||||||
|
(projectsForDropdown && projectsForDropdown.length === 1
|
||||||
|
? projectsForDropdown[0].name
|
||||||
|
: (isDashboard ? "All Projects" : "No Projects")) // Handle "No Projects" for non-dashboard views
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Only render the dropdown menu if shouldShowDropdown is true AND there are projects to display in it */}
|
{/* Only render the dropdown menu if shouldShowDropdown is true AND there are projects to show */}
|
||||||
{shouldShowDropdown && projectsForDropdown && projectsForDropdown.length > 0 && (
|
{shouldShowDropdown && projectsForDropdown && projectsForDropdown.length > 0 && (
|
||||||
<ul
|
<ul
|
||||||
className="dropdown-menu"
|
className="dropdown-menu"
|
||||||
style={{ overflow: "auto", maxHeight: "300px" }}
|
style={{ overflow: "auto", maxHeight: "300px" }}
|
||||||
>
|
>
|
||||||
{isDashboard && ( // "All Projects" option only appears in the dropdown if on dashboard and multiple projects
|
{isDashboard && (
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
className="dropdown-item"
|
className="dropdown-item"
|
||||||
|
@ -49,20 +49,7 @@ const ProjectNav = ({ onPillClick, activePill }) => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="nav-item">
|
|
||||||
<a
|
|
||||||
className={`nav-link ${
|
|
||||||
activePill === "imagegallary" ? "active" : ""
|
|
||||||
} fs-6`}
|
|
||||||
href="#"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault(); // Prevent page reload
|
|
||||||
onPillClick("imagegallary");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className='bx bxs-cog bx-sm me-1_5'></i> <span className="d-none d-md-inline">project Setup</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{(DirAdmin || DireManager || DirUser) && (
|
{(DirAdmin || DireManager || DirUser) && (
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<a
|
<a
|
||||||
@ -77,6 +64,20 @@ const ProjectNav = ({ onPillClick, activePill }) => {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
<li className="nav-item">
|
||||||
|
<a
|
||||||
|
className={`nav-link ${
|
||||||
|
activePill === "imagegallary" ? "active" : ""
|
||||||
|
} fs-6`}
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault(); // Prevent page reload
|
||||||
|
onPillClick("imagegallary");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className='bx bxs-cog bx-sm me-1_5'></i> <span className="d-none d-md-inline">project Setup</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
cacheData,
|
cacheData,
|
||||||
clearCacheKey,
|
clearCacheKey,
|
||||||
getCachedData,
|
getCachedData,
|
||||||
|
useSelectedproject,
|
||||||
} from "../../slices/apiDataManager";
|
} from "../../slices/apiDataManager";
|
||||||
import "./ProjectDetails.css";
|
import "./ProjectDetails.css";
|
||||||
import {
|
import {
|
||||||
@ -28,8 +29,7 @@ import { setProjectId } from "../../slices/localVariablesSlice";
|
|||||||
|
|
||||||
const ProjectDetails = () => {
|
const ProjectDetails = () => {
|
||||||
|
|
||||||
|
const projectId = useSelectedproject()
|
||||||
const projectId = useSelector((store) => store.localVariables.projectId);
|
|
||||||
|
|
||||||
const { projectNames, fetchData } = useProjectName();
|
const { projectNames, fetchData } = useProjectName();
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
@ -47,9 +47,10 @@ const ProjectDetails = () => {
|
|||||||
refetch,
|
refetch,
|
||||||
} = useProjectDetails(projectId);
|
} = useProjectDetails(projectId);
|
||||||
|
|
||||||
const [activePill, setActivePill] = useState("profile");
|
// const [activePill, setActivePill] = useState("profile");
|
||||||
|
const [activePill, setActivePill] = useState(() => {
|
||||||
|
return localStorage.getItem("lastActiveProjectTab") || "profile";
|
||||||
|
});
|
||||||
|
|
||||||
const handler = useCallback(
|
const handler = useCallback(
|
||||||
(msg) => {
|
(msg) => {
|
||||||
@ -65,9 +66,11 @@ const ProjectDetails = () => {
|
|||||||
return () => eventBus.off("project", handler);
|
return () => eventBus.off("project", handler);
|
||||||
}, [handler]);
|
}, [handler]);
|
||||||
|
|
||||||
const handlePillClick = (pillKey) => {
|
const handlePillClick = (pillKey) => {
|
||||||
setActivePill(pillKey);
|
setActivePill(pillKey);
|
||||||
};
|
localStorage.setItem("lastActiveProjectTab", pillKey); // ✅ Save to localStorage
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
if (projectLoading || !projects_Details) return <Loader />;
|
if (projectLoading || !projects_Details) return <Loader />;
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
flushApiCache,
|
flushApiCache,
|
||||||
} from "../slices/apiCacheSlice";
|
} from "../slices/apiCacheSlice";
|
||||||
import {setLoginUserPermmisions} from "./globalVariablesSlice";
|
import {setLoginUserPermmisions} from "./globalVariablesSlice";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
|
||||||
// Cache data
|
// Cache data
|
||||||
@ -36,4 +37,17 @@ export const cacheProfileData = ( data) => {
|
|||||||
// Get cached data
|
// Get cached data
|
||||||
export const getCachedProfileData = () => {
|
export const getCachedProfileData = () => {
|
||||||
return store.getState().globalVariables.loginUser;
|
return store.getState().globalVariables.loginUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useSelectedproject = () => {
|
||||||
|
const selectedProject = useSelector((store)=> store.localVariables.projectId);
|
||||||
|
var project = localStorage.getItem("project");
|
||||||
|
if(project){
|
||||||
|
return project
|
||||||
|
} else{
|
||||||
|
return selectedProject
|
||||||
|
}
|
||||||
|
// return project ? selectedProject
|
||||||
|
|
||||||
|
|
||||||
|
};
|
@ -21,7 +21,9 @@ const localVariablesSlice = createSlice({
|
|||||||
state.regularizationCount = action.payload;
|
state.regularizationCount = action.payload;
|
||||||
},
|
},
|
||||||
setProjectId: (state, action) => {
|
setProjectId: (state, action) => {
|
||||||
|
localStorage.setItem("project",null)
|
||||||
state.projectId = action.payload;
|
state.projectId = action.payload;
|
||||||
|
localStorage.setItem("project",state.projectId)
|
||||||
},
|
},
|
||||||
refreshData: ( state, action ) =>
|
refreshData: ( state, action ) =>
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user