import { useState, useMemo } from 'react'; import { usePrompts, usePromptOperations, Prompt } from '../../hooks/usePrompts'; import { useLanguage } from '../../contexts/LanguageContext'; import type { EditFieldConfig } from '../ui/Popup/EditForm'; // Helper function to determine if a prompt can be deleted const isPromptDeletable = (prompt: Prompt): boolean => { // Primary check: If backend explicitly sets _hideDelete, respect that if (prompt._hideDelete === true) { return false; } // Hardcoded list of the six default system prompt IDs that cannot be deleted const systemPromptIds = [ "097d34f0-9fcc-4233-bf1e-e64e13818464", "17546dc6-b792-40e1-9aa1-0fcc4860d0c1", "17c42519-2bf6-49b4-83f9-3cde7498310c", "2bb85d1e-4e02-4de8-98ae-0e815267d864", "93343a5b-49f0-4dbf-9513-2ab5f6938fd8", "cfb51260-486f-4b42-96fe-ef03f406dcf1" ]; // Check if this prompt is one of the system default prompts return !systemPromptIds.includes(prompt.id); }; import type { PromptsLogicReturn, PromptActionConfig, PromptColumnConfig } from './promptsTypes'; export function usePromptsLogic(): PromptsLogicReturn { const { prompts, loading, error, refetch } = usePrompts(); const { t } = useLanguage(); const { handlePromptDelete, handlePromptUpdate, deletingPrompts } = usePromptOperations(); // Edit modal state const [editModalOpen, setEditModalOpen] = useState(false); const [editingPrompt, setEditingPrompt] = useState(null); // Configure edit fields for prompt editing const editPromptFields: EditFieldConfig[] = useMemo(() => [ { key: 'name', label: t('prompts.field.name', 'Prompt Name'), type: 'string', editable: true, required: true, validator: (value: string) => { if (!value || value.trim() === '') { return t('prompts.validation.nameRequired', 'Prompt name cannot be empty'); } if (value.length > 100) { return t('prompts.validation.nameTooLong', 'Prompt name cannot exceed 100 characters'); } return null; } }, { key: 'content', label: t('prompts.field.content', 'Prompt Content'), type: 'textarea', editable: true, required: true, minRows: 4, maxRows: 8, validator: (value: string) => { if (!value || value.trim() === '') { return t('prompts.validation.contentRequired', 'Prompt content cannot be empty'); } if (value.length > 10000) { return t('prompts.validation.contentTooLong', 'Prompt content cannot exceed 10,000 characters'); } return null; } } ], [t]); // Configure columns for the prompts table const columns: PromptColumnConfig[] = useMemo(() => [ { key: 'name', label: t('prompts.column.name', 'Name'), type: 'string', width: 200, minWidth: 150, maxWidth: 300, sortable: true, filterable: true, searchable: true, formatter: (value: string | undefined) => ( {value || t('prompts.unnamed', 'Unnamed')} ) }, { key: 'content', label: t('prompts.column.content', 'Content'), type: 'string', width: 400, minWidth: 200, maxWidth: 600, sortable: true, filterable: true, searchable: true, formatter: (value: string | undefined) => ( {value && value.length > 100 ? `${value.substring(0, 100)}...` : value || '-'} ) } ], [t]); // Handle prompt actions const handleDeletePrompt = async (prompt: Prompt) => { const promptName = prompt.name || prompt.id; if (window.confirm(t('prompts.delete.confirm', 'Are you sure you want to delete "{name}"?').replace('{name}', promptName))) { const success = await handlePromptDelete(prompt.id); if (success) { refetch(); // Refresh the prompts list } } }; // Handle single prompt deletion for bulk delete const handleDeleteSingle = async (prompt: Prompt) => { const promptName = prompt.name || prompt.id; if (window.confirm(t('prompts.delete.confirm', 'Are you sure you want to delete "{name}"?').replace('{name}', promptName))) { const success = await handlePromptDelete(prompt.id); if (success) { refetch(); // Refresh the prompts list } else { console.error('Delete failed for prompt:', prompt.id); } } }; // Handle multiple prompt deletion const handleDeleteMultiple = async (promptsToDelete: Prompt[]) => { const promptCount = promptsToDelete.length; if (window.confirm(t('prompts.delete.confirmMultiple', 'Are you sure you want to delete {count} prompts?').replace('{count}', promptCount.toString()))) { // Start all delete operations simultaneously const deletePromises = promptsToDelete.map(async (prompt) => { try { const success = await handlePromptDelete(prompt.id); return { promptId: prompt.id, success }; } catch (error) { console.error('Failed to delete prompt:', prompt.id, error); return { promptId: prompt.id, success: false }; } }); // Wait for all deletions to complete const results = await Promise.all(deletePromises); // Check if any deletions failed const failedDeletions = results.filter(result => !result.success); if (failedDeletions.length > 0) { console.error('Some prompt deletions failed:', failedDeletions); } // Refresh the prompt list regardless of individual failures refetch(); } }; // Handle edit prompt const handleEditPrompt = (prompt: Prompt) => { setEditingPrompt(prompt); setEditModalOpen(true); }; // Handle save prompt const handleSavePrompt = async (updatedPrompt: Prompt) => { if (!editingPrompt) return; try { // Call API to update prompt - backend requires full Prompt object const updateData = { id: editingPrompt.id, name: updatedPrompt.name, content: updatedPrompt.content, mandateId: editingPrompt.mandateId }; const result = await handlePromptUpdate(editingPrompt.id, updateData); if (result.success) { // Close modal setEditModalOpen(false); setEditingPrompt(null); // Refresh prompt list await refetch(); // Notify other components that prompts have been updated window.dispatchEvent(new CustomEvent('promptUpdated', { detail: { promptId: editingPrompt.id, newName: updatedPrompt.name } })); } else { console.error('Failed to update prompt:', result.error); // TODO: Show error message to user } } catch (error) { console.error('Failed to update prompt:', error); // TODO: Show error message to user } }; // Handle cancel edit const handleCancelEdit = () => { setEditModalOpen(false); setEditingPrompt(null); }; // Handle copy prompt const handleCopyPrompt = async (prompt: Prompt) => { try { // Use the modern Clipboard API if available if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(prompt.content); } else { // Fallback for older browsers or non-secure contexts const textArea = document.createElement('textarea'); textArea.value = prompt.content; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; textArea.style.top = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); } // Show success feedback const promptName = prompt.name || t('prompts.unnamed', 'Unnamed'); console.log(`Copied content of "${promptName}" to clipboard`); // Optional: You could add a toast notification here in the future // showToast(t('prompts.copy.success', 'Prompt content copied to clipboard'), 'success'); } catch (error) { console.error('Failed to copy prompt content:', error); // Optional: You could add a toast notification here in the future // showToast(t('prompts.copy.error', 'Failed to copy prompt content'), 'error'); } }; // Configure action buttons const actions: PromptActionConfig[] = useMemo(() => [ { type: 'edit', title: t('prompts.action.edit', 'Edit'), onAction: (row: Prompt) => { handleEditPrompt(row); } }, { type: 'copy', title: t('prompts.action.copy', 'Copy'), onAction: (row: Prompt) => { handleCopyPrompt(row); } }, { type: 'delete', title: (row: Prompt) => { const isDeletable = isPromptDeletable(row); return isDeletable ? t('prompts.action.delete', 'Delete') : t('prompts.action.delete.disabled', 'No permission to delete prompt'); }, disabled: (row: Prompt) => !isPromptDeletable(row) // onAction is handled by FormGenerator for delete confirmation }, ] as any, [t, deletingPrompts, handleDeletePrompt, handleEditPrompt, handleCopyPrompt]); return { // Data prompts, loading, error, // Actions handleDeleteSingle, handleDeleteMultiple, handleEditPrompt, handleCopyPrompt, // Refetch function refetch, // Additional data for rendering columns, actions, // Edit modal state editModalOpen, editingPrompt, editPromptFields, // Edit modal actions handleSavePrompt, handleCancelEdit }; }