'use client' import React from 'react' import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/card' import { Separator } from '@/components/ui/separator' import { Checkbox } from '@/components/ui/checkbox' import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group' import { Label } from '@/components/ui/label' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { ShoppingCart, Check, AlertCircle, Lock } from 'lucide-react' import * as Icons from 'lucide-react' import { motion, AnimatePresence } from 'framer-motion' import { Category, Product, CategorySelection } from '@/lib/types' interface StepSoftwareProps { visibleCategories: Category[] products: Product[] selections: Record selectProduct: (catId: string, prodId: string) => void isProductDisabled: (prod: Product, catId: string) => boolean isModuleDisabled: (mod: any, selectedModIds: string[]) => boolean toggleModule: (catId: string, modId: string) => void moduleQuantities: Record setModuleQuantities: React.Dispatch>> selectedBillingInterval: 'one_time' | 'monthly' billingLabel: (interval: string) => string billingBadgeClass: (interval: string) => string /** 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 }) { const LucideIcon = icon ? (Icons as any)[icon] : null if (!LucideIcon) return return } export function StepSoftware({ visibleCategories, products, selections, selectProduct, isProductDisabled, isModuleDisabled, toggleModule, moduleQuantities, setModuleQuantities, selectedBillingInterval, billingLabel, billingBadgeClass, existingModuleIds = [], activeCategoryId, editingDeviceName = null, }: StepSoftwareProps) { const currentCategory = visibleCategories.find(c => c.id === activeCategoryId) ?? visibleCategories[0] ?? null if (!currentCategory) return null const catProducts = products.filter(p => { if (p.category_id !== currentCategory.id) return false return selectedBillingInterval === 'one_time' ? p.show_in_kauf !== false : p.show_in_abo !== false }) const sel = selections[currentCategory.id] const selectedProduct = catProducts.find(p => p.id === sel?.productId) ?? null return (
Optionen wählen
{editingDeviceName && ( ✏️ Bearbeite Kasse: "{editingDeviceName}" )}
Passen Sie die Konfiguration für {currentCategory.name} an.
{/* Category header */} {(() => { const isMissingRequired = currentCategory.is_required && !sel?.productId && (!sel?.productIds || sel.productIds.length === 0) return (

{currentCategory.name} {isMissingRequired && ( PFLICHTFELD AUSWÄHLEN! )}

{currentCategory.description && (

{currentCategory.description}

)}
{sel?.productIds && sel.productIds.length > 0 ? ( {sel.productIds.length} Ausgewählt ) : sel?.productId ? ( Ausgewählt ) : currentCategory.is_required ? ( Bitte auswählen! ) : ( Optional )}
) })()} {catProducts.length === 0 ? (

Keine Produkte in dieser Kategorie im aktuellen Abrechnungsmodell vorhanden.

) : currentCategory.allow_multiselect ? (
{catProducts.map(product => { const isChecked = sel?.productIds?.includes(product.id) ?? false const disabled = isProductDisabled(product, currentCategory.id) return (
) })}
) : ( selectProduct(currentCategory.id, id)} className="grid gap-3" > {catProducts.map(product => { const disabled = isProductDisabled(product, currentCategory.id) const isChecked = sel?.productId === product.id return (
) })}
)} {/* Modules */} {selectedProduct?.modules && selectedProduct.modules.length > 0 && (

Zusatzmodule für {selectedProduct.name}

{selectedProduct.modules.map(module => { const isExistingLicense = existingModuleIds.includes(module.id) const disabled = isExistingLicense || isModuleDisabled(module, sel?.moduleIds ?? []) const checked = isExistingLicense || (sel?.moduleIds.includes(module.id) ?? false) return (
!isExistingLicense && toggleModule(currentCategory.id, module.id)} disabled={disabled} className="rounded border-white/20 data-[state=checked]:bg-primary" />
{module.description && (

{module.description}

)} {!isExistingLicense && disabled && (

{module.requirements?.length && !module.requirements.some( reqId => sel?.moduleIds.includes(reqId) ) ? 'Benötigt weitere Module' : 'Nicht kombinierbar mit aktueller Auswahl'}

)}
{/* Scalable Quantity */} {checked && !isExistingLicense && module.has_quantity && (
{ const val = Math.max(1, parseInt(e.target.value) || 1) setModuleQuantities(prev => ({ ...prev, [module.id]: val })) }} className="w-16 h-8 bg-white/5 border-white/10 text-white text-xs text-center rounded-lg focus:border-primary focus:ring-1 focus:ring-primary" /> Gesamt:{' '} {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', }).format(module.price * (moduleQuantities[module.id] || 1))}
)}
) })}
)}
) }