diff --git a/src/components/campaign/dashboard/CampaignGlobalSearchMount.tsx b/src/components/campaign/dashboard/CampaignGlobalSearchMount.tsx
new file mode 100644
index 00000000..04a53dba
--- /dev/null
+++ b/src/components/campaign/dashboard/CampaignGlobalSearchMount.tsx
@@ -0,0 +1,23 @@
+'use client'
+
+import type { ReactNode } from 'react'
+
+import { CampaignStaffGlobalSearchBody } from '@/components/campaign/dashboard/CampaignStaffGlobalSearch'
+import { HomeSearchProvider } from '@/components/campaign/dashboard/HomeSearchContext'
+import { useHomeSearchQuery } from '@/components/campaign/dashboard/useHomeSearchQuery'
+
+/** Owns debounce + focus state for any global search surface (Início, drawer B91). */
+export const CampaignGlobalSearchProvider = ({ children }: { children: ReactNode }) => {
+ const searchState = useHomeSearchQuery()
+ return {children}
+}
+
+/** Input + result groups — requires `CampaignGlobalSearchProvider` unless using the mount. */
+export const CampaignGlobalSearchBody = CampaignStaffGlobalSearchBody
+
+/** Provider + default global search body (drawer, smoke tests). */
+export const CampaignGlobalSearchMount = () => (
+
+
+
+)
diff --git a/src/components/campaign/dashboard/CampaignHomeStaffChrome.tsx b/src/components/campaign/dashboard/CampaignHomeStaffChrome.tsx
index ab17d8ec..596387fb 100644
--- a/src/components/campaign/dashboard/CampaignHomeStaffChrome.tsx
+++ b/src/components/campaign/dashboard/CampaignHomeStaffChrome.tsx
@@ -2,15 +2,15 @@
import type { ReactNode } from 'react'
+import { CampaignGlobalSearchProvider } from '@/components/campaign/dashboard/CampaignGlobalSearchMount'
import { CampaignHomeLayout } from '@/components/campaign/dashboard/CampaignHomeLayout'
import { CampaignHomeSearch } from '@/components/campaign/dashboard/CampaignHomeSearch'
import { CampaignStaffGlobalSearchBody } from '@/components/campaign/dashboard/CampaignStaffGlobalSearch'
-import { HomeSearchProvider } from '@/components/campaign/dashboard/HomeSearchContext'
+import { useHomeSearch } from '@/components/campaign/dashboard/HomeSearchContext'
import {
HomeSearchResultsProvider,
useHomeSearchResultsState,
} from '@/components/campaign/dashboard/HomeSearchResultsContext'
-import { useHomeSearchQuery } from '@/components/campaign/dashboard/useHomeSearchQuery'
const CampaignHomeStaffSearchSlot = ({ searchResults }: { searchResults: ReactNode }) => {
const searchResultsState = useHomeSearchResultsState()
@@ -24,7 +24,7 @@ const CampaignHomeStaffSearchSlot = ({ searchResults }: { searchResults: ReactNo
)
}
-export const CampaignHomeStaffChrome = ({
+const CampaignHomeStaffChromeInner = ({
actions,
searchResults,
summarySlot,
@@ -34,25 +34,40 @@ export const CampaignHomeStaffChrome = ({
searchResults?: ReactNode
summarySlot?: ReactNode
}) => {
- const searchState = useHomeSearchQuery()
- const focused = searchState.uiFocused
+ const { uiFocused: focused } = useHomeSearch()
return (
-
-
-
- ) : (
-
- )
- }
- summarySlot={summarySlot}
- />
-
-
+
+
+ ) : (
+
+ )
+ }
+ summarySlot={summarySlot}
+ />
+
)
}
+
+export const CampaignHomeStaffChrome = ({
+ actions,
+ searchResults,
+ summarySlot,
+}: {
+ actions: ReactNode
+ searchResults?: ReactNode
+ summarySlot?: ReactNode
+}) => (
+
+
+
+)
diff --git a/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx b/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx
index 2e137d2d..30b9f8a4 100644
--- a/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx
+++ b/src/components/campaign/shell/CampaignQuickActionsDrawer.tsx
@@ -3,6 +3,7 @@
import { useCallback, useState } from 'react'
import { CampaignHomeActionStrip } from '@/components/campaign/dashboard/CampaignHomeActionStrip'
+import { CampaignGlobalSearchMount } from '@/components/campaign/dashboard/CampaignGlobalSearchMount'
import { Drawer, DrawerContent, DrawerTitle } from '@/components/ui/Drawer'
import {
QUICK_ACTIONS_SNAP_COLLAPSED,
@@ -103,6 +104,7 @@ export const CampaignQuickActionsDrawer = ({
) : (
Nenhuma ação rápida nesta página.
)}
+
diff --git a/tests/unit/campaignQuickActionsDrawer.unit.spec.tsx b/tests/unit/campaignQuickActionsDrawer.unit.spec.tsx
new file mode 100644
index 00000000..38564915
--- /dev/null
+++ b/tests/unit/campaignQuickActionsDrawer.unit.spec.tsx
@@ -0,0 +1,67 @@
+import { cleanup, render, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { afterEach, describe, expect, it, vi } from 'vitest'
+
+import { CampaignQuickActionsDrawer } from '@/components/campaign/shell/CampaignQuickActionsDrawer'
+import { postCampaignJson } from '@/lib/campaignJsonRequest'
+
+vi.mock('@/lib/campaignJsonRequest', () => ({
+ postCampaignJson: vi.fn(),
+}))
+
+const idleSuggestPayload = {
+ status: 'success' as const,
+ resultKind: 'suggest' as const,
+ municipalities: [],
+ territories: [],
+ advisors: [],
+ leaderships: [],
+ stateDeputies: [],
+ activities: [],
+ demands: [],
+}
+
+afterEach(() => {
+ cleanup()
+ vi.mocked(postCampaignJson).mockReset()
+})
+
+describe('CampaignQuickActionsDrawer (B91)', () => {
+ it('shows global search in the expanded snap', async () => {
+ vi.mocked(postCampaignJson).mockResolvedValue({
+ ok: true,
+ payload: idleSuggestPayload,
+ })
+
+ const user = userEvent.setup()
+ render()
+
+ expect(screen.queryByLabelText('Buscar na campanha')).toBeNull()
+
+ await user.click(screen.getByRole('button', { name: 'Mostrar ações rápidas' }))
+
+ expect(screen.getByLabelText('Buscar na campanha')).toBeTruthy()
+ expect(screen.getByRole('region', { name: 'Resultados da busca' })).toBeTruthy()
+ })
+
+ it('posts home-search when the drawer query is active', async () => {
+ vi.mocked(postCampaignJson).mockResolvedValue({
+ ok: true,
+ payload: idleSuggestPayload,
+ })
+
+ const user = userEvent.setup()
+ render()
+
+ await user.click(screen.getByRole('button', { name: 'Mostrar ações rápidas' }))
+ await user.type(screen.getByLabelText('Buscar na campanha'), 'cairu')
+
+ await vi.waitFor(() => {
+ expect(postCampaignJson).toHaveBeenCalledWith(
+ '/campanha/home-search',
+ { mode: 'search', query: 'cairu' },
+ expect.any(AbortSignal),
+ )
+ })
+ })
+})