feat(quotes): catálogo navegável + resumo ao vivo na Nova Oferta

Substitui a tabela de linhas com dropdown de produto por duas colunas,
no padrão do legado OrçaFácil: "Adicionar Produtos" à esquerda (busca,
ordenação, lista com preço da faixa do período de contrato, clique
adiciona ao carrinho) e "Resumo da Oferta" à direita, sticky (itens
com stepper, breakdown de implantação, implantação geral, condição de
pagamento, condição especial e observações — todos migrados pra dentro
do painel —, totais ao vivo com Total do Contrato em destaque).

Fórmula do preview espelha exatamente pricing.ts::computeQuotePricing
— nada muda no backend, é só a experiência de montar a oferta antes de
enviar; o servidor continua sendo a única fonte de verdade nos totais
persistidos.

pnpm turbo run typecheck build: 28/28. Suíte @eden/api: 113/113
(inalterada). Testado ao vivo ponta a ponta, incluindo o caso de
aprovação por desconto.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 17:24:26 -03:00
parent ef4591b8bc
commit 8ab18ababc
2 changed files with 490 additions and 200 deletions

View File

@@ -812,3 +812,21 @@ Data: 2026-09-18. Fecha exatamente a pendência registrada acima. Usuário: "vam
### Achado adicional, resolvido no caminho (não pedido, mas real)
Usuário reportou "testei o cadastro de revenda e continua só com nome/documento/e-mail" — investigado ao vivo: a tela de edição de uma revenda existente já mostrava todas as seções corretamente (confirmado abrindo a revenda real "Handix" pela lista). O que ele via era a tela de **criação** (`/resellers/new`), que por design mesmo só mostra os 3 campos mínimos até a revenda ser salva (CNPJ/sócios/representante precisam de um ID existente) — mas sem nenhuma explicação disso na tela, parecendo um cadastro incompleto. Adicionado um aviso claro no formulário de criação: "Salve com o nome pra continuar o cadastro — busca de CNPJ, representante legal, sócios, endereço e contatos ficam disponíveis logo em seguida, na tela de edição desta revenda." Confirmado ao vivo via screenshot.
---
## Nova oferta — catálogo navegável + resumo ao vivo, no padrão do legado OrçaFácil
Data: 2026-09-18. Usuário mandou uma captura de tela de como o legado montava essa tela (produtos navegáveis à esquerda, resumo se montando ao lado conforme adicionava) e um link de uma página de exemplo do tema DreamsERP como "só uma ideia" — na prática essa página do tema acabou sendo só inspiração de acabamento solta (é uma tabela de fatura genérica, não tem o padrão de catálogo+carrinho do legado). Pedido: "pode fazer mais legal".
`QuoteFormPage.tsx` (agente `eden-frontend`): a seção de itens, que era uma tabela chata de linhas com dropdown de produto (sem preço visível, sem busca, sem total em tempo real), virou duas colunas — **"Adicionar Produtos"** à esquerda (busca por código/nome, ordenar por Código/Nome, lista rolável com badge de código, preço da faixa do período de contrato selecionado, tag "plano Nm", clique adiciona ao carrinho) e **"Resumo da Oferta"** à direita, sticky (cartão por item com stepper de quantidade e remover, breakdown de implantação por item, os campos que já existiam — implantação geral, condição de pagamento, condição especial/valor mensal final, observações — todos migrados pra dentro deste painel, e totais calculados ao vivo com "Total do Contrato" em destaque). Fórmula do preview espelha `apps/api/src/quotes/pricing.ts::computeQuotePricing` exatamente — mesma disciplina já documentada no próprio arquivo desde que foi criado: todo total mostrado aqui é ilustrativo, o servidor recalcula tudo ao salvar, nada muda no backend.
**Achado real do próprio agente**: produtos sem preço cadastrado pra faixa do período de contrato selecionado (existem de verdade nos dados seedados) precisavam de tratamento — aparecem na lista como "indisponível p/ este período", não clicáveis, em vez de quebrar ou mostrar "R$ null/mês".
**Limpeza feita por mim depois**: a lista de produtos navegável tornou a poluição de dados de teste (`qa-test-*`, acumulada a sessão inteira nas suítes de `product-catalogs`) muito mais visível do que era como dropdown — 173 de 177 produtos ativos eram lixo de teste. Desativados (mesma disciplina de higiene já seguida o resto da sessão), junto com uma nova rodada de limpeza nos catálogos de Tipo/Grupo/Subgrupo/Marca/Unidade (mais rodadas de suíte desde a última limpeza tinham acumulado mais linhas). Sobrou 1 produto real ativo ("Link Dedicado 100Mbps").
### Verificação
`pnpm turbo run typecheck build` 28/28. Suíte 113/113 (inalterada — mudança é só de frontend). Testado ao vivo pelo agente: busca/ordenação filtrando corretamente, período de contrato trocando o preço mostrado e o badge de plano, stepper incrementando/decrementando (desabilita em 1), totais batendo à mão com a fórmula pra vários produtos/quantidades, duas ofertas completas criadas de ponta a ponta com o total final batendo exatamente com o que o servidor calculou (uma delas disparando aprovação por desconto, confirmado o banner "aguarda aprovação"). Confirmado por mim depois, com screenshot, com o catálogo já limpo.
### Achado não resolvido (fora de escopo, registrado pelo agente)
Na tela de sucesso pós-criação, o campo "Implantação total" mostra só `implementation_fee` (implantação dos produtos), sem somar `impl_geral` — quando esse campo é preenchido, o rótulo sub-representa o valor que efetivamente compõe o "Total do contrato". Não é um bug introduzido por esta leva, é pré-existente; não corrigido por estar fora do escopo pedido (só a tela de montagem da oferta).