- Compile docs/roadmap.md into a next-steps document (277→206 lines): R0–R5/M1–M5 tables and the delivered map/list item paragraphs compressed into 'Já entregue'; janelas, grafo and cortes list only open IDs; C10/C11/C8 fill-ins keep their original triggers; C5 moved under 'A validar'. - Record the production deploy of the destructive remodel chain (2026-07-23 Vercel builds) across roadmap, AGENTS.md, the project notebook and plans — supersedes every 'deploy pendente'; smoke pós-deploy + onboarding remain the open blockers. - Fix AGENTS.md internal contradictions: Município locked-decisions bullet (435, Camaçari whole, candidate role), campaignUser role enum, deploy-checklist item 7 as historical, access/* structure note, election-aggregates artifact + election-tse revalidate runbook. - Sync open plans to real identifiers (plaza*/nucleus* → municipality*): the intelligence program (master + E8–E15/B13/C12 with artifact/caching context and satisfied deps), B8 rescoped to Salvador ZE 1–19 only, WhatsApp D3–D5, D2, A6 (now the insight layer over stateDeputy), RS+, onda-0 smoke step. - Close items verified done in code: C8 F4 (DRY de forms) complete, filtros-auto shared pending shell, petition generateStaticParams select/depth; ledger the surviving user-visible 'Praça' copy in src as new P2 debt. - Banner delivered praça-era plans (production note + rename pointer); mark remodelagem-pracas.md superseded and remodelagem-municipios.md delivered. - TECH-DEBT smell statuses, TESTING RBAC row, README quality gates, campanha UI rules updated to current component names.
8.8 KiB
Mapa das Praças filtrado pela lista
Nota (2026-07-24): entregue na era Praças e em produção desde 2026-07-23. A remodelagem M1 renomeou os identificadores
plaza*→municipality*e as rotaspracas/→municipios/; os nomes neste plano são os da época. Nomes atuais: ver remodelagem-municipios.md.
Status: entregue (em produção desde 2026-07-23)
Atualizado em: 2026-07-21 (gatilho fitBounds → B12)
Item do roadmap: docs/roadmap.md (Trilha B, item B7 — entregue 2026-07-21)
Impeccable: B — encaixe em /campanha/pracas (PlazaMapPanel + loader; sem rota nova)
Appetite: ~0,5 dia eng; wire buildPlazaListWhere no loader do mapa + teste + empty state
Responsável: —
Revisão 2026-07-21 (pós-implementação + /simplify): loadPlazaMapBundle aceita rawSearchParams; loadScopedPlazas usa buildPlazaListWhere(state); tipo PlazaListSearchParams exportado de plazaUi.ts; testes em tests/int/plazaMapData.int.spec.ts. Cleanup simplify: parse único no map loader (PlazaListState passado a loadScopedPlazas). Débito de perf triplicado → A9+ entregue (buildPlazaMapBundleFromPlazas recebe agregados do bundle da lista).
Design (Impeccable)
Âncoras: PRODUCT.md / DESIGN.md (register product — Field Desk) · tema data-theme='campaign' · shells existentes (CampaignPageShell, PlazaFilters, PlazaMapPanel).
Na implementação (implement-roadmap-item): craft compacto → critique → polish (sem shape longo — superfície já existe).
Brief compacto:
- Persona / contexto: Alex (coordenador geral) ou Assessor filtra Praças por TI / tipo / cobertura / tendência e espera que o mapa acima diga a mesma coisa que a lista.
- Job principal: o coroplético reflete exatamente o conjunto filtrado da URL (não só o escopo de access).
- Estratégia de cor: Restrained (inalterada); modo comparativo divergente permanece.
- Anti-goals: não mover filtros neste item; não redesenhar o mapa; não filtrar por
page(paginação da lista não reduz o mapa).
Contexto
Em /campanha/pracas a lista e o overview já aplicavam buildPlazaListWhere(state) a partir da URL (q, region, kind, coverage, priority, trend). O mapa carregava todas as Praças acessíveis ao papel (where: {} em loadScopedPlazas). Pedido de produto (2026-07-21): o Mapa das Praças deve usar o mesmo filtro da lista abaixo.
Entregue 2026-07-21: loadPlazaMapBundle(payload, user, rawSearchParams) em page.tsx; loadScopedPlazas com buildPlazaListWhere; conjunto vazio → null (painel omitido); compare só modo comparativo.
Objetivos
- Com qualquer combinação de filtros da URL (exceto
compareepage), o bundle do mapa agrega votos somente das Praças que passam embuildPlazaListWhere. - Conjunto filtrado vazio → mapa omitido (
null), alinhado ao overview que já retornanullsem docs. comparecontinua só modo do mapa (não filtra lista nem mapa);pagecontinua só paginação da lista.- Guardrails: sem migration, sem collection, sem Consent, sem server action; leituras com
user+overrideAccess: false.
Decisões travadas
- Item próprio B7 (não absorver em R6 nem em B6). É correção de produto/contrato lista↔mapa, não polish visual (R6) nem
setStyleincremental (B6). (2026-07-21, classificação roadmap-item.) Rejeitado: fill-in sem plano (perde o contrato e o teste); fase de remodelagem-pracas.md (R0–R5 já entregues). - Mesmo
Whereda lista/overview — reusarbuildPlazaListWhere. Uma fonte de verdade; overview já é o precedente (conjunto filtrado inteiro,pagination: false). Rejeitado: filtro client-side noPlazaMapPanel(vazaria dados não filtrados no HTML/Flight); segundo builder de where só para o mapa. - Mapa sobre o conjunto filtrado inteiro, não a página corrente. Paridade com
loadPlazaListOverviewData. Rejeitado: respeitarpage/plazaPageSizeno mapa (mapa paginado não faz sentido geográfico). - Empty → omitir o painel do mapa. Mesma regra do overview. Rejeitado: Bahia cinza vazia com lista empty (dois empty states competindo).
- i18n e naming (AGENTS.md): identificadores em inglês (
loadPlazaMapBundle,PlazaListState,buildPlazaListWhere); strings visíveis inalteradas salvo copy mínima se o empty do mapa precisar (preferir só omitir o painel).
Questões em aberto
- Mover
PlazaFilterspara cima do mapa? Opções: A) neste item | B) R6 | C) deixar. Recomendação: B/C — fora do appetite; o filtro já é URL-driven e o mapa reage no refresh RSC. Marcar como polish visual em R6 se a coordenação reclamar da ordem. - Highlight / fitBounds só nos municípios do filtro? Opções: A) só coroplético nos valores filtrados (polígonos restantes cinza) | B) além disso
fitBoundsno footprint filtrado. Recomendação (B7): A. B promovido a B12 (aproximar-mapa-pracas.md) quando o gatilho disparou (2026-07-21).
Abordagem proposta
flowchart LR
url["URL searchParams"] --> parse["parsePlazaListParams"]
parse --> where["buildPlazaListWhere"]
where --> list["loadPlazaListPageData"]
where --> overview["loadPlazaListOverviewData"]
where --> map["loadPlazaMapBundle"]
map --> panel["PlazaMapPanel"]
Componentes:
loadScopedPlazas/loadPlazaMapBundle(src/utilities/plazaMapData.ts):searchParams→parsePlazaListParams→buildPlazaListWhere(state)nopayload.find(user+overrideAccess: false).loadScopedPlazasrecebePlazaListState(parse único no bundle). Zero docs →null.comparedestate.compare.pracas/page.tsx:loadPlazaMapBundle(payload, user, rawSearchParams)— paridade com lista/overview.- Depth check: não criar
plazaMapFilters.tspass-through; não duplicar clauses deq/region/… — só reusarbuildPlazaListWheredeplazaUi.ts. - Teste: int (ou unit com Payload mock) garantindo que com
region(oukind) o bundle só contémibgeCodes das Praças filtradas; e que conjunto vazio →null. Precedente de access já comentado no loader (assessor). - Migration: Sem migration, sem collection, sem server action.
Dependências
- Dura: R2 superfícies core (mapa + filtros) — já entregue.
- Suave: A9 (estimativa-votos-praca.md) — métrica 2026 passa a
expectedVotes ?? effectiveTotal; B7 continua válido só com pledges até A9. B6 (setStyle) independente. - Reusa:
buildPlazaListWhere/parsePlazaListParams(plazaUi.ts), padrão overview emplazaPageData.ts,PlazaMapPanel/BahiaMap.
Não escopo
- Reordenar mapa vs filtros / redesign do painel → R6.
BahiaMapsetStyle incremental → B6 (escala-dry-pos-b3.md).- Hover / destaque + total de votos no polígono → B10 (hover-mapa-pracas.md).
- Polígonos por zona / painel de zona → B8 (poligonos-pracas-zona.md).
- Novos filtros de lista; alterar semântica de
compare.
Rabbit holes
- Filtro no cliente após carregar Bahia inteira. Se alguém “só esconder no Leaflet”: vaza números no Flight e o Assessor ainda baixa dados fora do filtro. Mitigação: where no servidor.
- FitBounds / zoom automático por filtro. Explode em edge cases (TI pequena vs Salvador multi-zona). Mitigação: defer com gatilho — promovido a B12 (aproximar-mapa-pracas.md) em 2026-07-21 quando o gatilho disparou.
- Unificar list+overview+map num único fetch. DRY prematuro (<3 call sites já compartilham o where). Mitigação: só compartilhar o
Where; fetch único só se profiling pós-B7 mostrar triplo load caro.
Adiado com gatilho
Gatilho disparado 2026-07-21 → B12 (aproximar-mapa-pracas.md).fitBoundsao footprint filtrado.- Mover filtros acima do mapa. Revisitar no ciclo R6 se critique/smoke apontar ordem confusa.
Referências
docs/roadmap.md(Trilha B, item B7; Remodelagem R2)src/app/(campaign)/campanha/(app)/pracas/page.tsx— composição mapa + filtros + listasrc/utilities/plazaMapData.ts—loadScopedPlazas/loadPlazaMapBundlesrc/utilities/plazaUi.ts—buildPlazaListWhere,PlazaListState,PlazaListSearchParamstests/int/plazaMapData.int.spec.ts— contrato filtro + accesssrc/utilities/plazaPageData.ts— precedente overview filtrado (pagination: false)docs/plans/mapa-bahia-geometrias.md— contrato histórico “mapa escopado pelos mesmos filtros”docs/plans/remodelagem-pracas.md— mapa v1 / access do assessor- AGENTS.md — Campaign auth,
overrideAccess: false, naming PRODUCT.md/DESIGN.md— Field Desk; mapa como instrumento de coordenação, não dashboard SaaS