"use client"; import { useEffect, useState } from "react"; import { getApiBase } from "../lib/auth"; import BrandingLogo from "../ui/BrandingLogo"; import "./recaps.css"; type LinkAction = { action: "confirm" | "unsubscribe"; token: string }; export default function EmailRecapLinkPage() { const [link, setLink] = useState(null); const [state, setState] = useState("loading"); const [error, setError] = useState(""); const [busy, setBusy] = useState(false); useEffect(() => { let controller: AbortController | null = null; const checkLink = () => { controller?.abort(); const abort = new AbortController(); controller = abort; setError(""); setState("loading"); setLink(null); // Fragments stay out of web-server access logs and referrers. Opening the link only checks it. const params = new URLSearchParams(window.location.hash.slice(1)); const action = params.get("action"); const token = params.get("token") || ""; if ((action !== "confirm" && action !== "unsubscribe") || !/^[A-Za-z0-9_-]{40,100}$/.test(token)) { setError("This email link is incomplete. Open Profile to manage your monthly recaps."); setState("error"); return; } const payload = { action, token } as LinkAction; setLink(payload); void fetch(`${getApiBase()}/email-recaps/check`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), signal: abort.signal, credentials: "omit", }) .then(async (response) => { const result = await response.json().catch(() => ({})); if (!response.ok) throw new Error( typeof result.detail === "string" ? result.detail : "Could not check this email link. Please open it again.", ); if (!abort.signal.aborted) setState(result.state); }) .catch((err: Error) => { if (!abort.signal.aborted) { setError(err.message); setState("error"); } }); }; checkLink(); window.addEventListener("hashchange", checkLink); return () => { controller?.abort(); window.removeEventListener("hashchange", checkLink); }; }, []); const apply = async () => { if (!link || busy) return; setBusy(true); setError(""); try { const response = await fetch(`${getApiBase()}/email-recaps/confirm`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(link), credentials: "omit", }); const result = await response.json().catch(() => ({})); if (!response.ok) throw new Error( typeof result.detail === "string" ? result.detail : "Could not update your preference. Please try again.", ); setState(result.state); window.history.replaceState(null, "", "/email-recaps"); } catch (err) { setError(err instanceof Error ? err.message : "Could not update your preference."); } finally { setBusy(false); } }; const done = state === "enabled" || state === "off"; return (
Magent
Personal viewing reports

{state === "enabled" ? "You’re on the list." : state === "off" ? "Recaps are turned off." : state === "loading" ? "Checking your email link" : state === "error" ? "This link needs another look" : link?.action === "unsubscribe" ? "Unsubscribe from recaps?" : "Your month, delivered."}

{state === "enabled" ? "Your email is confirmed. You’ll receive your personal viewing recap when the monthly schedule runs." : state === "off" ? "You won’t receive further monthly recaps. You can turn them back on in Profile." : state === "ready" && link?.action === "unsubscribe" ? "This turns off all personal viewing report emails. You can still explore all your reports in Magent." : state === "ready" ? "Confirm to email yourself your minutes, movies, episodes, longest run and requests. Manage automatic monthly delivery separately in Profile." : ""}

{error && (

{error}

)} {state === "ready" && ( )} {(done || state === "error") && ( Manage email preferences ↗ )} {state === "loading" &&

One moment…

}
); }