Merge pull request #83 from fsolla/cursor/pool-i25-c746bf60-aaf2

B89 — Ações rápidas em Contatos (liderança)
This commit is contained in:
Francisco Solla 2026-08-01 02:39:55 -03:00 committed by GitHub
commit 010a655cf4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 87 additions and 2 deletions

View file

@ -63,8 +63,9 @@ export const LeaderContactForm = ({
return (
<section
id="leader-contact-form"
aria-labelledby="leader-contact-form-title"
className="flex flex-col gap-4 rounded-xl border p-4"
className="flex flex-col gap-4 rounded-xl border p-4 scroll-mt-4"
>
<div className="flex items-center gap-2">
<UserPlusIcon className="size-5 text-muted-foreground" aria-hidden="true" />

View file

@ -30,8 +30,9 @@ type LeaderContactsPanelProps = {
const LeaderContactsList = ({ contacts }: { contacts: LeaderContactListItem[] }) => (
<section
id="leader-contacts-list"
aria-labelledby="leader-contacts-list-title"
className="flex flex-col gap-3 rounded-xl border p-4"
className="flex flex-col gap-3 rounded-xl border p-4 scroll-mt-4"
>
<h2 id="leader-contacts-list-title" className="text-base font-medium">
Meus contatos ({contacts.length})

View file

@ -3,12 +3,14 @@ import { resolveStaffHomeQuickActions } from '@/lib/campaignHomeActions'
import { resolveMunicipalityQuickActionsForPath } from '@/lib/campaignMunicipalityQuickActions'
import { CAMPAIGN_TERRITORIES_HOME } from '@/lib/campaignPaths'
import type { CampaignQuickActionContext } from '@/lib/campaignQuickActionContext'
import { isLeaderContactsPath } from '@/lib/campaignQuickActionMount'
import {
parseActivityQuickActionSurface,
parseOrganizationQuickActionSurface,
} from '@/lib/campaignQuickActionPaths'
import type { CampaignQuickAction } from '@/lib/campaignQuickActionTypes'
import type { CampaignRole } from '@/lib/campaignRoles'
import { resolveLeaderContactsQuickActions } from '@/lib/leaderContactsQuickActions'
import { resolveOrganizationQuickActions } from '@/lib/organizationQuickActions'
const isTerritoriesListPath = (pathname: string): boolean =>
@ -24,6 +26,10 @@ export const resolveQuickActionsForPath = (
role: CampaignRole,
context: CampaignQuickActionContext,
): readonly CampaignQuickAction[] => {
if (isLeaderContactsPath(pathname)) {
return resolveLeaderContactsQuickActions(role, context)
}
const activitySurface = parseActivityQuickActionSurface(pathname)
if (activitySurface) {
return resolveActivityQuickActions(activitySurface, role, context)

View file

@ -0,0 +1,31 @@
import {
homeActionsForRole,
toHomeActionButtonProps,
type ResolvedCampaignHomeAction,
} from '@/lib/campaignHomeActions'
import type { CampaignQuickActionContext } from '@/lib/campaignQuickActionContext'
import type { CampaignQuickAction } from '@/lib/campaignQuickActionTypes'
import type { CampaignRole } from '@/lib/campaignRoles'
/** In-page anchors on `/campanha/contatos` — hash navigation from the B89 drawer. */
export const LEADER_CONTACT_FORM_HASH = '#leader-contact-form' as const
export const LEADER_CONTACTS_LIST_HASH = '#leader-contacts-list' as const
const toLeaderContactsQuickAction = (action: ResolvedCampaignHomeAction): CampaignQuickAction => {
if (action.id === 'register-supporter') {
return { ...action, href: LEADER_CONTACT_FORM_HASH }
}
if (action.id === 'my-contacts') {
return { ...action, href: LEADER_CONTACTS_LIST_HASH }
}
return action
}
export const resolveLeaderContactsQuickActions = (
role: CampaignRole,
_context: CampaignQuickActionContext,
): readonly CampaignQuickAction[] => {
if (role !== 'leader') return []
return toHomeActionButtonProps(homeActionsForRole('leader')).map(toLeaderContactsQuickAction)
}

View file

@ -0,0 +1,46 @@
import { describe, expect, it } from 'vitest'
import { homeActionsForRole } from '@/lib/campaignHomeActions'
import { LEADER_CONTACTS_HOME } from '@/lib/campaignPaths'
import {
LEADER_CONTACT_FORM_HASH,
LEADER_CONTACTS_LIST_HASH,
resolveLeaderContactsQuickActions,
} from '@/lib/leaderContactsQuickActions'
describe('leaderContactsQuickActions (B89)', () => {
const leaderActionIds = homeActionsForRole('leader').map((action) => action.id)
it('returns the B45 leader catalog with in-page hash hrefs', () => {
const actions = resolveLeaderContactsQuickActions('leader', {})
expect(actions.map((action) => action.id)).toEqual(leaderActionIds)
expect(actions.find((action) => action.id === 'register-supporter')?.href).toBe(
LEADER_CONTACT_FORM_HASH,
)
expect(actions.find((action) => action.id === 'my-contacts')?.href).toBe(
LEADER_CONTACTS_LIST_HASH,
)
})
it('returns empty catalog for staff lockdown', () => {
expect(resolveLeaderContactsQuickActions('coordinator', {})).toEqual([])
expect(resolveLeaderContactsQuickActions('advisor', {})).toEqual([])
})
})
describe('campaignQuickActionRegistry leader contacts (B89)', () => {
it('delegates contatos routes to the leader catalog', async () => {
const { resolveQuickActionsForPath } = await import('@/lib/campaignQuickActionRegistry')
const actions = resolveQuickActionsForPath(LEADER_CONTACTS_HOME, 'leader', {})
expect(actions.map((action) => action.id)).toEqual(['register-supporter', 'my-contacts'])
expect(actions.find((action) => action.id === 'register-supporter')?.href).toBe(
LEADER_CONTACT_FORM_HASH,
)
})
it('returns empty catalog on contatos for staff', async () => {
const { resolveQuickActionsForPath } = await import('@/lib/campaignQuickActionRegistry')
expect(resolveQuickActionsForPath(LEADER_CONTACTS_HOME, 'coordinator', {})).toEqual([])
})
})