Roteamento
React Router, rotas protegidas e lazy loading
React Router
O app usa createBrowserRouter do React Router com lazy loading via React.lazy.
Estrutura de rotas
Rotas públicas:
/login
/esqueci-senha
/redefinir-senha
/auth/callback
/termos, /privacidade
/p/:token ← proposta pública (sem login)
Rotas protegidas (AppLayout):
/dashboard
/primeiros-passos ← onboarding tour
/negocios
/negocios/:id ← hub do negócio
/contatos, /contatos/:id
/empresas, /empresas/:id
/atividades
/importar ← wizard de importação CSV/XLSX
/propostas
/propostas/:id
/propostas/:id/preview
/propostas/:id/wizard ← wizard de edição (25 passos)
/base-de-clientes
/base-de-clientes/nova
/base-de-clientes/:baseId ← análise (8 abas por slug)
/admin/workspaces ← painel super admin (apenas super admins)
/settings/empresa, /settings/equipe, /settings/metas
/settings/segmentos, /settings/pipelines, /settings/produtos
/settings/tipos-negocio, /settings/origens, /settings/atividades
/settings/motivos-perda, /settings/qualificacao
/settings/qualificacao/new, /settings/qualificacao/new/blank
/settings/qualificacao/:id/edit
/settings/campos, /settings/propostas, /settings/perfilProtectedRoute
Wrapper que verifica autenticação antes de renderizar rotas protegidas. Redireciona para /login se o usuário não estiver autenticado.
Lazy loading
Todas as pages são carregadas com React.lazy e envolvidas em SuspenseWrapper:
const DealsPage = lazy(() => import("@/features/deals/DealsPage"));
// Na rota:
element: (
<SuspenseWrapper>
<DealsPage />
</SuspenseWrapper>
)Constantes de rotas
As URLs são definidas em src/lib/constants.ts via ROUTES:
import { ROUTES } from "@/lib/constants";
navigate(ROUTES.deals);
navigate(ROUTES.settings.pipelines);A lista completa vem de ROUTES
☠️ Esta página lista as rotas principais, mas não é a lista completa — e listar rota à mão em
doc é como ela desatualiza. A fonte da verdade é a constante ROUTES em src/lib/constants.ts,
e o que está montado de fato está em src/routes/router.tsx.
Rotas que existem hoje e costumam faltar em documentação antiga: /prospeccao, /automacoes,
/aurora, /copiloto (e /copiloto/conversar, /copiloto/base), /conhecimento, /exportar,
/plano, /config/ia, /montar-processo, as públicas /assinar, /t/:contractId e
/criar-senha, as de admin (/admin/vendas, /admin/roteador-ia, /admin/ai-ops,
/admin/exclusao-de-dados) e as de configuração (/settings/chaves-api, /settings/alertas,
/settings/email, /settings/modelos-email).
O lazy() não é o React.lazy cru
O router.tsx define um lazy() próprio. Ele existe por causa de um defeito real: depois de
um deploy, o navegador que ficou com a página aberta tenta buscar um chunk que não existe mais.
Com o React.lazy puro, o React renderizava undefined e a tela ficava branca. O wrapper devolve
uma promessa que nunca resolve e força o recarregamento — a pessoa vê a tela carregando, não a
tela quebrada.
Ao criar rota nova, use o lazy() local, não importe o do React.