import { useState, useEffect, useRef } from 'react'; import Header from './components/Header'; import ConsultorCard from './components/ConsultorCard'; import CompararModal from './components/CompararModal'; import FiltroSelos from './components/FiltroSelos'; import { rankingService } from './services/api'; import './App.css'; function App() { const [consultores, setConsultores] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [processing, setProcessing] = useState(false); const [processMessage, setProcessMessage] = useState(''); const processStartedRef = useRef(false); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(50); const [totalPages, setTotalPages] = useState(0); const [highlightId, setHighlightId] = useState(null); const [busca, setBusca] = useState(''); const [buscando, setBuscando] = useState(false); const [selecionados, setSelecionados] = useState([]); const [modalAberto, setModalAberto] = useState(false); const [filtroSelos, setFiltroSelos] = useState([]); const toggleSelecionado = (consultor) => { setSelecionados((prev) => { const existe = prev.find((c) => c.id_pessoa === consultor.id_pessoa); if (existe) { return prev.filter((c) => c.id_pessoa !== consultor.id_pessoa); } if (prev.length >= 2) { return [prev[1], consultor]; } return [...prev, consultor]; }); }; const limparSelecao = () => { setSelecionados([]); setModalAberto(false); }; useEffect(() => { loadRanking(); }, [page, pageSize, filtroSelos]); const loadRanking = async (retryCount = 0) => { const MAX_RETRIES = 10; const RETRY_DELAY = 2000; try { setLoading(true); setError(null); setProcessMessage(''); const response = await rankingService.getRanking(page, pageSize, filtroSelos); setConsultores(response.consultores); setTotal(response.total); setTotalPages(response.total_pages || 0); setPage(response.page || page); } catch (err) { const status = err?.response?.status; const isNetworkError = !err?.response || err?.code === 'ERR_NETWORK'; if (isNetworkError && retryCount < MAX_RETRIES) { setProcessMessage(`Aguardando API... (tentativa ${retryCount + 1}/${MAX_RETRIES})`); await new Promise((r) => setTimeout(r, RETRY_DELAY)); return loadRanking(retryCount + 1); } if (status === 503) { try { setProcessing(true); if (!processStartedRef.current) { processStartedRef.current = true; setProcessMessage('Ranking ainda não processado. Iniciando processamento...'); try { await rankingService.processarRanking(true); } catch (e) { const st = e?.response?.status; if (st !== 409) throw e; // 409 = job já em execução (ex.: StrictMode) } } else { setProcessMessage('Processamento do ranking já iniciado. Aguardando...'); } const MAX_POLLING_TIME = 45 * 60 * 1000; const POLLING_INTERVAL = 4000; const startTime = Date.now(); while (Date.now() - startTime < MAX_POLLING_TIME) { try { const st = await rankingService.getStatus(); setProcessMessage(st.mensagem || `Processando... ${st.progress || 0}%`); if (!st.running) { if (st.erro) throw new Error(st.erro); break; } } catch (e) { setProcessMessage('Aguardando status do processamento...'); } await new Promise((r) => setTimeout(r, POLLING_INTERVAL)); } if (Date.now() - startTime >= MAX_POLLING_TIME) { throw new Error('Timeout: processamento demorou mais que 45 minutos'); } const response = await rankingService.getRanking(page, pageSize, filtroSelos); setConsultores(response.consultores); setTotal(response.total); setTotalPages(response.total_pages || 0); setPage(response.page || page); } catch (e) { console.error('Erro ao processar ranking:', e); setError('Erro ao processar ranking. Verifique a conexão com o Elasticsearch.'); } finally { setProcessing(false); } return; } console.error('Erro ao carregar ranking:', err); setError('Erro ao carregar ranking. Verifique se a API está rodando.'); } finally { setLoading(false); } }; const handleBuscar = async () => { if (busca.trim().length < 3) return; try { setBuscando(true); const resultados = await rankingService.searchConsultor(busca.trim(), 5); if (resultados && resultados.length > 0) { const alvo = resultados[0]; const pos = alvo.posicao || 1; const pagina = Math.ceil(pos / pageSize); setHighlightId(alvo.id_pessoa); setPage(pagina); } else { alert('Nenhum consultor encontrado.'); } } catch (err) { alert('Erro ao buscar consultor.'); } finally { setBuscando(false); } }; const handleSubmitBuscar = (e) => { e.preventDefault(); if (buscando) return; handleBuscar(); }; if (loading) { return (
{processMessage || (processing ? 'Processando ranking...' : 'Carregando ranking...')}
); } if (error) { return (

Erro

{error}

); } return (
{ setFiltroSelos(selos); setPage(1); }} />
setBusca(e.target.value)} />
Página {page} de {totalPages || '?'}
{consultores.map((consultor) => ( c.id_pessoa === consultor.id_pessoa)} onToggleSelecionado={toggleSelecionado} /> ))}
{selecionados.length > 0 && (
{selecionados.length}/2 selecionados {selecionados.map((c) => ( {c.nome.split(' ')[0]} ))}
)} {modalAberto && ( setModalAberto(false)} /> )}
); } export default App;