-
- Konfigurierte Kassen ({selectedOrder.order_data?.items?.length || 0})
+
+
+
+ Konfigurierte Kassen ({displayItems.length})
+
+ {selectedOrder.status === 'in_review' && !isEditingSnapshot && (
+
+ )}
+ {isEditingSnapshot && (
+
+
Sie befinden sich im Preiskorrektur-Modus.
+
+
+
+
+
+ )}
+
- {(selectedOrder.order_data?.items || []).map((item: any, idx: number) => {
+ {displayItems.map((item: any, idx: number) => {
const devName = item.device_name || `Kasse #${idx + 1}`
const licNum = item.license_number
const modules = item.selected_modules || []
@@ -492,10 +621,23 @@ export function OrdersTable({ initialOrders }: OrdersTableProps) {
{/* Inhalt der Kasse: Hauptprodukt + Preis */}
{item.product_name}
- {(item.price || item.base_price) && (
-
- {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(item.price || item.base_price)}
-
+ {isEditingSnapshot ? (
+
+
+ updateItemBasePrice(idx, parseFloat(e.target.value) || 0)}
+ className="w-20 h-7 bg-slate-950 border-white/10 text-white text-xs px-2 font-mono"
+ />
+
+ ) : (
+ (item.price || item.base_price) && (
+
+ {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(item.price || item.base_price)}
+
+ )
)}
@@ -508,14 +650,34 @@ export function OrdersTable({ initialOrders }: OrdersTableProps) {
{modules.map((mod: any, mIdx: number) => (
-
+
- + {mod.module_name || mod.name} {mod.quantity > 1 ? `(${mod.quantity}x)` : ''}
+ + {mod.module_name || mod.name} {!isEditingSnapshot && mod.quantity > 1 ? `(${mod.quantity}x)` : ''}
- {mod.price && (
-
- +{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(mod.price)}
-
+ {isEditingSnapshot ? (
+
+ updateModulePriceOrQty(idx, mIdx, 'price', parseFloat(e.target.value) || 0)}
+ className="w-14 h-6 bg-slate-900 border-white/10 text-white text-[10px] px-1 font-mono"
+ />
+ x
+ updateModulePriceOrQty(idx, mIdx, 'quantity', parseInt(e.target.value) || 1)}
+ className="w-10 h-6 bg-slate-900 border-white/10 text-white text-[10px] px-1 font-mono"
+ />
+
+ ) : (
+ mod.price && (
+
+ +{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(mod.price * (mod.quantity || 1))}
+
+ )
)}
))}
@@ -571,34 +733,34 @@ export function OrdersTable({ initialOrders }: OrdersTableProps) {
-
-
+
+
-
-
+
+
)}
diff --git a/shop/components/customer-accordion-list.tsx b/shop/components/customer-accordion-list.tsx
index 72373b3..98f8235 100644
--- a/shop/components/customer-accordion-list.tsx
+++ b/shop/components/customer-accordion-list.tsx
@@ -1,6 +1,7 @@
'use client'
import React, { useState } from 'react'
+import { motion, AnimatePresence } from 'framer-motion'
import Link from 'next/link'
import type { EndCustomerWithDevices, FlattenedDevice } from '@/lib/types'
import {
@@ -250,7 +251,16 @@ export function CustomerAccordionList({ customers }: CustomerAccordionListProps)
{/* Akkordeon-Header */}
toggleCustomer(customer.id)}
- className="p-5 flex items-center justify-between cursor-pointer hover:bg-white/[0.02] transition-colors select-none gap-4 flex-wrap"
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault()
+ toggleCustomer(customer.id)
+ }
+ }}
+ tabIndex={0}
+ role="button"
+ aria-expanded={isOpen}
+ className="p-5 flex items-center justify-between cursor-pointer hover:bg-white/[0.02] transition-colors select-none gap-4 flex-wrap focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-inset"
>
@@ -324,28 +334,38 @@ export function CustomerAccordionList({ customers }: CustomerAccordionListProps)
{/* Ausgeklappter Bereich mit Kassen */}
- {isOpen && (
-
- {devices.length === 0 ? (
-
- Keine Kassen oder Bestellungen für diesen Kunden vorhanden.
+
+ {isOpen && (
+
+
+ {devices.length === 0 ? (
+
+ Keine Kassen oder Bestellungen für diesen Kunden vorhanden.
+
+ ) : (
+
+
+ Zugeordnete Kassen ({devices.length})
+
+ {devices.map((device, idx) => (
+
+ ))}
+
+ )}
- ) : (
-
-
- Zugeordnete Kassen ({devices.length})
-
- {devices.map((device, idx) => (
-
- ))}
-
- )}
-
- )}
+
+ )}
+
)
})}
diff --git a/shop/components/invoice-pdf.tsx b/shop/components/invoice-pdf.tsx
index c1e6a5a..2d5bddd 100644
--- a/shop/components/invoice-pdf.tsx
+++ b/shop/components/invoice-pdf.tsx
@@ -105,6 +105,8 @@ export const InvoicePDF = ({
const items = orderSnapshot?.items ?? [];
const taxRate = orderSnapshot?.tax_rate ?? 19;
const isSubscription = order?.type === 'subscription' || orderSnapshot?.billing_cycle === 'monthly';
+ const formattedOrderNumber = (order.order_number || order.id || '').replace(/^BE-/, 'AE-');
+ const isUpgrade = !!orderSnapshot?.last_license_date;
let oneTimeNet = 0;
let monthlyNet = 0;
@@ -162,7 +164,7 @@ export const InvoicePDF = ({
- Anfragebestätigung: {order.order_number || order.id}
+ {isUpgrade ? 'Erweiterungsangebot' : 'Anfragebestätigung'}: #{formattedOrderNumber}
@@ -177,7 +179,7 @@ export const InvoicePDF = ({
Bestelldetails
- Bestellnummer: {order.order_number || order.id}
+ Bestellnummer: #{formattedOrderNumber}
Zahlungsart: {isSubscription ? 'SEPA-Lastschrift' : 'Rechnung'}
Datum: {new Date(order.created_at || Date.now()).toLocaleDateString('de-DE')}
@@ -197,7 +199,7 @@ export const InvoicePDF = ({
- {deviceName === 'Zusatzleistung' ? 'Backoffice' : `Kasse: ${deviceName}`}
+ {deviceName === 'Zusatzleistung' ? 'Backoffice' : `${isUpgrade ? 'Erweiterung für Gerät' : 'Kasse'}: ${deviceName}`}
{devItems.map((item: any, idx: number) => (
diff --git a/shop/components/order-wizard.tsx b/shop/components/order-wizard.tsx
index 8e43404..ff5f1d8 100644
--- a/shop/components/order-wizard.tsx
+++ b/shop/components/order-wizard.tsx
@@ -1097,6 +1097,7 @@ export function OrderWizard({
billingBadgeClass={billingBadgeClass}
existingModuleIds={existingModuleIds}
activeCategoryId={activeCategoryId}
+ editingDeviceName={editingIdx !== null ? (basketItems[editingIdx]?.deviceName || `Kasse ${editingIdx + 1}`) : null}
/>
diff --git a/shop/components/wizard/step-software.tsx b/shop/components/wizard/step-software.tsx
index 0c7be32..e91ea75 100644
--- a/shop/components/wizard/step-software.tsx
+++ b/shop/components/wizard/step-software.tsx
@@ -29,6 +29,7 @@ interface StepSoftwareProps {
/** Modul-IDs, die bereits lizenziert sind (Upgrade-Modus) */
existingModuleIds?: string[]
activeCategoryId: string | null
+ editingDeviceName?: string | null
}
export function CategoryIcon({ icon, className }: { icon?: string | null; className?: string }) {
@@ -52,6 +53,7 @@ export function StepSoftware({
billingBadgeClass,
existingModuleIds = [],
activeCategoryId,
+ editingDeviceName = null,
}: StepSoftwareProps) {
const currentCategory = visibleCategories.find(c => c.id === activeCategoryId) ?? visibleCategories[0] ?? null
@@ -69,15 +71,22 @@ export function StepSoftware({
return (
-
-
- Optionen wählen
+
+
+
+ Optionen wählen
+
+ {editingDeviceName && (
+
+ ✏️ Bearbeite Kasse: "{editingDeviceName}"
+
+ )}
Passen Sie die Konfiguration für {currentCategory.name} an.
-
+
diff --git a/shop/components/wizard/step-summary.tsx b/shop/components/wizard/step-summary.tsx
index 11a40ee..ca27f77 100644
--- a/shop/components/wizard/step-summary.tsx
+++ b/shop/components/wizard/step-summary.tsx
@@ -70,6 +70,8 @@ export function StepSummary({
onAddNewBasketItem,
onDeleteBasketItem,
}: StepSummaryProps) {
+ const [confirmDeleteIdx, setConfirmDeleteIdx] = React.useState(null)
+
return (
{/* LINKER BEREICH: Scrollbares Bedienfeld */}
@@ -211,16 +213,26 @@ export function StepSummary({
{onDeleteBasketItem && (
)}
diff --git a/shop/components/wizard/summary-sidebar.tsx b/shop/components/wizard/summary-sidebar.tsx
index 29b7acc..f9dd17f 100644
--- a/shop/components/wizard/summary-sidebar.tsx
+++ b/shop/components/wizard/summary-sidebar.tsx
@@ -294,7 +294,11 @@ export function SummarySidebar({
onClick={nextStep}
disabled={isNextStepDisabled && basketItems.length === 0}
>
- Weiter zu Schritt 4
+ {editingIdx !== null ? (
+ <>Änderungen für "{basketItems[editingIdx]?.deviceName || `Kasse ${editingIdx + 1}`}" übernehmen>
+ ) : (
+ <>Weiter zu Schritt 4 >
+ )}