/** * TrusteePositionDocumentsView * * Verknüpfungs-Verwaltung zwischen Positionen und Dokumenten. * Verwendet FormGeneratorTable für konsistentes UI. */ import React, { useState, useMemo, useEffect } from 'react'; import { useTrusteePositionDocuments, useTrusteePositionDocumentOperations, TrusteePositionDocument } from '../../../hooks/useTrustee'; import { useInstanceId } from '../../../hooks/useCurrentInstance'; import { FormGeneratorTable } from '../../../components/FormGenerator/FormGeneratorTable'; import { FormGeneratorForm } from '../../../components/FormGenerator/FormGeneratorForm'; import { FaSync, FaLink } from 'react-icons/fa'; import styles from '../../admin/Admin.module.css'; export const TrusteePositionDocumentsView: React.FC = () => { const instanceId = useInstanceId(); // Entity hook const { items: links, attributes, permissions, pagination, loading, error, refetch, removeOptimistically, } = useTrusteePositionDocuments(); // Operations hook const { handleDelete, handleCreate, deletingItems, creatingItem, } = useTrusteePositionDocumentOperations(); // Modal state const [isCreateMode, setIsCreateMode] = useState(false); // Initial fetch useEffect(() => { if (instanceId) { refetch(); } }, [instanceId]); // Generate columns from attributes const columns = useMemo(() => { return (attributes || []).map(attr => ({ key: attr.name, label: attr.label || attr.name, type: attr.type as any, sortable: attr.sortable !== false, filterable: attr.filterable !== false, searchable: attr.searchable !== false, width: attr.width || 150, minWidth: attr.minWidth || 100, maxWidth: attr.maxWidth || 400, })); }, [attributes]); // Check permissions const canCreate = permissions?.create !== 'n'; const canDelete = permissions?.delete !== 'n'; // Handle create click const handleCreateClick = () => { setIsCreateMode(true); }; // Handle form submit const handleFormSubmit = async (data: Partial) => { const result = await handleCreate(data); if (result.success) { setIsCreateMode(false); refetch(); } }; // Handle delete const handleDeleteLink = async (link: TrusteePositionDocument) => { if (window.confirm('Verknüpfung wirklich entfernen?')) { removeOptimistically(link.id); const success = await handleDelete(link.id); if (!success) { refetch(); // Revert on error } } }; // Close modal const handleCloseModal = () => { setIsCreateMode(false); }; // Form attributes (exclude system fields) const formAttributes = useMemo(() => { const excludedFields = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy']; return (attributes || []).filter(attr => !excludedFields.includes(attr.name)); }, [attributes]); if (error) { return (
⚠️

Fehler beim Laden der Verknüpfungen: {error}

); } return (

Belege mit Buchungspositionen verknüpfen

{canCreate && ( )}
{loading && (!links || links.length === 0) ? (
Lade Verknüpfungen...
) : !links || links.length === 0 ? (

Keine Verknüpfungen vorhanden

Verknüpfen Sie Belege mit Buchungspositionen.

{canCreate && ( )}
) : ( deletingItems.has(row.id), }] : []), ]} onDelete={handleDeleteLink} hookData={{ refetch, permissions, pagination, handleDelete, }} emptyMessage="Keine Verknüpfungen gefunden" /> )}
{/* Create Modal */} {isCreateMode && (
e.stopPropagation()}>

Neue Verknüpfung erstellen

{formAttributes.length === 0 ? (
Lade Formular...
) : ( )}
)}
); }; export default TrusteePositionDocumentsView;