From cc9da6ac6d61af7f299bd907b705e1b0c50fcb46 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 21 Jul 2026 11:15:44 +0000 Subject: [PATCH] feat(newsletter, checkout): add consent links, unify trust-note styling, optimize images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every email-signup form (Home/newsletter Newsletter section, /newsletter hero, /challenge, the Newsletter overlay) now links "Datenschutzerklärung" to /datenschutz next to its consent checkbox, opened in a new tab so a partially filled form isn't lost. Checkout gets an equivalent AGB + Datenschutzerklärung note under the order button, and the Versand modal's Widerrufsbelehrung link also opens in a new tab. Unified the "Keine Werbung. Jederzeit abbestellbar." trust note (icon + #888 copy) across all newsletter forms, matching /challenge's existing style instead of each form having its own wording/color. Also converted the remaining raw tags in these files to next/image per the no-img-element lint rule (bandwidth/LCP). --- app/challenge/page.tsx | 56 +++++++++++++++---- app/checkout/components/CheckoutContent.tsx | 21 +++++-- app/components/Newsletter.tsx | 49 ++++++++++++++-- app/components/NewsletterModal.tsx | 20 +++++-- .../components/WeeklyImpulsesHero.tsx | 41 ++++++++++++-- app/versand/components/VersandSections.tsx | 2 +- 6 files changed, 159 insertions(+), 30 deletions(-) diff --git a/app/challenge/page.tsx b/app/challenge/page.tsx index 034a340..77c0222 100644 --- a/app/challenge/page.tsx +++ b/app/challenge/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import Link from "next/link"; +import Image from "next/image"; import { Footer } from "../components/Footer"; import { Reveal, RevealGroup, RevealItem } from "../components/Reveal"; @@ -154,6 +155,28 @@ function EmailCapture({ buttonLabel = "Challenge starten" }: { buttonLabel?: str {buttonLabel} + {/* Consent checkbox — this signup's legal basis is consent (email + marketing), same wording as the other newsletter forms; colors + match this page's own hardcoded palette instead of the shared + design tokens, consistent with the rest of the page. */} +

Keine Werbung. Jederzeit abbestellbar. @@ -241,10 +264,12 @@ export default function ChallengePage() { todo-cards hero images; delay={0.15} mirrors their text→image stagger. */} - 7-Tage-Challenge {/* Badge */}

@@ -293,9 +318,11 @@ export default function ChallengePage() { // stacked below lg, this page's own structural // breakpoint) rather than hidden below lg like before.
-
@@ -324,14 +351,15 @@ export default function ChallengePage() { {/* Image */} - Notizbuch @@ -389,11 +417,15 @@ export default function ChallengePage() {

{t.quote}

- {t.name} +
+ {t.name} +

{t.name}

{t.role}

diff --git a/app/checkout/components/CheckoutContent.tsx b/app/checkout/components/CheckoutContent.tsx index db3b401..77dc3db 100644 --- a/app/checkout/components/CheckoutContent.tsx +++ b/app/checkout/components/CheckoutContent.tsx @@ -293,7 +293,9 @@ export function CheckoutContent({ {method.title} {method.icons.map((icon, i) => ( - +
+ +
))}
@@ -307,8 +309,19 @@ export function CheckoutContent({ Jetzt kaufen (zahlungspflichtig) +

+ Mit dem Kauf akzeptierst du unsere{" "} + + AGB + {" "} + und die{" "} + + Datenschutzerklärung + . +

+
- + Sichere SSL-Verschlüsselung
@@ -398,7 +411,7 @@ export function CheckoutContent({
{trustBadges.map((b) => (
- +

{b.title}

{b.description}

@@ -412,7 +425,7 @@ export function CheckoutContent({ which puts the divider under the icon — the two aren't meant to be identical, see project notes on this pattern). */}
- +
{/* Conditional on the (unchecked-by-default) consent checkbox above, not stated as a given — a pre-ticked diff --git a/app/components/Newsletter.tsx b/app/components/Newsletter.tsx index ec9274c..670fc9e 100644 --- a/app/components/Newsletter.tsx +++ b/app/components/Newsletter.tsx @@ -1,6 +1,20 @@ import type { ReactNode } from "react"; +import Link from "next/link"; +import Image from "next/image"; import { Reveal } from "./Reveal"; +// Same lock icon + copy as /challenge's and /newsletter's EmailCapture — +// unified across all newsletter-signup forms instead of each having its +// own wording/color for this trust note. +function LockIcon() { + return ( + + + + + ); +} + type NewsletterProps = { title?: ReactNode; description?: string; @@ -32,9 +46,11 @@ export function Newsletter({ {/* Decorative envelope icon, tilted -4° as per design */}
-
@@ -73,9 +89,34 @@ export function Newsletter({
- {/* Privacy note */} -

- Ich achte auf deine Daten. Kein Spam, jederzeit abbestellbar. + {/* Consent checkbox — required since this signup's legal + basis is consent (email marketing), not the "Ich achte + auf deine Daten" trust note alone. Same wording/pattern + as NewsletterModal's checkbox. */} + + + {/* Privacy note — same icon/copy/color as the other + newsletter forms (see /challenge's EmailCapture). */} +

+ + Keine Werbung. Jederzeit abbestellbar.

diff --git a/app/components/NewsletterModal.tsx b/app/components/NewsletterModal.tsx index 0bda90e..107c0e0 100644 --- a/app/components/NewsletterModal.tsx +++ b/app/components/NewsletterModal.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef } from "react"; import Image from "next/image"; +import Link from "next/link"; import { AnimatePresence, motion } from "motion/react"; const features = [ @@ -149,7 +150,7 @@ export function NewsletterModal({ open, onClose }: { open: boolean; onClose: () aria-label="Schließen" className="absolute top-6 right-6 z-10 size-6 flex items-center justify-center active:scale-90 transition-transform" > - + {/* modal-top: photo + copy/form, stacked below md */} @@ -170,7 +171,7 @@ export function NewsletterModal({ open, onClose }: { open: boolean; onClose: () uses this exact same asset); without it the icon renders flipped. */}
- +

- Ich akzeptiere die Datenschutzerklärung. + Ich akzeptiere die{" "} + + Datenschutzerklärung + + . @@ -224,8 +234,8 @@ export function NewsletterModal({ open, onClose }: { open: boolean; onClose: ()

{features.map((f) => (
-
- +
+

+ + + + ); +} + const checklist = [ "Jeden Mittwoch neue Impulse & Tipps", "Kurz & knackig – in 5 Minuten gelesen", @@ -47,7 +58,7 @@ export function WeeklyImpulsesHero() {

{/* Pill badge */}
- + Jeden Mittwoch in deinem Postfach @@ -73,7 +84,7 @@ export function WeeklyImpulsesHero() {
    {checklist.map((item) => (
  • - + {item}
  • ))} @@ -96,9 +107,31 @@ export function WeeklyImpulsesHero() {
+ {/* Consent checkbox — this signup's legal basis is consent + (email marketing), same wording/pattern as the shared + Newsletter component's and NewsletterModal's checkbox. */} + +
- - Keine Werbung. Jederzeit abbestellbar. + + Keine Werbung. Jederzeit abbestellbar.
diff --git a/app/versand/components/VersandSections.tsx b/app/versand/components/VersandSections.tsx index f54df24..a9137a5 100644 --- a/app/versand/components/VersandSections.tsx +++ b/app/versand/components/VersandSections.tsx @@ -102,7 +102,7 @@ export function VersandSections({ withAnchors = false }: { withAnchors?: boolean

Informationen zu Rückgabe, Rücksendekosten und deinem gesetzlichen Widerrufsrecht findest du in unserer{" "} - + Widerrufsbelehrung .