/** * RealEstateProjectsView * * Projekt-Verwaltung für eine Real Estate/PEK-Instanz. * Verwendet FormGeneratorTable analog zu TrusteeDocumentsView. */ import React, { useState, useMemo, useEffect } from 'react'; import { useRealEstateProjects, useRealEstateProjectOperations, type RealEstateProject, } from '../../../hooks/useRealEstate'; import { useInstanceId } from '../../../hooks/useCurrentInstance'; import { FormGeneratorTable } from '../../../components/FormGenerator/FormGeneratorTable'; import { FormGeneratorForm } from '../../../components/FormGenerator/FormGeneratorForm'; import { FaSync } from 'react-icons/fa'; import styles from '../../admin/Admin.module.css'; export const RealEstateProjectsView: React.FC = () => { const instanceId = useInstanceId(); const { items: projects, attributes, permissions, pagination, loading, error, refetch, fetchById, updateOptimistically, removeOptimistically, } = useRealEstateProjects(); const { handleDelete, handleCreate, handleUpdate, deletingItems, } = useRealEstateProjectOperations(); const [editingProject, setEditingProject] = useState(null); const [isCreateMode, setIsCreateMode] = useState(false); useEffect(() => { if (instanceId) refetch(); }, [instanceId, refetch]); const columns = useMemo(() => { return (attributes || []).map(attr => ({ key: attr.name, label: attr.label || attr.name, type: (attr.type || 'string') as 'string' | 'number' | 'date' | 'boolean', 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]); const canCreate = permissions?.create !== 'n'; const canUpdate = permissions?.update !== 'n'; const canDelete = permissions?.delete !== 'n'; const handleEditClick = async (project: RealEstateProject) => { const full = await fetchById(project.id); if (full) { setEditingProject(full); setIsCreateMode(false); } }; const handleCreateClick = () => { setEditingProject(null); setIsCreateMode(true); }; const handleFormSubmit = async (data: Partial) => { if (isCreateMode) { const result = await handleCreate(data); if (result.success) { setIsCreateMode(false); refetch(); } } else if (editingProject) { const result = await handleUpdate(editingProject.id, data); if (result.success) { setEditingProject(null); refetch(); } } }; const handleDeleteProject = async (project: RealEstateProject) => { removeOptimistically(project.id); const success = await handleDelete(project.id); if (!success) refetch(); }; const handleCloseModal = () => { setEditingProject(null); setIsCreateMode(false); }; const formAttributes = useMemo(() => { const excluded = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy']; return (attributes || []).filter(attr => !excluded.includes(attr.name)); }, [attributes]); const handleInlineUpdate = async (itemId: string, updateData: Partial, row: RealEstateProject) => { updateOptimistically(itemId, updateData); const result = await handleUpdate(itemId, { ...row, ...updateData }); if (!result.success) refetch(); }; if (error) { return (
⚠️

Fehler beim Laden der Projekte: {error}

); } return (

Projekte verwalten

{canCreate && ( )}
deletingItems.has(row.id) }] : []), ]} onDelete={handleDeleteProject} hookData={{ refetch, permissions, pagination, handleDelete, handleInlineUpdate, updateOptimistically }} emptyMessage="Keine Projekte gefunden" />
{(editingProject || isCreateMode) && (
e.stopPropagation()}>

{isCreateMode ? 'Neues Projekt' : 'Projekt bearbeiten'}

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