Merge branch 'cursor/12a461ea'

This commit is contained in:
Francisco Ignácio Fontoura Solla 2026-07-30 03:18:08 -03:00
commit f093d74b76
14 changed files with 904 additions and 6 deletions

View file

@ -7,6 +7,7 @@ alwaysApply: false
## Status
- **B79–B90 registrados (2026-07-30):** pós-**B73** (remover bottom nav), chrome mobile fora do Início = bottom drawer **não-modal** (ações contextuais + busca global) — chassis **B79** + catálogos por vertical **B80–B90** (Municípios, Territórios, Lideranças, Dobradinhas, Atividades, Demandas, Apoiadores, Assessores, Organizações, Contatos leader, Conceitos+Perfil). **Quadro fora** do inventário. Granularidade = uma vertical (lista+detalhe). Lote inteiro **não cortável**. Planos em `docs/plans/chassis-bottom-drawer-acoes-rapidas.md` e `acoes-rapidas-*.md`.
- **B77 registrado (2026-07-30):** simplificar wizard ajuste de votos — três cenários numa tela (strip + inputs como popover da lista); atalhos no input focado; coerência só no confirm com highlight; substitui ritual `?cenario=` de B61/B76. Plano: [`simplificar-ajuste-votos-wizard.md`](../../../docs/plans/simplificar-ajuste-votos-wizard.md).
- **B71 entregue em código (2026-07-30):** polimento visual dos resultados de busca no Início (UX-1) — `src/lib/homeSearchUi.ts` (`HOME_SEARCH_HIT_ROW_WRAPPER_CLASS` = bleed + hover + `focus-within`; heading/list); `HomeSearchHitRow` faixa full-bleed `-mx-4 px-4 md:-mx-6 md:px-6` (mantém `onMouseDown` preventDefault de B66); todos os `HomeSearch*Group` com `ul list-none` e título `text-xs` sentence-case (sem `uppercase`/`tracking-wide`). Unit `homeSearchUi.unit.spec.tsx`. Sem migration/action/JSON. Plano: [`polimento-resultados-busca-inicio.md`](../../../docs/plans/polimento-resultados-busca-inicio.md).
- **B66 entregue em código (2026-07-30):** modo focado da busca no **focus** (emenda B47) — `homeSearchUiFocused` (`inputFocused || query.isActive`) já no contrato/hook; overlap B68 (sugestões no focus vazio). **Nesta entrega:** `CampaignHomeLayout` retrai summary+spacer (`data-slot="home-chrome"`) e actions com grid `0fr/1fr` + opacity 220ms (`motion-reduce:transition-none`) em vez de `hidden`; `md:flex-none` no chrome; `HomeSearchHitRow` `onMouseDown` preventDefault (blur→click); e2e focus sem digitar + regressão com digitação. Sem migration. Plano: [`modo-focado-busca-no-focus.md`](../../../docs/plans/modo-focado-busca-no-focus.md).

View file

@ -0,0 +1,64 @@
# Ações rápidas — Apoiadores
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B86**)
Impeccable: B — drawer B79 em `/apoiadores` (staff)
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · C2 · B79. Craft + **Revisão na implementação**.
Brief: staff no cadastro nominal quer cadastrar / importar / buscar sem voltar ao Início. Leader usa **B89**, não esta rota.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/apoiadores` staff (access `canAccessSupporterArea`). Import CSV e create já existem na vertical.
## Objetivos
- Catálogo sugerido: “Cadastrar apoiador” (rota/create da vertical), atalho import se houver URL estável, busca global B79; **não** empurrar A1–A5 como primários.
- Sem migration / sem novo Consent (usa chaves C2 existentes nos flows).
## Revisão na implementação _(obrigatória)_
Se import estiver escondido atrás de wizard multi-step, o launcher deve apontar ao step 1 — não inventar atalho que bypassa preview.
## Decisões travadas
- **Staff only nesta rota.** Leader → B89. **Rejeitado:** misturar catálogos.
- **i18n:** `register-supporter` / labels da vertical.
## Questões em aberto
- **Incluir A1–A5 como secundários?** **Opções:** A) não | B) no expanded. **Recomendação:** **A**.
## Abordagem proposta
Registry `/apoiadores` → 1–2 launchers da vertical + busca.
## Dependências
Dura: **B79**. Soft: C2 eng ✓.
## Não escopo
B89 Contatos; B79.
## Rabbit holes
Import token / bulk no drawer. Mitigação: wizard existente.
## Adiado com gatilho
Nenhum neste item.
## Referências
`apoiadores/**` · B79 · C2 plans

View file

@ -0,0 +1,65 @@
# Ações rápidas — Assessores
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B87**)
Impeccable: B — drawer B79 em `/assessores` (unrestricted)
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · B19 ✓ · B79. Craft + **Revisão na implementação**.
Brief: CG/candidato gerindo contas quer novo assessor / abrir carteira / busca — sem A1–A5 como foco.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/assessores` + detalhe; só `isCampaignUnrestricted`. Assessor autenticado **não** monta esta vertical.
## Objetivos
- Catálogo: “Novo assessor” → `/assessores/nova` (ou rota real); no detalhe, atalho carteira/municípios se útil; busca global.
- Gate: drawer nesta rota só se o actor for unrestricted (alinhado ao page gate).
- Sem migration.
## Revisão na implementação _(obrigatória)_
Confirmar paths reais (`nova` / `[id]`) no tree atual antes de hardcodar hrefs.
## Decisões travadas
- **Sem ações de município como primárias.** **Rejeitado:** strip B45 completa aqui.
- **i18n:** `new-advisor`; labels pt-BR B19.
## Questões em aberto
- **Reset de senha no drawer?** **Opções:** A) não (fica no detalhe) | B) sim. **Recomendação:** **A**.
## Abordagem proposta
Registry + role gate unrestricted.
## Dependências
Dura: **B79**. Soft: B19 ✓.
## Não escopo
B79; B86.
## Rabbit holes
Editar carteira inteira no drawer. Mitigação: B34/B19 cells.
## Adiado com gatilho
Nenhum neste item.
## Referências
`assessores/**` · B19 plan · B79

View file

@ -0,0 +1,66 @@
# Ações rápidas — Atividades (lista + detalhe + giros)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B84**)
Impeccable: B — drawer B79 em `/atividades`, `/atividades/[slug]`, `/atividades/giros`
Appetite: ~0,5 dia eng; atalhos de criação/agenda; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · C13 · E13 giros · B79. Craft + **Revisão na implementação**.
Brief: staff na agenda quer criar atividade / planejar giro / (no detalhe) atalho ligado ao município da atividade. Anti-goal: segundo compositor no drawer.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
Lista, detalhe e compositor `/atividades/giros` (E13). Wizard A1–A5 do Início são secundários aqui; verbo próprio da vertical importa mais.
## Objetivos
- **Lista:** “Nova atividade” → `/atividades/nova`; “Planejar giro” → `/atividades/giros`; opcional subset Início sem prefill.
- **Detalhe:** se houver município na atividade, A1–A5 com `?municipio=`; atalho editar/tarefas via tabs existentes se útil.
- **Giros:** drawer mínimo (busca + voltar lista) — não competir com o compositor.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Se o compositor de giro já tiver CTAs suficientes, o agente pode **omitir** o drawer em `/giros` (exceção local ao mount B79) — documentar.
## Decisões travadas
- **Priorizar verbos da vertical sobre os 6 do Início.** **Rejeitado:** só espelhar B45.
- **i18n:** `new-activity`, `plan-tour`; labels pt-BR.
## Questões em aberto
- **Drawer em `/giros`?** **Opções:** A) omitir | B) só busca. **Recomendação:** **A** ou **B** — não strip de ações.
## Abordagem proposta
Registry por pathname; context `{ municipalitySlug? }` do loader do detalhe.
## Dependências
Dura: **B79**. Soft: E13 ✓, B45 ✓, B60 ✓.
## Não escopo
B79; demandas B85.
## Rabbit holes
Checklist de tarefas no drawer. Mitigação: fica no detalhe.
## Adiado com gatilho
Nenhum neste item.
## Referências
`atividades/**` · E13 plan · B79

View file

@ -0,0 +1,65 @@
# Ações rápidas — Conceitos + Perfil (só busca)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B90**)
Impeccable: B — drawer B79 sem strip de ações (ou strip vazia) em `/conceitos` e `/perfil`
Appetite: ~0,25 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · E18 conceitos · B79. Craft + **Revisão na implementação**.
Brief: páginas de referência/conta — usuário ainda precisa da busca global para sair rápido para um município/pessoa; ações de ritual **não** competem com leitura de glossário ou form de perfil.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/conceitos` (staff secondary nav); `/campanha/perfil`. Não são mesas de operação.
## Objetivos
- Mount B79 com **busca global staff** e **sem** catálogo de ações (ou só “Voltar ao Início” se critique exigir âncora).
- Leader em `/perfil`: sem home-search staff; drawer mínimo ou omitir — **Recomendação:** omitir drawer no perfil leader se não houver busca segura.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Se o perfil ganhar atalhos úteis (ex. biometria B40), o agente pode adicionar 1 launcher — não a strip B45.
## Decisões travadas
- **Sem A1–A5 em Conceitos/Perfil.** **Rejeitado:** paridade Início “por consistência”.
- **i18n:** nenhum id de ação obrigatório; `home-href` se existir.
## Questões em aberto
- **“Ir ao Início” no peek?** **Opções:** A) não (sidebar) | B) sim. **Recomendação:** **A**.
## Abordagem proposta
Registry entries com `actions: []` + search enabled para staff.
## Dependências
Dura: **B79**. Soft: B47 ✓.
## Não escopo
Quadro (fora do inventário 2026-07-30); B79 chrome.
## Rabbit holes
Glossário searchable no drawer. Mitigação: página Conceitos já é o índice.
## Adiado com gatilho
Nenhum neste item.
## Referências
`conceitos/**` · `perfil/**` · B79

View file

@ -0,0 +1,66 @@
# Ações rápidas — Contatos (liderança)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B89**)
Impeccable: B — drawer B79 para role `leader` em `/campanha/contatos`
Appetite: ~0,25–0,5 dia eng; lockdown; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT.md Depth for staff / light for leader · B43/B45 leader · B79. Craft + **Revisão na implementação**.
Brief: liderança no celular cadastra apoiador / vê contatos; **sem** omnibus estadual nem A1–A5.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
Leader home de trabalho = `/campanha/contatos` (B43). Catálogo B45: `register-supporter`, `my-contacts`.
## Objetivos
- Montar drawer só para `leader` nas rotas leader (Contatos; Início leader já tem ações — **sem** drawer no Início, mesma exclusão B79).
- Ações: espelho B45 leader; busca: **não** reusar `home-search` staff — ou omitir busca, ou busca local só nos próprios contatos se já existir endpoint/lista filter. **Recomendação v1:** ações + sem omnibox global (fail closed).
- Sem migration; Consent das actions de apoiador inalterado.
## Revisão na implementação _(obrigatória)_
Se no momento existir busca local de contatos, o agente pode plugar no slot de busca do B79 **sem** abrir `home-search` staff.
## Decisões travadas
- **Lockdown: zero wizards de município.** **Rejeitado:** “só leitura” de mapa/lista.
- **Sem POST `/campanha/home-search` para leader.** **Rejeitado:** scoped hack no mesmo endpoint sem access review.
- **i18n:** ids B45 leader.
## Questões em aberto
- **Busca local no drawer?** **Opções:** A) omitir v1 | B) filtrar lista client-side. **Recomendação:** **A** se a página já tem search; **B** se a lista for longa e sem filtro.
## Abordagem proposta
Registry role=leader + path contatos → 2 ações B45. Slot search vazio ou filtro local.
## Dependências
Dura: **B79**. Soft: B45 ✓, B43 ✓.
## Não escopo
B86 staff apoiadores; B79 staff search providers.
## Rabbit holes
WebAuthn / perfil no drawer. Mitigação: `/perfil` separado (B90).
## Adiado com gatilho
Nenhum neste item.
## Referências
`contatos/**` · `campaignHomeActions.ts` leader · B79

View file

@ -0,0 +1,65 @@
# Ações rápidas — Demandas (lista + detalhe)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B85**)
Impeccable: B — drawer B79 em `/demandas` (+ detalhe)
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · A5 register-demand · B79. Craft + **Revisão na implementação**.
Brief: staff quer registrar pedido ou agir no município da demanda aberta.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/demandas`; detalhe por slug se existir. Wizard `register-demand` (quando B59+ wiring existir) + forms da vertical.
## Objetivos
- **Lista:** `register-demand` (Início/wizard) + busca; opcional “Nova demanda” rota local se for o caminho canônico atual.
- **Detalhe:** se houver município vinculado, prefills A1–A5; atalho específico da demanda (escalar/fechar) só se já existir action/URL — senão omitir.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Confirmar se o caminho canônico de criação ainda é form da vertical ou já é wizard A5; alinhar o href único.
## Decisões travadas
- **Um launcher de “Registrar pedido”, não dois.** **Rejeitado:** botão wizard + botão `/nova` no mesmo peek.
- **i18n:** id `register-demand`.
## Questões em aberto
- **Wizard A5 vs form legado?** **Opções:** A) wizard quando rota existir | B) form. **Recomendação:** **A** se `/acoes/registrar-pedido` estiver no ar; senão B.
## Abordagem proposta
Registry + `wizardActionHref` / rota de create existente.
## Dependências
Dura: **B79**. Soft: B45 ✓, B53, wiring A5.
## Não escopo
B79; B84.
## Rabbit holes
Fila de decisão de demanda no drawer. Mitigação: detalhe.
## Adiado com gatilho
Nenhum neste item.
## Referências
`demandas/**` · B79 · fluxos UX-1 A5

View file

@ -0,0 +1,65 @@
# Ações rápidas — Dobradinhas
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B83**)
Impeccable: B — drawer B79 em `/dobradinhas` (+ detalhe se houver)
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · B79 · lista B37/B36. Craft + **Revisão na implementação**.
Brief: staff na vertical de state deputies quer buscar ou iniciar ritual ligado ao território da dobradinha — sem inventar wizard de dobradinha neste item.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/dobradinhas` (lista). Detalhe se existir na árvore de rotas — mesma política de context.
## Objetivos
- Catálogo sugerido: busca global (B79) + ações Início **sem** prefill; atalho opcional “Municípios desta dobradinha” se houver filtro/URL estável.
- Não inventar `?stateDeputy=` nos wizards A1–A5 nesta fatia.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Agente pode cortar ações Início se o único job real for navegação+busca; ou propor deep-link de filtro se o serializador de lista já permitir.
## Decisões travadas
- **Sem wizard novo de dobradinha.** **Rejeitado:** fluxo paralelo ao `MunicipalityStrategyForm`.
- **i18n:** ids B45; `stateDeputyId` só se nascer atalho.
## Questões em aberto
- **Incluir WA share (B55) como ação do drawer?** **Opções:** A) não (fica na linha de busca) | B) sim. **Recomendação:** **A**.
## Abordagem proposta
Registry `/dobradinhas` → subset staff (ações Início ou só busca+1–2 verbos). Soft link para lista de municípios filtrada se API de URL existir.
## Dependências
Dura: **B79**. Soft: B45 ✓, B52 ✓.
## Não escopo
B79; B82; chips B37.
## Rabbit holes
Prefill município “principal” da dobradinha. Mitigação: N municípios — mesma regra do B82.
## Adiado com gatilho
Nenhum neste item.
## Referências
`dobradinhas/**` · B79 · `campaignHomeActions.ts`

View file

@ -0,0 +1,65 @@
# Ações rápidas — Lideranças (lista + detalhe)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B82**)
Impeccable: B — catálogo drawer B79 em `/liderancas` e `/liderancas/[id]`
Appetite: ~0,5 dia eng; prefills A4 + município(s) da liderança; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · B45 · B70 · B79. Craft compacto + **Revisão na implementação**.
Brief: staff na rede quer atualizar a pessoa à frente ou lançar ritual no município dela. Anti-goal: spreadsheet no drawer.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
Lista `/campanha/liderancas`; detalhe `/campanha/liderancas/[id]`. Wizard A4 (**B70**) é o verbo central; municípios da liderança alimentam prefill opcional de A1–A3/A5.
## Objetivos
- **Lista:** subset — `update-leadership` (sem id), atalhos de lista se existirem; demais ações Início sem prefill _(recomendado: strip enxuta, não os 6)_ .
- **Detalhe:** `update-leadership` com context `leadershipId` (query a definir no B70/chassis — se ainda não houver, href para ficha `/editar` ou wizard quando o param existir); se a liderança tiver **um** município, prefills A1–A3/A5 com esse slug; se N, não adivinhar — usuário escolhe no B60.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Se B70 ainda não expuser query de liderança, o agente deve (1) propor o param mínimo no wizard ou (2) degradar para link da ficha — registrar escolha no as-built.
## Decisões travadas
- **Não auto-escolher município quando N>1.** **Rejeitado:** “primeiro da lista” / TI inteiro.
- **i18n:** `leadershipId` em inglês; labels B58.
## Questões em aberto
- **Query `?lideranca=` no wizard A4?** **Opções:** A) sim no B70/B82 | B) só município. **Recomendação:** **A** quando B70 estiver no ar — senão degradar.
## Abordagem proposta
Context `{ leadershipId, municipalitySlug? }` → registry. Reuso `wizardActionHref`.
## Dependências
Dura: **B79**. Soft: B70, B60 ✓, B45 ✓.
## Não escopo
Chassis B79; dobradinhas B83; Contatos leader B89.
## Rabbit holes
**Convite WhatsApp (B30) no drawer.** Mitigação: já está na lista; não duplicar.
## Adiado com gatilho
Prefill multi-município com picker no drawer — quando N>1 for o caso dominante em campo.
## Referências
`liderancas/**` · B70 plan · B79 plan · `campaignHomeActions.ts`

View file

@ -0,0 +1,88 @@
# Ações rápidas — Municípios (lista + detalhe)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B80** — consumer do B79)
Impeccable: B — encaixe no drawer B79; catálogo + prefills; sem rota nova
Appetite: ~0,5–0,75 dia eng; registry + hrefs contextualizados; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: `PRODUCT.md` / `DESIGN.md` · catálogo B45 · wizards B59+ · tema `campaign`.
Na implementação: craft compacto → critique → polish. **Antes do craft:** revisar o catálogo abaixo contra o estado atual dos wizards/rotas (seção Revisão).
Brief compacto:
- **Persona:** staff na lista ou no detalhe de município, no celular, quer agir sem voltar ao Início.
- **Job principal:** no detalhe, lançar A1–A5 **já com o município** (pula B60); na lista, mesmas ações do Início (escolhe município no wizard).
- **Estratégia de cor:** Restrained (herda B79).
- **Edit where you see:** não — launchers para wizards/listas já existentes.
- **Anti-goals:** duplicar formulários do detalhe no drawer; esconder edição inline da lista.
## Dados → decisão → apresentação
Dados: N/A — launchers; números ficam nos wizards/detalhe.
## Contexto
Exemplo canônico do pedido 2026-07-30: no detalhe `/campanha/municipios/[slug]`, as ações do Início partem com `?municipio=<slug>` via `wizardActionHref`. Lista `/campanha/municipios` usa os mesmos ids sem prefill (paridade B45).
## Objetivos
- Registrar no registry do **B79** as superfícies `municipios` (lista) e `municipios/[slug]` (detalhe).
- **Detalhe:** ações `update-votes`, `register-signal`, `change-trend`, `update-leadership`, `register-demand` com `wizardActionHref(slug, municipio)`; atalho `uncovered-municipalities` opcional (baixa prioridade no detalhe — pode omitir).
- **Lista:** espelhar catálogo staff do Início (B45), hrefs sem município.
- Assessor: mesmas regras de escopo (wizard/access já filtram).
- Sem migration / Consent / action nova.
## Revisão na implementação _(obrigatória)_
No Passo 4–7 de `implement-roadmap-item`, o agente **pode e deve** propor alteração de ids/rótulos/prefills se wizards novos, rotas renomeadas ou evidência de campo contradisserem esta tabela. Registrar a proposta em “Questões em aberto” do PR/plano as-built; não expandir appetite sem validar com produto se mudar o verbo principal.
## Decisões travadas
- **Detalhe = Início + `?municipio=` e skip da etapa B60.** **Rejeitado:** abrir `/editar`; Sheet local de votos no drawer.
- **Lista = paridade Início (sem prefill).** **Rejeitado:** forçar “último município visitado” sem pedido.
- **i18n:** ids estáveis do B45; labels curtos da strip (B58).
## Questões em aberto
- **Incluir “Ver esquecidos” no detalhe?** **Opções:** A) não | B) sim. **Recomendação:** **A** — fora de contexto no detalhe.
## Abordagem proposta
```mermaid
flowchart LR
page["municipios page RSC"] --> ctx["context.municipalitySlug?"]
ctx --> reg["resolveQuickActions"]
reg --> drawer["B79 drawer"]
drawer --> wiz[" /acoes/*?municipio= "]
```
Componentes:
- Provider/registry entries em `src/lib/` (ou ao lado do chassis) lendo `params.slug` no detalhe.
- Reuso `toHomeActionButtonProps` / `wizardActionHref`.
- **Migration:** nenhuma.
## Dependências
- Dura: **B79**. Soft: B45 ✓, B60 ✓, B61/B63/B64/B70 conforme disponíveis (href aponta; wizard incompleto = página ponte).
## Não escopo
- Chassis UI → **B79**. Outras verticais → **B81–B90**. Territórios → **B81**.
## Rabbit holes
- **Deep-link para tab específica do detalhe além do wizard.** **Mitigação:** só wizards + atalhos de lista neste item.
## Adiado com gatilho
- **Ação “Definir nível” (E14) no drawer do detalhe.** Revisitar quando o CG pedir N0–N4 no ritual mobile (hoje submit explícito + nota).
## Referências
- [chassis-bottom-drawer-acoes-rapidas.md](chassis-bottom-drawer-acoes-rapidas.md) · `campaignActionRoutes.ts` · `campaignHomeActions.ts` · `municipios/[slug]/page.tsx`

View file

@ -0,0 +1,64 @@
# Ações rápidas — Organizações
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B88**)
Impeccable: B — drawer B79 em `/organizacoes` (+ detalhe)
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: PRODUCT/DESIGN · vertical organizações · B79. Craft + **Revisão na implementação**.
Brief: staff em orgs (ramificações políticas, ex. SindMed) quer criar/buscar/ligar — prioridade baixa vs Municípios/Lideranças, mas **não cortável** no lote (produto 2026-07-30).
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/organizacoes` + `[slug]` / `nova`. Fora do `staffNav` principal em alguns momentos históricos — rota existe.
## Objetivos
- Catálogo: “Nova organização”, busca global; no detalhe, atalho para lideranças vinculadas se URL de lista filtrada existir; A1–A5 só se houver município óbvio (geralmente **não**).
- Sem migration.
## Revisão na implementação _(obrigatória)_
Se a vertical estiver pouco usada no momento do implement, manter **busca + nova** e omitir A1–A5 sem culpa.
## Decisões travadas
- **Drawer existe mesmo fora do bottom-nav histórico.** **Rejeitado:** pular org do lote.
- **i18n:** `new-organization`.
## Questões em aberto
- **Prefill liderança a partir da org?** **Opções:** A) não v1 | B) se B70 aceitar. **Recomendação:** **A**.
## Abordagem proposta
Registry paths org → launchers CRUD locais + busca.
## Dependências
Dura: **B79**. Soft: B69 ✓ (org permanece no modelo).
## Não escopo
B82; B79.
## Rabbit holes
Multi-org membership editor no drawer. Mitigação: forms existentes.
## Adiado com gatilho
Nenhum neste item.
## Referências
`organizacoes/**` · B79 · B69 plan

View file

@ -0,0 +1,67 @@
# Ações rápidas — Territórios de Identidade
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B81**)
Impeccable: B — catálogo no drawer B79 para `/campanha/territorios`
Appetite: ~0,25–0,5 dia eng; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: `PRODUCT.md` / `DESIGN.md` · B21 ✓ / E12 ✓ · B79.
Na implementação: craft compacto → critique → polish + **Revisão na implementação** (abaixo).
Brief: staff olhando TIs quer ou filtrar municípios da região ou iniciar ritual sem voltar ao Início. Restrained. Anti-goal: fingir que TI é município no `?municipio=`.
## Dados → decisão → apresentação
Dados: N/A.
## Contexto
`/campanha/territorios` (B21) é lista regional; linha → `municipios?region=`. Sem entidade “município atual”.
## Objetivos
- Catálogo sugerido: ações Início **sem** prefill de município + atalho “Ver municípios deste TI” quando houver linha/seleção _(se a UI expuser TI ativo; senão só ações Início)_.
- Sem inventar wizard de TI.
- Sem migration.
## Revisão na implementação _(obrigatória)_
Agente pode reordenar/cortar ações se, no momento do implement, o uso real de Territórios for só “pular para lista filtrada” — documentar desvio.
## Decisões travadas
- **Sem `?municipio=` a partir do TI.** **Rejeitado:** pegar “primeiro município do TI” como prefill (mentira geográfica).
- **i18n:** ids B45 + `territory-municipalities` se nascer atalho.
## Questões em aberto
- **Atalho por TI exige seleção de linha?** **Opções:** A) só ações Início na v1 | B) expandir drawer ao tocar linha com atalho. **Recomendação:** **A** neste appetite.
## Abordagem proposta
Registry path `/campanha/territorios` → catálogo staff Início (hrefs B45). Opcional: deep-link `buildMunicipalityListHref({ region })` se contexto de TI existir.
## Dependências
Dura: **B79**. Soft: B21 ✓, B45 ✓.
## Não escopo
Chassis → B79. Municípios → B80.
## Rabbit holes
**Agregar ações “por TI” com meta/cobertura.** Mitigação: fora — E12 já está na tabela.
## Adiado com gatilho
Nenhum neste item.
## Referências
`territorios/page.tsx` · `municipalityListUrl` · B79 plan

View file

@ -0,0 +1,116 @@
# Chassis do bottom drawer de ações rápidas + busca (mobile)
Status: rascunho
Atualizado em: 2026-07-30
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B79** — UX-1 chrome pós-B73)
Impeccable: C — chrome novo em toda rota `(app)` exceto Início e wizards; gesto drag + busca embutida
Appetite: ~1,5–2 dias eng; shell não-modal + snap/drag + slot de ações + reuso da busca global; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: `PRODUCT.md` (Clarity under pressure; Feel the action; anti spreadsheet) / `DESIGN.md` (hybrid mobile Mandate Red + sidebar Sheet) · tema `data-theme='campaign'` · primitivo `Drawer` (`src/components/ui/Drawer.tsx`, já com `modal={false}` que **não** monta overlay).
Na implementação (`implement-roadmap-item`): shape → craft → critique → polish.
Brief compacto:
- **Persona / contexto:** CG/assessor no celular, **fora** do Início — após **B73** a bottom nav some; o ritual de ação+busca só existia no Início; nas outras páginas sobra só o sidebar fechado.
- **Job principal:** ter ações rápidas do contexto da página + a mesma busca global do Início, sem escurecer nem bloquear a página atrás; poder recolher/expandir o drawer para ver mais conteúdo.
- **Estratégia de cor:** Restrained — superfície de chrome (fundo campaign), não modal dramático.
- **Edit where you see:** não neste item — launchers; escrita nos wizards/listas.
- **Anti-goals:** overlay que muda opacidade/`pointer-events` da página; segunda bottom nav de destinos de domínio; FAB flutuante; drawer no Início (já tem dock B65); drawer em `/campanha/acoes/*` (ritual B59/B75); reinventar busca (reusar B47+).
## Dados → decisão → apresentação
Dados: N/A — chrome de navegação/ação; hits da busca = providers B48+ já existentes.
## Contexto
Decisão de produto (2026-07-30): com a remoção da bottom nav (**B73**), a navegação mobile frequente fica no Início (ações + busca) e no sidebar (Sheet fechado por padrão, B38 ✓). Nas **demais** páginas falta um atalho de intenção. Solução: **bottom drawer** sempre montado no viewport &lt;`md` (desktop: fora — sidebar + chrome amplo bastam _(assumido)_), com:
1. Strip/catálogo de ações **contextualizadas** pela página atual (catálogos = **B80–B90**).
2. Barra de busca com o **mesmo escopo global** do Início (`POST /campanha/home-search`, providers B48–B55).
3. Gesto: arrastar para cima/baixo para expandir/recolher; tap na borda/handle superior também alterna.
O `Drawer` shadcn/base-ui já expõe `modal={false}` (não renderiza `DrawerOverlay`) e `snapPoints` — profundidade certa; não inventar segundo sheet.
## Objetivos
- Componente shell (ex. `CampaignQuickActionsDrawer`) montado no layout `(app)` **só** quando: viewport mobile, actor staff (ou leader nas rotas que o plano B89 pedir), pathname **não** é Início exato e **não** está sob `/campanha/acoes`.
- **Não-modal:** página atrás permanece 100% opaca, scrollável e interativa; o drawer **ocupa** faixa inferior (layout shift / padding do scroll) em vez de cobrir com scrim.
- Snap points mínimos: **collapsed** (handle + talvez 1 linha de peek) e **expanded** (ações + busca); drag e tap no handle/borda superior alternam. Persistência de snap na sessão _(recomendado: `sessionStorage`)_ — Adiado se estourar appetite.
- Slot `actions` (lista já resolvida com `href`s) + slot/região de busca reusando `CampaignHomeSearch` / `HomeSearchContext` / results shell — extrair o necessário para não acoplar ao `CampaignHomeLayout`.
- Contrato de contexto client-safe (ex. `CampaignQuickActionContext`: `municipalitySlug?`, `leadershipId?`, …) + helper que resolve `href` via `wizardActionHref` / atalhos de lista — **B80+** só preenchem o contexto e o catálogo.
- Ajuste de padding do `campaign-content-scroll` para a altura do peek (substitui o antigo `pb-24` da bottom nav após B73).
- Guardrails: sem migration, sem collection, sem Consent, sem server action nova de escrita; leader lockdown respeitado (sem omnibox estadual no drawer staff).
## Decisões travadas
- **Drawer não-modal (`modal={false}`), nunca scrim.** Pedido explícito 2026-07-30: não mudar opacidade/visibilidade/interatividade da página. **Rejeitado:** `modal={true}` (padrão do kit); Sheet full-screen; dim `bg-black/10`.
- **Fora do Início e fora de `/acoes/*`.** Início já tem dock; wizard tem chrome próprio (B75). **Rejeitado:** unificar Início no mesmo drawer (dois docks); drawer dentro do wizard.
- **Só mobile (&lt;`md`).** Desktop/tablet mantêm sidebar + busca do Início quando o usuário volta. **Rejeitado:** drawer em `md+` (ruído; compete com sidebar).
- **Catálogo por página = itens B80–B90**, não hardcode no chassis. O chassis só renderiza o que a rota fornece (via registry pathname→provider ou prop do layout segment). **Rejeitado:** um único catálogo global idêntico ao Início em toda rota (perde o prefill).
- **Busca = mesmo contrato do Início** (`home-search`, debounce, modo focado **dentro do drawer expandido**). **Rejeitado:** segunda API; command palette desktop neste item.
- **i18n:** ids `CampaignQuickActionsDrawer`, `quickActionContext`, `snap`; copy pt-BR (“Buscar na campanha”, aria do handle “Mostrar ações rápidas” / “Ocultar…”).
## Questões em aberto
- **Mount: layout `(app)` com registry vs. slot por `layout.tsx` de cada área?** **Opções:** A) registry central pathname→catalog no `(app)/layout` | B) cada área exporta `quickActions` via parallel route/slot. **Recomendação:** **A** — um mount, B80+ só registram; B se o registry virar switch gigante. _(assumido)_
- **Peek inicial: collapsed ou expanded?** **Opções:** A) collapsed (mais conteúdo) | B) expanded (ações à mão). **Recomendação:** **A** no 1º paint; expandir no tap/drag — campo precisa ver a lista. _(assumido — critique com device)_
- **Leader: drawer só em Contatos (B89) ou também se navegar a outras rotas?** **Opções:** A) só rotas leader | B) esconder sempre fora de Contatos. **Recomendação:** **A** — `getCampaignNav` leader já é mínimo.
## Abordagem proposta
```mermaid
flowchart TB
layout["(app)/layout.tsx mobile"] --> gate{"pathname Início ou acoes?"}
gate -->|sim| skip["sem drawer"]
gate -->|não| drawer["CampaignQuickActionsDrawer modal=false"]
drawer --> handle["handle + snap"]
drawer --> actions["ações do registry B80+"]
drawer --> search["HomeSearch* reusado"]
actions --> wizards["wizardActionHref + context"]
search --> api["POST /campanha/home-search"]
```
Componentes:
- **`CampaignQuickActionsDrawer`** (`src/components/campaign/shell/`): `Drawer` `modal={false}` + `snapPoints` + `showSwipeHandle`; região de ações (reuso visual de `CampaignHomeActionStrip` / botões B44 se couberem no peek) + busca.
- **`campaignQuickActionRegistry` / `resolveQuickActionsForPath`** (`src/lib/` client-safe): pathname + role + context → `ResolvedCampaignHomeAction[]` (ou tipo irmão). Contextos ricos entram pelos planos B80+.
- **Extrair busca do acoplamento ao Início** o mínimo necessário (`HomeSearchProvider` montável fora de `CampaignHomeStaffChrome`) — depth check: não duplicar debounce/contrato.
- **`(app)/layout.tsx`**: mount condicional; padding inferior do scroll = altura do peek.
- **Migration:** Sem migration, sem collection, sem server action de escrita.
## Dependências
- Dura: **B73** (remover bottom nav — senão dois chromes inferiores). Soft: **B47 ✓**/B48+ (busca); **B45 ✓**/B44 ✓ (strip/botão); **B60 ✓** (`wizardActionHref` + `?municipio=`).
- Desbloqueia **B80–B90**.
## Não escopo
- Catálogos e prefills por vertical → **B80–B90**.
- Novos wizards / novas actions de escrita.
- Desktop omnibox global.
- Quadro: **fora do inventário** (decisão de produto 2026-07-30).
## Rabbit holes
- **State machine de snap sincronizada com teclado virtual / visualViewport.** **Mitigação:** v1 = CSS snap + padding fixo; medir iOS no craft; Adiado com gatilho se o teclado cobrir a busca.
- **Reimplementar Drawer do zero.** **Mitigação:** `modal={false}` + snapPoints do kit.
- **Levantar strip do Início para shared sem medir bundle.** **Mitigação:** reusar botão; extrair strip só se o JSX divergir &lt;~20 linhas.
## Adiado com gatilho
- **Persistir snap expanded/collapsed entre navegações.** Revisitar se o CG reclamar de reabrir o drawer a cada rota.
- **Peek com 1–2 ações favoritas sem expandir.** Revisitar após 1 semana de uso do collapsed-only.
## Referências
- `docs/roadmap.md` (UX-1, B73, B79–B90)
- `src/components/ui/Drawer.tsx` — `modal={false}` sem overlay
- `src/lib/campaignActionRoutes.ts` — `wizardActionHref`
- `src/lib/campaignHomeActions.ts` + `CampaignHomeActionStrip` / `CampaignHomeSearch`
- `src/app/(campaign)/campanha/(app)/layout.tsx` — scroll + chrome
- [remover-bottom-nav-mobile.md](remover-bottom-nav-mobile.md) · [fluxos-acao-primeiro-inicio.md](fluxos-acao-primeiro-inicio.md)
- `PRODUCT.md` / `DESIGN.md` — Field Desk mobile

File diff suppressed because one or more lines are too long