From d04f23399f5a2c76417ad3f80560701cd11dbec3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Francisco=20Ign=C3=A1cio=20Fontoura=20Solla?=
Date: Wed, 29 Jul 2026 15:27:46 -0300
Subject: [PATCH] Fill-in: move estimate scenario into municipality list
filters.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cenário lives in MunicipalityFilters with provider wrapping filters and results; roadmap and plan marked delivered.
---
.cursor/rules/projects/nucleos-eleitorais.mdc | 1 +
.../plans/cenario-junto-filtros-municipios.md | 16 ++++++---
docs/roadmap.md | 6 ++--
.../campanha/(app)/municipios/page.tsx | 24 +++++++------
.../municipality/MunicipalityFilters.tsx | 36 +++++++++++++++++++
.../municipality/MunicipalityListOverview.tsx | 14 +-------
.../votePledge/VoteEstimateScenarioField.tsx | 4 +--
.../campaignListFilterNavigation.unit.spec.ts | 33 ++++++++++-------
8 files changed, 89 insertions(+), 45 deletions(-)
diff --git a/.cursor/rules/projects/nucleos-eleitorais.mdc b/.cursor/rules/projects/nucleos-eleitorais.mdc
index c2685289..ca53e017 100644
--- a/.cursor/rules/projects/nucleos-eleitorais.mdc
+++ b/.cursor/rules/projects/nucleos-eleitorais.mdc
@@ -7,6 +7,7 @@ alwaysApply: false
## Status
+- **Fill-in Cenário junto aos filtros entregue em código (2026-07-29):** em `/campanha/municipios` (staff), o seletor **Cenário** (`VoteEstimateScenarioField`) saiu do header do `MunicipalityListOverview` e entrou na barra slim de `MunicipalityFilters` (desktop: antes de Salvar/Limpar; mobile: após filtros staff, antes de Ordenar). `MunicipalityEstimateScenarioProvider` passou a envolver filtros + resultados; cenário continua estado local (fora da URL e do **Limpar**). Hint `VOTE_ESTIMATE_SCENARIO_FILTERS_HINT`. Sem migration/action/Consent. Plano: [`cenario-junto-filtros-municipios.md`](../../../docs/plans/cenario-junto-filtros-municipios.md).
- **B46 entregue em código (2026-07-29):** thumb-zone do Início (UX-1 chassis) — `CampaignHomeLayout` ancora `CampaignHomeActions` na metade inferior do viewport em mobile (`min-h-full` no shell + spacer `flex-1` acima da strip; clearance existente `pb-24` + bottom nav fixa, sem `position: fixed` na strip) e no topo em `md+` (`md:min-h-0`). Slots `data-slot="home-actions"` e opcional `searchSlot` → `data-slot="home-search"` (ordem documento mobile ações→busca; desktop busca→ações via `order-1`/`order-2`/`order-3`) para **B47**. Wire em `campanha/(app)/page.tsx`. Unit `campaignHomeLayout.unit.spec.ts`; e2e `campaignHomeActions` verde. Sem migration. Plano: [`posicao-botoes-acao-inicio-thumb-zone.md`](../../../docs/plans/posicao-botoes-acao-inicio-thumb-zone.md). Próximo: **B47** busca global.
- **B45 entregue em código (2026-07-29):** catálogo de ações do Início por persona (UX-1 chassis) — `src/lib/campaignHomeActions.ts` (`homeActionsForRole`, `toHomeActionButtonProps`) + ilha client `CampaignHomeActions` (ícones Lucide no client; RSC passa `role` + `uncoveredMunicipalitiesHref` de `buildMunicipalityListHref`). Staff (coordinator/candidate/advisor): 6 ações; `uncovered-municipalities` → `?coverage=sem_assessor&sort=votos`; demais inertes (`cursor-default`). Leader: 2 ações; `my-contacts` → `/campanha/contatos`. Seção "O que você quer fazer?" acima da strip B44. Unit `campaignHomeActions.unit.spec.ts`; e2e `campaignHomeActions.e2e.spec.ts`. Sem migration. Plano: [`catalogo-acoes-inicio-por-persona.md`](../../../docs/plans/catalogo-acoes-inicio-por-persona.md).
- **B46–B55 registrados no roadmap (2026-07-29):** ~~thumb-zone do Início (**B46**)~~ entregue; busca global fatiada (**B47** input → **B48** Municípios/TIs → **B49–B53** outros grupos → **B54** grid/cap → **B55** WA/share). Cadeia: B45 ✓ → B46 ✓ → B47 → …. Planos em `docs/plans/posicao-botoes-*` e `busca-global-*`. Assumido: staff-only na busca; clique = rotas de detalhe existentes; TIs no grupo Municípios.
diff --git a/docs/plans/cenario-junto-filtros-municipios.md b/docs/plans/cenario-junto-filtros-municipios.md
index 24bf1940..73dfa9cb 100644
--- a/docs/plans/cenario-junto-filtros-municipios.md
+++ b/docs/plans/cenario-junto-filtros-municipios.md
@@ -1,12 +1,14 @@
# Seletor de Cenário junto aos filtros de Municípios
-Status: rascunho — **nota Pass 2 W1 (2026-07-25):** o cenário continua client-side e NUNCA entra na serialização de URL da lista; mover para a URL é exatamente o escopo deste fill-in
-Atualizado em: 2026-07-24
+Status: entregue (2026-07-29)
+Atualizado em: 2026-07-29
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Fill-ins)
Impeccable: B — encaixe em `MunicipalityFilters` + `MunicipalityListOverview` (`/campanha/municipios`); sem rota nova
Appetite: ~0,25–0,5 dia eng; relocação de controle + ajuste do provider; sem migration
Responsável: —
+- **Revisão 2026-07-29 (implementação):** pós-B16 ✓ o Cenário pousou na **barra slim** (desktop: entre resumo e Salvar/Limpar; mobile: após filtros staff, antes de Ordenar). `MunicipalityEstimateScenarioProvider` envolve filtros + `CampaignListResults` em staff. Hint `VOTE_ESTIMATE_SCENARIO_FILTERS_HINT`. Testes do shell de filtros montam o provider (mesmo contrato que a página). Caminhos reais: `src/components/campaign/municipality/*`, `src/components/campaign/votePledge/VoteEstimateScenarioField.tsx`.
+
## Design (Impeccable)
Âncoras: `PRODUCT.md` (princípios 2 — clareza sob pressão — e 8 — Feel the action) / `DESIGN.md` (register `product`; Field Desk) · tema `data-theme='campaign'` · shells `MunicipalityFilters`, `VoteEstimateScenarioField`, `MunicipalityEstimateScenarioProvider`.
@@ -48,12 +50,12 @@ Polish anterior (notebook 2026-07-23) já tinha movido o seletor do mapa → ove
- **Fill-in com plano próprio (não reabrir A10; não absorver só em R6; não item de trilha B).** Relocação barata, paralelizável, cortável; A10 já entregue a semântica. (2026-07-24, classificação roadmap-item.) **Rejeitado:** fase informal de A10 (mistura entrega fechada com polish de layout); só R6 (atrasa quick win no critique largo); ID B novo (infla grafo por ~½ dia).
- **Provider envolve filtros + `CampaignListResults` (staff).** Necessário para o seletor viver em `MunicipalityFilters`. Custo: troca de cenário re-renderiza a árvore dos filtros — aceitável (controle local, sem navegação). **Rejeitado:** prop-drill `scenario`/`setScenario` sem provider; dois providers; manter seletor no overview _e_ nos filtros (duplicata).
- **Cenário continua fora da URL e fora de `buildMunicipalityFiltersKey` / Limpar.** Alinhado à decisão A10 (Ano/Escala locais; só `compare` na URL do mapa). **Rejeitado:** `?estimate=` neste item; Limpar resetar cenário (mistura recorte URL com lente de leitura).
-- **Hint:** adaptar copy do overview (hoje `VOTE_ESTIMATE_SCENARIO_OVERVIEW_HINT`) para o contexto dos filtros (“Troca o total da visão geral e os votos na lista…”); mapa no Início permanece com o hint próprio. **Rejeitado:** remover o `CampaignInfoHint`.
+- **Hint:** `VOTE_ESTIMATE_SCENARIO_FILTERS_HINT` no controle da barra de filtros; mapa no Início permanece com `VOTE_ESTIMATE_SCENARIO_MAP_HINT`.
- **i18n e naming** (AGENTS.md): identificadores existentes (`VoteEstimateScenarioField`, `MunicipalityEstimateScenarioProvider`); strings “Cenário” / Pessimista / Média / Otimista.
## Questões em aberto
-- **Posição exata na fileira (antes ou depois dos selects de recorte)?** **Opções:** A) após Prioridade (fim dos staff filters, antes de Limpar) | B) logo após a busca | C) fileira própria abaixo. **Recomendação:** **A** — Cenário é lente de leitura do resultado, não critério de where; fica com os controles staff sem competir com busca/TI. _(assumido — validar no craft se a fileira quebrar em mobile)_
+- **Posição exata na fileira (antes ou depois dos selects de recorte)?** **Resolvido 2026-07-29:** desktop = barra slim B16 (antes de Salvar/Limpar); mobile = após assessores, antes de Ordenar.
- **Mapa do Início: espelhar “Cenário nos filtros do dashboard”?** **Opções:** A) neste item | B) fora / R6 se critique pedir. **Recomendação:** **B** — pedido é a página de municípios; mapa já agrupa Cenário com Ano/Escala.
## Abordagem proposta
@@ -101,6 +103,12 @@ Depth check: reusa field + context + filters existentes; sem hook/shared shell n
## Adiado com gatilho
- **Mesma colocação mental no dashboard (mapa).** Revisitar quando: R6 critique o Início ou produto pedir “um só lugar para Cenário” entre mapa e lista.
+- **Cenário fora do `