diff --git a/frontend-react/src/pages/ReportsPage.tsx b/frontend-react/src/pages/ReportsPage.tsx index 3361d74..aa6b5c5 100644 --- a/frontend-react/src/pages/ReportsPage.tsx +++ b/frontend-react/src/pages/ReportsPage.tsx @@ -581,7 +581,9 @@ export default function ReportsPage() { const setEmbedAdb = store.setRptEmbedAdb; const embedTable = store.rptEmbedTable; const setEmbedTable = store.setRptEmbedTable; - const [embedLoading, setEmbedLoading] = useState(''); // '' = idle, 'all' = full embed, section name = section embed + const embedTaskId = store.rptEmbedTaskId; + const setEmbedTaskId = store.setRptEmbedTaskId; + const [embedLoading, setEmbedLoading] = useState(''); const [embedMsg, setEmbedMsg] = useState<{ type: 's' | 'e'; text: string } | null>(null); const [embedProgress, setEmbedProgress] = useState<{ inserted: number; skipped: number; processed: number; total: number } | null>(null); @@ -782,37 +784,53 @@ export default function ReportsPage() { } }; - const pollEmbeddingStatus = useCallback(async (taskId: string) => { - setEmbedMsg({ type: 's', text: 'Embedding iniciado...' }); - setEmbedProgress(null); + const pollEmbeddingStatus = useCallback((taskId: string) => { + setEmbedMsg({ type: 's', text: 'Embedding em andamento...' }); + setEmbedTaskId(taskId); const poll = setInterval(async () => { try { const s = await reportsApi.embeddingStatus(taskId); - if (s.total) { - setEmbedProgress({ - inserted: s.inserted || 0, - skipped: (s as unknown as Record).skipped || 0, - processed: (s as unknown as Record).processed || s.inserted || 0, - total: s.total, - }); + const data = s as unknown as Record; + const total = (data.total as number) || 0; + const inserted = (data.inserted as number) || 0; + const skipped = (data.skipped as number) || 0; + const processed = (data.processed as number) || inserted; + + if (total > 0) { + setEmbedProgress({ inserted, skipped, processed, total }); + } + + if (s.status === 'done') { + clearInterval(poll); + setEmbedProgress({ inserted, skipped, processed: total, total }); + setEmbedMsg({ type: 's', text: s.message }); + setTimeout(() => { setEmbedProgress(null); setEmbedLoading(''); setEmbedTaskId(''); }, 3000); + return; + } + if (s.status === 'error') { + clearInterval(poll); + setEmbedMsg({ type: 'e', text: s.message }); + setTimeout(() => { setEmbedProgress(null); setEmbedLoading(''); setEmbedTaskId(''); }, 3000); + return; } if (s.status === 'running') { setEmbedMsg({ type: 's', text: s.message }); - } else if (s.status === 'done') { - clearInterval(poll); - setEmbedMsg({ type: 's', text: s.message }); - setEmbedProgress(null); - setEmbedLoading(''); - } else if (s.status === 'error') { - clearInterval(poll); - setEmbedMsg({ type: 'e', text: s.message }); - setEmbedProgress(null); - setEmbedLoading(''); } - } catch { /* keep polling */ } + } catch { + // Network error — keep polling + } }, 2000); - setTimeout(() => { clearInterval(poll); setEmbedLoading(''); setEmbedProgress(null); }, 300000); - }, []); + // Cleanup on unmount + return () => clearInterval(poll); + }, [setEmbedTaskId]); + + // Resume polling if returning to page with active embed task + useEffect(() => { + if (!embedTaskId) return; + setEmbedLoading('all'); + const cleanup = pollEmbeddingStatus(embedTaskId); + return cleanup; + }, []); // eslint-disable-line react-hooks/exhaustive-deps const handleEmbed = async (rid: string) => { const adbId = embedAdb || (adbCfg.length > 0 ? adbCfg[0].id : ''); @@ -1530,7 +1548,7 @@ export default function ReportsPage() { {sec} ({secFiles.length}) - {adbCfg.length > 0 && secFiles.some((f) => f.file_name.endsWith('.csv')) && ( + {adbCfg.length > 0 && sec !== 'Error' && sec !== 'Other' && secFiles.some((f) => f.file_name.endsWith('.csv')) && (