From 7844afcc6bf1a344416a227fa73659fc73f1c234 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 1 Aug 2026 05:44:04 +0000 Subject: [PATCH] =?UTF-8?q?B90=20=E2=80=94=20A=C3=A7=C3=B5es=20r=C3=A1pida?= =?UTF-8?q?s=20Conceitos=20+=20Perfil=20(s=C3=B3=20busca=20staff)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Registry B79 para /campanha/conceitos e /campanha/perfil: catálogo vazio para staff, busca global no drawer expandido via CampaignStaffGlobalSearch. Leader em /perfil continua sem drawer (lockdown B89). Closes #26 Co-authored-by: Francisco Solla --- .../dashboard/CampaignStaffGlobalSearch.tsx | 13 ++++++ .../shell/CampaignQuickActionsDrawer.tsx | 4 +- src/lib/campaignPaths.ts | 2 + src/lib/campaignQuickActionRegistry.ts | 5 +++ src/lib/campaignReferenceQuickActions.ts | 25 +++++++++++ tests/unit/campaignQuickAction.unit.spec.ts | 12 +++++ ...campaignReferenceQuickActions.unit.spec.ts | 45 +++++++++++++++++++ 7 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/lib/campaignReferenceQuickActions.ts create mode 100644 tests/unit/campaignReferenceQuickActions.unit.spec.ts diff --git a/src/components/campaign/dashboard/CampaignStaffGlobalSearch.tsx b/src/components/campaign/dashboard/CampaignStaffGlobalSearch.tsx index 0fefbd0d..aba182c0 100644 --- a/src/components/campaign/dashboard/CampaignStaffGlobalSearch.tsx +++ b/src/components/campaign/dashboard/CampaignStaffGlobalSearch.tsx @@ -1,6 +1,7 @@ 'use client' import { CampaignHomeSearch } from '@/components/campaign/dashboard/CampaignHomeSearch' +import { HomeSearchProvider } from '@/components/campaign/dashboard/HomeSearchContext' import { HomeSearchActivityGroup } from '@/components/campaign/dashboard/HomeSearchActivityGroup' import { HomeSearchAdvisorGroup } from '@/components/campaign/dashboard/HomeSearchAdvisorGroup' import { HomeSearchDemandGroup } from '@/components/campaign/dashboard/HomeSearchDemandGroup' @@ -13,6 +14,7 @@ import { import { HomeSearchResultsLayout } from '@/components/campaign/dashboard/HomeSearchResultsLayout' import { HomeSearchResultsShell } from '@/components/campaign/dashboard/HomeSearchResultsShell' import { HomeSearchStateDeputyGroup } from '@/components/campaign/dashboard/HomeSearchStateDeputyGroup' +import { useHomeSearchQuery } from '@/components/campaign/dashboard/useHomeSearchQuery' const CampaignStaffGlobalSearchResults = () => { const searchResultsState = useHomeSearchResultsState() @@ -37,3 +39,14 @@ const CampaignStaffGlobalSearchResults = () => { /** Result groups + input — requires an ancestor `HomeSearchProvider`. */ export const CampaignStaffGlobalSearchBody = CampaignStaffGlobalSearchResults + +/** Self-contained staff global search for surfaces outside Início (B90 drawer, future B91). */ +export const CampaignStaffGlobalSearch = () => { + const searchState = useHomeSearchQuery() + + return ( + + + + ) +} diff --git a/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx b/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx index c5af7831..784818cf 100644 --- a/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx +++ b/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx @@ -101,9 +101,7 @@ export const CampaignQuickActionsDrawer = ({ }))} className="w-full" /> - ) : ( -

Nenhuma ação rápida nesta página.

- )} + ) : null} {expanded ? : null} diff --git a/src/lib/campaignPaths.ts b/src/lib/campaignPaths.ts index 3500430d..56c0bf02 100644 --- a/src/lib/campaignPaths.ts +++ b/src/lib/campaignPaths.ts @@ -8,3 +8,5 @@ export const CAMPAIGN_DEMANDS_HOME = '/campanha/demandas' as const export const CAMPAIGN_ADVISORS_HOME = '/campanha/assessores' as const export const LEADER_CONTACTS_HOME = '/campanha/contatos' as const + +export const CAMPAIGN_PROFILE_HOME = '/campanha/perfil' as const diff --git a/src/lib/campaignQuickActionRegistry.ts b/src/lib/campaignQuickActionRegistry.ts index 0e35e495..ba55f49a 100644 --- a/src/lib/campaignQuickActionRegistry.ts +++ b/src/lib/campaignQuickActionRegistry.ts @@ -23,6 +23,7 @@ import type { CampaignQuickAction } from '@/lib/campaignQuickActionTypes' import type { CampaignRole } from '@/lib/campaignRoles' import { resolveLeaderContactsQuickActions } from '@/lib/leaderContactsQuickActions' import { resolveOrganizationQuickActions } from '@/lib/organizationQuickActions' +import { resolveReferenceQuickActionsForPath, isReferenceQuickActionPath } from '@/lib/campaignReferenceQuickActions' const isTerritoriesListPath = (pathname: string): boolean => pathname === CAMPAIGN_TERRITORIES_HOME || pathname.startsWith(`${CAMPAIGN_TERRITORIES_HOME}/`) @@ -71,5 +72,9 @@ export const resolveQuickActionsForPath = ( if (isTerritoriesListPath(pathname)) { return resolveStaffHomeQuickActions(role) } + + const referenceActions = resolveReferenceQuickActionsForPath(pathname, role, context) + if (isReferenceQuickActionPath(pathname)) return referenceActions + return [] } diff --git a/src/lib/campaignReferenceQuickActions.ts b/src/lib/campaignReferenceQuickActions.ts new file mode 100644 index 00000000..a9ede31e --- /dev/null +++ b/src/lib/campaignReferenceQuickActions.ts @@ -0,0 +1,25 @@ +import { CAMPAIGN_CONCEPTS_PATH } from '@/lib/campaignIntelligenceConcepts' +import type { CampaignQuickActionContext } from '@/lib/campaignQuickActionContext' +import type { CampaignQuickAction } from '@/lib/campaignQuickActionTypes' +import { CAMPAIGN_PROFILE_HOME } from '@/lib/campaignPaths' +import { isStaffCampaignRole, type CampaignRole } from '@/lib/campaignRoles' + +export const isConceptsPath = (pathname: string): boolean => + pathname === CAMPAIGN_CONCEPTS_PATH || pathname === `${CAMPAIGN_CONCEPTS_PATH}/` + +export const isProfilePath = (pathname: string): boolean => + pathname === CAMPAIGN_PROFILE_HOME || pathname === `${CAMPAIGN_PROFILE_HOME}/` + +/** B90 — reference/account surfaces with search-only drawer (no action catalog). */ +export const isReferenceQuickActionPath = (pathname: string): boolean => + isConceptsPath(pathname) || isProfilePath(pathname) + +export const resolveReferenceQuickActionsForPath = ( + pathname: string, + role: CampaignRole, + _context: CampaignQuickActionContext, +): readonly CampaignQuickAction[] => { + if (!isStaffCampaignRole(role)) return [] + if (!isReferenceQuickActionPath(pathname)) return [] + return [] +} diff --git a/tests/unit/campaignQuickAction.unit.spec.ts b/tests/unit/campaignQuickAction.unit.spec.ts index 30ef56bf..b8336100 100644 --- a/tests/unit/campaignQuickAction.unit.spec.ts +++ b/tests/unit/campaignQuickAction.unit.spec.ts @@ -34,6 +34,8 @@ import { parseOrganizationQuickActionSurface, } from '@/lib/campaignQuickActionPaths' import { resolveQuickActionsForPath } from '@/lib/campaignQuickActionRegistry' +import { CAMPAIGN_CONCEPTS_PATH } from '@/lib/campaignIntelligenceConcepts' +import { CAMPAIGN_PROFILE_HOME } from '@/lib/campaignPaths' import { QUICK_ACTIONS_SNAP_COLLAPSED, QUICK_ACTIONS_SNAP_EXPANDED, @@ -86,9 +88,14 @@ describe('campaignQuickActionMount', () => { expect(shouldMountQuickActionsDrawer('/campanha/assessores/12', 'advisor')).toBe(false) }) +<<<<<<< HEAD it('mounts on dobradinhas for staff (B83)', () => { expect(shouldMountQuickActionsDrawer('/campanha/dobradinhas', 'coordinator')).toBe(true) expect(shouldMountQuickActionsDrawer('/campanha/dobradinhas/foo', 'advisor')).toBe(true) +======= + it('omits drawer on perfil for leader (B90)', () => { + expect(shouldMountQuickActionsDrawer(CAMPAIGN_PROFILE_HOME, 'leader')).toBe(false) +>>>>>>> 2291493 (B90 — Ações rápidas Conceitos + Perfil (só busca staff)) }) }) @@ -253,6 +260,11 @@ describe('campaignQuickActionRegistry', () => { expect(resolveQuickActionsForPath('/campanha/apoiadores', 'coordinator', {})).toEqual([]) }) + it('returns empty catalog on conceitos and perfil for staff (B90)', () => { + expect(resolveQuickActionsForPath(CAMPAIGN_CONCEPTS_PATH, 'coordinator', {})).toEqual([]) + expect(resolveQuickActionsForPath(CAMPAIGN_PROFILE_HOME, 'candidate', {})).toEqual([]) + }) + it('delegates municipality list and detail catalogs (B80)', () => { const list = resolveQuickActionsForPath('/campanha/municipios', 'coordinator', {}) expect(list).toHaveLength(6) diff --git a/tests/unit/campaignReferenceQuickActions.unit.spec.ts b/tests/unit/campaignReferenceQuickActions.unit.spec.ts new file mode 100644 index 00000000..e639c473 --- /dev/null +++ b/tests/unit/campaignReferenceQuickActions.unit.spec.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' + +import { CAMPAIGN_CONCEPTS_PATH } from '@/lib/campaignIntelligenceConcepts' +import { CAMPAIGN_PROFILE_HOME } from '@/lib/campaignPaths' +import { + isConceptsPath, + isProfilePath, + isReferenceQuickActionPath, + resolveReferenceQuickActionsForPath, +} from '@/lib/campaignReferenceQuickActions' + +describe('campaignReferenceQuickActions paths', () => { + it('matches conceitos exactly', () => { + expect(isConceptsPath(CAMPAIGN_CONCEPTS_PATH)).toBe(true) + expect(isConceptsPath(`${CAMPAIGN_CONCEPTS_PATH}/`)).toBe(true) + expect(isConceptsPath(`${CAMPAIGN_CONCEPTS_PATH}/foo`)).toBe(false) + }) + + it('matches perfil exactly', () => { + expect(isProfilePath(CAMPAIGN_PROFILE_HOME)).toBe(true) + expect(isProfilePath(`${CAMPAIGN_PROFILE_HOME}/`)).toBe(true) + expect(isProfilePath(`${CAMPAIGN_PROFILE_HOME}/editar`)).toBe(false) + }) + + it('groups reference surfaces', () => { + expect(isReferenceQuickActionPath(CAMPAIGN_CONCEPTS_PATH)).toBe(true) + expect(isReferenceQuickActionPath(CAMPAIGN_PROFILE_HOME)).toBe(true) + expect(isReferenceQuickActionPath('/campanha/municipios')).toBe(false) + }) +}) + +describe('resolveReferenceQuickActionsForPath (B90)', () => { + it('returns empty catalog for staff on conceitos and perfil', () => { + expect( + resolveReferenceQuickActionsForPath(CAMPAIGN_CONCEPTS_PATH, 'coordinator', {}), + ).toEqual([]) + expect(resolveReferenceQuickActionsForPath(CAMPAIGN_PROFILE_HOME, 'advisor', {})).toEqual([]) + }) + + it('returns empty catalog for leader lockdown', () => { + expect( + resolveReferenceQuickActionsForPath(CAMPAIGN_PROFILE_HOME, 'leader', {}), + ).toEqual([]) + }) +})