/** * TrusteePositionDocumentsView * * Verknüpfungs-Verwaltung zwischen Positionen und Dokumenten. * Verwendet FormGeneratorTable mit Spalten aus den Pydantic-Attributen. */ 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, handleUpdate, deletingItems, creatingItem, } = useTrusteePositionDocumentOperations(); // Modal state const [isCreateMode, setIsCreateMode] = useState(false); const [editingLink, setEditingLink] = useState(null); // Initial fetch useEffect(() => { if (instanceId) { refetch(); } }, [instanceId]); // Generate columns from attributes (like TrusteePositionsView) // Map frontend_options to fkSource for FK resolution const columns = useMemo(() => { if (!attributes || attributes.length === 0) return []; // Exclude system fields from table columns const excludedFields = ['id', 'mandateId', 'featureInstanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy']; return attributes .filter(attr => !excludedFields.includes(attr.name)) .map(attr => { // Replace {instanceId} placeholder in options URL let fkSource = attr.options; if (typeof fkSource === 'string' && instanceId) { fkSource = fkSource.replace('{instanceId}', instanceId); } return { 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 || 200, minWidth: attr.minWidth || 100, maxWidth: attr.maxWidth || 400, // Use frontend_options as fkSource for FK resolution fkSource: typeof fkSource === 'string' ? fkSource : undefined, fkDisplayField: 'label', }; }); }, [attributes, instanceId]); // Check permissions (general level) // Row-level permissions are handled automatically by FormGeneratorTable const canCreate = permissions?.create !== 'n'; const canUpdate = permissions?.update !== 'n'; const canDelete = permissions?.delete !== 'n'; // Handle create click const handleCreateClick = () => { setIsCreateMode(true); }; // Handle edit click const handleEditClick = (link: TrusteePositionDocument) => { setEditingLink(link); }; // Handle create form submit const handleFormSubmit = async (data: Partial) => { const result = await handleCreate(data); if (result.success) { setIsCreateMode(false); refetch(); } }; // Handle edit form submit const handleEditSubmit = async (data: Partial) => { if (!editingLink) return; const result = await handleUpdate(editingLink.id, data); if (result.success) { setEditingLink(null); refetch(); } }; // Handle delete (confirmation handled by DeleteActionButton) const handleDeleteLink = async (link: TrusteePositionDocument) => { 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', 'featureInstanceId', '_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), // Row-level permissions handled automatically by FormGeneratorTable }] : []), ]} attributes={formAttributes} onEdit={handleEditClick} 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...
) : ( )}
)} {/* Edit Modal */} {editingLink && (
setEditingLink(null)}>
e.stopPropagation()}>

Verknüpfung bearbeiten

{formAttributes.length === 0 ? (
Lade Formular...
) : ( setEditingLink(null)} submitButtonText="Speichern" cancelButtonText="Abbrechen" instanceId={instanceId} /> )}
)}
); }; export default TrusteePositionDocumentsView;