diff --git a/docs/plans/apoiadores-omnibox-fonte.md b/docs/plans/apoiadores-omnibox-fonte.md new file mode 100644 index 00000000..a61d56f1 --- /dev/null +++ b/docs/plans/apoiadores-omnibox-fonte.md @@ -0,0 +1,69 @@ +# Apoiadores — filtro por fonte na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #309 +Priority: P2 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/apoiadores` +Appetite: ~0,5 dia eng +Responsável: — + +## Intenção + +Apoiadores têm **fonte** no modelo (import CSV, manual, convite, evento, liderança, …) e isso aparece no trabalho diário (qualidade do cadastro, auditoria de import), mas a omnibox só oferece intenção de voto, cidade e município. Falta recortar “só importados” / “só da liderança X-path” pela barra. + +Queremos dimensão **Fonte** na omnibox. + +## Persona e fluxo + +- **Persona / contexto:** Coordenador (ou assessor no escopo) revisando a base de apoiadores. +- **Job principal:** ver só apoiadores de uma origem de cadastro. +- **Fluxo desejado:** digita “import” / “liderança” / “fonte” → escolhe → chip → lista; remove → volta ao recorte anterior; demais filtros permanecem. +- **Anti-goals de produto:** filtro por quem importou o lote (auditoria fina); edição em massa; expor PII extra. + +## Objetivo e aceite + +- Omnibox sugere e aplica **Fonte** com os valores de produto já usados no cadastro (rótulos pt-BR legíveis). +- Comportamento exclusivo ou inclusivo: seguir o padrão mais próximo das outras dims desta lista (hoje intenção/cidade/município são únicos) — **recomendação: exclusivo** num primeiro corte. +- Ausência de chip = todas as fontes. +- KPIs da lista continuam refletindo o recorte ativo (já o fazem). + +## Dados (intenção) + +- **Vou apresentar dados?** Não — filtro sobre dados já listados; KPIs já são aggregate da lista. +- **Decisões desbloqueadas:** staff — “esta fatia da base veio de onde?” +- **Forma:** _adiada_. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `SupporterFilters`, `supporterOmnibox`, parsers em `supporterUi` / `supporterPageData`, enum de `source` no schema de apoiador. +- **Precedente:** omnibox B128 apoiadores; Consent/LGPD inalterado (só filtra linhas já autorizadas ao papel). +- **Risco:** leader lockdown — liderança só vê o que já pode; não ampliar acesso via filtro. + +## Dependências + +- Nenhuma. Soft: bloqueio jurídico de dados reais de apoiador permanece política do repo (não muda neste item). + +## Fora de escopo + +- Filtro por lote de import / token. +- Ordenação na omnibox. +- Novas fontes de cadastro. + +## Rabbit holes de produto + +- **“Fonte = liderança específica”.** **Corte:** filtrar pelo enum de origem (`lideranca`), não por ID de liderança neste item. + +## Questões em aberto (produto) + +- **Exclusivo vs OR multi-fonte?** **Opções:** A) exclusivo (como intenção) · B) inclusivo OR. **Recomendação:** A. _(assumido)_ + +## Referências + +- Inventário plan-issue 2026-08-02 — gap 5 +- `src/utilities/supporter/supporterOmnibox.ts` +- `src/components/campaign/supporter/SupporterFilters.tsx` +- AGENTS.md — Campaign supporters (C2) `source` + +- GitHub Issue #309 diff --git a/docs/plans/assessores-omnibox-municipio-carteira.md b/docs/plans/assessores-omnibox-municipio-carteira.md new file mode 100644 index 00000000..34d54b9c --- /dev/null +++ b/docs/plans/assessores-omnibox-municipio-carteira.md @@ -0,0 +1,69 @@ +# Assessores — filtrar por município da carteira na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #310 +Priority: P2 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/assessores` +Appetite: ~0,5–1 dia eng +Responsável: — + +## Intenção + +A lista de assessores mostra a carteira (chips de municípios), mas a omnibox é só busca por nome/e-mail. O coordenador não consegue perguntar “quem cobre Feira?” pela barra — tem de varrer linhas. + +Queremos filtrar assessores **pelo município que administram** via omnibox. + +## Persona e fluxo + +- **Persona / contexto:** Coordenador Geral / Candidato (rota já restrita) montando cobertura. +- **Job principal:** achar quem tem um município na carteira. +- **Fluxo desejado:** digita nome do município → sugere sob grupo tipo “Município (carteira)” → chip → só assessores que administram aquele município; busca por nome continua; remove chip → lista ampla. +- **Anti-goals de produto:** filtro “sem carteira” / “cobertura completa” neste item salvo se for trivial; edição de carteira (já existe noutro sítio). + +## Objetivo e aceite + +- Omnibox permite restringir a lista a assessores cuja carteira inclui o(s) município(s) escolhido(s). +- Semântica: **inclusivo OR** se multi-município for natural (assessor entra se cobre **qualquer** selecionado); se a 1ª fatia for um município só, exclusivo também serve — **recomendação: inclusivo OR** alinhado a Município em lideranças. +- Busca por nome/e-mail permanece. +- Rota continua inacessível a quem já não a vê hoje. + +## Dados (intenção) + +- **Vou apresentar dados?** Não. +- **Decisões desbloqueadas:** CG — “quem cobre este município?” +- **Forma:** _adiada_. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `AdvisorFilters`, `advisorListUrl` / `advisorData`, sair do `searchOnlyListOmnibox` com dimensão de município; relação `municipality.advisors` / carteira já usada na lista. +- **Precedente:** filtro Município em lideranças; chips de carteira na linha. +- **Risco:** performance se facets forem ingênuos — executor mede; produto não exige facet de 435 se houver busca tipada. + +## Dependências + +- Nenhuma. + +## Fora de escopo + +- Filtro “sem nenhum município” / gaps de cobertura estadual (territórios já cobrem outro job). +- Saved filters. +- Mudança de RBAC. + +## Rabbit holes de produto + +- **Virar mapa de cobertura nesta lista.** **Corte:** só filtro de linhas da tabela de assessores. + +## Questões em aberto (produto) + +- **Um ou vários municípios no recorte?** **Opções:** A) um (exclusivo) · B) vários (OR). **Recomendação:** B. _(assumido)_ + +## Referências + +- Inventário plan-issue 2026-08-02 — gap 6 +- `src/components/campaign/advisor/AdvisorFilters.tsx` +- `src/utilities/advisor/advisorListUrl.ts` +- `src/lib/searchOnlyListOmnibox.ts` + +- GitHub Issue #310 diff --git a/docs/plans/atividades-omnibox-presets-busca.md b/docs/plans/atividades-omnibox-presets-busca.md new file mode 100644 index 00000000..d0285c57 --- /dev/null +++ b/docs/plans/atividades-omnibox-presets-busca.md @@ -0,0 +1,89 @@ +# Atividades — presets e busca na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #306 +Priority: P1 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/atividades` (omnibox existente) +Appetite: ~0,5–1 dia eng; um outcome verificável na lista de atividades +Responsável: — + +## Intenção + +Na lista de atividades, o staff ainda escolhe a janela de trabalho (Próximos / Todos / Realizados / Rascunhos) num seletor **acima** da omnibox, enquanto tipo/status/município já vivem na barra. Isso duplica o padrão das outras listas e esconde o modo ativo fora dos chips. Além disso não há busca por texto — achar uma atividade pelo título (ou responsável) exige varrer cards. + +Queremos **uma** barra: presets de janela como chips/sugestões (com a semântica atual de “Próximos”), busca livre, e o seletor de abas de cima some. + +## Persona e fluxo + +- **Persona / contexto:** Coordenador Geral ou Assessor na mesa ou no celular, montando a agenda do dia ou achando um evento pelo nome. +- **Job principal:** escolher a janela de atividades e/ou achar por texto sem sair da omnibox. +- **Fluxo desejado:** + 1. Abre `/campanha/atividades` → default continua **Próximos** (chip ou equivalente legível na barra). + 2. Digita “realizados” / “rascunhos” / “todos” / “próximos” → sugere o preset → escolhe → chip; lista atualiza; abas de cima já não existem. + 3. Digita parte do título (ou responsável, se fizer sentido no aceite) → chip **Busca: …** → cards filtrados. + 4. Remove o chip de janela ou de busca → aquele recorte some; demais filtros (tipo, município) permanecem. +- **Anti-goals de produto:** segundo seletor paralelo às abas; diluir “Próximos” em só status sem a janela temporal; inventar filtro de intervalo de datas genérico neste item; spreadsheet mode. + +### Esboço de fluxo (B) + +```text +[lista atividades] + → foca omnibox (sem abas acima) + → digita "próximos" | "realizados" | texto do título + → escolhe sugestão → chip na barra + lista coerente + → outcome: uma barra só; semântica de Próximos intacta +``` + +## Objetivo e aceite + +- O seletor de abas **acima** da omnibox **não** aparece mais; a janela ativa é comunicada e alterável **só** pela omnibox (chips + sugestões). +- Presets disponíveis com a **mesma semântica de produto** de hoje: Próximos (status planejado/confirmado + data ≥ agora), Todos, Realizados, Rascunhos. +- Default ao abrir a lista sem params continua **Próximos**. +- Texto livre confirmado vira chip **Busca: …** e restringe os cards (pelo menos por título; responsável se couber sem inflar o appetite). +- Tipo / município (e status quando a janela permitir) continuam na omnibox; limpar não inventa comportamento novo fora do padrão B128. +- Leader lockdown inalterado (liderança não usa esta lista). + +## Dados (intenção) + +- **Vou apresentar dados?** Não — só muda como o staff monta o recorte sobre a lista já existente. +- **Decisões desbloqueadas:** staff — “qual janela / qual atividade estou vendo agora?” com uma barra. +- **Forma:** _adiada ao plano de implementação_ — restrição: chip de janela legível (não esconder “Próximos” como status cru). + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `/campanha/atividades`, `ActivityFilters`, `activityOmnibox`, `activityUi` (tabs/params), cards da lista. +- **Precedente a olhar:** B127 mapa (preset de aba) + B128 adoção; decisão de produto 2026-08-02 = mover preset **para dentro** da omnibox. +- **Risco de acoplamento:** contrato de URL da lista de atividades; não quebrar deep-links/`tab` existentes sem migração de produto clara; chassis `CampaignListOmnibox`. + +## Dependências + +- Nenhuma dura. Soft: B127/B128 ✓ (chassis). Soft paralelo: B137 (colunas ao lado da omnibox) — não bloqueia. + +## Fora de escopo + +- Filtro genérico de intervalo de datas além da semântica de Próximos. +- Filtro por “deputado presente”, progresso de tarefas, organizações da atividade. +- Saved filters B18 nesta lista. +- Mudanças nas outras listas (Issues irmãs B139+). + +## Rabbit holes de produto + +- **Virar só Status + “data futura”.** Se alguém “só completar”: perde o modo diário nomeado. **Corte:** preset **Próximos** permanece nomeado. +- **Busca global / command palette.** **Corte:** busca filtra a lista corrente, não navega o Início. + +## Questões em aberto (produto) + +- **Busca inclui responsável além do título?** **Opções:** A) só título · B) título + nome do responsável. **Recomendação:** B se o campo já aparece no card; senão A. _(assumido B se trivial — validar na execução)_ + +## Referências + +- Inventário colaborativo (plan-issue 2026-08-02) — gaps 1–2 +- `docs/plans/barra-filtros-omnibox-listas.md` (B127) +- `docs/plans/adotar-barra-filtros-omnibox-listas.md` (B128) +- `src/components/campaign/activity/ActivityFilters.tsx` +- `src/utilities/activityOmnibox.ts` +- `src/utilities/activityUi.ts` + +- GitHub Issue #306 diff --git a/docs/plans/demandas-omnibox-tipo-busca.md b/docs/plans/demandas-omnibox-tipo-busca.md new file mode 100644 index 00000000..6646fa25 --- /dev/null +++ b/docs/plans/demandas-omnibox-tipo-busca.md @@ -0,0 +1,69 @@ +# Demandas — tipo e busca na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #308 +Priority: P2 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/demandas` +Appetite: ~0,5–1 dia eng +Responsável: — + +## Intenção + +A omnibox de demandas só expõe **Status**. Tipo já existe na URL (`kind`) e na coluna da tabela, mas sem superfície na barra; também não há busca por texto para achar uma demanda pelo que está escrito. Deep-links de atividade continuam sendo atalho, não o job diário da lista. + +Queremos **Tipo** + **Busca** na omnibox, junto do Status já existente. + +## Persona e fluxo + +- **Persona / contexto:** Staff triando ou revisando demandas. +- **Job principal:** filtrar por tipo e/ou achar por texto sem caçar na tabela. +- **Fluxo desejado:** digita tipo ou trecho do pedido → chip → lista filtrada; Status continua como hoje; limpar zera o recorte da barra (deep-link `activity` pode permanecer se já for política atual). +- **Anti-goals de produto:** inventar UI nova para deep-link de atividade neste item; segunda toolbar de chips. + +## Objetivo e aceite + +- Omnibox sugere e aplica **Tipo** (valores de produto já usados na vertical). +- Texto livre → chip **Busca: …** restringindo a lista (campos visíveis da linha: pelo menos o texto/assunto que o staff já lê na lista). +- Status permanece; chips coexistentes e removíveis. +- Ausência de tipo/busca = sem restrição naquela dimensão. + +## Dados (intenção) + +- **Vou apresentar dados?** Não. +- **Decisões desbloqueadas:** staff — “quais demandas deste tipo / com este texto?” +- **Forma:** _adiada_. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `DemandFilters`, `demandOmnibox`, `demandListUrl` / loaders de lista. +- **Precedente:** B127 “não inventar superfície de kind” → **agora pedido explícito**; Status já na omnibox (B128). +- **Risco:** URL com `kind`/`activity`/`status`; não quebrar deep-links de atividade. + +## Dependências + +- Nenhuma. + +## Fora de escopo + +- Filtro por município / solicitante / liderança (salvo se já for trivial e o aceite expandir — **não** neste appetite). +- Filtro omnibox pelo deep-link `activity` (continua URL-only). +- Saved filters. + +## Rabbit holes de produto + +- **Busca full-text em anexos / histórico.** **Corte:** só campos já mostrados na lista. + +## Questões em aberto (produto) + +- **O que a busca cobre?** **Opções:** A) título/resumo visível · B) também solicitante. **Recomendação:** A no mínimo; B se o nome já está na linha. _(assumido A+B se trivial)_ + +## Referências + +- Inventário plan-issue 2026-08-02 — gaps 4 e 8 +- `src/utilities/demand/demandOmnibox.ts` +- `src/utilities/demand/demandListUrl.ts` +- `src/components/campaign/demand/DemandFilters.tsx` + +- GitHub Issue #308 diff --git a/docs/plans/liderancas-omnibox-org-dobradinha.md b/docs/plans/liderancas-omnibox-org-dobradinha.md new file mode 100644 index 00000000..11b6f511 --- /dev/null +++ b/docs/plans/liderancas-omnibox-org-dobradinha.md @@ -0,0 +1,69 @@ +# Lideranças — filtrar por organização e dobradinha na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #311 +Priority: P2 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/liderancas` +Appetite: ~0,5–1 dia eng +Responsável: — + +## Intenção + +A ficha/lista de lideranças já carrega vínculos com **organizações** e **dobradinhas**, mas a omnibox só oferece status, município, acesso ao app e ordenação. O staff que monta recorte “lideranças do sindicato X” ou “quem está na dobradinha Y” não consegue pela barra. + +Queremos dimensões **Organização** e **Dobradinha** na omnibox desta lista. + +## Persona e fluxo + +- **Persona / contexto:** Staff preparando articulação ou varrendo rede. +- **Job principal:** ver lideranças ligadas a uma organização e/ou a um deputado estadual (dobradinha). +- **Fluxo desejado:** digita nome da org / do deputado → sugere nos grupos → chip(s) → lista; remove → amplia; demais filtros (status, município, acesso) permanecem. +- **Anti-goals de produto:** criar organização/dobradinha a partir da barra; spreadsheet; filtro por estimativa de votos (assimetría). + +## Objetivo e aceite + +- Omnibox sugere e aplica **Organização** e **Dobradinha** com rótulos legíveis (nome). +- Semântica: **inclusivo OR** dentro de cada dimensão (alinhado a Município/Status nesta lista), salvo evidência de que a URL atual force exclusivo. +- Ausência de chip na dimensão = sem restrição. +- Leader lockdown: esta lista continua staff; liderança não ganha superfície nova. + +## Dados (intenção) + +- **Vou apresentar dados?** Não. +- **Decisões desbloqueadas:** staff — “quem está ligado a esta org / dobradinha?” +- **Forma:** _adiada_ — sem % estadual / sem expor estimativas. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `LeadershipFilters`, `leadershipOmnibox`, `leadershipListUrl` / `leadershipData`, relações já usadas em detalhe/células. +- **Precedente:** filtros Município/Status nesta lista; lista de dobradinhas; portfolio cells. +- **Risco:** facets grandes — busca tipada como em município; não puxar estimatedVotes para o filtro. + +## Dependências + +- Nenhuma. Soft: existência das entidades organização/stateDeputy ✓. + +## Fora de escopo + +- Filtro por gênero / contagem de pledges / “sem organização”. +- Saved filters nesta lista. +- Mudanças na lista de dobradinhas ou organizações (Issues irmãs cobrem as omniboxes delas). + +## Rabbit holes de produto + +- **“Sem organização” / “sem dobradinha” como valores.** Útil, mas **corte** neste item salvo se couber no mesmo appetite sem nova UX de sentinela — preferir só valores positivos primeiro. + +## Questões em aberto (produto) + +- **As duas dimensões neste item ou só uma?** **Opções:** A) ambas · B) só organização · C) só dobradinha. **Recomendação:** A (pedido “todos” do lote). _(assumido A)_ + +## Referências + +- Inventário plan-issue 2026-08-02 — gap 7 +- `src/utilities/leadership/leadershipOmnibox.ts` +- `src/components/campaign/leadership/LeadershipFilters.tsx` +- `docs/plans/barra-filtros-omnibox-listas.md` + +- GitHub Issue #311 diff --git a/docs/plans/organizacoes-omnibox-tipo.md b/docs/plans/organizacoes-omnibox-tipo.md new file mode 100644 index 00000000..c27992c6 --- /dev/null +++ b/docs/plans/organizacoes-omnibox-tipo.md @@ -0,0 +1,69 @@ +# Organizações — tipo na omnibox + +Status: registrado +Atualizado em: 2026-08-02 +Issue: #307 +Priority: P2 +Model: composer-2.5 +Impeccable: B — encaixe na lista `/campanha/organizacoes` +Appetite: ~0,5 dia eng +Responsável: — + +## Intenção + +A lista de organizações já tem coluna/badge de **Tipo** e o parâmetro `kind` na URL, mas a omnibox é só busca. O staff não consegue montar “só sindicatos” (etc.) pela barra — tem de varrer ou conhecer o deep-link. + +Queremos expor **Tipo** como dimensão na omnibox (sugestões + chip), no mesmo espírito das outras listas pós-B128. + +## Persona e fluxo + +- **Persona / contexto:** Staff filtrando organizações de apoio por tipo. +- **Job principal:** restringir a lista a um tipo sem sair da barra. +- **Fluxo desejado:** digita “sindicato” / “tipo” → escolhe → chip **Tipo: …** → lista filtrada; remove o chip → volta a todas; busca por nome continua. +- **Anti-goals de produto:** inventar tipos novos; segunda toolbar; saved filters nesta lista. + +## Objetivo e aceite + +- Omnibox sugere e aplica **Tipo** com os valores de produto já existentes (rótulos pt-BR da lista). +- Ausência de chip de tipo = todas as organizações do escopo (comportamento atual da URL sem `kind`). +- Busca por nome permanece; chips de busca e tipo coexistentes e removíveis. +- Sem seletor paralelo fora da omnibox. + +## Dados (intenção) + +- **Vou apresentar dados?** Não. +- **Decisões desbloqueadas:** staff — “quais organizações deste tipo estou vendo?” +- **Forma:** _adiada_. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `OrganizationFilters`, `organizationListUrl` (já parseia `kind`), sair do degenerado `searchOnlyListOmnibox` ou estendê-lo com dimensão de tipo. +- **Precedente:** B128 omnibox degenerada; mapa B127 “não inventar” → **agora pedido explícito**. +- **Risco:** contrato URL; não quebrar `q` + `kind` existentes. + +## Dependências + +- Nenhuma. + +## Fora de escopo + +- Filtro por município de atuação / contagem de lideranças. +- Ordenação na omnibox se ainda não existir nesta lista. +- Demais listas (Issues irmãs). + +## Rabbit holes de produto + +- **Multi-tipo OR sem pedido.** **Corte:** manter exclusividade atual da URL (`kind` único) salvo evidência em contrário. + +## Questões em aberto (produto) + +- Nenhuma bloqueante — tipo único (exclusivo) como hoje na URL. _(assumido)_ + +## Referências + +- Inventário plan-issue 2026-08-02 — gap 3 +- `docs/plans/barra-filtros-omnibox-listas.md` +- `src/utilities/organization/organizationListUrl.ts` +- `src/components/campaign/organization/OrganizationFilters.tsx` + +- GitHub Issue #307