'use client'; import type { CmsFieldType } from '../schema/module.schema'; interface FieldDefinition { name: string; display_name: string; field_type: CmsFieldType; show_in_table: boolean; is_sortable: boolean; sort_order: number; } interface ModuleRecord { id: string; data: Record; status: string; created_at: string; updated_at: string; } interface Pagination { page: number; pageSize: number; total: number; totalPages: number; } interface ModuleTableProps { fields: FieldDefinition[]; records: ModuleRecord[]; pagination: Pagination; onPageChange: (page: number) => void; onSort: (field: string, direction: 'asc' | 'desc') => void; onRowClick?: (recordId: string) => void; selectedIds?: Set; onSelectionChange?: (ids: Set) => void; currentSort?: { field: string; direction: 'asc' | 'desc' }; } /** * Dynamic data table driven by module field definitions. * Replaces the legacy my_modulklasse table rendering. * Uses native table for now; Phase 3 enhancement will use @kit/ui/data-table. */ export function ModuleTable({ fields, records, pagination, onPageChange, onSort, onRowClick, selectedIds = new Set(), onSelectionChange, currentSort, }: ModuleTableProps) { const visibleFields = fields .filter((f) => f.show_in_table) .sort((a, b) => a.sort_order - b.sort_order); const formatCellValue = (value: unknown, fieldType: CmsFieldType): string => { if (value == null || value === '') return '—'; switch (fieldType) { case 'checkbox': return value ? '✓' : '✗'; case 'currency': return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(Number(value)); case 'date': try { return new Date(String(value)).toLocaleDateString('de-DE'); } catch { return String(value); } case 'password': return '••••••'; default: return String(value); } }; const handleSort = (fieldName: string) => { const newDirection = currentSort?.field === fieldName && currentSort.direction === 'asc' ? 'desc' : 'asc'; onSort(fieldName, newDirection); }; return (
{onSelectionChange && ( )} {visibleFields.map((field) => ( ))} {records.length === 0 ? ( ) : ( records.map((record) => ( onRowClick?.(record.id)} > {onSelectionChange && ( )} {visibleFields.map((field) => ( ))} )) )}
0 && records.every((r) => selectedIds.has(r.id))} onChange={(e) => { if (e.target.checked) { onSelectionChange(new Set(records.map((r) => r.id))); } else { onSelectionChange(new Set()); } }} /> field.is_sortable && handleSort(field.name)} > {field.display_name} {currentSort?.field === field.name && ( {currentSort.direction === 'asc' ? '↑' : '↓'} )}
Keine Datensätze gefunden
e.stopPropagation()}> { const next = new Set(selectedIds); if (e.target.checked) { next.add(record.id); } else { next.delete(record.id); } onSelectionChange(next); }} /> {formatCellValue(record.data[field.name], field.field_type)}
{/* Pagination */} {pagination.totalPages > 1 && (
{pagination.total} Datensätze — Seite {pagination.page} von {pagination.totalPages}
)}
); }