import { useEffect, useState, useMemo, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import Layout from '../components/Layout'; import RecordModal from '../components/RecordModal'; import CreateModal, { hasCreateForm } from '../components/CreateModal'; import { fetchAll, apiDelete } from '../lib/api'; import { TABLES, STATUS_COLORS } from '../lib/tables'; function truncate(str, n = 60) { if (str == null) return '—'; const s = String(str); return s.length > n ? s.slice(0, n) + '…' : s; } function CellValue({ col, value, linkedFields, navigate }) { if (value == null || value === '') return ; // Array of IDs (e.g. picture_ids, word_ids) if (Array.isArray(value)) { if (value.length === 0) return []; const targetTable = linkedFields[col]; return (
{value.slice(0, 3).map(id => ( ))} {value.length > 3 && ( +{value.length - 3} )}
); } // Single UUID FK (e.g. question_id) if (typeof value === 'string' && linkedFields[col]) { const targetTable = linkedFields[col]; return ( ); } // Status badge if (col === 'status') { const cls = STATUS_COLORS[value] || 'bg-slate-100 text-slate-600'; return {value}; } // Timestamp if (col.endsWith('_at') || col.endsWith('_timestamp')) { return {new Date(value).toLocaleDateString('de-DE')}; } // Picture link — show as thumbnail + link if (col === 'picture_link') { return ( Bild öffnen ); } return {truncate(value)}; } export default function TableView() { const { tableKey } = useParams(); const navigate = useNavigate(); const meta = TABLES[tableKey]; const [rows, setRows] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [textFilter, setTextFilter] = useState(''); const [highlightId, setHighlightId] = useState(null); const [modalRecord, setModalRecord] = useState(null); const [showCreate, setShowCreate] = useState(false); const [confirmDeleteId, setConfirmDeleteId] = useState(null); const [deleting, setDeleting] = useState(false); useEffect(() => { const params = new URLSearchParams(window.location.search); const id = params.get('id'); if (id) setHighlightId(id); }, []); useEffect(() => { if (!meta) return; setLoading(true); fetchAll(meta.endpoint) .then(data => setRows(Array.isArray(data) ? data : [])) .catch(err => setError(err.message)) .finally(() => setLoading(false)); }, [meta]); const statuses = useMemo(() => { const set = new Set(rows.map(r => r.status).filter(Boolean)); return [...set].sort(); }, [rows]); const filtered = useMemo(() => { return rows.filter(row => { if (statusFilter && row.status !== statusFilter) return false; if (textFilter) { const q = textFilter.toLowerCase(); return Object.values(row).some(v => v != null && String(v).toLowerCase().includes(q) ); } return true; }); }, [rows, statusFilter, textFilter]); function handleRecordSaved(updated) { setRows(prev => prev.map(r => (r.id === updated.id ? { ...r, ...updated } : r))); } function handleRecordCreated(newRecord) { setRows(prev => [newRecord, ...prev]); } const handleDelete = useCallback(async (id, e) => { e.stopPropagation(); setDeleting(true); try { await apiDelete(meta.endpoint, id); setRows(prev => prev.filter(r => r.id !== id)); setConfirmDeleteId(null); if (modalRecord?.id === id) setModalRecord(null); } catch (err) { alert('Fehler beim Löschen: ' + err.message); } finally { setDeleting(false); } }, [meta, modalRecord]); if (!meta) return

Unbekannte Tabelle: {tableKey}

; return (

{meta.icon} {meta.label} ({filtered.length}{rows.length === 500 ? '+' : ''} von {rows.length}{rows.length === 500 ? '+' : ''})

{hasCreateForm(tableKey) && ( )}
{/* Filters */}
setTextFilter(e.target.value)} className="border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white w-56" /> {meta.statusField && statuses.length > 0 && ( )} {(statusFilter || textFilter) && ( )}
{error &&
{error}
} {loading ? (
{[...Array(5)].map((_, i) => (
))}
) : (
{meta.columns.map(col => ( ))} {filtered.length === 0 && ( )} {filtered.map((row, i) => ( setModalRecord(row)} className={`group border-b border-slate-100 hover:bg-slate-50 transition-colors cursor-pointer ${highlightId && row.id === highlightId ? 'bg-indigo-50 ring-1 ring-indigo-300' : ''}`} > {meta.columns.map(col => ( ))} {/* Delete cell */} ))}
{col}
Keine Einträge gefunden
e.stopPropagation()}> {confirmDeleteId === row.id ? ( ) : ( )}
)} {modalRecord && ( setModalRecord(null)} onSaved={handleRecordSaved} /> )} {showCreate && ( setShowCreate(false)} onCreated={handleRecordCreated} /> )} ); }