Merge pull request #402 from fsolla/plans/b164-c89-nav-atualizacoes

docs: plans B164 bottom nav + C89 updates feed
This commit is contained in:
Francisco Solla 2026-08-06 04:04:24 +00:00 committed by GitHub
commit 49a236bfef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 204 additions and 0 deletions

View file

@ -0,0 +1,107 @@
# B164 — Barra de navegação inferior no mobile (+ página Mais)
Status: blocked (plano ainda não em main)
Atualizado em: 2026-08-06
Issue: #400
Priority: P1
Model: cursor-grok-4.5-medium
Model-local: deepseek-v4-high
Impeccable: C — chrome novo no shell mobile + página hub “Mais”
Canvas UI: `/home/fsolla/.cursor/projects/home-fsolla-cursor-worktrees-teqo-41rz/canvases/plan-b164-ui-draft.canvas.tsx`
Appetite: ~1–1,5 dia eng; um outcome verificável — staff no celular troca entre os 4 destinos primários e o overflow em um toque
Responsável: —
## Intenção
No telefone, a mesa precisa **trocar de domínio com o polegar** (Início → Municípios → o que está acontecendo → agenda → o resto) sem abrir o Sheet da sidebar a cada salto. Em 2026-07-29 o produto removeu a bottom bar (**B73**) a favor de intenção no Início + sidebar; na prática o campo ainda pede atalhos de domínio. Este item **reintroduz** a barra inferior no mobile com uma IA nova: quatro destinos de trabalho + **Mais** (página com o restante da navegação).
O destino **Atualizações** é o feed da campanha (cada atualização = fio de discussão) — superfície de produto em **C89**; aqui só o slot de navegação + rota âncora.
## Persona e fluxo
- **Persona / contexto:** coordenador / assessor / candidato no celular (campo ou deslocamento); uma mão; PWA; pressão de tempo entre Zap e visita.
- **Job principal:** ir aos destinos frequentes em um toque; achar Lideranças / Assessores / Dobradinhas / etc. sem caçar no Sheet.
- **Fluxo desejado:**
1. Em qualquer rota `(app)` no viewport mobile, vê barra fixa: **Início · Municípios · Atualizações · Agenda · Mais**.
2. Toca um dos quatro → navega para aquele destino (estado ativo visível).
3. Toca **Mais** → página com a lista dos destinos restantes (Lideranças, Organizações, Dobradinhas, Demandas, Apoiadores, Assessores, Quadro, Territórios, Conceitos, Perfil) + **Sair** no rodapé — filtrados por papel.
4. Desktop/tablet: sidebar continua como hoje; barra inferior **não** compete lá.
5. `SidebarTrigger` no header mobile **permanece** (escape hatch).
- **Anti-goals de produto:** segunda barra no desktop; spreadsheet de atalhos; reinventar catálogo de ações rápidas (FAB permanece); liberar liderança dos destinos staff; redesenhar o Início ou o FAB neste item; implementar o feed/threads neste item (→ **C89**).
### Esboço de fluxo (C)
```text
[qualquer página mobile staff]
→ barra: Início | Municípios | Atualizações | Agenda | Mais
→ [4 primários] → destino
→ [Mais] → página overflow → destino secundário / Sair
```
## Objetivo e aceite
- Viewport **< `md`**, papéis staff (`coordinator` / `advisor` / `candidate`): barra inferior fixa com exatamente esses cinco rótulos (copy pt-BR), na ordem pedida.
- Destinos primários (produto) — **confirmados no gate:**
- **Início** → `/campanha`
- **Municípios** → lista de municípios
- **Atualizações** → rota do feed da campanha (intenção em **C89**; até C89 landar, a rota pode existir como âncora/empty honesto, sem twin de C88)
- **Agenda** → rótulo Agenda; href da vertical de atividades até **C15**, depois cutover para `/campanha/agenda`
- **Mais** → página overflow (restante da nav + Conceitos + Perfil + Sair)
- Página **Mais**: lista clara dos destinos que **não** estão nos quatro primários; mesmo filtro de papel da nav atual (Assessores só unrestricted; Apoiadores só quem acessa a área; liderança não vê menu staff).
- Item ativo na barra (e na página Mais) reflete a rota corrente; safe-area inferior respeitada; conteúdo não fica escondido atrás da barra.
- **FAB** continua onde já existe; fica acima da barra / com folga.
- **Leader lockdown** intacto: liderança **não** ganha a barra de cinco destinos staff.
- Desktop/tablet: sem regressão da sidebar; sem barra inferior; `SidebarTrigger` mobile mantido.
- Sucessor explícito de **B73** — não editar o plano entregue.
## Dados (intenção)
- **Vou apresentar dados?** Não neste item — chrome de navegação. O feed (C89) é a superfície de dados/discussão.
- **Decisões desbloqueadas:** “para onde vou agora?” (domínio).
- **Forma:** adiada.
## Direção no codebase (hipótese)
- **Áreas prováveis:** shell `(app)` (layout, top bar mobile, padding do scroll), `src/components/campaign/shell/` (nav + bottom bar), rota overflow Mais, âncora de rota Atualizações; coexistência com FAB.
- **Precedente a olhar:** [remover-bottom-nav-mobile.md](remover-bottom-nav-mobile.md) (**B73**); `nav.ts`; [fab-acoes-rapidas-substituir-drawer.md](fab-acoes-rapidas-substituir-drawer.md); C14/C15; **C89** (feed); C87/C88 (modelo + deliberação).
- **Risco de acoplamento:** leader lockdown; filtros de papel; thumb-zone / FAB; não inventar segundo inventário de destinos fora da fonte da sidebar.
## Dependências
- Nenhuma dura para a barra + página Mais.
- Soft: **C15** / **C14** — cutover do href Agenda.
- Soft: **C89** — conteúdo rico do slot Atualizações (feed + threads).
- Soft: **C87** / **C88** — via C89 (modelo unificado + deliberação no fio).
## Fora de escopo
- Feed da campanha, interação e threads por atualização → **C89** (consome **C87** / **C88**).
- Remodel de registro / deliberação → **C87** / **C88**.
- FullCalendar / sync Google → **C15** / **C16**.
- Redesign do Início, FAB ou catálogo de ações.
- Bottom nav no desktop/tablet; esconder `SidebarTrigger` no mobile.
- Editar o plano entregue do B73.
## Rabbit holes de produto
- **"Já que voltou a barra, implementa o feed no mesmo PR."** Dois jobs. **Corte:** C89.
- **"Já que voltou a barra, mata o FAB / o Sheet."** Jobs diferentes. **Corte:** FAB e sidebar desktop ficam; trigger mobile fica.
- **"Coloca Quadro / Lideranças na barra primária."** **Corte:** primários fixos; resto em Mais.
- **"Liderança também ganha os cinco."** **Corte:** staff only.
## Questões em aberto (produto)
- Nenhuma pendente do gate anterior — respostas do humano (2026-08-06):
1. Atualizações = feed da campanha com discussão; cada update = thread → fatiado em **C89**.
2. Agenda = label Agenda; atividades até C15.
3. Mais = restante da nav + Conceitos + Perfil + Sair.
4. Manter `SidebarTrigger` no mobile.
## Referências
- GitHub Issue: [#400](https://github.com/fsolla/teqo/issues/400)
- Canvas UI (gate): [`plan-b164-ui-draft.canvas.tsx`](/home/fsolla/.cursor/projects/home-fsolla-cursor-worktrees-teqo-41rz/canvases/plan-b164-ui-draft.canvas.tsx)
- Irmão: [feed-atualizacoes-campanha-threads.md](feed-atualizacoes-campanha-threads.md) (**C89**)
- Sucessor de B73 / [#14](https://github.com/fsolla/teqo/issues/14) — [remover-bottom-nav-mobile.md](remover-bottom-nav-mobile.md)
- Soft: C14 [#389](https://github.com/fsolla/teqo/issues/389), C15 [#390](https://github.com/fsolla/teqo/issues/390); C87 [#396](https://github.com/fsolla/teqo/issues/396), C88 [#397](https://github.com/fsolla/teqo/issues/397)
- `src/components/campaign/shell/nav.ts`, layout `(app)`, FAB de ações rápidas

View file

@ -0,0 +1,97 @@
# C89 — Feed da campanha de atualizações (cada update = thread)
Status: blocked (plano ainda não em main)
Atualizado em: 2026-08-06
Issue: #401
Priority: P1
Model: cursor-grok-4.5-medium
Model-local: deepseek-v4-high
Impeccable: D — superfície nova: feed campanha-wide + interação por fio
Canvas UI: `/home/fsolla/.cursor/projects/home-fsolla-cursor-worktrees-teqo-41rz/canvases/plan-c89-ui-draft.canvas.tsx`
Appetite: ~1,5–2 dias eng; um outcome verificável — staff acompanha e discute o que aconteceu na carteira num só lugar
Responsável: —
## Intenção
A mesa precisa de um **feed da campanha** — não só o histórico dentro de um município — para ver o que está acontecendo, comentar e deliberar. Cada **atualização** vira um **fio (thread)**: o fato registrado é o post; a conversa (e, com C88, responsável / resolvido) vive ali. O slot **Atualizações** da barra mobile (**B164**) aponta para esta superfície; desktop também a alcança pela nav.
## Persona e fluxo
- **Persona / contexto:** coordenador varrendo a carteira no celular ou na mesa; assessor no recorte dos municípios que administra; pressão entre campo e WhatsApp.
- **Job principal:** ver o que aconteceu recentemente, entrar no fio de uma atualização, participar da discussão (e fechar quando couber).
- **Fluxo desejado:**
1. Abre **Atualizações** (barra mobile ou nav) → feed cronológico das atualizações da **carteira do ator** (assessor = só seus municípios; unrestricted = amplo).
2. Cada card = uma atualização (texto, polaridade/urgente quando C87 existir, município, idade).
3. Toca o card → o update abre como **thread**: corpo imutável do fato + comentários em sequência (+ responsável / resolvido quando **C88** estiver disponível).
4. Comenta / atribui / marca resolvido conforme o poder do papel (regras de C88); volta ao feed.
- **Anti-goals de produto:** segundo tracker estilo Jira; chat em tempo real; feed público / liderança; misturar Demandas/Atividades; spreadsheet de KPIs; twin do modelo de atualização fora de C87/C88.
### Esboço de fluxo (D)
```text
[Atualizações]
→ feed (carteira)
→ toca update
→ thread: fato + comentários (+ responsável / resolvido)
→ volta ao feed
```
## Objetivo e aceite
- Existe destino de produto **Atualizações** (rota de feed) usável por staff no escopo da carteira.
- Feed lista atualizações recentes com identidade do município e sinal de estado do fio (ex.: aberta / resolvida — quando C88 existir).
- Abrir um item mostra a atualização como **thread** interativa (comentar no fio); o corpo do fato permanece o registro original (imutável na intenção — alinhado a C88).
- Deliberação (responsável, resolvido, reabrir) **reusa** a intenção de **C88** — não inventa um segundo protocolo de ticket neste item.
- Leader lockdown: liderança **não** vê o feed nem os fios staff.
- Slot da barra **B164** e entrada de nav apontam para este destino (quando ambos existirem).
## Dados (intenção)
- **Vou apresentar dados?** Sim, superfície neste item (feed operacional, não KPI estadual).
- **Decisões desbloqueadas:**
- Coordenação/assessor: “o que aconteceu na carteira desde ontem?”
- No fio: “o que falta / quem resolve / podemos fechar?” (com C88)
- **Forma:** adiada — restrição: leitura relativa à carteira do ator; sem % estadual absoluto.
## Direção no codebase (hipótese)
- **Áreas prováveis:** rota `/campanha/atualizacoes` (ou equivalente), componentes de feed/thread no domínio de atualização de município, nav (`nav.ts` + slot B164), loaders no escopo do ator; actions de comentário/deliberação alinhadas a C88.
- **Precedente a olhar:** feed de atualizações no detalhe do município; C87 / C88; notificações `municipality_update`; B164.
- **Risco de acoplamento:** access por município; não criar pessoa fora de `campaignUser`/`Contact`; serialização com migrations de C87/C88.
## Dependências
- **Dura:** **C87** (modelo unificado de atualização) — o feed consome esse registro.
- **Dura:** **C88** (fio / responsável / resolvido) — a interação completa do thread; sem C88 o feed ainda pode listar e abrir o fato, mas deliberação fica incompleta — preferir shipar C89 **depois** de C88 ou degradar honestamente (só leitura + “comentários em breve”) se o gate pedir paralelismo com B164.
- Soft: **B164** (slot na barra); C15 irrelevante.
## Fora de escopo
- Chrome da barra inferior / página Mais → **B164**.
- Remodel do formulário de registro (polaridade / urgente) → **C87**.
- Definir de novo as regras de quem atribui/resolve → já em **C88** (não reabrir aqui).
- Mentions @, anexos rich, reações, SLA, kanban.
- Participação de liderança/apoiador.
- Sync externo / WhatsApp.
## Rabbit holes de produto
- **"Feed + barra no mesmo item."** Estoura appetite e mistura chrome com domínio. **Corte:** B164 vs C89.
- **"Vira rede social da campanha."** Curtidas, stories. **Corte:** fato + fio de trabalho.
- **"Filtros infinitos / analytics no feed."** **Corte:** cronológico da carteira; filtros só se couberem no appetite (município / abertas) sem virar BI.
- **"Comentário edita o fato."** **Corte:** corpo imutável; fio à parte (C88).
## Questões em aberto (produto)
- Nenhuma pendente — gate 2026-08-06 confirmou o lote com as recomendações:
1. **Ordem:** C87 → C88 → C89 (feed completo com thread); B164 pode âncora/empty antes.
2. **Desktop:** item “Atualizações” também na nav staff (mesmo destino).
3. **Criar no feed:** não nesta fatia — só caminhos existentes (município / wizard).
## Referências
- GitHub Issue: [#401](https://github.com/fsolla/teqo/issues/401)
- Canvas UI (gate): [`plan-c89-ui-draft.canvas.tsx`](/home/fsolla/.cursor/projects/home-fsolla-cursor-worktrees-teqo-41rz/canvases/plan-c89-ui-draft.canvas.tsx)
- Irmão chrome: [barra-navegacao-inferior-mobile.md](barra-navegacao-inferior-mobile.md) (**B164**)
- Depende: C87 [#396](https://github.com/fsolla/teqo/issues/396), C88 [#397](https://github.com/fsolla/teqo/issues/397)
- Planos: [atualizacao-unificada-polaridade-urgente.md](atualizacao-unificada-polaridade-urgente.md), [deliberacao-atualizacao-responsavel-thread.md](deliberacao-atualizacao-responsavel-thread.md)