Port para React — Fase 1: fundação, Login, Painel e Lotes
TLDR: portar o protótipo dc-runtime para um app React+Vite+TypeScript real, entregando a fundação (setup, design system, camada de serviços mockada, sessão) mais o primeiro fluxo vertical completo do gestor — Login, Painel e Lotes.
Contexto
Sistema de Cobrança.dc.html é um protótipo estático no formato “dc-runtime” (interpretado em runtime
pelo support.js, que é apenas o motor genérico do formato — sc-if/sc-for/{{ }} — e não contém
nenhuma lógica de negócio). Toda a lógica de negócio do app está embutida em um único
<script type="text/x-dc" data-dc-script> dentro do próprio .dc.html, junto com ~1560 linhas de
template HTML com estilos inline.
O objetivo é reescrever esse protótipo como um app React real, terminando com uma base que pode
receber integração com um back-end de verdade no futuro (por enquanto os dados continuam mockados,
mas isolados atrás de uma camada de serviços). O projeto ainda não existe como código React (a pasta
só tem os .dc.html de referência) e ainda não é um repositório git.
O protótipo tem 14 telas ao todo (Login, Painel, Lotes, Detalhe do lote, Atendimento/Ficha Unificada, Negativação, Contratos, Pagamentos, Clientes, Detalhe do cliente, Jurídico, Bots, Colaboradores, Meu perfil). Dado o tamanho, a entrega é faseada. Esta spec cobre apenas a Fase 1: fundação do projeto + Login + Painel + Lotes + Detalhe do lote — o primeiro fluxo vertical completo do gestor, que serve para validar a arquitetura de componentes/hooks antes de portar o restante.
Decisões travadas com o usuário
| Decisão | Escolha | Por quê |
|---|---|---|
| Linguagem | TypeScript | Não JavaScript puro |
| Acesso a dados | Camada de serviço isolada (services/) |
Funções que hoje retornam mock, consumidas por hooks; quando o back-end existir, só a implementação dos serviços muda |
| Navegação | React Router | URLs reais por tela, em vez do tela state único do protótipo |
| Estilos | CSS Modules (um .module.css por componente) |
Preserva os valores visuais do protótipo, com suporte nativo a :hover/:focus — o protótipo simulava isso via atributos style-hover/style-focus do dc-runtime |
Objetivos
- Criar o projeto Vite + React + TypeScript do zero, com estrutura de pastas organizada (
pages/separado decomponents/, componentes agrupados por domínio/generalidade). - Extrair toda lógica de estado/efeitos para hooks customizados — componentes ficam só com JSX + props.
- Construir o design system compartilhado (Sidebar, PageHeader, PillGroup, StatusChip, DataTable + Pagination, SearchInput, InfoHint, NavItem) como componentes genéricos reutilizáveis, parametrizados via props.
- Implementar sessão/login (mock) com roteamento protegido por papel (gestor vs atendente).
- Portar as telas Painel, Lotes e Detalhe do lote com paridade funcional com o protótipo (mesmos cálculos, mesmos estados, mesmo comportamento de filtros/paginação).
- Deixar a base pronta (roteador, layout, nav com badges, camada de serviços) para as próximas fases plugarem sem retrabalho estrutural.
Fora de escopo
- Telas: Atendimento (Ficha Unificada), Negativação, Contratos, Pagamentos, Clientes, Detalhe do cliente, Jurídico, Bots, Colaboradores, Meu perfil.
- Integração com back-end real (API real do Asaas, autenticação real) — fica tudo mockado nesta fase.
- O bug já identificado na Ficha Unificada (
vencBasenão definida ememitir()) — só será corrigido quando essa tela for portada, mas fica documentado para não se perder.
Mudanças
Novo projeto React (na época em cobranca-web/app/; hoje modules/frontend/), estrutura alvo:
src/
main.tsx
App.tsx # Router + providers
pages/
LoginPage/ PainelPage/ LotesPage/ LoteDetalhePage/
components/
layout/ # Sidebar, PageHeader, NavItem, AppShell
ui/ # PillGroup, StatusChip, DataTable, Pagination,
# SearchInput, InfoHint, Bar (barra de progresso)
painel/ # KpiCard, EvolucaoChart, AtendentesTable, ReguaDisparos
lotes/ # LoteAtivoCard, ImportarLotePanel, LoteConfigPanel,
# ImportStepList, LotesEncerradosTable
hooks/
auth/ # useSession, useLogin
nav/ # useNav (itens de menu por papel, badges)
painel/ # usePainelFiltros, usePainelDados (kpis, gráfico, atendentes)
lotes/ # useLotes, useImportarLote, useLoteConfig
loteDetalhe/ # useLoteDetalhe (busca + paginação)
shared/ # useToggleIndex (padrão kInfoOpen), usePagination
services/
session.ts # login mockado
lotes.ts # fetchLotes, fetchLoteDetalhe, importarLote (mock)
painel.ts # fetchPainelDados (mock)
mocks/
lotes.ts, painel.ts # dados estáticos determinísticos (equivalentes a
# NOMES_LOTE/STATUS_LOTE/MESES do protótipo)
types/
index.ts # tipos compartilhados (Lote, Aluno, Atendente, etc.)
styles/
tokens.css # cores, fontes (IBM Plex Sans/Mono), var(--ac)
Os arquivos de referência do protótipo (product_architecture.dc.html, unified_record.dc.html,
collection_system.dc.html, support.js, ibft_guide.txt) permaneceram como material de consulta,
fora do build — hoje em features/assets/prototype/.
Sequência de implementação
Este é um trabalho de portar UI/comportamento de um protótipo, não uma mudança em lógica de negócio testável isoladamente. O ciclo TDD tradicional foi adaptado: os “testes” de UI aqui são verificação manual no navegador (ver Como verificar), e os testes automatizados ficaram reservados para a lógica pura extraída aos hooks (cálculos do painel, paginação, filtros).
| # | Tipo | Entrega | Arquivos |
|---|---|---|---|
| 1 | feat | Scaffold Vite react-ts, ESLint/Prettier, React Router, tokens.css |
app/ (setup) |
| 2 | feat | Layout genérico: AppShell, Sidebar, NavItem, PageHeader |
src/components/layout/* |
| 3 | feat | UI genérica: PillGroup, StatusChip, DataTable, Pagination, SearchInput, InfoHint, Bar |
src/components/ui/* |
| 4 | test | usePagination, useToggleIndex — bordas (página 0, última página, índice repetido) |
src/hooks/shared/*.test.ts |
| 5 | feat | usePagination/useToggleIndex até os testes passarem |
src/hooks/shared/*.ts |
| 6 | feat | Sessão/login mockado + roteamento protegido por papel | src/pages/LoginPage/*, src/hooks/auth/*, src/services/session.ts |
| 7 | feat | useNav (itens por papel + badges) integrado ao Sidebar |
src/hooks/nav/* |
| 8 | test | usePainelDados — kpis, gráfico com meses dentro/fora do filtro, agregação por atendente |
src/hooks/painel/*.test.ts |
| 9 | feat | PainelPage completa |
src/pages/PainelPage/*, src/hooks/painel/*, src/components/painel/*, src/services/painel.ts, src/mocks/painel.ts |
| 10 | test | useLotes/useImportarLote — avanço de steps, criação de lote, stepper 7–56 dias |
src/hooks/lotes/*.test.ts |
| 11 | feat | LotesPage completa |
src/pages/LotesPage/*, src/hooks/lotes/*, src/components/lotes/*, src/services/lotes.ts, src/mocks/lotes.ts |
| 12 | test | useLoteDetalhe — busca por nome/CPF, paginação 10/página |
src/hooks/loteDetalhe/*.test.ts |
| 13 | feat | LoteDetalhePage completa |
src/pages/LoteDetalhePage/*, src/hooks/loteDetalhe/* |
| 14 | refactor | Revisão de duplicação entre as três páginas | — |
Como verificar
npm run buildenpm run lintpassam sem erros.- Testes unitários dos hooks (
npm test) verdes. - Rodar
npm run deve conferir manualmente, comparando lado a lado com o protótipo (collection_system.dc.htmlaberto localmente):- Login com e-mail contendo “aretha” entra como atendente (nav reduzida); qualquer outro e-mail entra como gestor (nav completa).
- Painel: trocar filtros de período/atendente atualiza KPIs, gráfico e tabela; abrir/fechar cada popover de info; baixar CSV.
- Lotes: abrir configurações do lote, alternar duração/automático, avançar os 5 passos de importação até criar um novo lote ativo; abrir “Ver detalhes” de um lote encerrado.
- Detalhe do lote: busca filtra por nome/CPF; paginação anterior/próxima funciona nos limites.
- Navegar entre todas as telas da Fase 1 via sidebar sem erros no console.
Documentação
- Camadas do app React — decisão da camada de serviços mockada + hooks, para orientar as próximas fases e a futura integração com back-end real.
- Quirks do protótipo dc-runtime — inconsistências que não devem
ser replicadas literalmente: dado duplicado/hardcoded do “Cléber Santana Farias” em Negativação,
valores literais não computados (Reincidência 47,7%, “893 (29,6%)” nas respostas da régua), e o bug
de
vencBaseindefinido emunified_record.dc.html.