405 lines
11 KiB
TypeScript
405 lines
11 KiB
TypeScript
import React from "react";
|
|
import {
|
|
Chat as ChatIcon,
|
|
Dashboard as DashboardIcon,
|
|
Description as DescriptionIcon,
|
|
BarChart as BarChartIcon,
|
|
Settings as SettingsIcon,
|
|
Work as WorkIcon,
|
|
Info as InfoIcon,
|
|
Person as PersonIcon,
|
|
Business as BusinessIcon,
|
|
Search as SearchIcon,
|
|
Bookmark as BookmarkIcon,
|
|
History as HistoryIcon,
|
|
QuestionAnswer as QuestionAnswerIcon,
|
|
AttachMoney as AttachMoneyIcon,
|
|
Quiz as QuizIcon,
|
|
Analytics as AnalyticsIcon,
|
|
BubbleChart,
|
|
} from "@mui/icons-material";
|
|
|
|
import { BackstoryLogo } from "components/ui/BackstoryLogo";
|
|
import { HomePage } from "pages/HomePage";
|
|
import { CandidateChatPage } from "pages/CandidateChatPage";
|
|
import { DocsPage } from "pages/DocsPage";
|
|
import { CreateProfilePage } from "pages/candidate/ProfileWizard";
|
|
import { VectorVisualizerPage } from "pages/VectorVisualizerPage";
|
|
import { BetaPage } from "pages/BetaPage";
|
|
import { CandidateListingPage } from "pages/FindCandidatePage";
|
|
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 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";
|
|
import { useAuth } from "hooks/AuthContext";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
// Beta page components for placeholder routes
|
|
const BackstoryPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Backstory</Typography>
|
|
</BetaPage>
|
|
);
|
|
const ResumesPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Resumes</Typography>
|
|
</BetaPage>
|
|
);
|
|
const QASetupPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Q&A Setup</Typography>
|
|
</BetaPage>
|
|
);
|
|
const SearchPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Search</Typography>
|
|
</BetaPage>
|
|
);
|
|
const SavedPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Saved</Typography>
|
|
</BetaPage>
|
|
);
|
|
const JobsPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Jobs</Typography>
|
|
</BetaPage>
|
|
);
|
|
const CompanyPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Company</Typography>
|
|
</BetaPage>
|
|
);
|
|
|
|
const LogoutPage = () => {
|
|
const { logout } = useAuth();
|
|
const navigate = useNavigate();
|
|
logout().then(() => {
|
|
navigate("/");
|
|
});
|
|
return (
|
|
<Typography variant="h4">Logging out...</Typography>
|
|
);
|
|
}
|
|
const AnalyticsPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Analytics</Typography>
|
|
</BetaPage>
|
|
);
|
|
const SettingsPage = () => (
|
|
<BetaPage>
|
|
<Typography variant="h4">Settings</Typography>
|
|
</BetaPage>
|
|
);
|
|
|
|
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",
|
|
icon: <WorkIcon />,
|
|
component: <JobAnalysisPage />,
|
|
userTypes: ["guest", "candidate", "employer"],
|
|
},
|
|
{
|
|
id: "chat",
|
|
label: "Candidate Chat",
|
|
path: "/chat",
|
|
icon: <ChatIcon />,
|
|
component: <CandidateChatPage />,
|
|
userTypes: ["guest", "candidate", "employer"],
|
|
},
|
|
{
|
|
id: "generate-candidate",
|
|
label: "Generate Candidate",
|
|
path: "/admin/generate-candidate",
|
|
icon: <PersonIcon />,
|
|
component: <GenerateCandidate />,
|
|
userTypes: ["admin"],
|
|
showInNavigation: true,
|
|
userMenuGroup: "system",
|
|
},
|
|
// 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: "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: "Settings",
|
|
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: "register",
|
|
label: "Register",
|
|
path: "/login/register",
|
|
component: (
|
|
<BetaPage>
|
|
<CreateProfilePage />
|
|
</BetaPage>
|
|
),
|
|
userTypes: ["guest"],
|
|
showInNavigation: false,
|
|
},
|
|
{
|
|
id: "login",
|
|
label: "Login",
|
|
path: "/login/*",
|
|
component: <LoginPage />,
|
|
userTypes: ["guest", "candidate", "employer"],
|
|
showInNavigation: false,
|
|
},
|
|
{
|
|
id: "verify-email",
|
|
label: "Verify Email",
|
|
path: "/login/verify-email",
|
|
component: <EmailVerificationPage />,
|
|
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 = false
|
|
): 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 = false
|
|
): 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 = false
|
|
): 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): NavigationItem[] => {
|
|
if (!userType) return [];
|
|
|
|
const extractUserMenuItems = (items: NavigationItem[]): NavigationItem[] => {
|
|
const menuItems: NavigationItem[] = [];
|
|
|
|
items.forEach((item) => {
|
|
if (!item.userTypes || item.userTypes.includes(userType)) {
|
|
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
|
|
): { [key: string]: NavigationItem[] } => {
|
|
const menuItems = getUserMenuItems(userType);
|
|
const grouped: { [key: string]: NavigationItem[] } = {
|
|
profile: [],
|
|
account: [],
|
|
system: [],
|
|
other: [],
|
|
};
|
|
|
|
menuItems.forEach((item) => {
|
|
const group = item.userMenuGroup || "other";
|
|
if (!grouped[group]) {
|
|
grouped[group] = [];
|
|
}
|
|
grouped[group].push(item);
|
|
});
|
|
|
|
return grouped;
|
|
};
|