/* email-composer.jsx * EmailComposer modal — appears on every stage-move action. * Requires: email-store.jsx, app.jsx (I, Avatar, Pill globals). */ /* ── Local icon helpers (not in app.jsx I object) ───────────────────────── */ const IcMail = (p) => (); const IcArrowRight = (p) => (); /* Stage-based hint copy */ const STAGE_HINTS = { intro_screening: "A short, warm note to schedule your 30-minute intro call.", hiring_manager: "Let them know they've impressed the team and what to expect next.", technical_test: "Set expectations clearly — effort required and timeline for the exercise.", offer: "Keep it warm and personal. This is a memorable moment for them.", hired: "Celebrate! Make them feel genuinely welcome before day one.", rejected: "Be respectful and specific. Leave the door open for future roles.", }; /* ── EmailComposer ───────────────────────────────────────────────────────── */ function EmailComposer({ candidateName, candidateEmail, candidateHue, postingTitle, fromStageId, fromStageLabel, toStageId, toStageLabel, toStageAccent, fromStageAccent, onSendAndMove, onDiscardAndMove, onCancel, }) { const { useState, useEffect, useRef, useCallback } = React; /* Load prefilled template */ const [subject, setSubject] = useState(""); const [body, setBody] = useState(""); const [loaded, setLoaded] = useState(false); const bodyRef = useRef(null); useEffect(() => { const firstName = (candidateName || "").split(" ")[0] || "there"; const tpl = getTemplateForStage(toStageId); if (tpl) { const rendered = renderEmailTemplate(tpl, { contact: { firstName, lastName: (candidateName || "").split(" ").slice(1).join(" ") }, posting: { title: postingTitle || "", location: "" }, stage: { label: toStageLabel || "" }, }); setSubject(rendered.subject); setBody(rendered.body); } setLoaded(true); }, [toStageId, candidateName, postingTitle, toStageLabel]); /* Auto-grow textarea */ useEffect(() => { if (bodyRef.current) { bodyRef.current.style.height = "auto"; bodyRef.current.style.height = bodyRef.current.scrollHeight + "px"; } }, [body]); /* Escape key */ useEffect(() => { const fn = (e) => { if (e.key === "Escape") onCancel && onCancel(); }; document.addEventListener("keydown", fn); return () => document.removeEventListener("keydown", fn); }, [onCancel]); const handleSend = useCallback(() => { onSendAndMove && onSendAndMove({ to: candidateEmail, subject, body, sentAt: new Date().toISOString(), }); }, [candidateEmail, subject, body, onSendAndMove]); const hint = STAGE_HINTS[toStageId] || "Send a note to keep the candidate informed."; return (
{ if (e.target === e.currentTarget) onCancel && onCancel(); }}>
{/* ── Header ── */}
Moving to · {toStageLabel}

Send {candidateName} an email?

{hint}

{/* Stage flow chip */}
{fromStageLabel} {toStageLabel}
{/* ── Meta rows ── */}
From {RECRUITER_NAME} <{RECRUITER_EMAIL}>
To {candidateName} {candidateEmail && ( <{candidateEmail}> )}
Re {postingTitle || "—"}
{/* ── Compose area ── */}
setSubject(e.target.value)} placeholder="Subject line…" />