backstory/frontend/src/NewApp/BackstoryApp.tsx

250 lines
10 KiB
TypeScript

import React, { ReactElement, useEffect, useState, useRef, useCallback} from 'react';
import { Box, Typography, Container, Paper } from '@mui/material';
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import DashboardIcon from '@mui/icons-material/Dashboard';
import PersonIcon from '@mui/icons-material/Person';
import ChatIcon from '@mui/icons-material/Chat';
import HistoryIcon from '@mui/icons-material/History';
import DescriptionIcon from '@mui/icons-material/Description';
import QuestionAnswerIcon from '@mui/icons-material/QuestionAnswer';
import BarChartIcon from '@mui/icons-material/BarChart';
import SettingsIcon from '@mui/icons-material/Settings';
import SearchIcon from '@mui/icons-material/Search';
import BookmarkIcon from '@mui/icons-material/Bookmark';
import WorkIcon from '@mui/icons-material/Work';
import InfoIcon from '@mui/icons-material/Info';
import BusinessIcon from '@mui/icons-material/Business';
import { SxProps, Theme } from '@mui/material';
import { ThemeProvider } from '@mui/material/styles';
import {Header} from './Components/Header';
import { Scrollable } from '../Components/Scrollable';
import { Footer } from './Components/Footer';
import { HomePage } from './Pages/HomePage';
// import { BackstoryThemeVisualizer } from './BackstoryThemeVisualizer';
import { HomePage as ChatPage } from '../Pages/HomePage';
import { ResumeBuilderPage } from '../Pages/ResumeBuilderPage';
import { Snack, SeverityType } from '../Components/Snack';
import { Query } from '../Components/ChatQuery';
import { ConversationHandle } from '../Components/Conversation';
import { AboutPage } from './Pages/AboutPage';
import { backstoryTheme } from '../BackstoryTheme';
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import { VectorVisualizerPage } from 'Pages/VectorVisualizerPage';
type NavigationLinkType = {
name: string;
path: string;
icon?: ReactElement<any>;
label?: ReactElement<any>;
};
const DefaultNavItems : NavigationLinkType[] = [
{ name: 'Chat', path: '/chat', icon: <ChatIcon /> },
{ name: 'Resume Builder', path: '/resume-builder', icon: <WorkIcon /> },
{ name: 'RAG Visualizer', path: '/rag-visualizer', icon: <WorkIcon /> },
{ name: 'About', path: '/about', icon: <InfoIcon /> },
// { name: 'How It Works', path: '/how-it-works', icon: <InfoIcon/> },
// { name: 'For Candidates', path: '/for-candidates', icon: <PersonIcon/> },
// { name: 'For Employers', path: '/for-employers', icon: <BusinessIcon/> },
// { name: 'Pricing', path: '/pricing', icon: <AttachMoneyIcon/> },
];
const CandidateNavItems : NavigationLinkType[]= [
{ name: 'Dashboard', icon: <DashboardIcon />, path: '/dashboard' },
{ name: 'Profile', icon: <PersonIcon />, path: '/profile' },
{ name: 'Backstory', icon: <HistoryIcon />, path: '/backstory' },
{ name: 'Resumes', icon: <DescriptionIcon />, path: '/resumes' },
{ name: 'Q&A Setup', icon: <QuestionAnswerIcon />, path: '/qa-setup' },
{ name: 'Analytics', icon: <BarChartIcon />, path: '/analytics' },
{ name: 'Settings', icon: <SettingsIcon />, path: '/settings' },
];
const EmployerNavItems: NavigationLinkType[] = [
{ name: 'Dashboard', icon: <DashboardIcon />, path: '/dashboard' },
{ name: 'Search', icon: <SearchIcon />, path: '/search' },
{ name: 'Saved', icon: <BookmarkIcon />, path: '/saved' },
{ name: 'Jobs', icon: <WorkIcon />, path: '/jobs' },
{ name: 'Company', icon: <BusinessIcon />, path: '/company' },
{ name: 'Analytics', icon: <BarChartIcon />, path: '/analytics' },
{ name: 'Settings', icon: <SettingsIcon />, path: '/settings' },
];
// Navigation links based on user type
const getNavigationLinks = (userType: string, isLoggedIn: boolean) : NavigationLinkType[] => {
if (!isLoggedIn) {
return DefaultNavItems;
}
if (userType === 'candidate') {
return CandidateNavItems;
}
// Employer navigation
return EmployerNavItems;
};
// Placeholder for page components
const DashboardPage = () => <Box p={3}><Typography variant="h4">Dashboard</Typography></Box>;
const ProfilePage = () => <Box p={3}><Typography variant="h4">Profile</Typography></Box>;
const BackstoryPage = () => <Box p={3}><Typography variant="h4">Backstory</Typography></Box>;
const ResumesPage = () => <Box p={3}><Typography variant="h4">Resumes</Typography></Box>;
const QASetupPage = () => <Box p={3}><Typography variant="h4">Q&A Setup</Typography></Box>;
const AnalyticsPage = () => <Box p={3}><Typography variant="h4">Analytics</Typography></Box>;
const SettingsPage = () => <Box p={3}><Typography variant="h4">Settings</Typography></Box>;
const SearchPage = () => <Box p={3}><Typography variant="h4">Search</Typography></Box>;
const SavedPage = () => <Box p={3}><Typography variant="h4">Saved</Typography></Box>;
const JobsPage = () => <Box p={3}><Typography variant="h4">Jobs</Typography></Box>;
const CompanyPage = () => <Box p={3}><Typography variant="h4">Company</Typography></Box>;
// This is a placeholder for your actual user context
type UserContext = {
user: {
type: string;
name: string;
avatar?: any;
};
isAuthenticated: boolean;
logout: () => void;
};
const useUserContext = () : UserContext => {
return {
user: {
type: 'candidate', // or 'employer'
name: 'John Doe',
avatar: null,
},
isAuthenticated: false,
logout: () => console.log('Logging out'),
};
};
interface BackstoryPageContainerProps {
children?: React.ReactNode;
sx?: SxProps<Theme>;
userContext: UserContext;
};
const BackstoryPageContainer = (props : BackstoryPageContainerProps) => {
const { children, sx } = props;
return (
<Container maxWidth="xl" sx={{ mt: 2, mb: 2, height: "calc(1024px - 72px)", ...sx }}>
<Paper
elevation={2}
sx={{
p: 3,
backgroundColor: 'background.paper',
borderRadius: 2,
minHeight: '80vh',
}}
>
<Scrollable>
{children}
</Scrollable>
</Paper>
</Container>
);
}
const BackstoryApp = () => {
const navigate = useNavigate();
const location = useLocation();
const userContext : UserContext = useUserContext();
const { user, isAuthenticated } = userContext;
const [navigationLinks, setNavigationLinks] = useState<NavigationLinkType[]>([]);
const snackRef = useRef<any>(null);
const chatRef = useRef<ConversationHandle>(null);
const setSnack = useCallback((message: string, severity?: SeverityType) => {
snackRef.current?.setSnack(message, severity);
}, [snackRef]);
const submitQuery = (query: Query) => {
console.log(`handleSubmitChatQuery:`, query, chatRef.current ? ' sending' : 'no handler');
chatRef.current?.submitQuery(query);
navigate('/chat');
};
const [page, setPage] = useState<string>("");
useEffect(() => {
const currentRoute = location.pathname.split("/")[1] ? `/${location.pathname.split("/")[1]}` : "/";
setPage(currentRoute);
}, [location.pathname]);
useEffect(() => {
setNavigationLinks(getNavigationLinks(user.type, isAuthenticated));
}, [user.type, isAuthenticated]);
// Render appropriate routes based on user type
return (
<ThemeProvider theme={backstoryTheme}>
<Header currentPath={page} navigate={navigate} navigationLinks={navigationLinks} showLogin={false}/>
<Box sx={{ display: "flex", minHeight: "72px", height: "72px" }}/>
<Scrollable sx={{
display: 'flex',
flexDirection: 'column',
backgroundColor: 'background.default',
maxHeight: "calc(100vh - 72px)",
}}>
<BackstoryPageContainer userContext={userContext}>
<Routes>
<Route path="/chat" element={<ChatPage ref={chatRef} setSnack={setSnack} sessionId={"684a0c7e-e638-4db7-b00d-0558bfefb710"} submitQuery={submitQuery}/>} />
<Route path="/about" element={<AboutPage setSnack={setSnack} sessionId={"684a0c7e-e638-4db7-b00d-0558bfefb710"} submitQuery={submitQuery}/>} />
<Route path="/about/:subPage" element={<AboutPage setSnack={setSnack} sessionId={"684a0c7e-e638-4db7-b00d-0558bfefb710"} submitQuery={submitQuery}/>} />
<Route path="/resume-builder" element={<ResumeBuilderPage setSnack={setSnack} sessionId={"684a0c7e-e638-4db7-b00d-0558bfefb710"} submitQuery={submitQuery}/>} />
<Route path="/rag-visualizer" element={<VectorVisualizerPage setSnack={setSnack} sessionId={"684a0c7e-e638-4db7-b00d-0558bfefb710"} submitQuery={submitQuery} />} />
<Route path="/dashboard" element={<DashboardPage />} />
<Route path="/" element={<HomePage/>}/>
{/* Candidate-specific routes */}
{user.type === 'candidate' && (
<>
<Route path="/profile" element={<ProfilePage />} />
<Route path="/backstory" element={<BackstoryPage />} />
<Route path="/resumes" element={<ResumesPage />} />
<Route path="/qa-setup" element={<QASetupPage />} />
</>
)}
{/* Employer-specific routes */}
{user.type === 'employer' && (
<>
<Route path="/search" element={<SearchPage />} />
<Route path="/saved" element={<SavedPage />} />
<Route path="/jobs" element={<JobsPage />} />
<Route path="/company" element={<CompanyPage />} />
</>
)}
{/* Common routes */}
<Route path="/analytics" element={<AnalyticsPage />} />
<Route path="/settings" element={<SettingsPage />} />
{/* Redirect to dashboard by default */}
<Route path="*" element={<HomePage />} />
</Routes>
</BackstoryPageContainer>
{ location.pathname === "/" && <Footer /> }
</Scrollable>
<Snack ref={snackRef}/>
</ThemeProvider>
);
};
const App = () => {
return (
<BackstoryApp />
);
};
export type {
UserContext,
NavigationLinkType
};
export {
BackstoryApp
};