import React, { useState, useEffect } from 'react'; import { IoIosTrash, IoIosCheckmark, IoIosClose } from 'react-icons/io'; import { useLanguage } from '../../../../contexts/LanguageContext'; import { useFileOperations, useUserFiles } from '../../../../hooks/useFiles'; import styles from '../ActionButton.module.css'; export interface DeleteActionButtonProps { row: T; disabled?: boolean; loading?: boolean; className?: string; title?: string; confirmTitle?: string; cancelTitle?: string; containerRef?: React.RefObject; onSuccess?: (row: T) => void; onError?: (row: T, error: string) => void; hookData?: any; // Contains all hook data including operations and refetch // Field mappings idField?: string; // Field name for the unique identifier operationName?: string; // Name of the delete operation in hookData loadingStateName?: string; // Name of the loading state in hookData } export function DeleteActionButton({ row, disabled = false, loading = false, className = '', title, confirmTitle, cancelTitle, containerRef, onSuccess, onError, hookData, idField = 'id', operationName = 'handleDelete', loadingStateName = 'deletingFiles' }: DeleteActionButtonProps) { const { t } = useLanguage(); const [isConfirming, setIsConfirming] = useState(false); const [isDeleting, setIsDeleting] = useState(false); // Use hook data if available, otherwise fall back to direct hook calls const handleDelete = hookData?.[operationName]; const removeOptimistically = hookData?.removeFileOptimistically || hookData?.removeOptimistically; const refetch = hookData?.refetch; const loadingState = hookData?.[loadingStateName]; // Fallback to direct hook calls if hookData not provided const { handleFileDelete: fallbackHandleDelete } = useFileOperations(); const { removeFileOptimistically: fallbackRemoveFileOptimistically, refetch: fallbackRefetch } = useUserFiles(); const finalHandleDelete = handleDelete || fallbackHandleDelete; const finalRemoveOptimistically = removeOptimistically || fallbackRemoveFileOptimistically; const finalRefetch = refetch || fallbackRefetch; // Handle clicks outside delete confirmation buttons useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (isConfirming && containerRef?.current) { if (!containerRef.current.contains(event.target as Node)) { setIsConfirming(false); } } }; if (isConfirming) { document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; } }, [isConfirming, containerRef]); const handleDeleteClick = (e: React.MouseEvent) => { e.stopPropagation(); if (!disabled && !loading && !isDeleting) { setIsConfirming(true); } }; const handleConfirmDelete = async (e: React.MouseEvent) => { e.stopPropagation(); setIsDeleting(true); try { // Get ID from row using configurable field name const itemId = (row as any)[idField]; if (!itemId) { throw new Error(`${idField} not found`); } // Immediately remove from UI for instant feedback if (finalRemoveOptimistically) { finalRemoveOptimistically(itemId); } // Call the delete API const success = await finalHandleDelete(itemId); if (success) { // Refetch to ensure UI is properly updated if (finalRefetch) { await finalRefetch(); } onSuccess?.(row); } else { // Refetch to restore the file in case of failure if (finalRefetch) { await finalRefetch(); } onError?.(row, 'Delete failed'); } } catch (error: any) { console.error('Delete failed:', error); onError?.(row, error.message || 'Delete failed'); // Refetch to restore the file in case of failure if (finalRefetch) { await finalRefetch(); } } finally { setIsDeleting(false); setIsConfirming(false); } }; const handleCancelDelete = (e: React.MouseEvent) => { e.stopPropagation(); setIsConfirming(false); }; const buttonTitle = title || t('files.action.delete', 'Delete'); const confirmButtonTitle = confirmTitle || t('formgen.delete.confirm', 'Confirm delete'); const cancelButtonTitle = cancelTitle || t('formgen.delete.cancel', 'Cancel delete'); // Use loading state from hookData if available const isDeletingFromHook = loadingState?.has((row as any)[idField]) || false; if (isConfirming) { return (
); } return ( ); } export default DeleteActionButton;