From 3e062749faa4ca0d88291c8151e078cc0b576aa1 Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Sun, 13 Sep 2026 13:29:04 -0300 Subject: [PATCH] =?UTF-8?q?feat(C154):=20vertical=20de=20comunica=C3=A7?= =?UTF-8?q?=C3=A3o=20=E2=80=94=20papel=20communicator=20e=20acervo=20pesqu?= =?UTF-8?q?is=C3=A1vel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Papel communicator com nav própria e gate speechCatalog; acervo em /campanha/comunicacao/acervo com busca normalizada (destaque no trecho), filtros de ano/tema/alcance/fase/município/duração em URL canônica e paginação por discurso via speech.searchText (GIN trgm + backfill). Detalhe com player nativo no trecho, transcrição clicável, baixar/abrir fonte e fallback sem VOD. Resolve o débito do C153 (Sollinha fora da vertical) e corrige o parser de keywords oficiais no dono. Closes #956 --- docs/changelog/2026-09-13-c154.md | 1 + docs/plans/acervo-videos-comunicacao-impl.md | 216 + scripts/lib/camaraSpeeches.mjs | 7 +- scripts/lib/e2e-affected-manifest.mjs | 14 + .../comunicacao/acervo/[id]/not-found.tsx | 29 + .../(app)/comunicacao/acervo/[id]/page.tsx | 223 + .../(app)/comunicacao/acervo/loading.tsx | 26 + .../(app)/comunicacao/acervo/page.tsx | 86 + .../campanha/(app)/comunicacao/page.tsx | 14 + src/app/(campaign)/campanha/(app)/layout.tsx | 1 + src/app/(campaign)/campanha/(app)/page.tsx | 6 + src/collections/Speech.ts | 16 + .../shared/CampaignHeaderFilterPopover.tsx | 58 +- .../campaign/shell/CampaignDesktopHeader.tsx | 11 +- .../shell/ai/CampaignAISidebarShell.tsx | 6 + src/components/campaign/shell/nav.ts | 24 +- .../campaign/speech/SpeechAcervoFilters.tsx | 252 + .../campaign/speech/SpeechDetailPlayer.tsx | 119 + .../campaign/speech/SpeechHighlightParts.tsx | 19 + .../campaign/speech/SpeechResultCard.tsx | 134 + .../campaign/speech/SpeechResultList.tsx | 10 + src/lib/campaignPageChrome.ts | 19 + src/lib/campaignPaths.ts | 5 + src/lib/campaignRoles.ts | 8 + src/lib/speechHighlight.ts | 169 + ...0260913_145820_add_speech_search_text.json | 15103 ++++++++++++++++ .../20260913_145820_add_speech_search_text.ts | 11 + ..._backfill_speech_search_text_trgm_index.ts | 29 + src/migrations/index.ts | 16 +- src/payload-types.ts | 5 + src/utilities/campaignPageActor.ts | 26 +- src/utilities/speech/speechImport.ts | 13 +- src/utilities/speech/speechListFilters.ts | 58 + src/utilities/speech/speechListUrl.ts | 182 + src/utilities/speech/speechOmnibox.ts | 251 + src/utilities/speech/speechPageData.ts | 249 + src/utilities/speech/speechViewModels.ts | 263 + tests/e2e/campaignSpeechAcervo.e2e.spec.ts | 199 + tests/e2e/fixtures/campaignE2EFixtures.ts | 24 + tests/e2e/fixtures/campaignHttpTest.ts | 29 +- tests/helpers/speechBundleFixture.ts | 46 + tests/int/speechAcervo.int.spec.ts | 220 + tests/int/speechImport.int.spec.ts | 63 +- tests/unit/camaraSpeeches.unit.spec.ts | 11 +- tests/unit/campaignNav.unit.spec.ts | 34 +- tests/unit/campaignPageChrome.unit.spec.ts | 11 + tests/unit/speechHighlight.unit.spec.ts | 76 + tests/unit/speechListFilters.unit.spec.ts | 78 + tests/unit/speechListUrl.unit.spec.ts | 117 + tests/unit/speechOmnibox.unit.spec.ts | 112 + 50 files changed, 18614 insertions(+), 85 deletions(-) create mode 100644 docs/changelog/2026-09-13-c154.md create mode 100644 docs/plans/acervo-videos-comunicacao-impl.md create mode 100644 src/app/(campaign)/campanha/(app)/comunicacao/acervo/[id]/not-found.tsx create mode 100644 src/app/(campaign)/campanha/(app)/comunicacao/acervo/[id]/page.tsx create mode 100644 src/app/(campaign)/campanha/(app)/comunicacao/acervo/loading.tsx create mode 100644 src/app/(campaign)/campanha/(app)/comunicacao/acervo/page.tsx create mode 100644 src/app/(campaign)/campanha/(app)/comunicacao/page.tsx create mode 100644 src/components/campaign/speech/SpeechAcervoFilters.tsx create mode 100644 src/components/campaign/speech/SpeechDetailPlayer.tsx create mode 100644 src/components/campaign/speech/SpeechHighlightParts.tsx create mode 100644 src/components/campaign/speech/SpeechResultCard.tsx create mode 100644 src/components/campaign/speech/SpeechResultList.tsx create mode 100644 src/lib/speechHighlight.ts create mode 100644 src/migrations/20260913_145820_add_speech_search_text.json create mode 100644 src/migrations/20260913_145820_add_speech_search_text.ts create mode 100644 src/migrations/20260913_150000_backfill_speech_search_text_trgm_index.ts create mode 100644 src/utilities/speech/speechListFilters.ts create mode 100644 src/utilities/speech/speechListUrl.ts create mode 100644 src/utilities/speech/speechOmnibox.ts create mode 100644 src/utilities/speech/speechPageData.ts create mode 100644 src/utilities/speech/speechViewModels.ts create mode 100644 tests/e2e/campaignSpeechAcervo.e2e.spec.ts create mode 100644 tests/helpers/speechBundleFixture.ts create mode 100644 tests/int/speechAcervo.int.spec.ts create mode 100644 tests/unit/speechHighlight.unit.spec.ts create mode 100644 tests/unit/speechListFilters.unit.spec.ts create mode 100644 tests/unit/speechListUrl.unit.spec.ts create mode 100644 tests/unit/speechOmnibox.unit.spec.ts diff --git a/docs/changelog/2026-09-13-c154.md b/docs/changelog/2026-09-13-c154.md new file mode 100644 index 00000000..1503ae33 --- /dev/null +++ b/docs/changelog/2026-09-13-c154.md @@ -0,0 +1 @@ +**C154 — Vertical Comunicação: papel communicator + Acervo pesquisável (2026-09-13):** o assessor de comunicação ganhou a vertical própria. `communicator` vê e navega só `/campanha/comunicacao` (nav própria; sem áreas de staff, sem Sollinha — o débito do C153 dos chips de líder foi resolvido escondendo as superfícies do assistente para esse papel via `canUseCampaignAssistant`); `coordinator`/`candidate` também veem; `advisor`/`leader` são redirecionados pelo gate novo `speechCatalog` do `requireCampaignPageActor`. O Acervo (`/campanha/comunicacao/acervo`) busca por termo com e sem acento sobre os segmentos ASR (destaque `` no trecho) e keywords oficiais como termo exato, com filtros de ano, tema, alcance, fase, município citado e duração em URL canônica (`resolveListUrl`/`CampaignListOmnibox`/`CampaignHeaderFilterPopover` com trigger em chip opt-in) e paginação **por discurso**: `speech.searchText` (concatenação normalizada dos segmentos, mantida pelo `upsertSpeechBundle`, coluna opcional + índice GIN `pg_trgm` hand-written com backfill em `20260913_150000_backfill_speech_search_text_trgm_index`) resolve o "N falas encontradas" sem dedupe entre páginas. O detalhe (`/campanha/comunicacao/acervo/[id]`) tem player `