/* settings.jsx — Email template management settings page. * Requires: app.jsx (Sidebar, Topbar, I, Avatar, Pill globals) * email-store.jsx (loadTemplateStore, saveTemplateStore, etc.) */ /* ── Stage list for the settings page (minus "applied") ─────────────────── */ const ST_STAGE_GROUPS = [ { id: "intro_screening", label: "Intro screening" }, { id: "hiring_manager", label: "Hiring manager" }, { id: "technical_test", label: "Technical test" }, { id: "offer", label: "Offer" }, { id: "hired", label: "Hired" }, { id: "rejected", label: "Rejected" }, ]; const STAGE_ACCENT = { intro_screening: "var(--neutral-50)", hiring_manager: "var(--indigo-50)", technical_test: "var(--violet-50)", offer: "var(--yellow-50)", hired: "var(--green-50)", rejected: "var(--red-50)", }; /* Sample data used for live preview */ const PREVIEW_CTX = { contact: { firstName: "Alex", lastName: "Rivera" }, posting: { title: "Senior backend engineer", location: "Remote · LatAm" }, stage: { label: "Intro screening" }, }; /* ── Variable insert chip ─────────────────────────────────────────────────── */ function VarChip({ label, onClick }) { return ( ); } /* ── TemplateEditor ──────────────────────────────────────────────────────── */ function TemplateEditor({ tpl, bindings, allTemplates, onSave, onDelete }) { const { useState, useEffect, useRef } = React; const [name, setName] = useState(tpl.name || ""); const [stageId, setStageId] = useState(tpl.stageId || "intro_screening"); const [subject, setSubject] = useState(tpl.subject || ""); const [body, setBody] = useState(tpl.body || ""); const [isDefault, setIsDefault] = useState(false); const [showPreview, setShowPreview] = useState(false); const bodyRef = useRef(null); const subjectRef = useRef(null); useEffect(() => { setName(tpl.name || ""); setStageId(tpl.stageId || "intro_screening"); setSubject(tpl.subject || ""); setBody(tpl.body || ""); setIsDefault(bindings[tpl.stageId] === tpl.id); }, [tpl.id]); useEffect(() => { if (bodyRef.current) { bodyRef.current.style.height = "auto"; bodyRef.current.style.height = bodyRef.current.scrollHeight + "px"; } }, [body]); const insertVar = (fieldRef, setter, varName) => { const el = fieldRef.current; if (!el) return; const start = el.selectionStart || 0; const end = el.selectionEnd || 0; const val = el.value; const token = `{{${varName}}}`; const next = val.slice(0, start) + token + val.slice(end); setter(next); setTimeout(() => { el.focus(); el.setSelectionRange(start + token.length, start + token.length); }, 0); }; const preview = showPreview ? renderEmailTemplate({ subject, body }, { ...PREVIEW_CTX, stage: { label: ST_STAGE_GROUPS.find(s => s.id === stageId)?.label || "" } }) : null; const VARS = ["firstName", "lastName", "role", "stageName", "recruiter", "recruiterTitle"]; return (
setName(e.target.value)} placeholder="Template name" />
{/* Stage binding row */}
Linked stage
{showPreview ? ( /* Live preview */
Preview with sample data (Alex Rivera → {ST_STAGE_GROUPS.find(s => s.id === stageId)?.label})
Subject {preview.subject}
Body
{preview.body}
) : ( /* Edit form */
{/* Variable chips */}
Insert variable {VARS.map(v => ( { /* Insert into whichever field was last focused — default body */ insertVar(bodyRef, setBody, v); }} /> ))}
{/* Subject */}
setSubject(e.target.value)} placeholder="Email subject line…" onFocus={() => {}} />
{/* Body */}