From c08237aa736ab87ac0ae67a2eb53d9137e21a08e Mon Sep 17 00:00:00 2001 From: DanielS Date: Thu, 6 Aug 2026 17:44:51 +0200 Subject: [PATCH] refactor(wizard): redesign step summary layout with step indicator --- shop/components/order-wizard.tsx | 6 +- shop/components/wizard/step-summary.tsx | 437 ++++++++++++------------ 2 files changed, 213 insertions(+), 230 deletions(-) diff --git a/shop/components/order-wizard.tsx b/shop/components/order-wizard.tsx index 918fb23..f65f1ce 100644 --- a/shop/components/order-wizard.tsx +++ b/shop/components/order-wizard.tsx @@ -939,10 +939,10 @@ export function OrderWizard({ {step === 4 && ( - -
- +
+ {/* LINKER BEREICH: Linksbündige Überschrift & Notizfeld */} +
+
+
+
+ +
+ + Schritt 4 von 4 — Abschluss + +
+

+ Anfrage prüfen +

+

+ Fast fertig! Bitte überprüfen Sie Ihre ausgewählte Konfiguration vor dem Absenden. +

- Anfrage prüfen - - Fast fertig! Bitte überprüfen Sie Ihre Auswahl. - - - -
- {finalItemsToShow.map((item, itemIdx) => ( -
-
- Kasse: {item.deviceName} - {item.billingInterval === 'one_time' ? 'Kauf' : 'Abo'} -
- {visibleCategories.map(cat => { - const sel = item.selections[cat.id] - const selectedProds: Product[] = [] - if (cat.allow_multiselect && sel?.productIds) { - sel.productIds.forEach((pId: string) => { - const p = products.find(prod => prod.id === pId) - if (p) selectedProds.push(p) - }) - } else if (sel?.productId) { - const p = products.find(prod => prod.id === sel.productId) - if (p) selectedProds.push(p) - } - - if (selectedProds.length === 0) return null - - const sortedProds = [...selectedProds].sort((a, b) => a.base_price - b.base_price) - const freeLimit = cat.allow_multiselect ? cat.free_items_limit : 0 - - return ( -
-
- - {cat.name} -
- {sortedProds.map((prod, idx) => { - const isFree = idx < freeLimit - const actualPrice = isFree ? 0 : prod.base_price - const catTotal = - Number(actualPrice) + - (sel?.moduleIds?.reduce((acc: number, mId: string) => { - const mod = prod.modules?.find(m => m.id === mId) - const qty = item.moduleQuantities[mId] || 1 - return acc + (Number(mod?.price ?? 0) * qty) - }, 0) || 0) - - return ( -
-
- - {prod.name} {isFree && (Frei)} - - - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(catTotal)} - -
- {sel?.moduleIds && sel.moduleIds.length > 0 && ( -

- Module: {sel.moduleIds - .map((id: string) => { - const mod = prod.modules?.find(m => m.id === id) - const qty = item.moduleQuantities[id] || 1 - return mod ? `${mod.name}${mod.has_quantity ? ` (x${qty})` : ''}` : '' - }) - .filter(Boolean) - .join(', ')} -

- )} -
- ) - })} -
- ) - })} -
- ))} - {linkedFeeProducts && linkedFeeProducts.length > 0 && ( -
-
- Backoffice -
- {linkedFeeProducts.map(p => ( -
-
- {p.name} - - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(p.base_price)} - {' '}{p.billing_interval === 'monthly' ? '/ mtl.' : 'einmalig'} - -
-
- ))} -
- )} - -
- {selectedEndCustomer ? ( - <> -

- - {selectedEndCustomer.company_name} -

-

{[selectedEndCustomer.first_name, selectedEndCustomer.last_name].filter(Boolean).join(' ')}

-

{[selectedEndCustomer.street, selectedEndCustomer.zip, selectedEndCustomer.city].filter(Boolean).join(', ')}

-

Endkunde Ihres Partners

- {lastLicenseDate && ( -

- - Letzte Lizenz vom: {new Date(lastLicenseDate).toLocaleDateString('de-DE')} -

- )} - - ) : ( - <> -

{customerData.company_name}

-

{customerData.first_name} {customerData.last_name}

-

{customerData.address}, {customerData.zip_code} {customerData.city}

- - )} -
-
- {oneTimeTotal > 0 && monthlyTotal > 0 ? ( -
-
-

Einmaliger Betrag:

-
- Netto: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeNet)} -
-
- zzgl. 19% MwSt.: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeTax)} -
-
- Brutto: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeGross)} -
-
- {updatePriceModifier.label && ( -
- {updatePriceModifier.label} -
- )} -
-

Monatlicher Betrag:

-
- Netto: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyNet)} / mtl. -
-
- zzgl. 19% MwSt.: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyTax)} / mtl. -
-
- Brutto: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyGross)} / mtl. -
-
-
- ) : oneTimeTotal > 0 ? ( -
-
- Netto-Gesamtbetrag: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeNet)} -
-
- zzgl. 19% MwSt.: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeTax)} -
- {updatePriceModifier.label && ( -
- {updatePriceModifier.label} -
- )} -
- Gesamtbetrag (brutto): - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(oneTimeGross)} -
-
- ) : ( -
-
- Netto-Gesamtbetrag: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyNet)} / mtl. -
-
- zzgl. 19% MwSt.: - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyTax)} / mtl. -
-
- Gesamtbetrag (brutto): - {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(monthlyGross)} / mtl. + {/* Kunden-Info Card */} + {selectedEndCustomer && ( +
+
+ + Ausgewählter Endkunde
+

{selectedEndCustomer.company_name}

+

{selectedEndCustomer.first_name} {selectedEndCustomer.last_name}

+

{selectedEndCustomer.zip} {selectedEndCustomer.city}

)} - {/* Anmerkungen / Notizfeld */} -
-