388 lines
11 KiB
TypeScript
388 lines
11 KiB
TypeScript
import React, { JSX } from 'react';
|
|
import {
|
|
Chat as ChatIcon,
|
|
Dashboard as DashboardIcon,
|
|
Settings as SettingsIcon,
|
|
Work as WorkIcon,
|
|
Person as PersonIcon,
|
|
BubbleChart,
|
|
AutoFixHigh,
|
|
} from '@mui/icons-material';
|
|
import EditDocumentIcon from '@mui/icons-material/EditDocument';
|
|
|
|
import { BackstoryLogo } from 'components/ui/BackstoryLogo';
|
|
import { CandidateChatPage } from 'pages/CandidateChatPage';
|
|
import { BetaPage } from 'pages/BetaPage';
|
|
import { JobAnalysisPage } from 'pages/JobAnalysisPage';
|
|
import { GenerateCandidate } from 'pages/GenerateCandidate';
|
|
import { LoginPage } from 'pages/LoginPage';
|
|
import { EmailVerificationPage } from 'components/EmailVerificationComponents';
|
|
import { Box, Typography } from '@mui/material';
|
|
import { CandidateDashboard } from 'pages/candidate/Dashboard';
|
|
import { NavigationConfig, NavigationItem } from 'types/navigation';
|
|
import { HowItWorks } from 'pages/HowItWorks';
|
|
import { CandidateProfile } from 'pages/candidate/Profile';
|
|
import { Settings } from 'pages/candidate/Settings';
|
|
import { VectorVisualizer } from 'components/VectorVisualizer';
|
|
import { DocumentManager } from 'components/DocumentManager';
|
|
import { useAuth } from 'hooks/AuthContext';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { JobsViewPage } from 'pages/JobsViewPage';
|
|
import { ResumeViewer } from 'components/ui/ResumeViewer';
|
|
|
|
const LogoutPage = (): JSX.Element => {
|
|
const { logout } = useAuth();
|
|
const navigate = useNavigate();
|
|
logout().then(() => {
|
|
navigate('/');
|
|
});
|
|
return <Typography variant="h4">Logging out...</Typography>;
|
|
};
|
|
|
|
export const navigationConfig: NavigationConfig = {
|
|
items: [
|
|
{
|
|
id: 'home',
|
|
label: <BackstoryLogo />,
|
|
path: '/',
|
|
component: <HowItWorks />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
exact: true,
|
|
},
|
|
{
|
|
id: 'job-analysis',
|
|
label: 'Job Analysis',
|
|
path: '/job-analysis/:candidateId?/:jobId?/:stepId?',
|
|
variant: 'fullWidth',
|
|
icon: <WorkIcon />,
|
|
component: <JobAnalysisPage />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
},
|
|
{
|
|
id: 'chat',
|
|
label: 'Candidate Chat',
|
|
path: '/chat',
|
|
icon: <ChatIcon />,
|
|
component: <CandidateChatPage />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
},
|
|
// {
|
|
// id: "explore",
|
|
// label: "Explore",
|
|
// icon: <SearchIcon />,
|
|
// userTypes: ["candidate", "guest", "employer"],
|
|
// children: [
|
|
// {
|
|
// id: "explore-candidates",
|
|
// label: "Candidates",
|
|
// path: "/candidate/candidates",
|
|
// icon: <SearchIcon />,
|
|
// component: (
|
|
// <CandidatePicker />
|
|
// ),
|
|
// userTypes: ["candidate", "guest", "employer"],
|
|
// },
|
|
// ],
|
|
// showInNavigation: true,
|
|
// },
|
|
|
|
{
|
|
id: 'generate-candidate',
|
|
label: 'Generate Candidate',
|
|
path: '/admin/generate-candidate',
|
|
icon: <AutoFixHigh />,
|
|
component: <GenerateCandidate />,
|
|
userTypes: ['admin'],
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
userMenuGroup: 'admin',
|
|
},
|
|
// User menu only items (not shown in main navigation)
|
|
{
|
|
id: 'candidate-profile',
|
|
label: 'Profile',
|
|
icon: <PersonIcon />,
|
|
path: '/candidate/profile',
|
|
component: <CandidateProfile />,
|
|
userTypes: ['candidate'],
|
|
userMenuGroup: 'profile',
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
},
|
|
{
|
|
id: 'candidate-dashboard',
|
|
label: 'Dashboard',
|
|
path: '/candidate/dashboard',
|
|
icon: <DashboardIcon />,
|
|
component: <CandidateDashboard />,
|
|
userTypes: ['candidate'],
|
|
userMenuGroup: 'profile',
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
},
|
|
{
|
|
id: 'explore-jobs',
|
|
label: 'Jobs',
|
|
path: '/candidate/jobs/:jobId?',
|
|
icon: <WorkIcon />,
|
|
component: <JobsViewPage />,
|
|
variant: 'fullWidth',
|
|
userTypes: ['candidate', 'guest', 'employer'],
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
userMenuGroup: 'profile',
|
|
},
|
|
{
|
|
id: 'explore-resumes',
|
|
label: 'Resumes',
|
|
path: '/candidate/resumes/:resumeId?',
|
|
icon: <EditDocumentIcon />,
|
|
component: <ResumeViewer />,
|
|
variant: 'fullWidth',
|
|
userTypes: ['candidate', 'guest', 'employer'],
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
userMenuGroup: 'profile',
|
|
},
|
|
{
|
|
id: 'candidate-docs',
|
|
label: 'Content',
|
|
icon: <BubbleChart />,
|
|
path: '/candidate/documents',
|
|
component: (
|
|
<Box sx={{ display: 'flex', width: '100%', flexDirection: 'column' }}>
|
|
<VectorVisualizer />
|
|
<DocumentManager />
|
|
</Box>
|
|
),
|
|
userTypes: ['candidate'],
|
|
userMenuGroup: 'profile',
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
},
|
|
// {
|
|
// id: "candidate-qa-setup",
|
|
// label: "Q&A Setup",
|
|
// icon: <QuizIcon />,
|
|
// path: "/candidate/qa-setup",
|
|
// component: (
|
|
// <BetaPage>
|
|
// <Box>Candidate q&a setup page</Box>
|
|
// </BetaPage>
|
|
// ),
|
|
// userTypes: ["candidate"],
|
|
// showInNavigation: false,
|
|
// showInUserMenu: true,
|
|
// },
|
|
// {
|
|
// id: "candidate-analytics",
|
|
// label: "Analytics",
|
|
// icon: <AnalyticsIcon />,
|
|
// path: "/candidate/analytics",
|
|
// component: (
|
|
// <BetaPage>
|
|
// <Box>Candidate analytics page</Box>
|
|
// </BetaPage>
|
|
// ),
|
|
// userTypes: ["candidate"],
|
|
// showInNavigation: false,
|
|
// showInUserMenu: true,
|
|
// },
|
|
// {
|
|
// id: "candidate-resumes",
|
|
// label: "Resumes",
|
|
// icon: <DescriptionIcon />,
|
|
// path: "/candidate/resumes",
|
|
// component: (
|
|
// <BetaPage>
|
|
// <Box>Candidate resumes page</Box>
|
|
// </BetaPage>
|
|
// ),
|
|
// userTypes: ["candidate"],
|
|
// showInNavigation: false,
|
|
// showInUserMenu: true,
|
|
// },
|
|
{
|
|
id: 'candidate-settings',
|
|
label: 'System Information',
|
|
path: '/candidate/settings',
|
|
icon: <SettingsIcon />,
|
|
component: <Settings />,
|
|
userTypes: ['candidate'],
|
|
userMenuGroup: 'account',
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
},
|
|
{
|
|
id: 'logout',
|
|
label: 'Logout',
|
|
icon: <PersonIcon />, // This will be handled specially in Header
|
|
userTypes: ['candidate', 'employer'],
|
|
showInNavigation: false,
|
|
showInUserMenu: true,
|
|
userMenuGroup: 'system',
|
|
},
|
|
// Auth routes (special handling)
|
|
{
|
|
id: 'auth',
|
|
label: 'Auth',
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
showInNavigation: false,
|
|
children: [
|
|
{
|
|
id: 'verify-email',
|
|
label: 'Verify Email',
|
|
path: '/login/verify-email',
|
|
component: <EmailVerificationPage />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
showInNavigation: false,
|
|
},
|
|
{
|
|
id: 'login',
|
|
label: 'Login',
|
|
path: '/login/:tab?',
|
|
component: <LoginPage />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
showInNavigation: false,
|
|
},
|
|
{
|
|
id: 'logout-page',
|
|
label: 'Logout',
|
|
path: '/logout',
|
|
component: <LogoutPage />,
|
|
userTypes: ['candidate', 'employer'],
|
|
showInNavigation: false,
|
|
},
|
|
],
|
|
},
|
|
// Catch-all route
|
|
{
|
|
id: 'catch-all',
|
|
label: 'Not Found',
|
|
path: '*',
|
|
component: <BetaPage />,
|
|
userTypes: ['guest', 'candidate', 'employer'],
|
|
showInNavigation: false,
|
|
},
|
|
],
|
|
};
|
|
|
|
// Utility functions for working with navigation config
|
|
export const getNavigationItemsForUser = (
|
|
userType: 'guest' | 'candidate' | 'employer' | null,
|
|
isAdmin: boolean
|
|
): NavigationItem[] => {
|
|
const currentUserType = userType || 'guest';
|
|
|
|
const filterItems = (items: NavigationItem[]): NavigationItem[] => {
|
|
return items
|
|
.filter(
|
|
item =>
|
|
!item.userTypes ||
|
|
item.userTypes.includes(currentUserType) ||
|
|
(item.userTypes.includes('admin') && isAdmin)
|
|
)
|
|
.filter(item => item.showInNavigation !== false) // Default to true if not specified
|
|
.map(item => ({
|
|
...item,
|
|
children: item.children ? filterItems(item.children) : undefined,
|
|
}))
|
|
.filter(item => item.path || (item.children && item.children.length > 0));
|
|
};
|
|
|
|
return filterItems(navigationConfig.items);
|
|
};
|
|
|
|
export const getAllRoutes = (
|
|
userType: 'guest' | 'candidate' | 'employer' | null,
|
|
isAdmin: boolean
|
|
): NavigationItem[] => {
|
|
const currentUserType = userType || 'guest';
|
|
|
|
const extractRoutes = (items: NavigationItem[]): NavigationItem[] => {
|
|
const routes: NavigationItem[] = [];
|
|
|
|
items.forEach(item => {
|
|
if (
|
|
!item.userTypes ||
|
|
item.userTypes.includes(currentUserType) ||
|
|
(item.userTypes.includes('admin') && isAdmin)
|
|
) {
|
|
if (item.path && item.component) {
|
|
routes.push(item);
|
|
}
|
|
if (item.children) {
|
|
routes.push(...extractRoutes(item.children));
|
|
}
|
|
}
|
|
});
|
|
|
|
return routes;
|
|
};
|
|
|
|
return extractRoutes(navigationConfig.items);
|
|
};
|
|
|
|
export const getMainNavigationItems = (
|
|
userType: 'guest' | 'candidate' | 'employer' | null,
|
|
isAdmin: boolean
|
|
): NavigationItem[] => {
|
|
return getNavigationItemsForUser(userType, isAdmin).filter(
|
|
item =>
|
|
item.id !== 'auth' &&
|
|
item.id !== 'catch-all' &&
|
|
item.showInNavigation !== false &&
|
|
(item.path || (item.children && item.children.length > 0))
|
|
);
|
|
};
|
|
|
|
export const getUserMenuItems = (
|
|
userType: 'candidate' | 'employer' | 'guest' | null,
|
|
isAdmin: boolean
|
|
): NavigationItem[] => {
|
|
if (!userType) return [];
|
|
|
|
const extractUserMenuItems = (items: NavigationItem[]): NavigationItem[] => {
|
|
const menuItems: NavigationItem[] = [];
|
|
|
|
items.forEach(item => {
|
|
if (!item.userTypes || item.userTypes.includes(userType) || isAdmin) {
|
|
if (item.showInUserMenu) {
|
|
menuItems.push(item);
|
|
}
|
|
if (item.children) {
|
|
menuItems.push(...extractUserMenuItems(item.children));
|
|
}
|
|
}
|
|
});
|
|
|
|
return menuItems;
|
|
};
|
|
|
|
return extractUserMenuItems(navigationConfig.items);
|
|
};
|
|
|
|
export const getUserMenuItemsByGroup = (
|
|
userType: 'candidate' | 'employer' | 'guest' | null,
|
|
isAdmin: boolean
|
|
): { [key: string]: NavigationItem[] } => {
|
|
const menuItems = getUserMenuItems(userType, isAdmin);
|
|
const grouped: { [key: string]: NavigationItem[] } = {
|
|
profile: [],
|
|
account: [],
|
|
system: [],
|
|
admin: [],
|
|
other: [],
|
|
};
|
|
|
|
menuItems.forEach(item => {
|
|
const group = item.userMenuGroup || 'other';
|
|
if (!grouped[group]) {
|
|
grouped[group] = [];
|
|
}
|
|
grouped[group].push(item);
|
|
});
|
|
|
|
return grouped;
|
|
};
|