5.2 KiB
Sistema de listas da campanha (Pass 2 — W1)
Status: entregue (Pass 2, 2026-07-25) Atualizado em: 2026-07-25 Item pai: IMPROVE-CODE-QUALITY-PLAN.md — Pass 2, W1 (2 entregas) Appetite: ~4 dias; sem migration, sem mudança de comportamento visível Gate: W0 (pinagem-superficies-lista.md) verde
Contexto
12 superfícies ui/Table no /campanha, cada uma com parser de URL, header, paginação e filtros re-implementados por feature. Uma espinha compartilhada já existe pela metade (campaignListUrl.ts 6 importers, CampaignListPagination 9, CampaignListPendingBoundary 8, CampaignSearchForm 4) — mas a lista de municípios (a mais rica: sort, filtros no header, células editáveis B9, overview E8/E9) é um monolito (MunicipalityList.tsx 496 + MunicipalityFilters 354 + MunicipalityHeaderFilter 311 + municipalityUi.ts 765/59 exports), e as listas de lideranças/organizações/dobradinhas são clones de página com 5 parsers locais duplicados. B17 (seletor de colunas) e B18 (filtros salvos) pousariam em cima disso multiplicado.
Objetivos
- Definições de coluna como dado:
id, header, cell renderer,sortKey?,filterDef?,mandatory?,defaultVisible?, tratamento mobile. - Estado de URL genérico (parse/canonicalize/serialize) estendendo
campaignListUrl.ts— contrato de URL existente byte-idêntico (pins de W0 verdes). - Tabela server-first + ilhas client generalizadas de
MunicipalitySortableHead/MunicipalityHeaderFilter. - Slots de toolbar (busca, barra de filtros, botões futuros de B17/B18); empty state que mantém o chrome montado (lição de B16); slot de card-stack mobile; paginação/pending pelos shells existentes.
- Superfície migrada = código antigo deletado na mesma entrega (knip limpo).
Entregas
D1 — núcleo + lista de municípios. O sistema nasce extraído da lista mais rica, não inventado: column defs, URL state, ilhas, toolbar. Absorve o B16+ (escala-dry-pos-b16.md): hook useOptimistic de navegação compartilhado, hrefs de opção a partir de uma base URLSearchParams, payload de facet por slugs. Divide municipalityUi.ts nas costuras naturais (url/filters/sort/labels/freshness). Células de edição inline (B9) viram cell-renderer islands.
D2 — migra o resto + deleta o superado. Tripé de entidades (lideranças/organizações/dobradinhas) numa composição de página compartilhada + parsers de campaignListUrl (fecha o débito de parser do C8 F3); demandas (CampaignFilterChips → filter def); apoiadores (mantém cards mobile); assessores (tabela client adota estado/toolbar/paginação; inline-create continua bespoke).
Fora do escopo (D5 do sign-off — anti-classitis, documentado)
ActionPlanList— domínio de cards, não de tabela; adota só toolbar/URL state.TerritoryOverviewTable— exceção documentada de sort no cliente (dataset ≤27 linhas, já carregado).MunicipalityCandidateComparisonTable,LeaderContactsPanel, preview do wizard de import — pequenas/estáticas demais.- B17/B18 não são implementados — o sistema deixa as costuras (visibilidade por column id, serializador de filtros) e para aí.
Impacto no roadmap
- Quase de graça depois: B17 (seletor de colunas = toggle de visibilidade sobre column ids + localStorage), B18 (filtros salvos = serializador + slot na toolbar), "Cenário junto aos filtros" (slot na barra; cenário nunca entra na serialização de URL), ícone de prioridade (accessory slot na célula de nome).
- Costuras para: E10/E14 (nova coluna = nova column def + ilha inline opcional), E12 (ponto de extensão de group-mode documentado, não construído).
- Absorve: B16+ (plano marcado como absorvido).
- Conflitos: precisa terminar antes do trabalho de colunas da janela 3 (~16/08) e antes de B17/B18 entrarem em desenvolvimento.
- Supersede premissas em: seletor-colunas-lista-municipios.md, filtros-salvos-municipios.md, cenario-junto-filtros-municipios.md, escala-dry-pos-b16.md (seções marcadas em W5).
Rabbit holes
- Generalizar
MunicipalityHeaderFilterinteiro no D1. As facetas de município (435 opções + busca) são as mais complexas; a generalização é a interface (filterDef + slot), a implementação rica continua específica até um segundo consumidor pedir. - DataTable do shadcn como base. Consultar composição, mas a casa já tem
ui/Table+ DESIGN.md; introduzir TanStack Table trocaria o modelo server-first por client state — não. - Mexer na semântica de URL "aproveitando". Congelada (B18 depende dela).
Referências
src/utilities/campaignListUrl.ts,src/utilities/municipalityUi.ts,src/components/campaign/MunicipalityList.tsx,MunicipalitySortableHead.tsx,MunicipalityHeaderFilter.tsx,MunicipalityFilters.tsxsrc/app/(campaign)/campanha/(app)/{liderancas,organizacoes,dobradinhas,demandas,apoiadores,assessores}/page.tsx- escala-dry-pos-c6.md (C8 F3/F4), filtros-no-header-lista-municipios.md (B16), DESIGN.md