/** * PromptsPage * * Page for managing prompt templates using FormGeneratorTable. * Follows the pattern established in AdminUsersPage/WorkflowsPage. */ import React, { useState, useMemo, useEffect, useCallback } from 'react'; import { usePrompts, usePromptOperations } from '../../hooks/usePrompts'; import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable'; import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm'; import { FaSync, FaPlus } from 'react-icons/fa'; import styles from '../admin/Admin.module.css'; import { useLanguage } from '../../providers/language/LanguageContext'; import { resolveColumnTypes } from '../../utils/columnTypeResolver'; interface Prompt { id: string; name: string; content: string; [key: string]: any; } export const PromptsPage: React.FC = () => { const { t } = useLanguage(); // Data hook const { prompts, attributes, permissions, pagination, loading, error, refetch, fetchPromptById, updateOptimistically, } = usePrompts(); // Operations hook const { handlePromptCreate, handlePromptUpdate, handlePromptDelete, handleInlineUpdate, deletingPrompts, } = usePromptOperations(); const [showCreateModal, setShowCreateModal] = useState(false); const [editingPrompt, setEditingPrompt] = useState(null); // ── Table refetch wrapper (stable signature used by FormGeneratorTable) ── const _tableRefetch = useCallback(async (params?: any) => { await refetch(params); }, [refetch]); // ── Refresh-All for the header "Aktualisieren" button ──────────────────── // Forces a paginated request so the cache key matches what the table uses // internally. This guarantees fresh (non-cached) data is pulled in. const _refreshAll = useCallback(async () => { await _tableRefetch({ page: 1, pageSize: 25 }); }, [_tableRefetch]); // Initial fetch useEffect(() => { _tableRefetch({ page: 1, pageSize: 25 }); }, [_tableRefetch]); // Generate columns from attributes - exclude ID fields from display const columns = useMemo(() => { // Fields to hide in table view const hiddenColumns = ['id', 'mandateId', 'sysCreatedAt', 'sysModifiedAt', '_hideDelete', '_permissions']; const cols = (attributes || []) .filter(attr => !hiddenColumns.includes(attr.name)) .map(attr => ({ key: attr.name, label: attr.label || attr.name, sortable: attr.sortable !== false, filterable: attr.filterable !== false, searchable: attr.searchable !== false, width: attr.name === 'content' ? 300 : attr.width || 150, minWidth: attr.minWidth || 100, maxWidth: attr.name === 'content' ? 500 : attr.maxWidth || 400, displayField: (attr as any).displayField, frontendFormat: (attr as any).frontendFormat, frontendFormatLabels: (attr as any).frontendFormatLabels, })); // Add sysCreatedBy column with FK resolution to show username cols.push({ key: 'sysCreatedBy', label: t('Erstellt von'), sortable: true, filterable: true, searchable: true, width: 150, minWidth: 100, maxWidth: 250, displayField: 'sysCreatedByLabel', frontendFormat: undefined, frontendFormatLabels: undefined, }); return resolveColumnTypes(cols, attributes || []); }, [attributes, t]); // Check permissions const canCreate = permissions?.create !== 'n'; const canUpdate = permissions?.update !== 'n'; const canDelete = permissions?.delete !== 'n'; // Handle edit click const handleEditClick = async (prompt: Prompt) => { const fullPrompt = await fetchPromptById(prompt.id); if (fullPrompt) { setEditingPrompt(fullPrompt as Prompt); } }; // Handle create submit const handleCreateSubmit = async (data: Partial) => { const result = await handlePromptCreate({ name: data.name || '', content: data.content || '' }); if (result?.success) { setShowCreateModal(false); _refreshAll(); } }; // Handle edit submit const handleEditSubmit = async (data: Partial) => { if (!editingPrompt) return; const result = await handlePromptUpdate(editingPrompt.id, { name: data.name || editingPrompt.name, content: data.content || editingPrompt.content }); if (result.success) { setEditingPrompt(null); _refreshAll(); } }; // Handle delete single prompt (confirmation handled by DeleteActionButton) const handleDelete = async (prompt: Prompt) => { const success = await handlePromptDelete(prompt.id); if (success) { _refreshAll(); } }; // Form attributes for create/edit modal const formAttributes = useMemo(() => { const excludedFields = ['id', 'mandateId', 'isSystem', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', '_hideDelete', '_permissions']; return (attributes || []) .filter(attr => !excludedFields.includes(attr.name)); }, [attributes]); if (error) { return (
⚠️

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

); } return (

{t('Prompts')}

{t('Prompt-Templates verwalten')}

{canCreate && ( )}
deletingPrompts.has(row.id), }] : []), ]} onDelete={handleDelete} hookData={{ refetch: _tableRefetch, permissions, pagination, handleDelete: handlePromptDelete, handleInlineUpdate, updateOptimistically, }} emptyMessage={t('Keine Prompts gefunden')} />
{/* Create Modal */} {showCreateModal && (

{t('Neuer Prompt')}

{formAttributes.length === 0 ? (
{t('Formular laden')}
) : ( setShowCreateModal(false)} submitButtonText={t('Erstellen')} cancelButtonText={t('Abbrechen')} /> )}
)} {/* Edit Modal */} {editingPrompt && (

{t('Prompt bearbeiten')}

{formAttributes.length === 0 ? (
{t('Formular laden')}
) : ( setEditingPrompt(null)} submitButtonText={t('Speichern')} cancelButtonText={t('Abbrechen')} /> )}
)}
); }; export default PromptsPage;