Scrum4Me/actions/active-sprint.ts
Janpeter Visser 4a9db57e94
feat(PBI-63): meerdere sprints per product + EXCLUDED + sprint-switcher (#161)
- Sprint lifecycle: ACTIVE→OPEN, COMPLETED→CLOSED, +ARCHIVED (FAILED behouden)
- TaskStatus: +EXCLUDED (overgeslagen door agent-loop via bestaande TO_DO filter)
- Cookie-gebaseerde actieve sprint per product (lib/active-sprint.ts)
- Route splitsen: /products/[id]/sprint/[sprintId] + /sprint redirect-page
- NavBar: gestapelde product/sprint dropdowns + BUILDING-badge derivatie
- Backlog selectie-modus + nieuwe-sprint-dialog (createSprintWithPbisAction)
- Migratie 20260507210000_sprint_lifecycle: ALTER TYPE RENAME (geen data-rewrite)
- Version bump 1.0.0 → 1.2.0

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:15:04 +02:00

42 lines
1.4 KiB
TypeScript

'use server'
import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { z } from 'zod'
import { prisma } from '@/lib/prisma'
import { SessionData, sessionOptions } from '@/lib/session'
import { productAccessFilter } from '@/lib/product-access'
import { setActiveSprintCookie } from '@/lib/active-sprint'
async function getSession() {
return getIronSession<SessionData>(await cookies(), sessionOptions)
}
const setSchema = z.object({
productId: z.string().min(1),
sprintId: z.string().min(1),
})
export async function setActiveSprintAction(productId: string, sprintId: string) {
const session = await getSession()
if (!session.userId) return { error: 'Niet ingelogd' }
if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }
const parsed = setSchema.safeParse({ productId, sprintId })
if (!parsed.success) return { error: 'Ongeldig product- of sprint-id' }
const sprint = await prisma.sprint.findFirst({
where: {
id: parsed.data.sprintId,
product_id: parsed.data.productId,
product: productAccessFilter(session.userId),
},
select: { id: true },
})
if (!sprint) return { error: 'Sprint niet gevonden of niet toegankelijk' }
await setActiveSprintCookie(parsed.data.productId, parsed.data.sprintId)
revalidatePath('/', 'layout')
return { success: true, sprintId: parsed.data.sprintId }
}