"use client"; import { useRef, useState, type FormEvent } from "react"; import { validateEmailFormat } from "./email"; import type { NewsletterOptInSource } from "./brevo"; // Shared state/submit logic behind every newsletter-signup form // (Newsletter.tsx, NewsletterModal.tsx, WeeklyImpulsesHero.tsx's inline // hero form, /challenge's EmailCapture) — four places with the same // email+consent+submit shape but different markup/visual style, so only // the logic is shared here rather than a one-size-fits-all component. // Per the user's own explicit wording request, see the newsletter-DOI // memory — kept here once rather than duplicated across all 4 forms. const SUCCESS_MESSAGE = "Fast geschafft! Schau kurz in dein Postfach – da wartet schon eine Mail von uns."; // Deliberately routed through the *error* state, not a success variant — // per explicit feedback: swapping the whole form out for a bare message // (the real-success treatment) felt wrong for "you're already signed up, // nothing to do" — the form should stay visible, with a small note below // it, exactly like every other inline validation error already does. const ALREADY_SUBSCRIBED_MESSAGE = "Diese E-Mail-Adresse ist schon für unseren Newsletter angemeldet."; export function useNewsletterSignup(source: NewsletterOptInSource) { const [email, setEmail] = useState(""); const [emailError, setEmailError] = useState(""); const [consent, setConsent] = useState(false); const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle"); const [error, setError] = useState(""); const emailRef = useRef(null); // Clears a previous submit-time error (real failure or "already // subscribed") the moment the customer interacts with the form again — // same "stale validation message shouldn't linger" behavior // emailError already had for itself, extended to the submit-result // error too, since it's otherwise easy to misread as still describing // the current (possibly already-corrected) input. function clearSubmitError() { if (status === "error") { setStatus("idle"); setError(""); } } function handleEmailChange(value: string) { setEmail(value); if (emailError) setEmailError(""); clearSubmitError(); } function handleEmailBlur(value: string) { setEmailError(validateEmailFormat(value)); } function handleConsentChange(checked: boolean) { setConsent(checked); clearSubmitError(); } async function handleSubmit(e: FormEvent) { e.preventDefault(); const formatError = validateEmailFormat(email); setEmailError(formatError); if (formatError) { emailRef.current?.focus(); return; } setStatus("submitting"); setError(""); try { const res = await fetch("/api/newsletter/subscribe", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, consent, source }), }); const data = await res.json(); if (!data.ok) { setError(data.reason || "Anmeldung ist fehlgeschlagen. Bitte versuche es später erneut."); setStatus("error"); return; } if (data.alreadySubscribed) { setError(ALREADY_SUBSCRIBED_MESSAGE); setStatus("error"); return; } setStatus("success"); } catch { setError("Anmeldung ist fehlgeschlagen. Bitte versuche es später erneut."); setStatus("error"); } } return { email, emailError, consent, handleConsentChange, status, error, successMessage: SUCCESS_MESSAGE, emailRef, handleEmailChange, handleEmailBlur, handleSubmit }; }