Commit graph

254 commits

Author SHA1 Message Date
Francisco Solla
423c61d40b feat: distinguish municipality column defaults from explicit visibility 2026-08-05 10:49:58 -03:00
Francisco Ignácio Fontoura Solla
9fa701633e feat(campaign): unify municipality relation editors 2026-08-05 02:01:40 -03:00
Francisco Solla
4b79f00125
Merge pull request #373 from fsolla/feature/ai-chat-sollinha
feat: AI chat 'Sollinha' — campaign data assistant (v1 read-only)
2026-08-04 06:26:48 -03:00
Francisco Ignácio Fontoura Solla
f9cd1df7b2 feat: AI chat 'Sollinha' — campaign data assistant (v1 read-only)
- Streaming AI endpoint at /campanha/api/ai-chat with DeepSeek V4 Flash
- 8 tools: calculate, getMunicipalityVotes, getTopDeputies, getDobradinhas,
  getMunicipalityOverview, getLeaderships, getOrganizations, searchEntities
- In-memory rate limiter (50 msgs / 15 min per user)
- Desktop: resizable right sidebar via react-resizable-panels
- Mobile: full-screen Drawer opened by FAB (2/3 size of quick-actions FAB)
- Markdown rendering with react-markdown + remark-gfm (tables, bold, lists)
- Session-bound context (clean slate each open)
- Auth via existing campaign-token cookie, tools respect user RBAC
- Architecture doc: docs/plans/ai-chat-sollinha.md
- E2E tests: campaignAiChat.e2e.spec.ts (mocked endpoint)
2026-08-04 06:17:31 -03:00
Francisco Ignácio Fontoura Solla
6b8864debb B156 — assessores por dobradinha (campo, coluna e seção; RelationOptionCell extraído) 2026-08-04 04:57:15 -03:00
Francisco Ignácio Fontoura Solla
086a9c8ee0 B157 — coluna de dobradinhas na lista de municípios (+ criação inline) 2026-08-04 02:53:43 -03:00
Francisco Ignácio Fontoura Solla
596085c977 feat(campanha): B155 — coluna de lideranças na lista de municípios
Espelho da coluna de Assessores: chips com nome do contato, popover/sheet
com Command + delta otimista e criação inline (Nome + Celular). Sem
migration — leitura reversa de leadership.municipalities no bundle e
escrita reusando as actions B34/wizard; rota POST
/campanha/municipios/leaderships via campaignJsonMutationRoute.
2026-08-04 01:49:55 -03:00
Francisco Ignácio Fontoura Solla
b74268714c C86+ — simplify: JSDoc do contrato home, testes de borda e nota no impl plan
Fixes do /simplify (3 revisores read-only): JSDoc de normalizePathname/isListPath
documentando o invariante (homes nunca são '/' nem terminam em slash), teste de
multi-slash e inputs degenerados, comentário de isCampaignHomePath encurtado.
Sem mudança de comportamento.
2026-08-04 01:17:53 -03:00
Francisco Ignácio Fontoura Solla
4a90fb19ec C86+ — pathname de lista das ações rápidas em fonte única (isListPath)
Extrai isListPath + normalizePathname exportados em campaignQuickActionPaths.ts
e migra os 9 wrappers (7 públicos + 2 privados) + a 3a cópia de normalize em
campaignPageChrome.ts. Refactor estrutural sem mudança de comportamento;
derivação de regex de detalhe numérico adiada (gatilho: 3o vertical [id]).
Inclui docs/plans/escala-dry-pos-acoes-rapidas-impl.md e o fix de format
pré-existente de docs/plans/liderancas-coluna-municipios.md (bloqueava format:check).
2026-08-04 01:14:35 -03:00
Francisco Ignácio Fontoura Solla
26b2205c3a B154 — criar assessor inline no popover da lista de municípios
Closes #352

- POST /campanha/municipios/advisors aceita body de criação (name) na union;
  createMunicipalityAdvisorRecord cria campaignUser advisor (stub
  <slug>@criado.invalid, senha aleatória) e atribui ao município na mesma
  transação (cap 10 com rollback, lock municipality-advisors:{id})
- MunicipalityAdvisorCreateProvider compartilha o assessor criado entre linhas;
  opção "+ Criar assessor" e chip otimista com id temporário no control
- advisorNameSchema unificado em primitives.ts; predicado de placeholder cobre
  @criado.invalid (reset de senha e célula de e-mail tratam stubs inline)
- Destrava o spec e2e de municipios (falhas pré-existentes em main): key
  warning do fragment trailing de MunicipalityFilters; settle-wait da animação
  do Drawer no teste B136
2026-08-03 22:46:06 -03:00
Francisco Ignácio Fontoura Solla
d200a1b012 B86 — ações rápidas — apoiadores (staff): catálogo no FAB/overlay 2026-08-03 21:03:13 -03:00
Cursor Agent
bb4c1ab199
B153 — editar nome, e-mail e celular da liderança (lista + detalhe)
- leadershipContactUpdateSchema + updateLeadershipContactRecord
- LeadershipContactFieldControl (lápis → input → blur-save)
- Lista e bloco Contato no detalhe
- Int tests para update, conflito de telefone e escopo

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 14:02:59 +00:00
Cursor Agent
30a5a8a5e3
B151 — FAB secundário no detalhe município v2 (#334)
- Catálogo v2 de ações rápidas: dossiê, eleições, nova liderança, giro
- Integra no chassis B126 via registry + context sync na rota v2
- Omitido registrar sinal (já na faixa de status B147)

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 01:03:10 +00:00
Cursor Agent
5696aef9ed
B145 — move entity identity to shell header on detail pages
- Detail routes return null from campaignPageChrome catalog (override per page)
- SetCampaignPageChrome + generateMetadata on 8 entity detail routes
- Remove body hero (h1, Voltar links, duplicate identity chips)
- Keep operational badges/chips in page body
- Update zone map e2e to assert shell chrome title slot

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:29:48 +00:00
Francisco Solla
fd29d0ecb4
Merge pull request #327 from fsolla/cursor/pool-i304-dfa7cbb3-3c18
B137 — Colunas ao lado da omnibox (e fim do “Ordenado por …” residual)
2026-08-02 21:21:28 -03:00
Cursor Agent
6c6a742cb4
B137 — restore searchOnlyListOmnibox from main (CI merge ref) 2026-08-03 00:06:16 +00:00
Cursor Agent
fd435d54f6
B137 — remove dead searchOnlyListOmnibox exports after org omnibox 2026-08-03 00:06:16 +00:00
Cursor Agent
d6455b1333
B137 — Colunas ao lado da omnibox e fim do Ordenado por residual
Move CampaignColumnPicker to omnibox trailing via CampaignColumnPickerTrailing
on all seven B17 list surfaces (+ organizações). Remove the picker row from
CampaignTable and drop visible sort-summary spans on territórios, lideranças
and dobradinhas (sr-only table captions keep sort context).

Closes #304

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:06:15 +00:00
Cursor Agent
a2553e1f03
merge main into B147; keep optional sinal body for v2 status
Align with B134 engagement write path; preserve B147 sinal empty-motivo
(collection + zod) required by the status-strip confirm rite.
2026-08-02 23:48:29 +00:00
Cursor Agent
64f3af5a6a
chore: delete unused search-only omnibox helpers (knip) 2026-08-02 23:35:31 +00:00
Cursor Agent
0aa47f8673
feat(campanha): B147 município v2 shell + faixa de status
Rota paralela /campanha/municipio/<slug>/v2 com selects de nível, tendência e
sinal (modal de motivo opcional), classe territorial e agregado. Soft-dep B134:
motivo opcional no movimento de nível e remoção do campo “voltar atrás” do
write path/lista.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:29:05 +00:00
Francisco Solla
6539d0cc55
Merge pull request #329 from fsolla/cursor/pool-i288-97b0de1d-f857
B134 — Motivo opcional (tendência + nível); remover voltar atrás do DB
2026-08-02 20:25:23 -03:00
Francisco Solla
8a60b6f0f7
Merge pull request #326 from fsolla/cursor/pool-i310-73006baf-d8e9
B142 — Assessores — filtrar por município da carteira na omnibox
2026-08-02 20:22:16 -03:00
Francisco Solla
56b96198cb
Merge pull request #324 from fsolla/cursor/pool-i309-84ab81f4-8444
B141 — Apoiadores — filtro por fonte na omnibox
2026-08-02 20:20:40 -03:00
Cursor Agent
1841e722f7
B142 — simplify: remove dead filter exports, centralize hasActiveFilters
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:08:17 +00:00
Cursor Agent
d50f16cb57
chore: format B141 files 2026-08-02 23:06:35 +00:00
Cursor Agent
fa53f5d66e
Keep WizardStepKind internal (knip) 2026-08-02 23:05:45 +00:00
Cursor Agent
989e3abab8
Format B135 wizard back navigation files 2026-08-02 23:05:09 +00:00
Cursor Agent
28525aab4b
B135 — Voltar no wizard usa passo lógico anterior na cadeia (#289)
- wizardPreviousHref em wizardActionChain para todos os elos B98
- Avanço encadeado com router.push; Voltar no chrome com replace
- Testes unitários para href anterior e navegação pending

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:04:26 +00:00
Cursor Agent
b509c7d7b3
B141 — filtro por fonte na omnibox de apoiadores (#309)
Adiciona dimensão Fonte ao estado de lista, where-builder, aggregate SQL
e adapter omnibox (B128), com guard isSupporterSource e testes.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:03:22 +00:00
Cursor Agent
5335f69b43
B134 — motivo opcional (tendência + nível); remove reversalSignals
- Make engagement level note optional in schema and UI
- Remove reversalSignals field from popover, action snapshot and DB
- Add data migration to strip reversalSignals from movimento snapshots
- Wizard trend note step no longer requires text; labels show (opcional)

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:02:53 +00:00
Cursor Agent
6cc17f0d4e
fix(campanha): B133 typecheck — optional catalog subtitle + chrome component return
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 21:17:48 +00:00
Cursor Agent
f89fc4b81f
feat(campanha): B133 — listas sem subtítulo de prosa + filtro salvo no header
- Remove prose subtitles from list routes, Quadro and create/edit chrome
- Keep subtitles on Organizações, Conceitos, Perfil, Contatos (out of scope)
- MunicipalityListPageChrome: saved filter name as header subtitle when URL matches
- Edit pages: title-only chrome override
- Impl plan: docs/plans/listas-sem-subtitulo-prosa-impl.md

Closes #283

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 21:16:46 +00:00
Cursor Agent
cf78c61757
chore: remove orphaned list filter shells after B128 omnibox migration
Delete CampaignSearchForm, CampaignFilterChips, collapsible/mobile filter
components and useCampaignFilterValues. Slim useCampaignListFilterNavigation
to navigate-only; drop unused territory sort serializers.
2026-08-02 20:57:47 +00:00
Cursor Agent
f59d4a6736
chore: format + e2e manifest mappings for B128 omnibox modules 2026-08-02 20:56:12 +00:00
Cursor Agent
0903576f9e
B128 — Adotar barra omnibox nas demais listas /campanha
Estende o chassis B127 (CampaignListOmnibox + adapters puros por domínio)
para territórios, lideranças, dobradinhas, apoiadores, atividades, demandas,
organizações e assessores. Remove pilhas antigas (search debounced, collapsible,
mobile selects, CampaignFilterChips). URL contracts extraídos para módulos
client-safe onde necessário (demand/organization/advisor). Testes unitários
nos adapters + hook navigate-only.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 20:55:12 +00:00
Cursor Agent
3064d7341a
chore: drop exports orphaned by B127 omnibox (knip) 2026-08-02 20:30:55 +00:00
Cursor Agent
21e20a6719
feat(campanha): B127 omnibox filter bar chassis + Municípios pilot
Replace the stacked município filter controls with a shared omnibox
(chips + suggestions) backed by the frozen list URL contract; scenario
and non-default sort appear as presentation chips.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 20:30:55 +00:00
Francisco Solla
7839a88a5a
Merge pull request #270 from fsolla/cursor/pool-i250-d89b6314-599f
B123 — Campanha — orientação na shell + aba (sem títulos grandes de seção)
2026-08-02 16:16:58 -03:00
Francisco Solla
5e7219f849
Merge pull request #269 from fsolla/cursor/pool-i260-ac255f26-42ec
B126 — FAB de ações rápidas (substituir bottom drawer persistente)
2026-08-02 16:15:01 -03:00
Cursor Agent
dbce18002c
B126 — FAB de ações rápidas substitui drawer persistente
Remove o bottom drawer não-modal (snap/peek/scroll-coupling) e introduz
um FAB em todas as larguras fora do Início e wizards. Abrir o FAB mostra
overlay modal: Dialog no desktop (busca em cima) e Drawer no mobile
(ações em cima), reutilizando strip e busca globais do Início.

Closes #260

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 18:39:27 +00:00
Cursor Agent
7e6bc9d984
B125 — nearest município first in search suggest + wizard
- Restore B117 home search: scopeMunicipalities, merge prefix, session prompt
- Shared useNearestMunicipalitySlug (B14 key) for busca geral + wizard
- Wizard merge uses geoSlug only — no Perto de você / km copy on rows
- Impl plan: docs/plans/municipio-geo-topo-sugestoes-busca-impl.md

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 18:21:52 +00:00
Cursor Agent
d4425251c6
style: prettier em arquivos B123 2026-08-02 18:11:54 +00:00
Cursor Agent
ccfbf592a8
B123 — orientação na shell + aba sem títulos de seção no corpo
Move page title/subtitle to CampaignMobileTopBar, CampaignDesktopHeader,
and tab metadata (Solla - Campanha - %s). Strip section headers and scope
chips from list/create routes; detail pages keep entity h1.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 18:08:47 +00:00
Francisco Solla
8741eb5151
Merge pull request #154 from fsolla/cursor/pool-i149-d8165a59-5947
B110 — Wizard return path via allowlisted from query
2026-08-01 18:04:14 -03:00
Francisco Solla
ab910b499b
Merge pull request #153 from fsolla/cursor/pool-i148-3c37da6e-2281
B109 — Bottom drawer: dock polish, fullscreen search, exclude current entity
2026-08-01 18:03:27 -03:00
Cursor Agent
2e3740ef3f
Format B110 wizard return path changes 2026-08-01 20:40:04 +00:00
Cursor Agent
d5697bcfcb
B110 — wizard return path via allowlisted from query
Propagate return path from quick actions through the B98 wizard chain so
dismiss, skip, and chain end navigate back to the originating page instead
of always redirecting to Início.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 20:39:24 +00:00
Cursor Agent
fcd0206da6
chore: prettier format (B109) 2026-08-01 20:38:53 +00:00
Cursor Agent
490d5deeb7
B109 — bottom drawer: fullscreen search, wider labels, exclude current entity
- Add QUICK_ACTIONS_SNAP_FULL; drawer expands on search focus and hides action strip
- Tighten dock bottom gap; restore dock/collapsed on blur per scroll position (B100)
- Widen CampaignHomeActionButton to w-[5.5rem] for two-line labels
- Client-side filter excludes current page entity from drawer search hits
- Unit + e2e coverage for full snap, exclusion, and label readability
2026-08-01 20:38:10 +00:00