'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' async function getSession() { return getIronSession(await cookies(), sessionOptions) } const taskSchema = z.object({ title: z.string().min(1, 'Titel is verplicht').max(200), description: z.string().max(1000).optional(), priority: z.coerce.number().int().min(1).max(4), }) export async function createTaskAction(_prevState: unknown, formData: FormData) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const storyId = formData.get('storyId') as string const sprintId = formData.get('sprintId') as string const parsed = taskSchema.safeParse({ title: formData.get('title'), description: formData.get('description') || undefined, priority: formData.get('priority') ?? 2, }) if (!parsed.success) return { error: parsed.error.flatten().fieldErrors } const story = await prisma.story.findFirst({ where: { id: storyId, product: { user_id: session.userId } }, }) if (!story) return { error: 'Story niet gevonden' } const last = await prisma.task.findFirst({ where: { story_id: storyId }, orderBy: { sort_order: 'desc' }, }) const task = await prisma.task.create({ data: { story_id: storyId, sprint_id: sprintId || null, title: parsed.data.title, description: parsed.data.description ?? null, priority: parsed.data.priority, sort_order: (last?.sort_order ?? 0) + 1.0, status: 'TO_DO', }, }) revalidatePath(`/products/${story.product_id}/sprint/planning`) return { success: true, task } } export async function updateTaskAction(_prevState: unknown, formData: FormData) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const id = formData.get('id') as string const parsed = taskSchema.safeParse({ title: formData.get('title'), description: formData.get('description') || undefined, priority: formData.get('priority'), }) if (!parsed.success) return { error: parsed.error.flatten().fieldErrors } const task = await prisma.task.findFirst({ where: { id }, include: { story: { include: { product: true } } }, }) if (!task || task.story.product.user_id !== session.userId) return { error: 'Taak niet gevonden' } await prisma.task.update({ where: { id }, data: { title: parsed.data.title, description: parsed.data.description ?? null, priority: parsed.data.priority }, }) revalidatePath(`/products/${task.story.product_id}/sprint/planning`) return { success: true } } export async function updateTaskStatusAction(id: string, status: 'TO_DO' | 'IN_PROGRESS' | 'DONE') { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const task = await prisma.task.findFirst({ where: { id }, include: { story: { include: { product: true } } }, }) if (!task || task.story.product.user_id !== session.userId) return { error: 'Taak niet gevonden' } await prisma.task.update({ where: { id }, data: { status } }) revalidatePath(`/products/${task.story.product_id}/sprint/planning`) return { success: true } } export async function deleteTaskAction(id: string) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const task = await prisma.task.findFirst({ where: { id }, include: { story: { include: { product: true } } }, }) if (!task || task.story.product.user_id !== session.userId) return { error: 'Taak niet gevonden' } await prisma.task.delete({ where: { id } }) revalidatePath(`/products/${task.story.product_id}/sprint/planning`) return { success: true } } export async function reorderTasksAction(storyId: string, orderedIds: string[]) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const story = await prisma.story.findFirst({ where: { id: storyId, product: { user_id: session.userId } }, }) if (!story) return { error: 'Story niet gevonden' } await prisma.$transaction( orderedIds.map((id, i) => prisma.task.update({ where: { id }, data: { sort_order: i + 1.0 } }) ) ) revalidatePath(`/products/${story.product_id}/sprint/planning`) return { success: true } }