import { useEffect, useMemo, useState } from "react"; import SecaoHeader from "../components/SecaoHeader.jsx"; import { consultaTipos, consultaBuscar, consultaDetalhar } from "../api.js"; // Tela de Consulta: busca e detalhe somente-leitura sobre Salesforce, com // cache Turso como camada rápida (modo híbrido). Nenhum cálculo é feito // aqui — apenas exibição do que o backend Python já retornou. const ROTULOS_TIPO = { conta: { icone: "🏢", cor: "#0018FF" }, oportunidade: { icone: "💼", cor: "#16C79A" }, contrato: { icone: "📄", cor: "#0004DD" }, item: { icone: "🧾", cor: "#FFC453" }, }; export default function Search({ notificar }) { const [tiposInfo, setTiposInfo] = useState(null); const [tiposAtivos, setTiposAtivos] = useState([]); const [termo, setTermo] = useState(""); const [buscando, setBuscando] = useState(false); const [resultados, setResultados] = useState(null); const [erroBusca, setErroBusca] = useState(null); const [selecionado, setSelecionado] = useState(null); // { tipo, id, name } const [detalhe, setDetalhe] = useState(null); const [carregandoDetalhe, setCarregandoDetalhe] = useState(false); const [erroDetalhe, setErroDetalhe] = useState(null); useEffect(() => { consultaTipos() .then((d) => { setTiposInfo(d); setTiposAtivos((d.tipos || []).map((t) => t.tipo)); }) .catch(() => setTiposInfo(null)); }, []); const tiposDisponiveis = useMemo(() => tiposInfo?.tipos || [], [tiposInfo]); function alternarTipo(tipo) { setTiposAtivos((atuais) => atuais.includes(tipo) ? atuais.filter((t) => t !== tipo) : [...atuais, tipo] ); } async function executarBusca(e) { e?.preventDefault(); const t = termo.trim(); if (t.length < 2) { setErroBusca("Digite ao menos 2 caracteres."); return; } setBuscando(true); setErroBusca(null); setResultados(null); try { const d = await consultaBuscar(t, tiposAtivos, 20); setResultados(d.resultados || {}); } catch (err) { setErroBusca(err.message); notificar?.("Falha na busca: " + err.message, "bad"); } finally { setBuscando(false); } } async function abrirDetalhe(tipo, item) { setSelecionado({ tipo, id: item.id, name: item.name }); setDetalhe(null); setErroDetalhe(null); setCarregandoDetalhe(true); try { const d = await consultaDetalhar(tipo, item.id); setDetalhe(d); } catch (err) { setErroDetalhe(err.message); } finally { setCarregandoDetalhe(false); } } const totalResultados = resultados ? Object.values(resultados).reduce((acc, arr) => acc + arr.length, 0) : 0; return ( <>
SF_CONTRACT_ITEM_PARENT_FIELD no .env). O contrato ainda pode ser
consultado, mas sem a lista de itens relacionados.
| {c.campo} | {String(c.valor)} |
|---|