import React, { useEffect, useRef, useState } from 'react'; import { Box, Link, Typography, Avatar, Grid, SxProps, CardActions, Chip, Stack, CardHeader, Button, LinearProgress, IconButton, Tooltip, Card, CardContent, Divider, useTheme, useMediaQuery, TextField, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; import { Delete as DeleteIcon, Restore as RestoreIcon, Save as SaveIcon, Edit as EditIcon, Description as DescriptionIcon, Work as WorkIcon, Person as PersonIcon, Schedule as ScheduleIcon, Visibility as VisibilityIcon, VisibilityOff as VisibilityOffIcon } from '@mui/icons-material'; import { useAuth } from 'hooks/AuthContext'; import { useAppState } from 'hooks/GlobalContext'; import { StyledMarkdown } from 'components/StyledMarkdown'; import { Resume } from 'types/types'; interface ResumeInfoProps { resume: Resume; sx?: SxProps; action?: string; elevation?: number; variant?: "minimal" | "small" | "normal" | "all" | null; } const ResumeInfo: React.FC = (props: ResumeInfoProps) => { const { setSnack } = useAppState(); const { resume } = props; const { user, apiClient } = useAuth(); const { sx, action = '', elevation = 1, variant = "normal" } = props; const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')) || variant === "minimal"; const isAdmin = user?.isAdmin; const [activeResume, setActiveResume] = useState({ ...resume }); const [isContentExpanded, setIsContentExpanded] = useState(false); const [shouldShowMoreButton, setShouldShowMoreButton] = useState(false); const [deleted, setDeleted] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [editContent, setEditContent] = useState(''); const [saving, setSaving] = useState(false); const contentRef = useRef(null); useEffect(() => { if (resume && resume.id !== activeResume?.id) { setActiveResume(resume); } }, [resume, activeResume]); // Check if content needs truncation useEffect(() => { if (contentRef.current && resume.resume) { const element = contentRef.current; setShouldShowMoreButton(element.scrollHeight > element.clientHeight); } }, [resume.resume]); const deleteResume = async (resumeId: string | undefined) => { if (resumeId) { try { await apiClient.deleteResume(resumeId); setDeleted(true); setSnack('Resume deleted successfully.'); } catch (error) { setSnack('Failed to delete resume.'); } } }; const handleReset = async () => { setActiveResume({ ...resume }); }; const handleSave = async () => { setSaving(true); try { const result = await apiClient.updateResume(activeResume.id || '', editContent); const updatedResume = { ...activeResume, resume: editContent, updatedAt: new Date() }; setActiveResume(updatedResume); setEditDialogOpen(false); setSnack('Resume updated successfully.'); } catch (error) { setSnack('Failed to update resume.'); } finally { setSaving(false); } }; const handleEditOpen = () => { setEditContent(activeResume.resume); setEditDialogOpen(true); }; if (!resume) { return No resume provided.; } const formatDate = (date: Date | undefined) => { if (!date) return 'N/A'; return new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(date); }; return ( {/* Header Information */} {activeResume.candidate && ( Candidate )} {activeResume.candidate?.fullName || activeResume.candidateId} {activeResume.job && ( <> Job {activeResume.job.title} at {activeResume.job.company} )} Timeline Created: {formatDate(activeResume.createdAt)} Updated: {formatDate(activeResume.updatedAt)} Resume ID: {activeResume.resumeId} {/* Resume Content */} {activeResume.resume && ( } sx={{ p: 0, pb: 1 }} action={ isAdmin && ( ) } /> {activeResume.resume} {shouldShowMoreButton && variant !== "all" && ( )} )} {variant === 'all' && activeResume.resume && ( )} {/* Admin Controls */} {isAdmin && ( { e.stopPropagation(); handleEditOpen(); }} > { e.stopPropagation(); deleteResume(activeResume.id); }} > { e.stopPropagation(); handleReset(); }} > {saving && ( Saving resume... )} )} {/* Edit Dialog */} setEditDialogOpen(false)} maxWidth="lg" fullWidth fullScreen={isMobile} > Edit Resume Content Resume for {activeResume.candidate?.fullName || activeResume.candidateId} setEditContent(e.target.value)} variant="outlined" sx={{ mt: 1, '& .MuiInputBase-input': { fontFamily: 'monospace', fontSize: '0.875rem' } }} placeholder="Enter resume content..." /> ); }; export { ResumeInfo };