feat(ST-513): expose lowercase status on API and accept lowercase in PATCH /api/tasks

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-26 21:48:40 +02:00
parent 405abc3094
commit 62572b84f6
3 changed files with 27 additions and 6 deletions

View file

@ -1,6 +1,7 @@
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 async function GET(
request: Request,
@ -44,8 +45,14 @@ export async function GET(
}
const tasks = story.tasks.map((t, idx) => ({
...t,
id: t.id,
code: story.code ? `${story.code}.${idx + 1}` : null,
title: t.title,
description: t.description,
implementation_plan: t.implementation_plan,
priority: t.priority,
sort_order: t.sort_order,
status: taskStatusToApi(t.status),
}))
return Response.json({
@ -54,6 +61,7 @@ export async function GET(
title: story.title,
description: story.description,
acceptance_criteria: story.acceptance_criteria,
status: storyStatusToApi(story.status),
tasks,
})
}

View file

@ -1,6 +1,7 @@
import { authenticateApiRequest } from '@/lib/api-auth'
import { prisma } from '@/lib/prisma'
import { productAccessFilter } from '@/lib/product-access'
import { taskStatusToApi } from '@/lib/task-status'
export async function GET(
request: Request,
@ -62,7 +63,7 @@ export async function GET(
story_code: t.story.code,
priority: t.priority,
sort_order: t.sort_order,
status: t.status,
status: taskStatusToApi(t.status),
}
})

View file

@ -1,10 +1,11 @@
import { authenticateApiRequest } from '@/lib/api-auth'
import { prisma } from '@/lib/prisma'
import { z } from 'zod'
import { TASK_STATUS_API_VALUES, taskStatusFromApi, taskStatusToApi } from '@/lib/task-status'
const patchSchema = z
.object({
status: z.enum(['TO_DO', 'IN_PROGRESS', 'DONE']).optional(),
status: z.enum(TASK_STATUS_API_VALUES as [string, ...string[]]).optional(),
implementation_plan: z.string().optional(),
})
.refine((data) => data.status !== undefined || data.implementation_plan !== undefined, {
@ -56,13 +57,24 @@ export async function PATCH(
const body = await request.json().catch(() => null)
const parsed = patchSchema.safeParse(body)
if (!parsed.success) {
return Response.json({ error: parsed.error.flatten() }, { status: 400 })
return Response.json({ error: parsed.error.flatten() }, { status: 422 })
}
let dbStatus: ReturnType<typeof taskStatusFromApi> | undefined
if (parsed.data.status !== undefined) {
dbStatus = taskStatusFromApi(parsed.data.status)
if (dbStatus === null) {
return Response.json(
{ error: { fieldErrors: { status: ['Onbekende status'] } } },
{ status: 422 },
)
}
}
const updated = await prisma.task.update({
where: { id },
data: {
...(parsed.data.status !== undefined && { status: parsed.data.status }),
...(dbStatus !== undefined && dbStatus !== null && { status: dbStatus }),
...(parsed.data.implementation_plan !== undefined && {
implementation_plan: parsed.data.implementation_plan,
}),
@ -71,7 +83,7 @@ export async function PATCH(
return Response.json({
id: updated.id,
status: updated.status,
status: taskStatusToApi(updated.status),
implementation_plan: updated.implementation_plan,
})
}