/** * TrusteeDocumentsView * * Dokument-Verwaltung für eine Trustee-Instanz. * Verwendet FormGeneratorTable für konsistentes UI. */ import React, { useState, useMemo, useEffect } from 'react'; import { useTrusteeDocuments, useTrusteeDocumentOperations, TrusteeDocument } from '../../../hooks/useTrustee'; import { useInstanceId } from '../../../hooks/useCurrentInstance'; import { FormGeneratorTable } from '../../../components/FormGenerator/FormGeneratorTable'; import { FormGeneratorForm } from '../../../components/FormGenerator/FormGeneratorForm'; import { FaSync, FaDownload } from 'react-icons/fa'; import { useToast } from '../../../contexts/ToastContext'; import api from '../../../api'; import styles from '../../admin/Admin.module.css'; import { useLanguage } from '../../../providers/language/LanguageContext'; export const TrusteeDocumentsView: React.FC = () => { const { t } = useLanguage(); const { showError } = useToast(); const instanceId = useInstanceId(); // Entity hook const { items: documents, attributes, permissions, pagination, loading, error, refetch, fetchById, updateOptimistically, removeOptimistically, } = useTrusteeDocuments(); // Operations hook const { handleDelete, handleCreate, handleUpdate, deletingItems, } = useTrusteeDocumentOperations(); // Modal state const [editingDocument, setEditingDocument] = useState(null); const [isCreateMode, setIsCreateMode] = useState(false); const [downloadingId, setDownloadingId] = useState(null); // 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 canUpdate = permissions?.update !== 'n'; const canDelete = permissions?.delete !== 'n'; // Handle edit click const handleEditClick = async (doc: TrusteeDocument) => { const fullDoc = await fetchById(doc.id); if (fullDoc) { setEditingDocument(fullDoc); setIsCreateMode(false); } }; // Handle create click const handleCreateClick = () => { setEditingDocument(null); setIsCreateMode(true); }; // Handle form submit const handleFormSubmit = async (data: Partial) => { if (isCreateMode) { const result = await handleCreate(data); if (result.success) { setIsCreateMode(false); refetch(); } } else if (editingDocument) { const result = await handleUpdate(editingDocument.id, data); if (result.success) { setEditingDocument(null); refetch(); } } }; // Handle delete (confirmation handled by DeleteActionButton) const handleDeleteDoc = async (doc: TrusteeDocument) => { removeOptimistically(doc.id); const success = await handleDelete(doc.id); if (!success) { refetch(); // Revert on error } }; // Handle download const handleDownload = async (doc: TrusteeDocument) => { if (!instanceId) return; setDownloadingId(doc.id); try { const response = await api.get( `/api/trustee/${instanceId}/documents/${doc.id}/data`, { responseType: 'blob' } ); const blob = new Blob([response.data], { type: doc.documentMimeType }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = doc.documentName || 'document'; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); } catch (err) { console.error('Download error:', err); showError(t('Fehler'), t('Fehler beim Herunterladen des Dokuments.')); } finally { setDownloadingId(null); } }; // Close modal const handleCloseModal = () => { setEditingDocument(null); setIsCreateMode(false); }; // Form attributes (exclude system fields) const formAttributes = useMemo(() => { const excludedFields = ['id', 'mandateId', 'instanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy']; return (attributes || []).filter(attr => !excludedFields.includes(attr.name)); }, [attributes]); // Handle inline update const handleInlineUpdate = async (itemId: string, updateData: Partial, row: TrusteeDocument) => { updateOptimistically(itemId, updateData); const result = await handleUpdate(itemId, { ...row, ...updateData }); if (!result.success) { refetch(); // Revert on error } }; if (error) { return (
⚠️

{t('Fehler beim Laden der Dokumente: {detail}', { detail: String(error) })}

); } return (

{t('Belege und Dokumente verwalten')}

{canCreate && ( )}
deletingItems.has(row.id), }] : []), ]} customActions={[ { id: 'download', icon: , onClick: handleDownload, title: t('Herunterladen'), loading: (row: TrusteeDocument) => downloadingId === row.id, }, ]} onDelete={handleDeleteDoc} hookData={{ refetch, permissions, pagination, handleDelete, handleInlineUpdate, updateOptimistically, }} emptyMessage={t('Keine Dokumente gefunden')} />
{/* Create/Edit Modal */} {(editingDocument || isCreateMode) && (
e.stopPropagation()}>

{isCreateMode ? t('Neues Dokument') : t('Dokument bearbeiten')}

{formAttributes.length === 0 ? (
{t('Formular laden')}
) : ( )}
)}
); }; export default TrusteeDocumentsView;