import React from 'react'; import { Box, Typography, SxProps, Theme } from '@mui/material'; import { Email as EmailIcon, Phone as PhoneIcon, LocationOn as LocationIcon, } from '@mui/icons-material'; import { parsePhoneNumberFromString } from 'libphonenumber-js'; import { StyledMarkdown } from 'components/StyledMarkdown'; import * as Types from 'types/types'; import './ResumePreview.css'; // Resume Style Definitions export interface ResumeStyle { name: string; description: string; headerStyle: SxProps; footerStyle: SxProps; contentStyle: SxProps; markdownStyle: SxProps; color: { primary: string; secondary: string; accent: string; text: string; background: string; }; } const generateResumeStyles = (): Record => { return { classic: { name: 'Classic', description: 'Traditional, professional serif design', headerStyle: { display: 'flex', flexDirection: 'row', fontFamily: '"Times New Roman", Times, serif', borderBottom: '2px solid #2c3e50', paddingBottom: 2, marginBottom: 3, } as SxProps, footerStyle: { fontFamily: '"Times New Roman", Times, serif', borderTop: '2px solid #2c3e50', paddingTop: 2, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textTransform: 'uppercase', alignContent: 'center', fontSize: '0.8rem', pb: 2, mb: 2, } as SxProps, contentStyle: { fontFamily: '"Times New Roman", Times, serif', lineHeight: 1.6, color: '#2c3e50', } as SxProps, markdownStyle: { fontFamily: '"Times New Roman", Times, serif', '& h1, & h2, & h3': { fontFamily: '"Times New Roman", Times, serif', color: '#2c3e50', borderBottom: '1px solid #bdc3c7', paddingBottom: 1, marginBottom: 2, }, '& p, & li': { lineHeight: 1.6, marginBottom: 1, }, '& ul': { paddingLeft: 3, }, } as SxProps, color: { primary: '#2c3e50', secondary: '#34495e', accent: '#3498db', text: '#2c3e50', background: '#ffffff', }, }, modern: { name: 'Modern', description: 'Clean, minimalist sans-serif layout', headerStyle: { display: 'flex', flexDirection: 'row', fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', borderLeft: '4px solid #3498db', paddingLeft: 2, marginBottom: 3, backgroundColor: '#f8f9fa', padding: 2, borderRadius: 1, } as SxProps, footerStyle: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', borderLeft: '4px solid #3498db', backgroundColor: '#f8f9fa', paddingTop: 2, borderRadius: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textTransform: 'uppercase', alignContent: 'center', fontSize: '0.8rem', pb: 2, mb: 2, } as SxProps, contentStyle: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', lineHeight: 1.5, color: '#2c3e50', } as SxProps, markdownStyle: { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', '& h1, & h2, & h3': { fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', color: '#3498db', fontWeight: 300, marginBottom: 1.5, }, '& h1': { fontSize: '1.75rem', }, '& h2': { fontSize: '1.5rem', }, '& h3': { fontSize: '1.25rem', }, '& p, & li': { lineHeight: 1.5, marginBottom: 0.75, }, '& ul': { paddingLeft: 2.5, }, } as SxProps, color: { primary: '#3498db', secondary: '#2c3e50', accent: '#e74c3c', text: '#2c3e50', background: '#ffffff', }, }, creative: { name: 'Creative', description: 'Colorful, unique design with personality', headerStyle: { display: 'flex', flexDirection: 'row', fontFamily: '"Montserrat", "Helvetica Neue", Arial, sans-serif', background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', color: '#ffffff', padding: 2.5, borderRadius: 1.5, marginBottom: 3, } as SxProps, footerStyle: { fontFamily: '"Montserrat", "Helvetica Neue", Arial, sans-serif', background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', color: '#ffffff', paddingTop: 2, borderRadius: 1.5, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textTransform: 'uppercase', alignContent: 'center', fontSize: '0.8rem', pb: 2, mb: 2, } as SxProps, contentStyle: { fontFamily: '"Open Sans", Arial, sans-serif', lineHeight: 1.6, color: '#444444', } as SxProps, markdownStyle: { fontFamily: '"Open Sans", Arial, sans-serif', '& h1, & h2, & h3': { fontFamily: '"Montserrat", "Helvetica Neue", Arial, sans-serif', color: '#667eea', fontWeight: 600, marginBottom: 2, }, '& h1': { fontSize: '1.5rem', }, '& h2': { fontSize: '1.25rem', }, '& h3': { fontSize: '1.1rem', }, '& p, & li': { lineHeight: 1.6, marginBottom: 1, color: '#444444', }, '& strong': { color: '#764ba2', fontWeight: 600, }, '& ul': { paddingLeft: 3, }, } as SxProps, color: { primary: '#667eea', secondary: '#764ba2', accent: '#f093fb', text: '#444444', background: '#ffffff', }, }, corporate: { name: 'Corporate', description: 'Formal, structured business format', headerStyle: { display: 'flex', flexDirection: 'row', fontFamily: '"Arial", sans-serif', border: '2px solid #34495e', padding: 2.5, marginBottom: 3, backgroundColor: '#ecf0f1', } as SxProps, footerStyle: { fontFamily: '"Arial", sans-serif', border: '2px solid #34495e', backgroundColor: '#ecf0f1', paddingTop: 2, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textTransform: 'uppercase', alignContent: 'center', fontSize: '0.8rem', pb: 2, mb: 2, } as SxProps, contentStyle: { fontFamily: '"Arial", sans-serif', lineHeight: 1.4, color: '#2c3e50', } as SxProps, markdownStyle: { fontFamily: '"Arial", sans-serif', '& h1, & h2, & h3': { fontFamily: '"Arial", sans-serif', color: '#34495e', fontWeight: 'bold', textTransform: 'uppercase', fontSize: '0.875rem', letterSpacing: '1px', marginBottom: 1.5, borderBottom: '1px solid #bdc3c7', paddingBottom: 0.5, }, '& h1': { fontSize: '1rem', }, '& h2': { fontSize: '0.875rem', }, '& h3': { fontSize: '0.75rem', }, '& p, & li': { lineHeight: 1.4, marginBottom: 0.75, fontSize: '0.75rem', }, '& ul': { paddingLeft: 2, }, } as SxProps, color: { primary: '#34495e', secondary: '#2c3e50', accent: '#95a5a6', text: '#2c3e50', background: '#ffffff', }, }, }; }; export const resumeStyles: Record = generateResumeStyles(); // Styled Header Component interface StyledHeaderProps { candidate: Types.Candidate; style: ResumeStyle; } const StyledHeader: React.FC = ({ candidate, style }) => { const phone = parsePhoneNumberFromString(candidate.phone || '', 'US'); return ( {candidate.fullName} {candidate.description && ( {candidate.description} )} {candidate.email && ( {candidate.email} )} {phone?.isValid() && ( {phone.formatInternational()} )} {candidate.location && ( {candidate.location.city ? `${candidate.location.city}, ${candidate.location.state}` : candidate.location.text} )} ); }; // Styled Footer Component interface StyledFooterProps { candidate: Types.Candidate; job?: Types.Job; style: ResumeStyle; } const StyledFooter: React.FC = ({ candidate, job, style }) => { return ( <> Dive deeper into my qualifications at Backstory... {candidate?.username ? `${window.location.protocol}://${window.location.host}/u/${candidate?.username}` : 'backstory'}   ); }; // Main ResumePreview Component export interface ResumePreviewProps { resume: Types.Resume; selectedStyle?: string; shadeMargins?: boolean; } export const ResumePreview: React.FC = (props: ResumePreviewProps) => { const { resume, selectedStyle = 'corporate', shadeMargins = true } = props; const currentStyle = resumeStyles[selectedStyle] || resumeStyles.corporate; const job: Types.Job | null = resume.job || null; const candidate: Types.Candidate | null = resume.candidate || null; if (!resume || !candidate || !job) { return ( No resume data available. ); } return ( {/* Custom Header */} {/* Styled Markdown Content */} {/* QR Code Footer */} {job && } ); }; export default ResumePreview;