Port para React — Fase 2: Clientes, Negativação, Contratos e Pagamentos
TLDR: portar as próximas 5 telas do protótipo — Clientes, Detalhe do cliente, Negativação, Contratos e Pagamentos — reaproveitando o design system e a arquitetura (services/mocks/hooks/pages) estabelecidos na Fase 1.
Contexto
A Fase 1 (fundação + Login + Painel + Lotes) está
mergeada em main. Esta fase continua o port do Sistema de Cobrança.dc.html, substituindo os
placeholders ComingSoonPage de 5 rotas por telas reais: Clientes, Detalhe do cliente,
Negativação, Contratos e Pagamentos. Todas reaproveitam os componentes genéricos já
construídos (DataTable, Pagination, SearchInput, StatusChip, Card, Button, PillGroup) e o
padrão hooks+services+mocks.
Sem repositório remoto configurado ainda — como na Fase 1, o trabalho é commitado direto em main
(sem branch nem PR), a pedido do usuário.
Descoberta: estado de Pagamentos é compartilhado entre duas telas
No protótipo original, tudo é um único componente com um único state — por isso, tanto a tela
Pagamentos (duplicar pagamento) quanto a aba “Pagamentos” do Detalhe do cliente (pagamento
avulso) leem e escrevem no mesmo array pagamentos. Uma cobrança avulsa criada no Detalhe do cliente
aparece imediatamente na tela Pagamentos, e vice-versa.
Ao portar para hooks isolados por página, esse comportamento se perderia por padrão. Por isso a Fase 2
introduz o primeiro Context compartilhado entre páginas além da sessão: PagamentosProvider (em
hooks/pagamentos/PagamentosContext.tsx), com o mesmo formato do SessionProvider da Fase 1. Ele
expõe pagamentos, atualizarStatus(index, patch) e adicionarPagamento(pagamento); as duas telas
consomem o mesmo contexto via hooks próprios.
mermaid
graph TD
PP["PagamentosPage<br/>(duplicar)"] --> CTX["PagamentosContext"]
CD["ClienteDetalhePage<br/>aba Pagamentos<br/>(avulso)"] --> CTX
CTX --> ST["pagamentos[]<br/>atualizarStatus · adicionarPagamento"]
style CTX fill:#1f2937,color:#fff
Objetivos
- Portar Negativação (fila de elegíveis + remoções pendentes) com paridade funcional.
- Portar Contratos (esteira de assinatura, ciclo de status por clique).
- Portar Pagamentos (busca + filtro de status, exportar CSV, menu de ações por linha, duplicar pagamento).
- Portar Clientes (busca + drawer de filtros por status/curso, paginação 8/página).
- Portar Detalhe do cliente (5 abas: Pessoais, Acadêmico, Pagamentos — com pagamento avulso —, Histórico, Auditoria).
- Introduzir
PagamentosProviderpara o estado de pagamentos ser compartilhado entre as telas Pagamentos e Detalhe do cliente, igual ao protótipo original. - Atualizar
hooks/nav(badge de Negativação e Contratos, hoje sempre vazios) para refletir a contagem real assim que os dados existirem. - Registrar em quirks do protótipo qualquer quirk novo encontrado ao implementar (ex.: duplicação do registro “Cléber Santana Farias” entre Negativação e Clientes, já antecipada na Fase 1).
Fora de escopo
- Atendimento / Ficha Unificada (Fase 3).
- Jurídico, Bots, Colaboradores, Meu perfil (Fase 4).
- Correção do bug
vencBaseda Ficha Unificada (só ao portar essa tela). - Qualquer paginação na tela Pagamentos — o protótipo original não pagina essa lista, só filtra.
Mudanças
Novos arquivos, seguindo a mesma estrutura de pastas da Fase 1:
``` types/negativacao.ts, types/contratos.ts, types/pagamentos.ts, types/clientes.ts
mocks/negativacao.ts → fila (3 registros) + registro de remoção pendente mocks/contratos.ts → 3 contratos mocks/pagamentos.ts → 6 pagamentos mocks/clientes.ts → 6 clientes (cada um com cursos[], hist[], aud[])
services/negativacao.ts, services/contratos.ts, services/pagamentos.ts, services/clientes.ts
hooks/negativacao/useFilaNegativacao.ts → fetch + negativar(i) hooks/negativacao/useRemocaoPendente.ts → fetch + removerNeg() hooks/contratos/useContratos.ts → fetch + ciclo de status por clique hooks/pagamentos/PagamentosContext.tsx → provider compartilhado hooks/pagamentos/usePagamentosFiltro.ts → busca + filtro de status (view local, lê do contexto) hooks/pagamentos/usePagamentoAcoes.ts → menu aberto/copiado, ações por linha hooks/pagamentos/useDuplicarPagamento.ts → estado do painel de duplicação + gerar hooks/clientes/useClientes.ts → fetch + busca + filtro status/curso + drawer + usePagination hooks/clienteDetalhe/useClienteDetalhe.ts → cliente por rota, abas, dados derivados hooks/clienteDetalhe/usePagamentoAvulso.ts → formulário de cobrança avulsa, escreve no PagamentosContext
components/negativacao/{FilaNegativacaoTable,RemocaoPendenteCard} components/contratos/ContratosTable components/pagamentos/{PagamentosTable,DuplicarPagamentoPanel,RowActionsMenu} components/clientes/{ClientesTable,FiltrosDrawer} components/clienteDetalhe/{ClienteHeader,PessoaisTab,AcademicoTab,PagamentosTab,HistoricoTab,AuditoriaTab}
pages/NegativacaoPage, pages/ContratosPage, pages/PagamentosPage, pages/ClientesPage, pages/ClienteDetalhePage ```
RowActionsMenu e FiltrosDrawer vão para components/ui se, ao implementar, não houver nada
específico do domínio — decisão tomada durante a implementação, não travada aqui.
Rotas atualizadas em App.tsx: /negativacao, /contratos, /pagamentos, /clientes,
/clientes/:clienteId. Esta última é nova — o protótipo usa um índice em memória; portamos para um id
de rota, com clSel virando “cliente encontrado por id” via service.
RequireRole roles={['gestor']} continua em Negativação e Contratos (gestor-only); Pagamentos,
Clientes e Detalhe do cliente continuam acessíveis a ambos os papéis, como no protótipo.
Sequência de implementação
| # | Tipo | Entrega |
|---|---|---|
| 1 | feat | Tipos + mocks + services das 5 telas (dados 1:1 com o protótipo) |
| 2 | test | useContratos — ciclo PENDENTE→ASSINADO→FINALIZADO, ação some quando FINALIZADO |
| 3 | feat | useContratos + ContratosTable + ContratosPage |
| 4 | test | useFilaNegativacao (marcar não afeta outras linhas), useRemocaoPendente |
| 5 | feat | Negativação completa |
| 6 | test | PagamentosContext/usePagamentosFiltro (busca, filtro, combinação) e useDuplicarPagamento (novo pendente + original regerado, parcelas 1–12, parse BRL) |
| 7 | feat | Pagamentos completo (contexto, tabela, menu de ações, painel de duplicar, export CSV) |
| 8 | test | useClientes — busca + filtro status + filtro curso combinados, paginação 8/página, limpar filtros |
| 9 | feat | Clientes completo |
| 10 | test | useClienteDetalhe (troca de aba, clCobrancas cruzando o PagamentosContext pelo nome) e usePagamentoAvulso |
| 11 | feat | Detalhe do cliente completo (5 abas) |
| 12 | refactor | Revisão de duplicação entre as 5 telas novas e as já existentes |
Como verificar
npm run build,npm run lint,npm testpassam sem erros.- Manual (
npm run dev), comparando com o protótipo aberto localmente:- Negativação: negativar um aluno da fila remove o botão de ação e mostra o chip “NEGATIVADO HOJE”; remover a negativação pendente troca o chip/texto e some o botão.
- Contratos: clicar na ação avança PENDENTE→ASSINADO→FINALIZADO; ao chegar em FINALIZADO, mostra “Arquivado” sem botão.
- Pagamentos: busca e filtro de status combinam; menu “⋯” mostra as ações certas por status; duplicar um pagamento pago/pendente cria um novo PENDENTE e marca o original como CANCELADO/RE-GERADO; exportar CSV baixa o arquivo.
- Clientes: busca por nome/CPF/e-mail; drawer de filtros por status e curso (com badge “ · 1” quando algum filtro ativo); paginação 8/página; “Ver detalhes” abre o cliente certo.
- Detalhe do cliente: 5 abas trocam corretamente; gerar um pagamento avulso aparece
imediatamente na tela Pagamentos (mesmo Context); “Levar para atendimento” navega para
/atendimento(ainda placeholder).
Documentação
- Camadas do app React — seção sobre
PagamentosContext: por que existe, quando usar Context compartilhado vs. service+hook local. - Quirks do protótipo dc-runtime — o registro duplicado “Cléber Santana Farias” entre Negativação e Clientes já está documentado; validar se há outros ao portar.