'use client' import { useState, useMemo, useCallback } from 'react' import { useSDK } from '@/lib/sdk' import { Database, Search, Plus, ChevronDown, ChevronRight, BarChart3, Layers, Users, Settings, } from 'lucide-react' import type { CatalogId, CatalogModule, CatalogEntry, CatalogMeta, CustomCatalogEntry, } from '@/lib/sdk/catalog-manager/types' import { CATALOG_MODULE_LABELS } from '@/lib/sdk/catalog-manager/types' import { CATALOG_REGISTRY, getAllEntries, getCatalogsByModule, getOverviewStats, searchCatalog, } from '@/lib/sdk/catalog-manager/catalog-registry' import CatalogModuleTabs from '@/components/catalog-manager/CatalogModuleTabs' import CatalogTable from '@/components/catalog-manager/CatalogTable' import CatalogEntryForm from '@/components/catalog-manager/CatalogEntryForm' // ============================================================================= // STAT CARD COMPONENT // ============================================================================= interface StatCardProps { icon: React.ReactNode label: string value: number color: 'violet' | 'blue' | 'emerald' | 'amber' } const colorMap = { violet: { bg: 'bg-violet-50 dark:bg-violet-900/20', text: 'text-violet-600 dark:text-violet-400', }, blue: { bg: 'bg-blue-50 dark:bg-blue-900/20', text: 'text-blue-600 dark:text-blue-400', }, emerald: { bg: 'bg-emerald-50 dark:bg-emerald-900/20', text: 'text-emerald-600 dark:text-emerald-400', }, amber: { bg: 'bg-amber-50 dark:bg-amber-900/20', text: 'text-amber-600 dark:text-amber-400', }, } function StatCard({ icon, label, value, color }: StatCardProps) { const colors = colorMap[color] return (
{icon}

{label}

{value.toLocaleString('de-DE')}

) } // ============================================================================= // MAIN CONTENT COMPONENT // ============================================================================= export function CatalogManagerContent() { const { state, dispatch } = useSDK() const customCatalogs = state.customCatalogs ?? {} // UI State const [activeModule, setActiveModule] = useState('all') const [selectedCatalogId, setSelectedCatalogId] = useState(null) const [searchQuery, setSearchQuery] = useState('') const [expandedCatalogs, setExpandedCatalogs] = useState>(new Set()) const [formState, setFormState] = useState<{ open: boolean catalog: CatalogMeta | null entry: CatalogEntry | null }>({ open: false, catalog: null, entry: null }) // Computed data const overviewStats = useMemo(() => getOverviewStats(customCatalogs), [customCatalogs]) const visibleCatalogs = useMemo(() => { if (activeModule === 'all') { return Object.values(CATALOG_REGISTRY) } return getCatalogsByModule(activeModule) }, [activeModule]) const selectedCatalog = selectedCatalogId ? CATALOG_REGISTRY[selectedCatalogId] : null const catalogEntries = useMemo(() => { if (!selectedCatalogId) return [] const custom = customCatalogs[selectedCatalogId] || [] if (searchQuery.trim()) { return searchCatalog(selectedCatalogId, searchQuery, custom) } return getAllEntries(selectedCatalogId, custom) }, [selectedCatalogId, customCatalogs, searchQuery]) // Handlers const toggleCatalogExpand = useCallback((id: CatalogId) => { setExpandedCatalogs(prev => { const next = new Set(prev) if (next.has(id)) { next.delete(id) } else { next.add(id) } return next }) }, []) const handleSelectCatalog = useCallback((id: CatalogId) => { setSelectedCatalogId(id) setSearchQuery('') }, []) const handleAddEntry = useCallback((catalog: CatalogMeta) => { setFormState({ open: true, catalog, entry: null }) }, []) const handleEditEntry = useCallback((catalog: CatalogMeta, entry: CatalogEntry) => { setFormState({ open: true, catalog, entry }) }, []) const handleCloseForm = useCallback(() => { setFormState({ open: false, catalog: null, entry: null }) }, []) const handleSaveEntry = useCallback((data: Record) => { if (!formState.catalog) return if (formState.entry && formState.entry.source === 'custom') { // Update existing custom entry dispatch({ type: 'UPDATE_CUSTOM_CATALOG_ENTRY', payload: { catalogId: formState.catalog.id, entryId: formState.entry.id, data, }, }) } else { // Create new custom entry const newEntry: CustomCatalogEntry = { id: crypto.randomUUID(), catalogId: formState.catalog.id, data, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } dispatch({ type: 'ADD_CUSTOM_CATALOG_ENTRY', payload: newEntry, }) } handleCloseForm() }, [formState, dispatch, handleCloseForm]) const handleDeleteEntry = useCallback((catalogId: CatalogId, entryId: string) => { dispatch({ type: 'DELETE_CUSTOM_CATALOG_ENTRY', payload: { catalogId, entryId }, }) }, [dispatch]) // ============================================================================= // RENDER // ============================================================================= return (
{/* Header */}

Katalogverwaltung

Alle SDK-Kataloge und Auswahltabellen zentral verwalten

{/* Stats Bar */}
} label="Kataloge" value={overviewStats.totalCatalogs} color="violet" /> } label="System-Eintraege" value={overviewStats.totalSystemEntries} color="blue" /> } label="Eigene Eintraege" value={overviewStats.totalCustomEntries} color="emerald" /> } label="Gesamt" value={overviewStats.totalEntries} color="amber" />
{/* Module Tabs */}
{/* Content Area */}
{/* Left: Catalog List */}

{activeModule === 'all' ? 'Alle Kataloge' : CATALOG_MODULE_LABELS[activeModule]} ({visibleCatalogs.length})

{visibleCatalogs.map(catalog => { const customCount = customCatalogs[catalog.id]?.length ?? 0 const isSelected = selectedCatalogId === catalog.id return ( ) })}
{/* Right: Catalog Detail / Table */}
{selectedCatalog ? (
{/* Catalog Header */}

{selectedCatalog.name}

{selectedCatalog.description}

{CATALOG_MODULE_LABELS[selectedCatalog.module]} {selectedCatalog.allowCustom && ( Erweiterbar )}
{/* Table */} handleEditEntry(selectedCatalog, entry)} onDeleteCustomEntry={(entryId) => handleDeleteEntry(selectedCatalog.id, entryId)} onAddEntry={() => handleAddEntry(selectedCatalog)} />
) : ( /* Empty State */

Katalog auswaehlen

Waehlen Sie einen Katalog aus der Liste links, um dessen Eintraege anzuzeigen und zu verwalten.

)}
{/* Form Modal */} {formState.open && formState.catalog && ( )}
) }