mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:53:05 +00:00
- 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.
112 lines
9.6 KiB
Markdown
112 lines
9.6 KiB
Markdown
# Aproximar o Mapa das Praças à região filtrada
|
||
|
||
> **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 rotas `pracas/` → `municipios/`; os nomes neste plano são os da época. Nomes atuais: ver [remodelagem-municipios.md](remodelagem-municipios.md).
|
||
|
||
Status: entregue 2026-07-21 (em produção desde 2026-07-23)
|
||
Atualizado em: 2026-07-21
|
||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item B12)
|
||
Impeccable: B — encaixe em `PlazaMapPanel` / `BahiaMap` (sem rota nova)
|
||
Appetite: ~0,5 dia eng; `fitToKeys` no Leaflet + chaves estáveis do bundle + teste/checklist
|
||
Responsável: —
|
||
|
||
_Revisão 2026-07-21 (implementação): escopo ampliado com correção de três bugs de hover reportados em campo — (1) ênfase agressiva (fillOpacity + stroke grosso), (2) hover em municípios fora do filtro B7, (3) ênfase sticky no mouseout (`setHoveredKey` restyleava antes de limpar `hoveredKey` + `selectedKey` espelhava hover). Solução: `interactiveKeys` compartilhando chaves com `fitToKeys` (`plazasByIbgeCode`); hover stroke-only (fill inalterado, weight 2); clear síncrono de `hoveredKey`/`selectedKey` no mouseout desktop; touch pinned inalterado._
|
||
|
||
## Design (Impeccable)
|
||
|
||
Âncoras: `PRODUCT.md` / `DESIGN.md` (register product — Field Desk) · tema `data-theme='campaign'` · shells existentes (`PlazaMapPanel`, `BahiaMap`).
|
||
|
||
Na implementação (`implement-roadmap-item`): craft compacto → critique → polish (comportamento de viewport; sem shape longo).
|
||
|
||
Brief compacto:
|
||
|
||
- **Persona / contexto:** Alex (coordenador) ou Assessor filtra por TI / tipo / cobertura e olha o mapa — hoje a Bahia inteira continua no frame e a região filtrada fica pequena demais para ler.
|
||
- **Job principal:** ao mudar o conjunto filtrado (URL ou escopo de access), o mapa **aproxima** o footprint geográfico desse conjunto.
|
||
- **Estratégia de cor:** Restrained — coroplético inalterado; só muda o viewport.
|
||
- **Anti-goals:** não redesenhar o painel; não esconder polígonos fora do filtro (já é contrato B7); não re-zoom a cada troca de ano/escala; não segunda interação “resetar zoom” neste item se o fit automático bastar.
|
||
|
||
## Contexto
|
||
|
||
**B7** ([mapa-pracas-filtrado.md](mapa-pracas-filtrado.md)) alinhou os dados do mapa ao `buildPlazaListWhere` da lista — o coroplético só pinta o conjunto filtrado. O viewport, porém, continua em `BAHIA_BOUNDS` (`src/components/campaign/BahiaMap.tsx`): `PlazaMapPanel` não passa `highlightKeys`, e o `else` do render faz `map.fitBounds(BAHIA_BOUNDS)`.
|
||
|
||
O próprio `BahiaMap` **já sabe** aproximar: quando `highlightKeys` tem itens, monta `L.geoJSON(highlightedFeatures).getBounds()` e chama `fitBounds` com `padding: [24, 24]` e `maxZoom: 10`. B7 adiara exatamente esse uso:
|
||
|
||
> `fitBounds` ao footprint filtrado — revisit when coordenação filtrar TI/região e reportar que a Bahia inteira no viewport atrapalha.
|
||
|
||
Pedido de produto (2026-07-21): o gatilho disparou — ao filtrar, aproximar a região.
|
||
|
||
## Objetivos
|
||
|
||
- Com filtro URL (ou escopo de assessor) que reduz o conjunto de Praças, o mapa abre/ajusta o viewport ao bounding box dos municípios (`codarea`) presentes no bundle.
|
||
- Sem filtro (coordenador com Bahia quase completa), o viewport permanece equivalente à Bahia inteira (fit nas chaves ≈ `BAHIA_BOUNDS`).
|
||
- Trocar **Ano** / **Escala** / **Comparar** **não** deve re-disparar zoom (só o footprint geográfico).
|
||
- Guardrails: sem migration, sem collection, sem Consent, sem server action; sem mudar o contrato de dados do B7.
|
||
|
||
## Decisões travadas
|
||
|
||
- **Item próprio B12 (não reabrir B7 nem absorver em R6/B6).** Gatilho explícito do B7; é UX de viewport, não filtro de dados, polish genérico nem `setStyle`. (2026-07-21, roadmap-item.) **Rejeitado:** fill-in sem plano (edge cases de re-zoom e highlight merecem decisão); fase “entregue” do B7 (histórico as-built fica; trabalho novo ganha ID).
|
||
- **Prop dedicada `fitToKeys` (não reusar `highlightKeys`).** `highlightKeys` hoje acopla **destaque visual** (borda/weight vermelhos) + fitBounds. Passar todos os `codarea` filtrados como highlight pintaria a TI inteira com stroke grosso. **Rejeitado:** `highlightKeys={Object.keys(...)}` (ruído visual); esconder GeoJSON fora do filtro (muda o contrato B7 / rabbit hole).
|
||
- **Chaves = `Object.keys(bundle.plazasByIbgeCode)`** — footprint estável do conjunto já escopado (access + B7), independente de `year` / `scaleMode` / `displayValues`. **Rejeitado:** chaves de `displayValues` (troca de ano re-zooma); só quando a URL tem filtro explícito (assessor com poucas Praças sem `?region=` também precisa aproximar).
|
||
- **`fitBounds` só quando a identidade de `fitToKeys` muda** (string canônica sorted join), não a cada rebuild de layer por `values`. Separar do efeito que reaplica estilo/dados, ou early-return se o footprint não mudou. **Rejeitado:** deixar o fit dentro do efeito atual ligado a `values` (B11/ano resetam o pan do usuário).
|
||
- **i18n e naming** (AGENTS.md): `fitToKeys`, `fitKey` / `fitBoundsKey`; strings visíveis inalteradas neste item.
|
||
|
||
## Questões em aberto
|
||
|
||
- **Botão “Ver Bahia toda” / reset de viewport?** **Opções:** A) não neste item (pan/zoom Leaflet + limpar filtro bastam) | B) controle explícito. **Recomendação:** A — appetite; revisitar se a coordenação pedir após usar o fit automático. _(assumido — validar no craft)_
|
||
- **Limiar para não “aproximar” (ex. >N municípios ≈ Bahia)?** **Opções:** A) sempre `fitBounds` nas chaves (N grande ≈ Bahia) | B) se `keys.length > threshold`, forçar `BAHIA_BOUNDS`. **Recomendação:** A no v1 — menos knobs; B só se profiling/UX mostrar jitter no fit de ~400 features.
|
||
- **`maxZoom` / padding?** **Opções:** A) manter `maxZoom: 10`, `padding: [24, 24]` do caminho highlight | B) tunar. **Recomendação:** A; polish só se um município único ficar apertado demais no craft.
|
||
|
||
## Abordagem proposta
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
bundle["PlazaMapBundle.plazasByIbgeCode"] --> panel["PlazaMapPanel"]
|
||
panel -->|"fitToKeys = Object.keys(...)"| map["BahiaMap"]
|
||
map -->|"fitKey mudou"| fit["map.fitBounds(features)"]
|
||
map -->|"só values/ano/escala"| style["rebuild layer / setStyle — sem re-fit"]
|
||
```
|
||
|
||
Componentes:
|
||
|
||
- **`BahiaMap`** (`src/components/campaign/BahiaMap.tsx`): props `fitToKeys?: string[]` e `interactiveKeys?: string[]` (default `[]` = fit Bahia / tudo interativo). Efeito quando `canonicalMapKeysKey(fitToKeys)` muda → `fitMapToHighlights` (sem alterar estilo). `interactiveKeys` com gate em handlers + `interactive: false` nos paths fora do set. Hover stroke-only + clear síncrono no mouseout. Reusa `fitMapToHighlights` e `canonicalMapKeysKey` em `bahiaMapStyle.ts`.
|
||
- **`PlazaMapPanel`** (`src/components/campaign/PlazaMapPanel.tsx`): memo `scopedKeys = Object.keys(bundle.plazasByIbgeCode)` → `fitToKeys` + `interactiveKeys`. Não passar as mesmas chaves em `highlightKeys`.
|
||
- **Teste:** unit do helper de chave canônica / “quando fitKey muda”; checklist manual: filtrar TI → aproxima; limpar filtros → Bahia; trocar Ano/Escala → viewport estável; assessor com poucas Praças → aproxima sem filtro URL.
|
||
- **Migration:** Sem migration, sem collection, sem server action.
|
||
|
||
## Dependências
|
||
|
||
- **Dura:** R2 (mapa) + **B7** (conjunto filtrado no bundle) — ambos entregues.
|
||
- **Suave:** nenhuma. B6 (`setStyle`) e B8 (polígonos-zona) são independentes; B8 pode no futuro refinar fit em SSA/CMS, fora deste item.
|
||
- Reusa: `BahiaMap` fitBounds existente, `plazasByIbgeCode` do B10/B7, geometrias `bahiaGeometries`.
|
||
|
||
## Não escopo
|
||
|
||
- Filtrar / omitir dados do mapa → **B7** (já entregue).
|
||
- `setStyle` incremental / perf de rebuild → **B6** ([escala-dry-pos-b3.md](escala-dry-pos-b3.md)).
|
||
- Polígonos Praças-zona SSA/CMS (fit por zona) → **B8** ([poligonos-pracas-zona.md](poligonos-pracas-zona.md)).
|
||
- Mover filtros acima do mapa / polish visual → **R6**.
|
||
- Esconder polígonos cinza fora do filtro; animação `flyTo` obrigatória.
|
||
|
||
## Rabbit holes
|
||
|
||
- **Acoplar zoom a `highlightKeys`.** Se alguém “só passar as chaves”: stroke vermelho em dezenas de municípios. **Mitigação:** prop `fitToKeys` só para viewport.
|
||
- **Re-fit a cada `values`.** Troca de ano/escala (B11) ou hover rebuild reseta o pan. **Mitigação:** dependência só da identidade de `fitToKeys`.
|
||
- **Dissolver polígonos / PostGIS / clip do layer.** **Mitigação:** só `fitBounds`; geometria continua Bahia inteira.
|
||
- **Fit por Praça-zona em Salvador/Camaçari.** Sem polígono de zona o bbox é o município. **Mitigação:** aceitar agregado municipal até **B8**.
|
||
|
||
## Adiado com gatilho
|
||
|
||
- **Controle “Ver Bahia toda”.** Revisitar se, após B12, usuários pedirem reset sem limpar filtros.
|
||
- **Threshold N→`BAHIA_BOUNDS`.** Revisitar se fit em ~400 `codarea` causar jank perceptível.
|
||
- **Restyle diff só nos paths cujo `interactive` mudou.** Revisitar se troca frequente de filtro causar jank no O(n) `restyleAllPaths` (hoje full pass quando `interactiveKey` muda).
|
||
- **`flyTo` / `animate: true`.** Revisitar se critique pedir transição; default Leaflet `fitBounds` basta no v1.
|
||
|
||
## Referências
|
||
|
||
- `docs/roadmap.md` (Trilha B, item B12; gatilho de B7)
|
||
- `docs/plans/mapa-pracas-filtrado.md` — Adiado `fitBounds` (gatilho disparado 2026-07-21)
|
||
- `src/components/campaign/BahiaMap.tsx` — `BAHIA_BOUNDS`, fit em `highlightKeys` (linhas ~310–333)
|
||
- `src/components/campaign/PlazaMapPanel.tsx` — `<BahiaMap>` sem viewport keys hoje
|
||
- `src/utilities/plazaMapData.ts` — `PlazaMapBundle.plazasByIbgeCode`
|
||
- `src/lib/bahiaGeometries.ts` — `getMunicipalityFeature`
|
||
- AGENTS.md — Campaign map / naming
|
||
- `PRODUCT.md` / `DESIGN.md` — Field Desk; mapa como instrumento de coordenação
|