import { useEffect, useRef, useState } from 'react' import { deleteDocument, fetchDocuments } from '../api/api' import { useToast } from './Toast' function fileIcon(name) { const ext = name.split('.').pop()?.toLowerCase() const configs = { pdf: { bg: 'bg-red-50', text: 'text-red-500', label: 'PDF' }, docx: { bg: 'bg-blue-50', text: 'text-blue-500', label: 'DOC' }, doc: { bg: 'bg-blue-50', text: 'text-blue-500', label: 'DOC' }, xlsx: { bg: 'bg-emerald-50', text: 'text-emerald-600', label: 'XLS' }, xls: { bg: 'bg-emerald-50', text: 'text-emerald-600', label: 'XLS' }, png: { bg: 'bg-purple-50', text: 'text-purple-500', label: 'IMG' }, jpg: { bg: 'bg-purple-50', text: 'text-purple-500', label: 'IMG' }, jpeg: { bg: 'bg-purple-50', text: 'text-purple-500', label: 'IMG' }, } return configs[ext] ?? { bg: 'bg-stone-100', text: 'text-stone-500', label: 'DOC' } } function formatBytes(bytes) { if (!bytes) return '' if (bytes < 1024) return `${bytes} B` if (bytes < 1048576) return `${(bytes / 1024).toFixed(0)} KB` return `${(bytes / 1048576).toFixed(1)} MB` } export default function DocumentList({ refreshSignal, onDocumentSelect }) { const toast = useToast() const [docs, setDocs] = useState([]) const [loading, setLoading] = useState(false) const [fetchError, setFetchError] = useState(false) const [deletingDoc, setDeletingDoc] = useState(null) const [confirmDelete, setConfirmDelete] = useState(null) // Track the confirm-timeout per document so switching docs doesn't clear the wrong timer const confirmTimerRef = useRef(null) const load = async () => { setLoading(true) setFetchError(false) try { setDocs(await fetchDocuments()) } catch { setFetchError(true) toast.error('Failed to load documents.') } finally { setLoading(false) } } // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { load() }, [refreshSignal]) const handleDelete = async (name) => { if (confirmDelete !== name) { // Cancel any pending confirmation timer before starting a new one if (confirmTimerRef.current) clearTimeout(confirmTimerRef.current) setConfirmDelete(name) confirmTimerRef.current = setTimeout(() => { setConfirmDelete(null) confirmTimerRef.current = null }, 3000) return } if (confirmTimerRef.current) { clearTimeout(confirmTimerRef.current); confirmTimerRef.current = null } setConfirmDelete(null); setDeletingDoc(name) try { await deleteDocument(name); toast.success(`"${name}" deleted.`); await load() } catch { toast.error('Failed to delete document.') } finally { setDeletingDoc(null) } } if (loading && !docs.length) { return (
{[1, 2, 3].map(i => (
))}
) } if (fetchError) { return (

Failed to load documents

) } if (!docs.length) { return (

No documents yet

Upload a document to get started

) } return ( ) } const EmptyIcon = () => ( ) const ErrorIcon = () => ( ) const TrashIcon = () => ( ) const ConfirmIcon = () => ( )