789a818c6b
Extends the checkout pattern (inline red error text, refocus on submit if invalid) to all four newsletter-signup entry points. Two of them (WeeklyImpulsesHero's inline hero form on /newsletter, and /challenge's EmailCapture) turned out to be completely non-functional before this too — same static-markup-with-no-onSubmit issue as Newsletter.tsx/NewsletterModal.tsx had, just missed in the previous pass since they're separate components sharing only the visual pattern, not the code. Consolidated the shared email+consent+submit state (previously duplicated per-component) into useNewsletterSignup.ts, and pulled the plain email-format regex (previously duplicated in CheckoutContent.tsx and the subscribe route) into lib/email.ts as a single source of truth. /challenge's EmailCapture is now its own client component (app/challenge/components/EmailCapture.tsx) since its parent page is an async Server Component and can't hold form state itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
16 lines
677 B
TypeScript
16 lines
677 B
TypeScript
// Single source of truth for "is this a plausible email address" — used
|
|
// client-side (checkout, newsletter forms) for immediate on-blur feedback
|
|
// and server-side (newsletter subscribe route) as the same check, not a
|
|
// second one that could drift out of sync.
|
|
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
|
|
export function isValidEmail(value: string): boolean {
|
|
return EMAIL_PATTERN.test(value);
|
|
}
|
|
|
|
// Returns "" for valid, an error message otherwise.
|
|
export function validateEmailFormat(value: string): string {
|
|
if (!value.trim()) return "E-Mail-Adresse ist erforderlich.";
|
|
return isValidEmail(value) ? "" : "Bitte eine gültige E-Mail-Adresse angeben.";
|
|
}
|