Turn CV template chooser into visual carousel

This commit is contained in:
2026-04-11 22:45:24 +02:00
parent 54abc9f546
commit eea327e1f6
+84 -41
View File
@@ -937,53 +937,96 @@ export default function ProfilePage() {
</Box>
</Box>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(3, minmax(0, 1fr))" }, gap: 1.5, mb: 2 }}>
{REWRITE_TEMPLATES.map((option) => {
const selected = option.id === cvSectionStyle;
return (
<Paper
key={option.id}
role="button"
tabIndex={0}
onClick={() => setCvSectionStyle(option.id)}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
setCvSectionStyle(option.id);
}
}}
sx={{
p: 1.5,
borderRadius: 3.5,
cursor: "pointer",
border: "1px solid",
borderColor: selected ? "primary.main" : "divider",
boxShadow: selected ? "0 0 0 1px rgba(25,118,210,0.18), 0 12px 30px rgba(15,23,42,0.08)" : "0 6px 18px rgba(15,23,42,0.04)",
background: selected ? `linear-gradient(180deg, ${option.accent}12 0%, rgba(255,255,255,0.96) 100%)` : "background.paper",
transition: "transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease",
'&:hover': { transform: 'translateY(-2px)' },
}}
>
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1, mb: 1 }}>
<Box sx={{ mb: 2 }}>
<Paper sx={{ p: { xs: 1.5, md: 2 }, borderRadius: 4, border: "1px solid", borderColor: "divider", background: `linear-gradient(180deg, ${selectedRewriteTemplate.accent}14 0%, rgba(255,255,255,0.96) 100%)`, boxShadow: "0 18px 40px rgba(15,23,42,0.08)" }}>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", lg: "1.15fr 0.85fr" }, gap: 2, alignItems: "stretch" }}>
<Box sx={{ p: { xs: 1.25, md: 2 }, borderRadius: 3.5, background: "rgba(255,255,255,0.82)", border: "1px solid", borderColor: "rgba(15,23,42,0.08)" }}>
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1.5, mb: 1.5 }}>
<Box>
<Typography variant="overline" sx={{ color: option.accent, fontWeight: 900, letterSpacing: '0.14em' }}>{option.eyebrow}</Typography>
<Typography variant="subtitle2" sx={{ fontWeight: 900 }}>{option.title}</Typography>
<Typography variant="overline" sx={{ color: selectedRewriteTemplate.accent, fontWeight: 900, letterSpacing: '0.16em' }}>{selectedRewriteTemplate.eyebrow}</Typography>
<Typography variant="h6" sx={{ fontWeight: 900 }}>{selectedRewriteTemplate.title}</Typography>
<Typography variant="body2" sx={{ color: "text.secondary", mt: 0.25, maxWidth: 560 }}>{selectedRewriteTemplate.blurb}</Typography>
</Box>
<IconButton size="small" onClick={(event) => { event.stopPropagation(); setRewritePreviewTemplate(option); }}>
<IconButton size="small" onClick={() => setRewritePreviewTemplate(selectedRewriteTemplate)}>
<ZoomInOutlinedIcon fontSize="small" />
</IconButton>
</Box>
<Box sx={{ p: 1.25, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default", minHeight: 160 }}>
<Typography variant="caption" sx={{ display: "block", color: option.accent, fontWeight: 800, mb: 0.5 }}>{option.sampleHeading}</Typography>
<Typography variant="caption" sx={{ display: "block", color: "text.secondary", mb: 1 }}>{option.sampleMeta}</Typography>
{option.sampleBullets.map((bullet) => (
<Typography key={bullet} variant="caption" sx={{ display: "block", color: "text.primary", mb: 0.5 }}> {bullet}</Typography>
))}
<Box sx={{ borderRadius: 3.5, overflow: "hidden", border: "1px solid", borderColor: "rgba(15,23,42,0.1)", background: "white", minHeight: { xs: 280, md: 340 }, boxShadow: "inset 0 1px 0 rgba(255,255,255,0.7)" }}>
<Box sx={{ px: { xs: 2, md: 3 }, py: { xs: 2, md: 2.5 }, borderBottom: "1px solid", borderColor: "rgba(15,23,42,0.08)", background: `linear-gradient(135deg, ${selectedRewriteTemplate.accent}14 0%, rgba(255,255,255,0.96) 72%)` }}>
<Typography variant="caption" sx={{ display: "block", color: selectedRewriteTemplate.accent, fontWeight: 900, letterSpacing: '0.14em', mb: 0.5 }}>{selectedRewriteTemplate.eyebrow}</Typography>
<Typography sx={{ fontSize: { xs: '1.1rem', md: '1.35rem' }, fontWeight: 900, lineHeight: 1.1 }}>{selectedRewriteTemplate.sampleHeading}</Typography>
<Typography variant="body2" sx={{ color: "text.secondary", mt: 0.5 }}>{selectedRewriteTemplate.sampleMeta}</Typography>
</Box>
<Box sx={{ px: { xs: 2, md: 3 }, py: { xs: 2, md: 2.5 } }}>
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 1 }}>Preview of the generated PDF style</Typography>
{selectedRewriteTemplate.sampleBullets.map((bullet) => (
<Typography key={bullet} variant="body2" sx={{ display: "block", color: "text.primary", mb: 0.85, lineHeight: 1.55 }}> {bullet}</Typography>
))}
<Box sx={{ mt: 2, pt: 1.5, borderTop: "1px dashed", borderColor: "divider", display: "grid", gridTemplateColumns: { xs: "1fr", sm: "repeat(3, minmax(0, 1fr))" }, gap: 1 }}>
<Chip size="small" variant="outlined" label="Readable hierarchy" />
<Chip size="small" variant="outlined" label="PDF-first spacing" />
<Chip size="small" variant="outlined" label="ATS-safe structure" />
</Box>
</Box>
</Box>
<Typography variant="body2" sx={{ color: "text.secondary", mt: 1 }}>{option.blurb}</Typography>
</Paper>
);
})}
</Box>
<Box sx={{ display: "flex", flexDirection: "column", gap: 1.1 }}>
<Typography variant="subtitle2" sx={{ fontWeight: 900 }}>Choose a visual direction before generating</Typography>
<Box sx={{ display: "grid", gap: 1.1 }}>
{REWRITE_TEMPLATES.map((option) => {
const selected = option.id === cvSectionStyle;
return (
<Paper
key={option.id}
role="button"
tabIndex={0}
aria-label={`${option.title} template preview`}
onClick={() => setCvSectionStyle(option.id)}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
setCvSectionStyle(option.id);
}
}}
sx={{
p: 1.15,
borderRadius: 3,
cursor: "pointer",
border: "1px solid",
borderColor: selected ? "primary.main" : "divider",
background: selected ? `linear-gradient(180deg, ${option.accent}10 0%, rgba(255,255,255,0.98) 100%)` : "rgba(255,255,255,0.84)",
boxShadow: selected ? "0 0 0 1px rgba(25,118,210,0.16), 0 10px 24px rgba(15,23,42,0.08)" : "0 6px 16px rgba(15,23,42,0.04)",
transition: "transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease",
'&:hover': { transform: 'translateY(-1px)' },
}}
>
<Box sx={{ display: "grid", gridTemplateColumns: "92px minmax(0, 1fr)", gap: 1.1, alignItems: "stretch" }}>
<Box sx={{ borderRadius: 2.5, border: "1px solid", borderColor: "rgba(15,23,42,0.08)", background: `linear-gradient(180deg, ${option.accent}1e 0%, rgba(255,255,255,0.98) 100%)`, p: 1, minHeight: 102, display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
<Typography variant="caption" sx={{ color: option.accent, fontWeight: 900, letterSpacing: '0.08em' }}>{option.eyebrow}</Typography>
<Box>
<Typography variant="caption" sx={{ display: "block", fontWeight: 800, lineHeight: 1.25 }}>{option.sampleHeading}</Typography>
<Typography variant="caption" sx={{ display: "block", color: "text.secondary", mt: 0.5, lineHeight: 1.25 }}>{option.sampleMeta}</Typography>
</Box>
</Box>
<Box sx={{ minWidth: 0 }}>
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1 }}>
<Box sx={{ minWidth: 0 }}>
<Typography variant="subtitle2" sx={{ fontWeight: 900 }}>{option.title}</Typography>
<Typography variant="body2" sx={{ color: "text.secondary", mt: 0.25, lineHeight: 1.4 }}>{option.blurb}</Typography>
</Box>
{selected ? <Chip size="small" color="primary" label="Selected" /> : null}
</Box>
</Box>
</Box>
</Paper>
);
})}
</Box>
</Box>
</Box>
</Paper>
</Box>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 1.5, mb: 1.75 }}>