import { useCallback, useEffect, useRef, useState } from "react"; import Sidebar from "./components/Sidebar.jsx"; import Topbar from "./components/Topbar.jsx"; import RunModal from "./components/RunModal.jsx"; import Toasts from "./components/Toasts.jsx"; import Dashboard from "./views/Dashboard.jsx"; import Opportunities from "./views/Opportunities.jsx"; import Leads from "./views/Leads.jsx"; import Tasks from "./views/Tasks.jsx"; import Satisfaction from "./views/Satisfaction.jsx"; import Cancellations from "./views/Cancellations.jsx"; import Search from "./views/Search.jsx"; import Alerts from "./views/Alerts.jsx"; import Trends from "./views/Trends.jsx"; import Report from "./views/Report.jsx"; import Config from "./views/Config.jsx"; import { verificarSaude, listarDias, buscarDia, rodarAgente } from "./api.js"; let proximoIdToast = 1; export default function App() { const [view, setView] = useState("dashboard"); const [sidebarAberta, setSidebarAberta] = useState(false); const [tema, setTema] = useState(localStorage.getItem("af_theme") === "dark" ? "dark" : "light"); const [online, setOnline] = useState(null); const [dias, setDias] = useState([]); const [dia, setDia] = useState(null); const [carregandoDia, setCarregandoDia] = useState(false); const [erroDia, setErroDia] = useState(null); const [runModalAberto, setRunModalAberto] = useState(false); const [executando, setExecutando] = useState(false); const [segundos, setSegundos] = useState(0); const [toasts, setToasts] = useState([]); const timerRef = useRef(null); const notificar = useCallback((mensagem, tipo) => { const id = proximoIdToast++; setToasts((t) => [...t, { id, mensagem, tipo }]); setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 3500); }, []); useEffect(() => { document.documentElement.setAttribute("data-theme", tema); }, [tema]); const checarSaude = useCallback(async () => { try { await verificarSaude(); setOnline(true); } catch { setOnline(false); } }, []); const carregarDia = useCallback( async (data) => { if (!data || data === "—") return; setCarregandoDia(true); setErroDia(null); try { const d = await buscarDia(data); setDia(d); } catch (e) { setErroDia({ mensagem: e.message, data }); notificar("Falha ao carregar o dia: " + e.message, "bad"); } finally { setCarregandoDia(false); } }, [notificar] ); const carregarDias = useCallback(async () => { try { const d = await listarDias(); const lista = d.dates || []; setDias(lista); if (lista.length && (!dia || !lista.includes(dia.date))) { carregarDia(lista[0]); } } catch { /* mantém a tela anterior; o indicador "Offline" já avisa. */ } // eslint-disable-next-line react-hooks/exhaustive-deps }, [dia]); useEffect(() => { checarSaude(); carregarDias(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); function irPara(v) { setView(v); setSidebarAberta(false); } function alternarTema() { const novo = tema === "dark" ? "light" : "dark"; setTema(novo); localStorage.setItem("af_theme", novo); } function recarregar() { carregarDias(); if (dia) carregarDia(dia.date); notificar("Atualizando…"); } const [erroExecucao, setErroExecucao] = useState(null); async function executarAgente(payload) { setExecutando(true); setErroExecucao(null); setSegundos(0); timerRef.current = setInterval(() => setSegundos((s) => s + 1), 1000); try { const resultado = await rodarAgente(payload); setDia(resultado); setErroDia(null); notificar("Execução concluída ✓", "ok"); setRunModalAberto(false); carregarDias(); } catch (e) { setErroExecucao(e.message); notificar("Falha: " + e.message, "bad"); } finally { clearInterval(timerRef.current); setExecutando(false); checarSaude(); } } function renderConteudo() { if (view === "config") return { checarSaude(); carregarDias(); }} />; if (view === "tendencias") return ; if (view === "busca") return ; if (erroDia && !dia) { return (
⚠️
Não foi possível carregar {erroDia.data}
{erroDia.mensagem}
); } if (!dia) { if (carregandoDia) { return (
{Array.from({ length: 6 }).map((_, i) => (
))}
); } return (
Nenhum dia carregado.

Clique em ▶ Rodar para gerar o primeiro relatório, ou selecione um dia salvo no topo.
); } switch (view) { case "dashboard": return irPara("alertas")} />; case "oportunidades": return ; case "leads": return ; case "tarefas": return ; case "satisfacao": return ; case "cancelamentos": return ; case "alertas": return ; case "relatorio": return ; default: return
; } } return (
setRunModalAberto(true)} onAlternarSidebar={() => setSidebarAberta((v) => !v)} carregando={carregandoDia} />
{carregandoDia && dia &&
}
{renderConteudo()}
Integrações Salesforce Turso Hugging Face ClickUp Gmail FastAPI
{ setRunModalAberto(false); setErroExecucao(null); }} onExecutar={executarAgente} executando={executando} segundos={segundos} erro={erroExecucao} />
); }