From a4414cc0e6790091fe2e7d15dc4ca779ede01f1d Mon Sep 17 00:00:00 2001 From: DanielS Date: Fri, 3 Jul 2026 00:03:48 +0200 Subject: [PATCH] Angebote bearbeiten fuer Admin und Ersteller implementiert --- shop/app/my-orders/page.tsx | 7 + shop/app/order/page.tsx | 41 ++++- shop/components/admin/orders-table.tsx | 39 +++-- shop/components/order-wizard.tsx | 86 +++++++--- shop/lib/actions/orders.ts | 228 +++++++++++++++++++++++++ 5 files changed, 359 insertions(+), 42 deletions(-) diff --git a/shop/app/my-orders/page.tsx b/shop/app/my-orders/page.tsx index 08739fe..27908d2 100644 --- a/shop/app/my-orders/page.tsx +++ b/shop/app/my-orders/page.tsx @@ -132,6 +132,13 @@ export default async function MyOrdersPage() { Details ansehen + {o.status === 'pending' && ( + + + + )} {o.pdf_url && ( <> - - - ) : ( - Keine Bestätigung - )} +
+ + {order.pdf_url ? ( + <> + + + + ) : ( + Keine Bestätigung + )} +
); diff --git a/shop/components/order-wizard.tsx b/shop/components/order-wizard.tsx index fddbcf6..8d9f8f5 100644 --- a/shop/components/order-wizard.tsx +++ b/shop/components/order-wizard.tsx @@ -3,7 +3,7 @@ import { useState, useMemo } from 'react' import { useRouter } from 'next/navigation' import { motion, AnimatePresence } from 'framer-motion' -import { Product, ProductModule, Profile, EndCustomer } from '@/lib/types' +import { Product, ProductModule, Profile, EndCustomer, Order } from '@/lib/types' import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' @@ -12,7 +12,7 @@ import { Label } from '@/components/ui/label' import { Separator } from '@/components/ui/separator' import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group' import { Check, ChevronRight, ChevronLeft, ShoppingCart, User, ShieldCheck, Cloud, Utensils, HardDrive, Package, AlertCircle, Loader2, UserPlus, Building2, CreditCard, Calendar, Search } from 'lucide-react' -import { submitOrder } from '@/lib/actions/orders' +import { submitOrder, updateOrder } from '@/lib/actions/orders' import { createEndCustomer } from '@/lib/actions/end-customers' import { Category } from '@/lib/types' import { Badge } from '@/components/ui/badge' @@ -80,11 +80,13 @@ export function OrderWizard({ categories, initialProfile, initialEndCustomers, + initialOrder, }: { products: Product[] categories: Category[] initialProfile: Profile | null initialEndCustomers: EndCustomer[] + initialOrder?: Order | null }) { const router = useRouter() const [step, setStep] = useState(1) @@ -96,7 +98,9 @@ export function OrderWizard({ // Endkunden-State const [endCustomers, setEndCustomers] = useState(initialEndCustomers) const [selectedEndCustomerId, setSelectedEndCustomerId] = useState( - initialEndCustomers.length > 0 ? initialEndCustomers[0].id : null + initialOrder + ? initialOrder.end_customer_id + : (initialEndCustomers.length > 0 ? initialEndCustomers[0].id : null) ) const selectedEndCustomer = endCustomers.find(c => c.id === selectedEndCustomerId) ?? null @@ -134,13 +138,26 @@ export function OrderWizard({ }) // Abrechnungsmodell-Auswahl ('one_time' = Kauf, 'monthly' = Abo) - const [selectedBillingInterval, setSelectedBillingInterval] = useState<'one_time' | 'monthly'>('monthly') + const [selectedBillingInterval, setSelectedBillingInterval] = useState<'one_time' | 'monthly'>( + initialOrder?.order_data?.billing_cycle ?? 'monthly' + ) // Modulmengen (moduleId -> Menge) - const [moduleQuantities, setModuleQuantities] = useState>({}) + const [moduleQuantities, setModuleQuantities] = useState>(() => { + if (!initialOrder) return {} + const quantities: Record = {} + initialOrder.order_data?.items?.forEach(item => { + item.selected_modules?.forEach(mod => { + quantities[mod.module_id] = mod.quantity ?? 1 + }) + }) + return quantities + }) // Datum der letzten Lizenz (Bestandskunden-Update-Logik) - const [lastLicenseDate, setLastLicenseDate] = useState("") + const [lastLicenseDate, setLastLicenseDate] = useState( + initialOrder?.order_data?.last_license_date ?? "" + ) const lastLicenseMonths = useMemo(() => { if (!lastLicenseDate || customerMode !== 'select' || !selectedEndCustomerId) return null @@ -174,6 +191,16 @@ export function OrderWizard({ const [selections, setSelections] = useState>(() => { const init: Record = {} categories.forEach(cat => { + if (initialOrder) { + const item = initialOrder.order_data?.items?.find(i => i.category_id === cat.id) + if (item) { + init[cat.id] = { + productId: item.product_id, + moduleIds: item.selected_modules?.map(m => m.module_id) ?? [] + } + return + } + } const first = products.find(p => p.category_id === cat.id && p.show_in_abo !== false) init[cat.id] = { productId: first?.id ?? null, moduleIds: [] } }) @@ -335,21 +362,34 @@ export function OrderWizard({ if (isSubmitting) return // Doppelklick-Guard setIsSubmitting(true) try { - const order = await submitOrder({ - selections, - moduleQuantities, - products, - categories, - customerProfile: customerData, - endCustomerId: selectedEndCustomerId, - endCustomer: selectedEndCustomer, - billingInterval: selectedBillingInterval, - lastLicenseDate: lastLicenseDate || null, - }) + let order + if (initialOrder) { + order = await updateOrder(initialOrder.id, { + selections, + moduleQuantities, + customerProfile: customerData, + endCustomerId: selectedEndCustomerId, + endCustomer: selectedEndCustomer, + billingInterval: selectedBillingInterval, + lastLicenseDate: lastLicenseDate || null, + }) + } else { + order = await submitOrder({ + selections, + moduleQuantities, + products, + categories, + customerProfile: customerData, + endCustomerId: selectedEndCustomerId, + endCustomer: selectedEndCustomer, + billingInterval: selectedBillingInterval, + lastLicenseDate: lastLicenseDate || null, + }) + } router.push(`/order/success?id=${order.id}`) - } catch (error) { + } catch (error: any) { console.error(error) - alert('Fehler bei der Bestellung. Bitte versuchen Sie es erneut.') + alert(error?.message || (initialOrder ? 'Fehler beim Aktualisieren des Angebots.' : 'Fehler bei der Bestellung. Bitte versuchen Sie es erneut.')) setIsSubmitting(false) // Nur bei Fehler wieder entsperren } } @@ -1106,9 +1146,13 @@ export function OrderWizard({ disabled={isSubmitting} > {isSubmitting ? ( - <> Bestellung wird verarbeitet... + initialOrder ? ( + <> Angebot wird aktualisiert... + ) : ( + <> Bestellung wird verarbeitet... + ) ) : ( - 'Kostenpflichtig bestellen' + initialOrder ? 'Angebot aktualisieren' : 'Kostenpflichtig bestellen' )}