From 578ec767b2e67c684fe4d051bcad2b56d43889c1 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Fri, 25 Sep 2026 13:27:35 +0200 Subject: [PATCH] feat(ui): Checkout mit Schrittanzeige und Lieferart-Karten - Schrittanzeige "Deine Daten -> Bezahlen" mit Waben (rein anzeigend, gesteuert weiter ueber den bestehenden Zahlungszustand) - Lieferart als Karten mit Symbol, Auswahl mit Waben-Haekchen, aria-pressed - Bestelluebersicht abgehoben, Namen und Gesamtsumme in Serifenschrift - Keine Aenderung an Bezahllogik oder Formularfeldern Co-Authored-By: Claude Opus 5.5 (1M context) --- src/app/checkout/checkout-form.tsx | 136 ++++++++++++++++++++++++----- src/i18n/dictionaries/de.ts | 2 + src/i18n/dictionaries/en.ts | 2 + src/i18n/dictionary-type.ts | 2 + 4 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/app/checkout/checkout-form.tsx b/src/app/checkout/checkout-form.tsx index 82644aa..87c8641 100644 --- a/src/app/checkout/checkout-form.tsx +++ b/src/app/checkout/checkout-form.tsx @@ -303,6 +303,15 @@ export function CheckoutForm({ return (
+ {/* Zwei Schritte, sichtbar gemacht: erst Daten, dann die eingebettete + Zahlung. Rein anzeigend — gesteuert wird weiter ueber "payment". */} + + + {payment && stripePublishableKey ? (
@@ -358,21 +367,52 @@ export function CheckoutForm({

{t.checkoutPage.fulfillmentLabel}

-
- {(["VERSAND", "ABHOLUNG"] as const).map((option) => ( - - ))} +
+ {(["VERSAND", "ABHOLUNG"] as const).map((option) => { + const selected = fulfillment === option; + return ( + + ); + })}
{fulfillment === "VERSAND" ? (

@@ -603,15 +643,16 @@ export function CheckoutForm({

-
) : null}
-
- {t.cartPage.total} - {formatPrice(total, "EUR", locale)} +
+ {t.cartPage.total} + {formatPrice(total, "EUR", locale)}
@@ -685,3 +726,52 @@ function Field({ ); } + +/** Schrittanzeige mit Waben: erledigt = gefuellt, aktuell = Honig mit Puls. */ +function CheckoutSteps({ current, labels, ariaLabel }: { current: number; labels: string[]; ariaLabel: string }) { + return ( +
    + {labels.map((label, i) => { + const done = i < current; + const active = i === current; + return ( +
  1. + + + + {label} + + + {i < labels.length - 1 ? ( +
  2. + ); + })} +
+ ); +} diff --git a/src/i18n/dictionaries/de.ts b/src/i18n/dictionaries/de.ts index 5140277..2f6d982 100644 --- a/src/i18n/dictionaries/de.ts +++ b/src/i18n/dictionaries/de.ts @@ -1453,6 +1453,8 @@ export const de: Dictionary = { eyebrow: "Checkout", emptyCart: "Dein Warenkorb ist leer", yourDetails: "Deine Daten", + stepPayment: "Bezahlen", + stepsAriaLabel: "Schritte der Bestellung", firstName: "Vorname", lastName: "Nachname", email: "E-Mail", diff --git a/src/i18n/dictionaries/en.ts b/src/i18n/dictionaries/en.ts index 3c2a5a1..b9c6828 100644 --- a/src/i18n/dictionaries/en.ts +++ b/src/i18n/dictionaries/en.ts @@ -1439,6 +1439,8 @@ export const en: Dictionary = { eyebrow: "Checkout", emptyCart: "Your cart is empty", yourDetails: "Your Details", + stepPayment: "Payment", + stepsAriaLabel: "Checkout steps", firstName: "First name", lastName: "Last name", email: "Email", diff --git a/src/i18n/dictionary-type.ts b/src/i18n/dictionary-type.ts index 5d1813d..d9ee27a 100644 --- a/src/i18n/dictionary-type.ts +++ b/src/i18n/dictionary-type.ts @@ -1102,6 +1102,8 @@ export interface Dictionary { eyebrow: string; emptyCart: string; yourDetails: string; + stepPayment: string; + stepsAriaLabel: string; firstName: string; lastName: string; email: string;