90be4696af
Matches the Figma mockup (checkmark hero, order summary card,
delivery-status panel, testimonial band) with the checkout's 4-step
bar inserted (all steps done) and the "Bis dahin: Lass dich
inspirieren" block omitted, per request.
Extracted the step bar into a shared CheckoutSteps component so
/checkout and /bestellbestaetigung don't duplicate it. The actually-
selected shipping cost and payment method are captured into a
sessionStorage snapshot by /checkout's "Jetzt kaufen" click (there's
no real order backend, so this click is what "placing the order"
means here) and read back on the confirmation page — not just
defaulted to the first active method of each, so the receipt matches
what the shopper actually picked. Also tightened the checkout
newsletter-consent copy ("Wenn du zustimmst" instead of "Wenn du
oben zustimmst").
60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
const STEP_LABELS = ["Warenkorb", "Adresse", "Zahlung", "Abschluss"];
|
|
|
|
type StepState = "done" | "active" | "upcoming";
|
|
|
|
function StepCircle({ state, number }: { state: StepState; number: number }) {
|
|
if (state === "done") {
|
|
return (
|
|
<div className="flex size-9 items-center justify-center rounded-full bg-brand text-text-primary">
|
|
<svg viewBox="0 0 20 20" className="size-4" fill="none" aria-hidden="true">
|
|
<path d="m4 10 4 4 8-8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|
|
if (state === "active") {
|
|
return (
|
|
<div className="flex size-9 items-center justify-center rounded-full bg-brand font-bold text-body-sm text-bg-white">
|
|
{number}
|
|
</div>
|
|
);
|
|
}
|
|
return (
|
|
<div className="flex size-9 items-center justify-center rounded-full border border-border font-bold text-body-sm text-text-muted">
|
|
{number}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Shared by /checkout (mid-flow, one step active) and /bestellbestaetigung
|
|
// (every step done — `current` past the last step number makes every
|
|
// stepNum < current true, so passing STEP_LABELS.length + 1 there marks
|
|
// the whole bar complete without a separate "all done" branch).
|
|
export function CheckoutSteps({ current }: { current: number }) {
|
|
return (
|
|
<div className="flex items-center w-full max-w-[50rem]">
|
|
{STEP_LABELS.map((label, i) => {
|
|
const stepNum = i + 1;
|
|
const state: StepState = stepNum < current ? "done" : stepNum === current ? "active" : "upcoming";
|
|
return (
|
|
<div key={label} className="flex items-center flex-1 last:flex-initial">
|
|
<div className="flex flex-col items-center gap-0 shrink-0">
|
|
<div className="flex items-center gap-3">
|
|
<StepCircle state={state} number={stepNum} />
|
|
<span
|
|
className={`hidden sm:block text-body-sm whitespace-nowrap ${
|
|
state === "upcoming" ? "text-text-muted" : "font-semibold text-text-primary"
|
|
}`}
|
|
>
|
|
{label}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
{i < STEP_LABELS.length - 1 && <div className="h-px bg-border flex-1 mx-4 min-w-4" />}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|