/** Standalone HTML rendering for magic link response pages. */ import { magicLinkConfig } from "./config"; import type { ChoiceSession, ChoiceOption } from "../../modules/rchoices/schemas"; import type { CalendarEvent } from "../../modules/rcal/schemas"; function esc(str: string): string { return str.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } const styles = ` body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#f8fafc;color:#1e293b;margin:0;padding:20px} .card{max-width:500px;margin:40px auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px rgba(0,0,0,.1);padding:32px} h1{font-size:20px;margin:0 0 4px;color:#0f172a} .sub{font-size:14px;color:#64748b;margin-bottom:24px} .opt{display:block;width:100%;padding:14px 20px;margin:8px 0;border:2px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-size:16px;text-align:left;color:#1e293b;text-decoration:none;box-sizing:border-box;transition:border-color .15s,background .15s} .opt:hover{border-color:#6366f1;background:#eef2ff} .opt.sel{border-color:#22c55e;background:#f0fdf4} .rsvp-row{display:flex;gap:10px;margin:16px 0} .rsvp-btn{flex:1;padding:14px;border:2px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-size:15px;text-align:center;text-decoration:none;color:#1e293b;transition:border-color .15s,background .15s} .rsvp-btn:hover{border-color:#6366f1;background:#eef2ff} .rsvp-btn.sel{border-color:#22c55e;background:#f0fdf4} .banner{padding:12px;border-radius:8px;margin-bottom:20px;font-size:14px} .banner-ok{background:#22c55e;color:#fff} .banner-info{background:#3b82f6;color:#fff} .meta{font-size:13px;color:#64748b;margin:4px 0} .ft{text-align:center;font-size:12px;color:#94a3b8;margin-top:24px} .label{font-size:13px;color:#94a3b8;margin-top:16px;margin-bottom:4px} `; // ── Poll page ── export function renderPollPage( session: ChoiceSession, token: string, respondentName: string, existingChoice?: string, justVoted?: string, ): string { let banner = ""; if (justVoted) { const opt = session.options.find((o) => o.id === justVoted); banner = `
`; } else if (existingChoice) { const opt = session.options.find((o) => o.id === existingChoice); banner = ``; } const optionButtons = session.options .map((opt) => { const selected = (existingChoice === opt.id || justVoted === opt.id) ? " sel" : ""; return ``; }) .join("\n"); return `${esc(event.description)}
` : ""}${esc(message)}