Menu re-work almost done
This commit is contained in:
parent
4689aa66c6
commit
7a166fe920
@ -12,7 +12,7 @@ import { Snack, SetSnackType } from 'components/Snack';
|
|||||||
import { User } from 'types/types';
|
import { User } from 'types/types';
|
||||||
import { LoadingComponent } from "components/LoadingComponent";
|
import { LoadingComponent } from "components/LoadingComponent";
|
||||||
import { AuthProvider, useAuth, ProtectedRoute } from 'hooks/AuthContext';
|
import { AuthProvider, useAuth, ProtectedRoute } from 'hooks/AuthContext';
|
||||||
import { useSelectedCandidate } from 'hooks/GlobalContext';
|
import { useAppState, useSelectedCandidate } from 'hooks/GlobalContext';
|
||||||
import {
|
import {
|
||||||
getMainNavigationItems,
|
getMainNavigationItems,
|
||||||
getAllRoutes,
|
getAllRoutes,
|
||||||
@ -76,29 +76,28 @@ const BackstoryPageContainer = (props: BackstoryPageContainerProps) => {
|
|||||||
interface BackstoryLayoutProps {
|
interface BackstoryLayoutProps {
|
||||||
page: string;
|
page: string;
|
||||||
chatRef: React.Ref<any>;
|
chatRef: React.Ref<any>;
|
||||||
snackRef: React.Ref<any>;
|
|
||||||
submitQuery: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const BackstoryLayout: React.FC<BackstoryLayoutProps> = (props: BackstoryLayoutProps) => {
|
const BackstoryLayout: React.FC<BackstoryLayoutProps> = (props: BackstoryLayoutProps) => {
|
||||||
const { page, chatRef, snackRef, submitQuery } = props;
|
const { page, chatRef, } = props;
|
||||||
|
const { setSnack } = useAppState();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { guest, user } = useAuth();
|
const { guest, user } = useAuth();
|
||||||
const { selectedCandidate } = useSelectedCandidate();
|
|
||||||
const [navigationItems, setNavigationItems] = useState<NavigationItem[]>([]);
|
const [navigationItems, setNavigationItems] = useState<NavigationItem[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const userType = user?.userType || null;
|
const userType = user?.userType || null;
|
||||||
setNavigationItems(getMainNavigationItems(userType));
|
setNavigationItems(getMainNavigationItems(userType, user?.isAdmin ? true : false));
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
// Generate dynamic routes from navigation config
|
// Generate dynamic routes from navigation config
|
||||||
const generateRoutes = () => {
|
const generateRoutes = () => {
|
||||||
if (!guest) return null;
|
if (!guest && !user) return null;
|
||||||
|
|
||||||
const userType = user?.userType || null;
|
const userType = user?.userType || null;
|
||||||
const routes = getAllRoutes(userType);
|
const isAdmin = user?.isAdmin ? true : false;
|
||||||
|
const routes = getAllRoutes(userType, isAdmin);
|
||||||
|
|
||||||
return routes.map((route, index) => {
|
return routes.map((route, index) => {
|
||||||
if (!route.path || !route.component) return null;
|
if (!route.path || !route.component) return null;
|
||||||
@ -158,7 +157,7 @@ const BackstoryLayout: React.FC<BackstoryLayoutProps> = (props: BackstoryLayoutP
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BackstoryPageContainer>
|
<BackstoryPageContainer>
|
||||||
{!guest && (
|
{!guest && !user && (
|
||||||
<Box>
|
<Box>
|
||||||
<LoadingComponent
|
<LoadingComponent
|
||||||
loadingText="Creating session..."
|
loadingText="Creating session..."
|
||||||
@ -168,7 +167,7 @@ const BackstoryLayout: React.FC<BackstoryLayoutProps> = (props: BackstoryLayoutP
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{guest && (
|
{(guest || user) && (
|
||||||
<>
|
<>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<Routes>
|
<Routes>
|
||||||
@ -179,7 +178,6 @@ const BackstoryLayout: React.FC<BackstoryLayoutProps> = (props: BackstoryLayoutP
|
|||||||
{location.pathname === "/" && <Footer />}
|
{location.pathname === "/" && <Footer />}
|
||||||
</BackstoryPageContainer>
|
</BackstoryPageContainer>
|
||||||
</Scrollable>
|
</Scrollable>
|
||||||
<Snack ref={snackRef} />
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -20,7 +20,7 @@ const getBackstoryDynamicRoutes = (props: BackstoryDynamicRoutesProps): ReactNod
|
|||||||
const isAdmin = user?.isAdmin ? true : false;
|
const isAdmin = user?.isAdmin ? true : false;
|
||||||
|
|
||||||
// Get all routes from navigation config
|
// Get all routes from navigation config
|
||||||
const routes = getAllRoutes(userType);
|
const routes = getAllRoutes(userType, isAdmin);
|
||||||
|
|
||||||
return routes.map((route: NavigationItem, index: number) => {
|
return routes.map((route: NavigationItem, index: number) => {
|
||||||
if (!route.path || !route.component) return null;
|
if (!route.path || !route.component) return null;
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
|
SxProps,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { styled, useTheme } from '@mui/material/styles';
|
import { styled, useTheme } from '@mui/material/styles';
|
||||||
import {
|
import {
|
||||||
@ -38,7 +39,7 @@ import {
|
|||||||
ExpandLess,
|
ExpandLess,
|
||||||
KeyboardArrowDown,
|
KeyboardArrowDown,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
|
import FaceRetouchingNaturalIcon from '@mui/icons-material/FaceRetouchingNatural';
|
||||||
import { getUserMenuItemsByGroup } from 'config/navigationConfig';
|
import { getUserMenuItemsByGroup } from 'config/navigationConfig';
|
||||||
import { NavigationItem } from 'types/navigation';
|
import { NavigationItem } from 'types/navigation';
|
||||||
import { Beta } from 'components/ui/Beta';
|
import { Beta } from 'components/ui/Beta';
|
||||||
@ -125,8 +126,6 @@ interface HeaderProps {
|
|||||||
const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
||||||
const { user, logout } = useAuth();
|
const { user, logout } = useAuth();
|
||||||
const { setSnack } = useAppState();
|
const { setSnack } = useAppState();
|
||||||
const candidate: Candidate | null = (user && user.userType === "candidate") ? user as Candidate : null;
|
|
||||||
const employer: Employer | null = (user && user.userType === "employer") ? user as Employer : null;
|
|
||||||
const {
|
const {
|
||||||
transparent = false,
|
transparent = false,
|
||||||
className,
|
className,
|
||||||
@ -254,7 +253,7 @@ const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||||||
// Helper function to check if any child is current path
|
// Helper function to check if any child is current path
|
||||||
const hasActiveChild = (item: NavigationItem): boolean => {
|
const hasActiveChild = (item: NavigationItem): boolean => {
|
||||||
if (!item.children) return false;
|
if (!item.children) return false;
|
||||||
return item.children.some((child: any) => isCurrentPath(child) || hasActiveChild(child));
|
return item.children.some(child => isCurrentPath(child) || hasActiveChild(child));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Desktop dropdown handlers
|
// Desktop dropdown handlers
|
||||||
@ -328,7 +327,7 @@ const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||||||
transformOrigin={{ vertical: 'top', horizontal: 'left' }}
|
transformOrigin={{ vertical: 'top', horizontal: 'left' }}
|
||||||
TransitionComponent={Fade}
|
TransitionComponent={Fade}
|
||||||
>
|
>
|
||||||
{item.children?.map((child: any) => (
|
{item.children?.map(child => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={child.id}
|
key={child.id}
|
||||||
onClick={() => child.path && handleNavigate(child.path)}
|
onClick={() => child.path && handleNavigate(child.path)}
|
||||||
@ -416,7 +415,7 @@ const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
|||||||
{hasChildren && (
|
{hasChildren && (
|
||||||
<Collapse in={isExpanded} timeout="auto" unmountOnExit>
|
<Collapse in={isExpanded} timeout="auto" unmountOnExit>
|
||||||
<List disablePadding>
|
<List disablePadding>
|
||||||
{item.children?.map((child: any) => renderNavigationItem(child, depth + 1))}
|
{item.children?.map(child => renderNavigationItem(child, depth + 1))}
|
||||||
</List>
|
</List>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
)}
|
)}
|
||||||
|
@ -14,6 +14,9 @@ import {
|
|||||||
History as HistoryIcon,
|
History as HistoryIcon,
|
||||||
QuestionAnswer as QuestionAnswerIcon,
|
QuestionAnswer as QuestionAnswerIcon,
|
||||||
AttachMoney as AttachMoneyIcon,
|
AttachMoney as AttachMoneyIcon,
|
||||||
|
Quiz as QuizIcon,
|
||||||
|
Analytics as AnalyticsIcon,
|
||||||
|
BubbleChart,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
|
|
||||||
import { BackstoryLogo } from 'components/ui/BackstoryLogo';
|
import { BackstoryLogo } from 'components/ui/BackstoryLogo';
|
||||||
@ -28,9 +31,15 @@ import { JobAnalysisPage } from 'pages/JobAnalysisPage';
|
|||||||
import { GenerateCandidate } from 'pages/GenerateCandidate';
|
import { GenerateCandidate } from 'pages/GenerateCandidate';
|
||||||
import { LoginPage } from 'pages/LoginPage';
|
import { LoginPage } from 'pages/LoginPage';
|
||||||
import { EmailVerificationPage } from 'components/EmailVerificationComponents';
|
import { EmailVerificationPage } from 'components/EmailVerificationComponents';
|
||||||
import { Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import { CandidateDashboard } from 'pages/candidate/Dashboard';
|
import { CandidateDashboard } from 'pages/candidate/Dashboard';
|
||||||
import { NavigationConfig, NavigationItem } from 'types/navigation';
|
import { NavigationConfig, NavigationItem } from 'types/navigation';
|
||||||
|
import { HowItWorks } from 'pages/HowItWorks';
|
||||||
|
import SchoolIcon from '@mui/icons-material/School';
|
||||||
|
import { CandidateProfile } from 'pages/candidate/Profile';
|
||||||
|
import { Settings } from 'pages/candidate/Settings';
|
||||||
|
import { VectorVisualizer } from 'components/VectorVisualizer';
|
||||||
|
import { DocumentManager } from 'components/DocumentManager';
|
||||||
|
|
||||||
// Beta page components for placeholder routes
|
// Beta page components for placeholder routes
|
||||||
const BackstoryPage = () => (<BetaPage><Typography variant="h4">Backstory</Typography></BetaPage>);
|
const BackstoryPage = () => (<BetaPage><Typography variant="h4">Backstory</Typography></BetaPage>);
|
||||||
@ -46,8 +55,8 @@ const SettingsPage = () => (<BetaPage><Typography variant="h4">Settings</Typogra
|
|||||||
|
|
||||||
export const navigationConfig: NavigationConfig = {
|
export const navigationConfig: NavigationConfig = {
|
||||||
items: [
|
items: [
|
||||||
{ id: 'home', label: <BackstoryLogo />, path: '/', component: <HomePage />, userTypes: ['guest', 'candidate', 'employer'], exact: true, },
|
{ id: 'home', label: <BackstoryLogo />, path: '/', component: <HowItWorks />, userTypes: ['guest', 'candidate', 'employer'], exact: true, },
|
||||||
{ id: 'how-it-works', label: 'How It Works', path: '/how-it-works', icon: <SchoolIcon />, component: <HowItWorks />, userTypes: ['guest', 'candidate', 'employer',], },
|
// { id: 'how-it-works', label: 'How It Works', path: '/how-it-works', icon: <SchoolIcon />, component: <HowItWorks />, userTypes: ['guest', 'candidate', 'employer',], },
|
||||||
{ id: 'job-analysis', label: 'Job Analysis', path: '/job-analysis', icon: <WorkIcon />, component: <JobAnalysisPage />, userTypes: ['guest', 'candidate', 'employer',], },
|
{ id: 'job-analysis', label: 'Job Analysis', path: '/job-analysis', icon: <WorkIcon />, component: <JobAnalysisPage />, userTypes: ['guest', 'candidate', 'employer',], },
|
||||||
{ id: 'chat', label: 'Candidate Chat', path: '/chat', icon: <ChatIcon />, component: <CandidateChatPage />, userTypes: ['guest', 'candidate', 'employer',], }, {
|
{ id: 'chat', label: 'Candidate Chat', path: '/chat', icon: <ChatIcon />, component: <CandidateChatPage />, userTypes: ['guest', 'candidate', 'employer',], }, {
|
||||||
id: 'candidate-menu', label: 'Tools', icon: <PersonIcon />, userTypes: ['candidate'], children: [
|
id: 'candidate-menu', label: 'Tools', icon: <PersonIcon />, userTypes: ['candidate'], children: [
|
||||||
@ -75,8 +84,6 @@ export const navigationConfig: NavigationConfig = {
|
|||||||
{ id: 'employer-settings', label: 'Settings', path: '/employer/settings', icon: <SettingsIcon />, component: <SettingsPage />, userTypes: ['employer'], },
|
{ id: 'employer-settings', label: 'Settings', path: '/employer/settings', icon: <SettingsIcon />, component: <SettingsPage />, userTypes: ['employer'], },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'global-tools',
|
id: 'global-tools',
|
||||||
label: 'Tools',
|
label: 'Tools',
|
||||||
@ -218,12 +225,12 @@ export const navigationConfig: NavigationConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Utility functions for working with navigation config
|
// Utility functions for working with navigation config
|
||||||
export const getNavigationItemsForUser = (userType: 'guest' | 'candidate' | 'employer' | null): NavigationItem[] => {
|
export const getNavigationItemsForUser = (userType: 'guest' | 'candidate' | 'employer' | null, isAdmin: boolean = false): NavigationItem[] => {
|
||||||
const currentUserType = userType || 'guest';
|
const currentUserType = userType || 'guest';
|
||||||
|
|
||||||
const filterItems = (items: NavigationItem[]): NavigationItem[] => {
|
const filterItems = (items: NavigationItem[]): NavigationItem[] => {
|
||||||
return items
|
return items
|
||||||
.filter(item => !item.userTypes || item.userTypes.includes(currentUserType))
|
.filter(item => !item.userTypes || item.userTypes.includes(currentUserType) || (item.userTypes.includes('admin') && isAdmin))
|
||||||
.filter(item => item.showInNavigation !== false) // Default to true if not specified
|
.filter(item => item.showInNavigation !== false) // Default to true if not specified
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
...item,
|
...item,
|
||||||
@ -235,14 +242,14 @@ export const getNavigationItemsForUser = (userType: 'guest' | 'candidate' | 'emp
|
|||||||
return filterItems(navigationConfig.items);
|
return filterItems(navigationConfig.items);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAllRoutes = (userType: 'guest' | 'candidate' | 'employer' | null): NavigationItem[] => {
|
export const getAllRoutes = (userType: 'guest' | 'candidate' | 'employer' | null, isAdmin: boolean = false): NavigationItem[] => {
|
||||||
const currentUserType = userType || 'guest';
|
const currentUserType = userType || 'guest';
|
||||||
|
|
||||||
const extractRoutes = (items: NavigationItem[]): NavigationItem[] => {
|
const extractRoutes = (items: NavigationItem[]): NavigationItem[] => {
|
||||||
const routes: NavigationItem[] = [];
|
const routes: NavigationItem[] = [];
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
if (!item.userTypes || item.userTypes.includes(currentUserType)) {
|
if (!item.userTypes || item.userTypes.includes(currentUserType) || (item.userTypes.includes('admin') && isAdmin)) {
|
||||||
if (item.path && item.component) {
|
if (item.path && item.component) {
|
||||||
routes.push(item);
|
routes.push(item);
|
||||||
}
|
}
|
||||||
@ -258,8 +265,8 @@ export const getAllRoutes = (userType: 'guest' | 'candidate' | 'employer' | null
|
|||||||
return extractRoutes(navigationConfig.items);
|
return extractRoutes(navigationConfig.items);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMainNavigationItems = (userType: 'guest' | 'candidate' | 'employer' | null): NavigationItem[] => {
|
export const getMainNavigationItems = (userType: 'guest' | 'candidate' | 'employer' | null, isAdmin: boolean = false): NavigationItem[] => {
|
||||||
return getNavigationItemsForUser(userType)
|
return getNavigationItemsForUser(userType, isAdmin)
|
||||||
.filter(item =>
|
.filter(item =>
|
||||||
item.id !== 'auth' &&
|
item.id !== 'auth' &&
|
||||||
item.id !== 'catch-all' &&
|
item.id !== 'catch-all' &&
|
||||||
|
@ -7,7 +7,7 @@ export interface NavigationItem {
|
|||||||
icon?: ReactElement;
|
icon?: ReactElement;
|
||||||
children?: NavigationItem[];
|
children?: NavigationItem[];
|
||||||
component?: ReactElement;
|
component?: ReactElement;
|
||||||
userTypes?: ('candidate' | 'employer' | 'guest')[];
|
userTypes?: ('candidate' | 'employer' | 'guest' | 'admin')[];
|
||||||
exact?: boolean;
|
exact?: boolean;
|
||||||
divider?: boolean;
|
divider?: boolean;
|
||||||
showInNavigation?: boolean; // Controls if item appears in main navigation
|
showInNavigation?: boolean; // Controls if item appears in main navigation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user