diff --git a/shop/app/my-orders/MyOrdersClient.tsx b/shop/app/my-orders/MyOrdersClient.tsx index 196d8d4..6d0ca95 100644 --- a/shop/app/my-orders/MyOrdersClient.tsx +++ b/shop/app/my-orders/MyOrdersClient.tsx @@ -2,7 +2,7 @@ import React, { useState, useMemo } from 'react' import Link from 'next/link' -import { Download, ExternalLink, ShoppingBag, ArrowLeft, Package, Search, ChevronLeft, ChevronRight } from 'lucide-react' +import { Download, ExternalLink, ShoppingBag, ArrowLeft, Package, Search, ChevronLeft, ChevronRight, Building2, Monitor, RefreshCw, FileText } from 'lucide-react' import { Button } from '@/components/ui/button' import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' @@ -35,24 +35,38 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) { const [currentPage, setCurrentPage] = useState(1) const pageSize = 10 + const fmt = (val: number) => new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(val) + // Volltextsuche filtern const filteredOrders = useMemo(() => { const term = searchTerm.toLowerCase().trim() if (!term) return orders return orders.filter(o => { - // Order number + // Anfragenummer if (o.order_number?.toString().toLowerCase().includes(term)) return true - // Status label or raw status + // Status const label = statusLabel[o.status] || o.status if (label.toLowerCase().includes(term) || o.status.toLowerCase().includes(term)) return true - // Date + // Datum const dateStr = new Date(o.created_at).toLocaleDateString('de-DE') if (dateStr.includes(term)) return true - // Order items (device name, product name, module name) + // Endkunde (Firma / Name) + const customer = (o as any).end_customer_data || o.order_data?.end_customer + if (customer) { + if (customer.company_name?.toLowerCase().includes(term)) return true + if (customer.first_name?.toLowerCase().includes(term)) return true + if (customer.last_name?.toLowerCase().includes(term)) return true + if (customer.customer_number?.toLowerCase().includes(term)) return true + } + + // Notizen + if (o.notes?.toLowerCase().includes(term)) return true + + // Kassen & Module const items = o.order_data?.items ?? [] for (const item of items) { if (item.device_name?.toLowerCase().includes(term)) return true @@ -82,23 +96,30 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) { return (
-
+
{/* Header */} -
- - + +
+

+ + Meine Anfragen +

+

+ Alle Ihre Bestellungen und Konfigurationen auf einen Blick. +

+
+
+ + -
-

- - Meine Anfragen -

-

- Alle Ihre Anfragen auf einen Blick – inkl. aktuellem Status. -

-
{/* Suche & Statistik */} @@ -107,14 +128,16 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) {
-
- Gefunden: {filteredOrders.length} von {orders.length} Anfragen +
+ Anfragen: + {filteredOrders.length} + {searchTerm && (gefiltert aus {orders.length})}
@@ -156,84 +179,130 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) {
{paginatedOrders.map((o) => { const items = o.order_data?.items ?? [] + const customer = (o as any).end_customer_data || o.order_data?.end_customer + return ( - - - {/* Kopfzeile */} -
+ + + {/* Header-Zeile der Karte */} +
-

Anfragenummer

-

#{o.order_number}

+
+ Anfragenummer + + {statusLabel[o.status] ?? o.status} + +
+

#{o.order_number}

-
-

Datum

-

+ + {/* Endkunde Details (falls vorhanden) */} + {customer && ( +

+ +
+

{customer.company_name || `${customer.first_name} ${customer.last_name}`}

+ {(customer.first_name || customer.city) && ( +

+ {[customer.first_name && customer.last_name ? `${customer.first_name} ${customer.last_name}` : null, customer.city].filter(Boolean).join(' · ')} +

+ )} +
+
+ )} + +
+

Datum & Preis

+

{new Date(o.created_at).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', })}

-
-
-

Status

- - {statusLabel[o.status] ?? o.status} - -
-
-

Gesamt

-

- {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(o.total_price)} +

+ {fmt(o.total_price)}

- {/* Produkte kurz */} + {/* Kassen & Produkte Detail-Übersicht */} {items.length > 0 && ( -
- {items.map((item, idx) => ( - - {item.device_name || 'Kasse'}: - {item.product_name} - {item.selected_modules.length > 0 && ( - - (+{item.selected_modules.length} {item.selected_modules.length === 1 ? 'Modul' : 'Module'}) - - )} - - ))} +
+

+ + Enthaltene Kassen ({items.length}): +

+
+ {items.map((item, idx) => ( +
+
+ + + {item.device_name || `Kasse ${idx + 1}`} + + + {item.billing_interval === 'one_time' ? 'Kauf' : 'Abo'} + +
+

{item.product_name}

+ {item.license_number && ( +

Lizenz: {item.license_number}

+ )} + {item.selected_modules && item.selected_modules.length > 0 && ( +
+ {item.selected_modules.map((mod: any, mIdx: number) => ( + + + {mod.module_name || mod.name} {mod.quantity > 1 ? `(${mod.quantity}x)` : ''} + + ))} +
+ )} +
+ ))} +
)} - {/* Aktionen */} -
- - - - {o.status !== 'completed' && ( - - - )} + {o.status !== 'completed' && ( + + + + )} +
+ {o.pdf_url && ( - <> - - - +
)}
@@ -255,7 +324,7 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) { size="sm" onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} - className="border-white/10 text-xs gap-1" + className="border-white/10 text-xs gap-1 rounded-xl" > Vorherige @@ -264,7 +333,7 @@ export function MyOrdersClient({ orders, error }: MyOrdersClientProps) { size="sm" onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages} - className="border-white/10 text-xs gap-1" + className="border-white/10 text-xs gap-1 rounded-xl" > Nächste