// PBI-74 / Story 9 / T-882: GET /api/sprints/:id/workspace // // Levert een SprintWorkspaceSnapshot (sprint + stories + tasksByStory) voor // de sprint-workspace-store (ensureSprintLoaded). Auth + access-control via // product-membership. import { authenticateApiRequest } from '@/lib/api-auth' import { prisma } from '@/lib/prisma' import { productAccessFilter } from '@/lib/product-access' import { storyStatusToApi, taskStatusToApi } from '@/lib/task-status' export const dynamic = 'force-dynamic' export async function GET( request: Request, { params }: { params: Promise<{ id: string }> }, ) { const auth = await authenticateApiRequest(request) if ('error' in auth) { return Response.json({ error: auth.error }, { status: auth.status }) } const { id } = await params const sprint = await prisma.sprint.findFirst({ where: { id, product: productAccessFilter(auth.userId) }, select: { id: true, product_id: true, code: true, sprint_goal: true, status: true, start_date: true, end_date: true, created_at: true, completed_at: true, product: { select: { id: true, name: true } }, }, }) if (!sprint) { return Response.json({ error: 'Sprint niet gevonden' }, { status: 404 }) } const [stories, tasks] = await Promise.all([ prisma.story.findMany({ where: { sprint_id: id }, orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }, { created_at: 'asc' }], include: { tasks: { select: { id: true, status: true } }, assignee: { select: { id: true, username: true } }, }, }), prisma.task.findMany({ where: { sprint_id: id }, orderBy: [{ sort_order: 'asc' }, { created_at: 'asc' }], select: { id: true, code: true, title: true, description: true, priority: true, sort_order: true, status: true, story_id: true, sprint_id: true, created_at: true, }, }), ]) const tasksByStory: Record = {} for (const task of tasks) { const apiTask = { ...task, status: taskStatusToApi(task.status) } if (!tasksByStory[task.story_id]) tasksByStory[task.story_id] = [] tasksByStory[task.story_id].push(apiTask) } return Response.json({ product: sprint.product, sprint: { id: sprint.id, product_id: sprint.product_id, code: sprint.code, sprint_goal: sprint.sprint_goal, status: sprint.status, start_date: sprint.start_date ? sprint.start_date.toISOString().slice(0, 10) : null, end_date: sprint.end_date ? sprint.end_date.toISOString().slice(0, 10) : null, created_at: sprint.created_at, completed_at: sprint.completed_at, }, stories: stories.map((s) => ({ id: s.id, code: s.code, title: s.title, description: s.description, acceptance_criteria: s.acceptance_criteria, priority: s.priority, sort_order: s.sort_order, status: storyStatusToApi(s.status), pbi_id: s.pbi_id, sprint_id: s.sprint_id, created_at: s.created_at, taskCount: s.tasks.length, doneCount: s.tasks.filter((t) => t.status === 'DONE').length, assignee_id: s.assignee_id, assignee_username: s.assignee?.username ?? null, })), tasksByStory, }) }