From 081a0a51c349b7a21452fff9a0183b536c8d2f3e Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Mon, 4 May 2026 08:36:52 +0200 Subject: [PATCH] feat(codes): UI toont en accepteert code voor taken - TaskDialog: code-input boven titel (font-mono, optional, placeholder "auto"), CodeBadge in dialog header bij edit - EditTaskLoader: select code uit DB voor de dialog - Solo page: vervang inline deriveTaskCode-logica door directe task.code uit DB - Sprint page + TaskList + SprintBoardClient: Task-type krijgt verplicht code-veld; TaskList laat ongebruikte storyCode prop vallen omdat code-derivatie niet meer nodig is Co-Authored-By: Claude Opus 4.7 (1M context) --- app/(app)/products/[id]/solo/page.tsx | 35 ++++++++++------------ app/(app)/products/[id]/sprint/page.tsx | 1 + app/_components/tasks/edit-task-loader.tsx | 1 + app/_components/tasks/task-dialog.tsx | 34 +++++++++++++++++++-- components/sprint/sprint-board-client.tsx | 1 - components/sprint/task-list.tsx | 9 +++--- 6 files changed, 52 insertions(+), 29 deletions(-) diff --git a/app/(app)/products/[id]/solo/page.tsx b/app/(app)/products/[id]/solo/page.tsx index 12fdd16..868e579 100644 --- a/app/(app)/products/[id]/solo/page.tsx +++ b/app/(app)/products/[id]/solo/page.tsx @@ -72,26 +72,21 @@ export default async function SoloProductPage({ params }: Props) { }), ]) - const tasks: SoloTask[] = rawTasks.map(t => { - const positionInStory = t.story.tasks.findIndex(st => st.id === t.id) - const taskCode = - t.story.code && positionInStory >= 0 ? `${t.story.code}.${positionInStory + 1}` : null - return { - id: t.id, - title: t.title, - description: t.description, - implementation_plan: t.implementation_plan, - priority: t.priority, - sort_order: t.sort_order, - status: t.status as SoloTask['status'], - verify_only: t.verify_only, - verify_required: t.verify_required as SoloTask['verify_required'], - story_id: t.story.id, - story_code: t.story.code, - story_title: t.story.title, - task_code: taskCode, - } - }) + const tasks: SoloTask[] = rawTasks.map(t => ({ + id: t.id, + title: t.title, + description: t.description, + implementation_plan: t.implementation_plan, + priority: t.priority, + sort_order: t.sort_order, + status: t.status as SoloTask['status'], + verify_only: t.verify_only, + verify_required: t.verify_required as SoloTask['verify_required'], + story_id: t.story.id, + story_code: t.story.code, + story_title: t.story.title, + task_code: t.code, + })) const unassignedStories: UnassignedStory[] = rawUnassigned.map(s => ({ id: s.id, diff --git a/app/(app)/products/[id]/sprint/page.tsx b/app/(app)/products/[id]/sprint/page.tsx index e8a6b9e..e72bf56 100644 --- a/app/(app)/products/[id]/sprint/page.tsx +++ b/app/(app)/products/[id]/sprint/page.tsx @@ -81,6 +81,7 @@ export default async function SprintBoardPage({ params, searchParams }: Props) { for (const story of sprintStories) { tasksByStory[story.id] = story.tasks.map(t => ({ id: t.id, + code: t.code, title: t.title, description: t.description, priority: t.priority, diff --git a/app/_components/tasks/edit-task-loader.tsx b/app/_components/tasks/edit-task-loader.tsx index f66cce9..9c03194 100644 --- a/app/_components/tasks/edit-task-loader.tsx +++ b/app/_components/tasks/edit-task-loader.tsx @@ -25,6 +25,7 @@ export async function EditTaskLoader({ }, select: { id: true, + code: true, title: true, description: true, implementation_plan: true, diff --git a/app/_components/tasks/task-dialog.tsx b/app/_components/tasks/task-dialog.tsx index abb9ce3..4e25f27 100644 --- a/app/_components/tasks/task-dialog.tsx +++ b/app/_components/tasks/task-dialog.tsx @@ -27,6 +27,8 @@ import { } from '@/components/ui/alert-dialog' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' +import { CodeBadge } from '@/components/shared/code-badge' +import { MAX_CODE_LENGTH } from '@/lib/code' import { DemoTooltip } from '@/components/shared/demo-tooltip' import { useDirtyCloseGuard, @@ -45,6 +47,7 @@ import { cn } from '@/lib/utils' export interface TaskDialogTask { id: string + code: string | null title: string description: string | null implementation_plan: string | null @@ -88,6 +91,7 @@ export function TaskDialog({ task, storyId, productId, closePath, isDemo = false resolver: zodResolver(taskSchema), mode: 'onTouched', defaultValues: { + code: task?.code ?? '', title: task?.title ?? '', description: task?.description ?? '', implementation_plan: task?.implementation_plan ?? '', @@ -173,9 +177,12 @@ export function TaskDialog({ task, storyId, productId, closePath, isDemo = false > {/* Sticky header */}
- - {isEdit ? 'Taak bewerken' : 'Nieuwe taak'} - +
+ + {isEdit ? 'Taak bewerken' : 'Nieuwe taak'} + + {isEdit && task?.code && } +
{isEdit && ( Aangemaakt:{' '} @@ -190,6 +197,27 @@ export function TaskDialog({ task, storyId, productId, closePath, isDemo = false {/* Scrollable form body */}
+ {/* Code */} +
+ + { if (e.key === 'Enter') e.preventDefault() }} + /> + {form.formState.errors.code && ( +

+ {form.formState.errors.code.message} +

+ )} +
+ {/* Title */}