From d684732ec8e14af0f7fa807f98822860dc0b1934 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sun, 26 Apr 2026 17:49:19 +0200 Subject: [PATCH] feat: show tasks with priority and status in unassigned stories sheet Tasks are always visible under each story. Click a task to expand its description. Co-Authored-By: Claude Sonnet 4.6 --- app/(app)/products/[id]/solo/page.tsx | 13 ++- components/solo/unassigned-stories-sheet.tsx | 92 +++++++++++++++++--- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/app/(app)/products/[id]/solo/page.tsx b/app/(app)/products/[id]/solo/page.tsx index d87f7b5..1e833c4 100644 --- a/app/(app)/products/[id]/solo/page.tsx +++ b/app/(app)/products/[id]/solo/page.tsx @@ -53,7 +53,10 @@ export default async function SoloProductPage({ params }: Props) { select: { id: true, title: true, - _count: { select: { tasks: true } }, + tasks: { + select: { id: true, title: true, description: true, priority: true, status: true }, + orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }], + }, }, orderBy: { sort_order: 'asc' }, }), @@ -74,7 +77,13 @@ export default async function SoloProductPage({ params }: Props) { const unassignedStories: UnassignedStory[] = rawUnassigned.map(s => ({ id: s.id, title: s.title, - task_count: s._count.tasks, + tasks: s.tasks.map(t => ({ + id: t.id, + title: t.title, + description: t.description, + priority: t.priority, + status: t.status, + })), })) return ( diff --git a/components/solo/unassigned-stories-sheet.tsx b/components/solo/unassigned-stories-sheet.tsx index 8d35690..b6ccbb5 100644 --- a/components/solo/unassigned-stories-sheet.tsx +++ b/components/solo/unassigned-stories-sheet.tsx @@ -8,11 +8,20 @@ import { } from '@/components/ui/sheet' import { DemoTooltip } from '@/components/shared/demo-tooltip' import { claimStoryAction } from '@/actions/stories' +import { cn } from '@/lib/utils' + +export interface UnassignedStoryTask { + id: string + title: string + description: string | null + priority: number + status: string +} export interface UnassignedStory { id: string title: string - task_count: number + tasks: UnassignedStoryTask[] } interface UnassignedStoriesSheetProps { @@ -24,6 +33,60 @@ interface UnassignedStoriesSheetProps { onClaim: (storyId: string) => void } +const PRIORITY_BORDER: Record = { + 1: 'border-l-2 border-l-priority-critical', + 2: 'border-l-2 border-l-priority-high', + 3: 'border-l-2 border-l-priority-medium', + 4: 'border-l-2 border-l-priority-low', +} + +const STATUS_COLORS: Record = { + TO_DO: 'bg-status-todo/15 text-status-todo', + IN_PROGRESS: 'bg-status-in-progress/15 text-status-in-progress', + REVIEW: 'bg-status-in-progress/15 text-status-in-progress', + DONE: 'bg-status-done/15 text-status-done', +} + +const STATUS_LABELS: Record = { + TO_DO: 'To Do', + IN_PROGRESS: 'Bezig', + REVIEW: 'Review', + DONE: 'Klaar', +} + +const PRIORITY_LABELS: Record = { 1: 'Kritiek', 2: 'Hoog', 3: 'Gemiddeld', 4: 'Laag' } + +function TaskRow({ task }: { task: UnassignedStoryTask }) { + const [expanded, setExpanded] = useState(false) + + return ( +
setExpanded(e => !e)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpanded(v => !v) } }} + className={cn( + 'px-3 py-2 cursor-pointer select-none', + PRIORITY_BORDER[task.priority], + )} + > +
+ {task.title} + + {STATUS_LABELS[task.status] ?? task.status} + + {PRIORITY_LABELS[task.priority]} +
+ {expanded && ( +

+ {task.description ?? 'Geen beschrijving.'} +

+ )} +
+ ) +} + function ClaimButton({ isDemo }: { isDemo: boolean }) { const { pending } = useFormStatus() return ( @@ -53,16 +116,25 @@ function ClaimStoryRow({ } return ( -
-
-

{story.title}

-

- {story.task_count} {story.task_count === 1 ? 'taak' : 'taken'} -

+
+
+
+

{story.title}

+

+ {story.tasks.length} {story.tasks.length === 1 ? 'taak' : 'taken'} +

+
+
+ +
-
- - + {story.tasks.length > 0 && ( +
+ {story.tasks.map(task => ( + + ))} +
+ )}
) }