518 lines
21 KiB
TypeScript
518 lines
21 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
AppBar, Avatar, Box, Button, Chip, Container, Divider, Drawer,
|
|
IconButton, InputBase, List, ListItem, ListItemButton, ListItemIcon,
|
|
ListItemText, Paper, Tab, Tabs, TextField, Typography,
|
|
useMediaQuery, useTheme
|
|
} from '@mui/material';
|
|
import {
|
|
Menu as MenuIcon, Search as SearchIcon, Description as FileTextIcon,
|
|
Person as UserIcon, Settings as SettingsIcon, Add as PlusIcon,
|
|
Edit as EditIcon, Visibility as EyeIcon, Save as SaveIcon,
|
|
Delete as TrashIcon, AccessTime as ClockIcon, ChevronRight as ChevronRightIcon
|
|
} from '@mui/icons-material';
|
|
|
|
interface Resume {
|
|
id: number;
|
|
name: string;
|
|
date: string;
|
|
isRecent: boolean;
|
|
}
|
|
|
|
const MockupPage = () => {
|
|
const theme = useTheme();
|
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
const [activeTab, setActiveTab] = useState<string>("resume");
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState<boolean>(false);
|
|
const [selectedResume, setSelectedResume] = useState<number | null>(null);
|
|
|
|
// Mock data
|
|
const savedResumes: Resume[] = [
|
|
{ id: 1, name: "Software Engineer - Tech Co", date: "May 15, 2025", isRecent: true },
|
|
{ id: 2, name: "Product Manager - StartupX", date: "May 10, 2025", isRecent: false },
|
|
{ id: 3, name: "Data Scientist - AI Corp", date: "May 5, 2025", isRecent: false },
|
|
];
|
|
|
|
return (
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%', bgcolor: 'background.default' }}>
|
|
{/* Header */}
|
|
<AppBar position="static" color="default" elevation={1} sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', px: 2, py: 1 }}>
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
<Typography variant="h6" component="h1" fontWeight="bold" color="text.primary">Backstory</Typography>
|
|
{isMobile && (
|
|
<IconButton edge="start" color="inherit" onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}>
|
|
<MenuIcon />
|
|
</IconButton>
|
|
)}
|
|
</Box>
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
{!isMobile && (
|
|
<Button
|
|
startIcon={<PlusIcon />}
|
|
color="primary"
|
|
size="small"
|
|
>
|
|
New Resume
|
|
</Button>
|
|
)}
|
|
<IconButton sx={{ bgcolor: 'action.hover', borderRadius: '50%' }}>
|
|
<UserIcon />
|
|
</IconButton>
|
|
</Box>
|
|
</Box>
|
|
</AppBar>
|
|
|
|
<Box sx={{ display: 'flex', flex: 1, overflow: 'hidden' }}>
|
|
{/* Sidebar - hidden on mobile */}
|
|
{!isMobile && (
|
|
<Drawer
|
|
variant="permanent"
|
|
sx={{
|
|
width: 240,
|
|
flexShrink: 0,
|
|
[`& .MuiDrawer-paper`]: { width: 240, boxSizing: 'border-box', position: 'relative' },
|
|
}}
|
|
>
|
|
<Box sx={{ p: 2, display: 'flex', flexDirection: 'column', height: '100%' }}>
|
|
<Box sx={{ mb: 3 }}>
|
|
<Typography variant="overline" color="text.secondary" gutterBottom>Main</Typography>
|
|
<List disablePadding>
|
|
<ListItem disablePadding>
|
|
<ListItemButton sx={{ borderRadius: 1 }}>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<SearchIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Q&A" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
<ListItem disablePadding>
|
|
<ListItemButton
|
|
sx={{ borderRadius: 1, bgcolor: 'primary.lighter', color: 'primary.main' }}
|
|
>
|
|
<ListItemIcon sx={{ minWidth: 36, color: 'primary.main' }}>
|
|
<FileTextIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Resume Builder" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
</List>
|
|
</Box>
|
|
|
|
<Box sx={{ mb: 3 }}>
|
|
<Typography variant="overline" color="text.secondary" gutterBottom>My Content</Typography>
|
|
<List disablePadding>
|
|
<ListItem disablePadding>
|
|
<ListItemButton sx={{ borderRadius: 1 }}>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<FileTextIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="My Resumes" />
|
|
<Chip
|
|
label={savedResumes.length}
|
|
size="small"
|
|
sx={{ height: 20, fontSize: 12 }}
|
|
/>
|
|
</ListItemButton>
|
|
</ListItem>
|
|
<ListItem disablePadding>
|
|
<ListItemButton sx={{ borderRadius: 1 }}>
|
|
<ListItemIcon sx={{ minWidth: 36 }}>
|
|
<SettingsIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Settings" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
</List>
|
|
</Box>
|
|
|
|
<Box sx={{ mt: 'auto' }}>
|
|
<Paper variant="outlined" sx={{ p: 2, bgcolor: 'background.default' }}>
|
|
<Typography variant="subtitle2" color="text.primary" gutterBottom>Recent Activity</Typography>
|
|
<List dense disablePadding>
|
|
{savedResumes.filter(r => r.isRecent).map(resume => (
|
|
<ListItem key={resume.id} disablePadding sx={{ mb: 0.5 }}>
|
|
<ListItemIcon sx={{ minWidth: 24 }}>
|
|
<ClockIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<Typography variant="body2" noWrap>{resume.name}</Typography>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</Paper>
|
|
</Box>
|
|
</Box>
|
|
</Drawer>
|
|
)}
|
|
|
|
{/* Mobile menu - drawer */}
|
|
<Drawer
|
|
anchor="left"
|
|
open={isMobileMenuOpen}
|
|
onClose={() => setIsMobileMenuOpen(false)}
|
|
sx={{
|
|
display: { xs: 'block', md: 'none' },
|
|
'& .MuiDrawer-paper': { width: 240 }
|
|
}}
|
|
>
|
|
<Box sx={{ p: 2, display: 'flex', flexDirection: 'column', height: '100%' }}>
|
|
<Box sx={{ mb: 3 }}>
|
|
<Typography variant="overline" color="text.secondary" gutterBottom>Main</Typography>
|
|
<List disablePadding>
|
|
<ListItem disablePadding>
|
|
<ListItemButton onClick={() => setIsMobileMenuOpen(false)}>
|
|
<ListItemIcon>
|
|
<SearchIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Q&A" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
<ListItem disablePadding>
|
|
<ListItemButton
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
sx={{ bgcolor: 'primary.lighter', color: 'primary.main' }}
|
|
>
|
|
<ListItemIcon sx={{ color: 'primary.main' }}>
|
|
<FileTextIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Resume Builder" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
</List>
|
|
</Box>
|
|
|
|
<Box sx={{ mb: 3 }}>
|
|
<Typography variant="overline" color="text.secondary" gutterBottom>My Content</Typography>
|
|
<List disablePadding>
|
|
<ListItem disablePadding>
|
|
<ListItemButton onClick={() => setIsMobileMenuOpen(false)}>
|
|
<ListItemIcon>
|
|
<FileTextIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="My Resumes" />
|
|
<Chip
|
|
label={savedResumes.length}
|
|
size="small"
|
|
sx={{ height: 20, fontSize: 12 }}
|
|
/>
|
|
</ListItemButton>
|
|
</ListItem>
|
|
<ListItem disablePadding>
|
|
<ListItemButton onClick={() => setIsMobileMenuOpen(false)}>
|
|
<ListItemIcon>
|
|
<SettingsIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText primary="Settings" />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
</List>
|
|
</Box>
|
|
</Box>
|
|
</Drawer>
|
|
|
|
{/* Main content */}
|
|
<Box sx={{ flex: 1, overflow: 'auto', p: 3 }}>
|
|
{/* Resume Builder content */}
|
|
<Box sx={{ mb: 4 }}>
|
|
<Typography variant="h5" component="h2" fontWeight="bold" gutterBottom>Resume Builder</Typography>
|
|
<Typography variant="body2" color="text.secondary">Generate and customize resumes based on job descriptions</Typography>
|
|
</Box>
|
|
|
|
{/* Tabs */}
|
|
<Box sx={{ borderBottom: 1, borderColor: 'divider', mb: 3 }}>
|
|
<Tabs
|
|
value={activeTab}
|
|
onChange={(_, newValue) => setActiveTab(newValue)}
|
|
aria-label="Resume builder tabs"
|
|
variant={isMobile ? "scrollable" : "standard"}
|
|
scrollButtons={isMobile ? "auto" : undefined}
|
|
>
|
|
<Tab label="Job Description" value="job" />
|
|
<Tab label="Resume" value="resume" />
|
|
<Tab label="Fact Check" value="fact" />
|
|
<Tab label="Saved Resumes" value="saved" />
|
|
</Tabs>
|
|
</Box>
|
|
|
|
{/* Tab content */}
|
|
{activeTab === 'job' && (
|
|
<Paper variant="outlined" sx={{ p: 3 }}>
|
|
<Typography variant="h6" gutterBottom>Job Description</Typography>
|
|
<TextField
|
|
fullWidth
|
|
multiline
|
|
rows={10}
|
|
placeholder="Paste the job description here..."
|
|
variant="outlined"
|
|
/>
|
|
<Box sx={{ mt: 3 }}>
|
|
<Button variant="contained" color="primary">
|
|
Generate Resume
|
|
</Button>
|
|
</Box>
|
|
</Paper>
|
|
)}
|
|
|
|
{activeTab === 'resume' && (
|
|
<Paper variant="outlined" sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
|
<Typography variant="h6">Resume Editor</Typography>
|
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
|
<Button
|
|
variant="outlined"
|
|
size="small"
|
|
startIcon={<SaveIcon />}
|
|
>
|
|
Save
|
|
</Button>
|
|
<Button
|
|
variant="outlined"
|
|
size="small"
|
|
startIcon={<EyeIcon />}
|
|
>
|
|
Preview
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Resume content editor with sections */}
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
{/* Contact information */}
|
|
<Paper variant="outlined" sx={{ p: 2 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography variant="subtitle1" fontWeight="medium">Contact Information</Typography>
|
|
<IconButton size="small" color="default">
|
|
<EditIcon fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
<Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' }, gap: 2 }}>
|
|
<Box>
|
|
<Typography variant="caption" color="text.secondary" display="block" gutterBottom>
|
|
Full Name
|
|
</Typography>
|
|
<TextField size="small" fullWidth defaultValue="John Doe" />
|
|
</Box>
|
|
<Box>
|
|
<Typography variant="caption" color="text.secondary" display="block" gutterBottom>
|
|
Email
|
|
</Typography>
|
|
<TextField size="small" fullWidth defaultValue="john@example.com" />
|
|
</Box>
|
|
</Box>
|
|
</Paper>
|
|
|
|
{/* Professional Summary */}
|
|
<Paper variant="outlined" sx={{ p: 2 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography variant="subtitle1" fontWeight="medium">Professional Summary</Typography>
|
|
<IconButton size="small" color="default">
|
|
<EditIcon fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
<TextField
|
|
fullWidth
|
|
multiline
|
|
rows={3}
|
|
size="small"
|
|
defaultValue="Experienced software developer with 8+ years in full-stack development, specializing in React, Node.js, and cloud infrastructure. Passionate about creating scalable, maintainable applications."
|
|
/>
|
|
</Paper>
|
|
|
|
{/* Work Experience */}
|
|
<Paper variant="outlined" sx={{ p: 2 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography variant="subtitle1" fontWeight="medium">Work Experience</Typography>
|
|
<Button
|
|
startIcon={<PlusIcon />}
|
|
color="primary"
|
|
size="small"
|
|
>
|
|
Add Position
|
|
</Button>
|
|
</Box>
|
|
|
|
{/* Job entry */}
|
|
<Paper variant="outlined" sx={{ p: 2, mb: 2, bgcolor: 'background.default' }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
<Typography variant="subtitle2" fontWeight="medium">Senior Developer</Typography>
|
|
<Box sx={{ display: 'flex', gap: 0.5 }}>
|
|
<IconButton size="small">
|
|
<EditIcon fontSize="small" />
|
|
</IconButton>
|
|
<IconButton size="small" color="error">
|
|
<TrashIcon fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
</Box>
|
|
<Typography variant="body2" color="text.secondary">Tech Company Inc. • 2020-Present</Typography>
|
|
<Box component="ul" sx={{ pl: 2, mt: 1 }}>
|
|
<Typography component="li" variant="body2">Led development of company's flagship product</Typography>
|
|
<Typography component="li" variant="body2">Improved performance by 40% through code optimization</Typography>
|
|
</Box>
|
|
</Paper>
|
|
</Paper>
|
|
|
|
{/* Add more sections button */}
|
|
<Button
|
|
variant="outlined"
|
|
fullWidth
|
|
sx={{
|
|
borderStyle: 'dashed',
|
|
p: 1.5,
|
|
color: 'text.secondary',
|
|
'&:hover': { bgcolor: 'background.default' }
|
|
}}
|
|
startIcon={<PlusIcon />}
|
|
>
|
|
Add Section
|
|
</Button>
|
|
</Box>
|
|
</Paper>
|
|
)} {activeTab === 'saved' && (
|
|
<Paper variant="outlined" sx={{ p: 3 }}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
|
<Typography variant="h6">Saved Resumes</Typography>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
size="small"
|
|
startIcon={<PlusIcon />}
|
|
>
|
|
New Resume
|
|
</Button>
|
|
</Box>
|
|
|
|
{/* Resume list */}
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
{savedResumes.map(resume => (
|
|
<Paper
|
|
key={resume.id}
|
|
variant="outlined"
|
|
sx={{
|
|
p: 2,
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
cursor: 'pointer',
|
|
bgcolor: selectedResume === resume.id ? 'primary.lighter' : 'background.paper',
|
|
borderColor: selectedResume === resume.id ? 'primary.light' : 'divider',
|
|
'&:hover': { bgcolor: selectedResume === resume.id ? 'primary.lighter' : 'action.hover' }
|
|
}}
|
|
onClick={() => setSelectedResume(resume.id)}
|
|
>
|
|
<Box>
|
|
<Typography variant="subtitle2">{resume.name}</Typography>
|
|
<Typography variant="caption" color="text.secondary">Last edited: {resume.date}</Typography>
|
|
</Box>
|
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
|
<IconButton size="small">
|
|
<EditIcon fontSize="small" />
|
|
</IconButton>
|
|
<IconButton size="small" color="error">
|
|
<TrashIcon fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
</Paper>
|
|
))}
|
|
</Box>
|
|
</Paper>
|
|
)}
|
|
|
|
{activeTab === 'fact' && (
|
|
<Paper variant="outlined" sx={{ p: 3 }}>
|
|
<Typography variant="h6" gutterBottom>Fact Check</Typography>
|
|
<Typography variant="body2" color="text.secondary" paragraph>
|
|
This tab shows how your resume content compares to your employment history data.
|
|
</Typography>
|
|
|
|
<Box sx={{ mt: 2 }}>
|
|
<Paper variant="outlined" sx={{ p: 2, mb: 2, bgcolor: 'success.lighter' }}>
|
|
<Typography variant="subtitle2" fontWeight="medium" color="success.dark">
|
|
✓ Work History Verification
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
All employment dates match your documented history.
|
|
</Typography>
|
|
</Paper>
|
|
|
|
<Paper variant="outlined" sx={{ p: 2, mb: 2, bgcolor: 'warning.lighter' }}>
|
|
<Typography variant="subtitle2" fontWeight="medium" color="warning.dark">
|
|
⚠ Skills Verification
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
Some skills listed (React Native, Flutter) are not strongly supported by your experience documents.
|
|
</Typography>
|
|
</Paper>
|
|
</Box>
|
|
</Paper>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Mobile bottom navigation */}
|
|
{isMobile && (
|
|
<Paper
|
|
sx={{
|
|
position: 'fixed',
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
display: 'flex',
|
|
justifyContent: 'space-around',
|
|
borderTop: 1,
|
|
borderColor: 'divider',
|
|
zIndex: 1100
|
|
}}
|
|
elevation={3}
|
|
>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
py: 1,
|
|
px: 2,
|
|
color: 'text.secondary'
|
|
}}
|
|
component="button"
|
|
>
|
|
<SearchIcon />
|
|
<Typography variant="caption">Q&A</Typography>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
py: 1,
|
|
px: 2,
|
|
color: 'primary.main'
|
|
}}
|
|
component="button"
|
|
>
|
|
<FileTextIcon />
|
|
<Typography variant="caption">Resume</Typography>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
py: 1,
|
|
px: 2,
|
|
color: 'text.secondary'
|
|
}}
|
|
component="button"
|
|
>
|
|
<UserIcon />
|
|
<Typography variant="caption">Profile</Typography>
|
|
</Box>
|
|
</Paper>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
export {
|
|
MockupPage
|
|
}; |