mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
B83 — catálogo de ações rápidas para /dobradinhas
Registra no drawer B79: lista (Nova dobradinha + 6 ações Início sem prefill), detalhe e /nova (só Início). Integra com catálogos B80–B89. Closes #19
This commit is contained in:
parent
5c6ed8cf31
commit
21e5027b8b
4 changed files with 123 additions and 2 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# Ações rápidas — Dobradinhas
|
||||
|
||||
Status: rascunho
|
||||
Atualizado em: 2026-07-30
|
||||
Status: entregue (B83 — #19)
|
||||
Atualizado em: 2026-08-01
|
||||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B83**)
|
||||
Impeccable: B — drawer B79 em `/dobradinhas` (+ detalhe se houver)
|
||||
Appetite: ~0,25–0,5 dia eng; sem migration
|
||||
|
|
@ -63,3 +63,9 @@ Nenhum neste item.
|
|||
## Referências
|
||||
|
||||
`dobradinhas/**` · B79 · `campaignHomeActions.ts`
|
||||
|
||||
## As-built (#19)
|
||||
|
||||
- Registry: `campaignQuickActionDobradinhas.ts` — lista (`Nova dobradinha` + 6 ações Início sem prefill), detalhe/nova (só Início).
|
||||
- Atalho “Municípios desta dobradinha” **omitido** — `municipalityListUrl` não expõe filtro por `stateDeputy`.
|
||||
- WA share (B55) **omitido** no drawer (recomendação A do plano).
|
||||
|
|
|
|||
52
src/lib/campaignQuickActionDobradinhas.ts
Normal file
52
src/lib/campaignQuickActionDobradinhas.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { Plus } from 'lucide-react'
|
||||
|
||||
import { resolveStaffHomeQuickActions } from '@/lib/campaignHomeActions'
|
||||
import type { CampaignQuickAction } from '@/lib/campaignQuickActionTypes'
|
||||
import { isStaffCampaignRole, type CampaignRole } from '@/lib/campaignRoles'
|
||||
|
||||
const STATE_DEPUTY_LIST_PATH = '/campanha/dobradinhas' as const
|
||||
const STATE_DEPUTY_CREATE_PATH = '/campanha/dobradinhas/nova' as const
|
||||
const STATE_DEPUTY_PATH_PREFIX = `${STATE_DEPUTY_LIST_PATH}/` as const
|
||||
|
||||
const isStateDeputyListPath = (pathname: string): boolean =>
|
||||
pathname === STATE_DEPUTY_LIST_PATH || pathname === `${STATE_DEPUTY_LIST_PATH}/`
|
||||
|
||||
const isStateDeputyCreatePath = (pathname: string): boolean => pathname === STATE_DEPUTY_CREATE_PATH
|
||||
|
||||
export const parseStateDeputyDetailSlug = (pathname: string): string | undefined => {
|
||||
if (!pathname.startsWith(STATE_DEPUTY_PATH_PREFIX)) return undefined
|
||||
const slug = pathname.slice(STATE_DEPUTY_PATH_PREFIX.length)
|
||||
if (!slug || slug.includes('/') || slug === 'nova') return undefined
|
||||
return slug
|
||||
}
|
||||
|
||||
export const matchesDobradinhasQuickActionSurface = (pathname: string): boolean =>
|
||||
isStateDeputyListPath(pathname) ||
|
||||
isStateDeputyCreatePath(pathname) ||
|
||||
parseStateDeputyDetailSlug(pathname) !== undefined
|
||||
|
||||
const newStateDeputyAction = (): CampaignQuickAction => ({
|
||||
id: 'new-state-deputy',
|
||||
label: 'Nova dobradinha',
|
||||
icon: Plus,
|
||||
description: 'Cadastrar um deputado estadual parceiro da campanha',
|
||||
href: STATE_DEPUTY_CREATE_PATH,
|
||||
})
|
||||
|
||||
/** B83 — `/dobradinhas` list, detail and create surfaces. */
|
||||
export const resolveDobradinhasQuickActions = (
|
||||
pathname: string,
|
||||
role: CampaignRole,
|
||||
): readonly CampaignQuickAction[] => {
|
||||
if (!matchesDobradinhasQuickActionSurface(pathname) || !isStaffCampaignRole(role)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const staffActions = resolveStaffHomeQuickActions(role)
|
||||
|
||||
if (isStateDeputyListPath(pathname)) {
|
||||
return [newStateDeputyAction(), ...staffActions]
|
||||
}
|
||||
|
||||
return staffActions
|
||||
}
|
||||
|
|
@ -10,6 +10,10 @@ import {
|
|||
resolveDemandDetailQuickActions,
|
||||
resolveDemandsListQuickActions,
|
||||
} from '@/lib/campaignQuickActionDemands'
|
||||
import {
|
||||
matchesDobradinhasQuickActionSurface,
|
||||
resolveDobradinhasQuickActions,
|
||||
} from '@/lib/campaignQuickActionDobradinhas'
|
||||
import { isLeaderContactsPath } from '@/lib/campaignQuickActionMount'
|
||||
import {
|
||||
parseActivityQuickActionSurface,
|
||||
|
|
@ -57,6 +61,10 @@ export const resolveQuickActionsForPath = (
|
|||
const municipalityActions = resolveMunicipalityQuickActionsForPath(pathname, role, context)
|
||||
if (municipalityActions.length > 0) return municipalityActions
|
||||
|
||||
if (matchesDobradinhasQuickActionSurface(pathname)) {
|
||||
return resolveDobradinhasQuickActions(pathname, role)
|
||||
}
|
||||
|
||||
const advisorActions = resolveAdvisorQuickActionsForPath(pathname, role, context)
|
||||
if (advisorActions.length > 0) return advisorActions
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ import {
|
|||
resolveDemandDetailQuickActions,
|
||||
resolveDemandsListQuickActions,
|
||||
} from '@/lib/campaignQuickActionDemands'
|
||||
import {
|
||||
matchesDobradinhasQuickActionSurface,
|
||||
parseStateDeputyDetailSlug,
|
||||
resolveDobradinhasQuickActions,
|
||||
} from '@/lib/campaignQuickActionDobradinhas'
|
||||
import {
|
||||
isCampaignActionsPath,
|
||||
isCampaignHomePath,
|
||||
|
|
@ -80,6 +85,11 @@ describe('campaignQuickActionMount', () => {
|
|||
expect(shouldMountQuickActionsDrawer('/campanha/assessores', 'advisor')).toBe(false)
|
||||
expect(shouldMountQuickActionsDrawer('/campanha/assessores/12', 'advisor')).toBe(false)
|
||||
})
|
||||
|
||||
it('mounts on dobradinhas for staff (B83)', () => {
|
||||
expect(shouldMountQuickActionsDrawer('/campanha/dobradinhas', 'coordinator')).toBe(true)
|
||||
expect(shouldMountQuickActionsDrawer('/campanha/dobradinhas/foo', 'advisor')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('campaignQuickActionPaths (activities)', () => {
|
||||
|
|
@ -182,6 +192,46 @@ describe('activityQuickActions (B84)', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('campaignQuickActionDobradinhas (B83)', () => {
|
||||
const staffActionIds = homeActionsForRole('coordinator').map((action) => action.id)
|
||||
|
||||
it('recognizes list, create and detail surfaces', () => {
|
||||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas')).toBe(true)
|
||||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas/nova')).toBe(true)
|
||||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas/eduardo-alves')).toBe(true)
|
||||
expect(matchesDobradinhasQuickActionSurface('/campanha/municipios')).toBe(false)
|
||||
})
|
||||
|
||||
it('parses detail slug and rejects nova', () => {
|
||||
expect(parseStateDeputyDetailSlug('/campanha/dobradinhas/eduardo-alves')).toBe('eduardo-alves')
|
||||
expect(parseStateDeputyDetailSlug('/campanha/dobradinhas/nova')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('returns list catalog with Nova dobradinha plus staff Início actions without prefill', () => {
|
||||
const actions = resolveDobradinhasQuickActions('/campanha/dobradinhas', 'coordinator')
|
||||
expect(actions.map((action) => action.id)).toEqual(['new-state-deputy', ...staffActionIds])
|
||||
expect(actions[0]?.href).toBe('/campanha/dobradinhas/nova')
|
||||
expect(actions.find((action) => action.id === 'update-votes')?.href).toBe(
|
||||
'/campanha/acoes/atualizar-votos',
|
||||
)
|
||||
expect(actions.find((action) => action.id === 'uncovered-municipalities')?.href).toBe(
|
||||
UNCOVERED_MUNICIPALITIES_LIST_HREF,
|
||||
)
|
||||
})
|
||||
|
||||
it('returns staff actions without Nova on detail and create', () => {
|
||||
for (const pathname of ['/campanha/dobradinhas/eduardo-alves', '/campanha/dobradinhas/nova']) {
|
||||
const actions = resolveDobradinhasQuickActions(pathname, 'advisor')
|
||||
expect(actions.map((action) => action.id)).toEqual(staffActionIds)
|
||||
expect(actions.some((action) => action.id === 'new-state-deputy')).toBe(false)
|
||||
}
|
||||
})
|
||||
|
||||
it('returns empty for leader lockdown', () => {
|
||||
expect(resolveDobradinhasQuickActions('/campanha/dobradinhas', 'leader')).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('campaignQuickActionRegistry', () => {
|
||||
const staffActionIds = homeActionsForRole('coordinator').map((action) => action.id)
|
||||
|
||||
|
|
@ -221,6 +271,11 @@ describe('campaignQuickActionRegistry', () => {
|
|||
expect(actions.map((action) => action.id)).toEqual(['new-activity', 'plan-tour'])
|
||||
})
|
||||
|
||||
it('delegates dobradinhas paths to the B83 catalog', () => {
|
||||
const actions = resolveQuickActionsForPath('/campanha/dobradinhas', 'coordinator', {})
|
||||
expect(actions.some((action) => action.id === 'new-state-deputy')).toBe(true)
|
||||
})
|
||||
|
||||
it('builds wizard hrefs with municipality slug from context', () => {
|
||||
const actions = resolveQuickActionsForPath(
|
||||
'/campanha/atividades/evento-zona-1',
|
||||
|
|
|
|||
Loading…
Reference in a new issue