import React, { useCallback, useEffect, useState } from "react"; import { uploadMediaFile } from "../../../services/api"; import { whatsappBlastsApi } from "../../../services/api/whatsappBlasts"; import { PanelShell, RadioGroup, Label, Field, HelperText, IS, focusIn, focusOut } from "../panels/PanelShell"; import { WhatsAppCtaEditor, normalizeCtasForSave, type WhatsAppCtaItem } from "../whatsapp/WhatsAppCtaEditor"; function toDatetimeLocalValue(d: Date) { const pad = (n: number) => String(n).padStart(2, "0"); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; } export function SendWhatsAppNotificationPanel({ eventId, eventName, onClose, onSuccess, }: { eventId: string; eventName?: string; onClose: () => void; onSuccess?: () => void; }) { const [body, setBody] = useState(""); const [mediaType, setMediaType] = useState<"none" | "image" | "video">("none"); const [mediaUrl, setMediaUrl] = useState(""); const [ctas, setCtas] = useState([]); const [when, setWhen] = useState<"now" | "schedule">("now"); const [scheduleLocal, setScheduleLocal] = useState(""); const [eligible, setEligible] = useState(null); const [eligibleError, setEligibleError] = useState(""); const [uploading, setUploading] = useState(false); const [saving, setSaving] = useState(false); const [err, setErr] = useState(""); const loadEligible = useCallback(async () => { setEligibleError(""); const res = await whatsappBlastsApi.eligibleCount(eventId); if (res.error) { setEligible(null); setEligibleError(res.error); return; } setEligible(res.data?.count ?? 0); }, [eventId]); useEffect(() => { void loadEligible(); const t = window.setInterval(() => void loadEligible(), 30_000); return () => window.clearInterval(t); }, [loadEligible]); const onPickMedia = async (file: File | null) => { if (!file) return; const mime = String(file.type || "").toLowerCase(); const nextType = mime.startsWith("video/") ? "video" : mime.startsWith("image/") ? "image" : null; if (!nextType) { setErr("Attach an image or video file."); return; } setUploading(true); setErr(""); try { const up = await uploadMediaFile(file, { eventId, module: "whatsapp/notifications" }); if (!up.url) { setErr("Upload failed"); return; } setMediaType(nextType); setMediaUrl(up.url); } catch (e) { setErr(e instanceof Error ? e.message : "Upload failed"); } finally { setUploading(false); } }; const submit = async () => { const text = body.trim(); let ctasPayload: WhatsAppCtaItem[] = []; try { ctasPayload = normalizeCtasForSave(ctas); } catch (e) { setErr(e instanceof Error ? e.message : "Invalid buttons"); return; } if (ctasPayload.length && !text) { setErr("Message text is required when buttons are set."); return; } if (!text && !mediaUrl) { setErr("Enter a message or attach media."); return; } let sendAt: string | undefined; if (when === "schedule") { if (!scheduleLocal) { setErr("Pick a date and time."); return; } const d = new Date(scheduleLocal); if (Number.isNaN(d.getTime())) { setErr("Invalid schedule time."); return; } sendAt = d.toISOString(); } setSaving(true); setErr(""); const res = await whatsappBlastsApi.create(eventId, { body: text, mediaType: mediaUrl ? mediaType : "none", mediaUrl: mediaUrl || "", ctas: ctasPayload, ...(sendAt ? { sendAt } : {}), }); setSaving(false); if (res.error) { setErr(res.error); return; } onSuccess?.(); onClose(); }; const eligibleLine = eligibleError ? eligibleError : eligible == null ? "Counting people in the 24-hour WhatsApp window…" : `${eligible} ${eligible === 1 ? "person" : "people"} on this event can receive this now (open WhatsApp chat, last 24 hours).`; return ( void submit()} showProgress={false} panelWidth="min(560px, 100vw)" >

{eligibleLine}