import { useState, useRef } from "react"; const SYSTEM_PROMPT = `You are a scholarship program communications specialist. Generate exactly three deadline reminder emails (30-day, 7-day, 48-hour) based on the inputs provided. Each email must be under 120 words (body text only, not counting subject line). Tone: 30-day = informational and welcoming; 7-day = warm and encouraging; 48-hour = urgent and action-oriented. Do NOT use em-dashes. Be human, not corporate. Return ONLY a valid JSON object with no markdown, no backticks, no explanation. Use this exact structure: { "thirty": { "subject": "...", "body": "..." }, "seven": { "subject": "...", "body": "..." }, "fortyeight": { "subject": "...", "body": "..." } }`; function buildUserPrompt(program, deadline, link) { return `Program name: ${program} Application deadline: ${deadline} Application link: ${link} Generate the three email drafts now.`; } function countWords(text) { return text.trim().split(/\s+/).filter(Boolean).length; } const LABELS = [ { key: "thirty", days: "30 Days Out", color: "#1a5c8a", badge: "INFORMATIONAL", icon: "📅" }, { key: "seven", days: "7 Days Out", color: "#c07a00", badge: "ENCOURAGING", icon: "⏳" }, { key: "fortyeight", days: "48 Hours Out", color: "#b3000c", badge: "URGENT", icon: "🚨" }, ]; export default function EmailGenerator() { const [program, setProgram] = useState(""); const [deadline, setDeadline] = useState(""); const [link, setLink] = useState(""); const [emails, setEmails] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [copied, setCopied] = useState({}); const abortRef = useRef(null); async function generate() { if (!program.trim() || !deadline || !link.trim()) { setError("Please fill in all three fields."); return; } setError(""); setEmails(null); setLoading(true); try { const res = await fetch("https://api.anthropic.com/v1/messages", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "claude-sonnet-4-20250514", max_tokens: 1000, system: SYSTEM_PROMPT, messages: [{ role: "user", content: buildUserPrompt(program, deadline, link) }], }), }); const data = await res.json(); const raw = data?.content?.find(b => b.type === "text")?.text || ""; const parsed = JSON.parse(raw); setEmails(parsed); } catch (e) { setError("Generation failed. Check your inputs and try again."); } finally { setLoading(false); } } function copyEmail(key, subject, body) { const text = `Subject: ${subject}\n\n${body}`; navigator.clipboard.writeText(text).then(() => { setCopied(c => ({ ...c, [key]: true })); setTimeout(() => setCopied(c => ({ ...c, [key]: false })), 2000); }); } function formatDeadlineDisplay(dateStr) { if (!dateStr) return ""; const d = new Date(dateStr + "T12:00:00"); return d.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }); } return (
{/* Header */}
Scholarship Communications Tool

Deadline Reminder Email Generator

Enter three inputs. Get three ready-to-send reminder emails.

{/* Input card */}
setProgram(e.target.value)} />
setDeadline(e.target.value)} />
setLink(e.target.value)} />
{deadline && (
Deadline: {formatDeadlineDisplay(deadline)}
)} {error && (
{error}
)}
{/* Email output */} {emails && (
{LABELS.map(({ key, days, color, badge, icon }) => { const email = emails[key]; if (!email) return null; const wc = countWords(email.body); const over = wc > 120; return (
{/* Email header */}
{icon}
{days}
{badge}
{wc} words {over ? "(⚠ over 120)" : "✓"}
{/* Email content */}
Subject
{email.subject}
Body
{email.body}
); })} {/* Footer note */}
Before sending: Personalize salutations, confirm the deadline date is accurate, verify the application link resolves, and have a staff member approve each draft.
)}
); } const labelStyle = { display: "block", fontFamily: "sans-serif", fontSize: 12, fontWeight: 700, color: "#444", letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 6, }; const inputStyle = { width: "100%", boxSizing: "border-box", fontFamily: "sans-serif", fontSize: 14, color: "#111", background: "#fafafa", border: "1px solid #ccc", borderRadius: 4, padding: "9px 12px", transition: "border-color 0.15s", };