feat(ST-507): show code badges on cards, lists and dialogs across the app

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-26 20:36:59 +02:00
parent 66063f035a
commit b71eb53fa8
15 changed files with 122 additions and 38 deletions

View file

@ -22,7 +22,9 @@ export interface SoloTask {
sort_order: number
status: 'TO_DO' | 'IN_PROGRESS' | 'REVIEW' | 'DONE'
story_id: string
story_code: string | null
story_title: string
task_code: string | null
}
export interface SoloBoardProps {

View file

@ -3,6 +3,7 @@
import { useDraggable } from '@dnd-kit/core'
import { CSS } from '@dnd-kit/utilities'
import { cn } from '@/lib/utils'
import { CodeBadge } from '@/components/shared/code-badge'
import type { SoloTask } from './solo-board'
const PRIORITY_BORDER: Record<number, string> = {
@ -39,8 +40,14 @@ export function SoloTaskCard({ task, isDemo, onClick }: SoloTaskCardProps) {
)}
{...(!isDemo ? { ...attributes, ...listeners } : {})}
>
<p className="text-sm text-foreground leading-snug">{task.title}</p>
<p className="text-xs text-muted-foreground mt-0.5 truncate">{task.story_title}</p>
<div className="flex items-start justify-between gap-2">
<p className="text-sm text-foreground leading-snug flex-1">{task.title}</p>
{task.task_code && <CodeBadge code={task.task_code} className="shrink-0 mt-0.5" />}
</div>
<p className="text-xs text-muted-foreground mt-0.5 truncate">
{task.story_code && <span className="font-mono mr-1">{task.story_code}</span>}
{task.story_title}
</p>
</div>
)
}
@ -53,8 +60,14 @@ export function SoloTaskCardOverlay({ task }: { task: SoloTask }) {
PRIORITY_BORDER[task.priority],
)}
>
<p className="text-sm text-foreground leading-snug">{task.title}</p>
<p className="text-xs text-muted-foreground mt-0.5 truncate">{task.story_title}</p>
<div className="flex items-start justify-between gap-2">
<p className="text-sm text-foreground leading-snug flex-1">{task.title}</p>
{task.task_code && <CodeBadge code={task.task_code} className="shrink-0 mt-0.5" />}
</div>
<p className="text-xs text-muted-foreground mt-0.5 truncate">
{task.story_code && <span className="font-mono mr-1">{task.story_code}</span>}
{task.story_title}
</p>
</div>
)
}

View file

@ -77,11 +77,19 @@ function TaskDetailContent({ task, productId, isDemo, onClose }: TaskDetailConte
<DialogTitle className="text-sm font-medium leading-snug flex-1">
{task.title}
</DialogTitle>
{task.task_code && (
<span className="font-mono text-[11px] text-muted-foreground border border-border rounded-md bg-surface-container px-1.5 py-0.5 shrink-0">
{task.task_code}
</span>
)}
<Badge className={cn('text-xs border shrink-0', STATUS_COLORS[task.status])}>
{STATUS_LABELS[task.status]}
</Badge>
</div>
<p className="text-xs text-muted-foreground">{task.story_title}</p>
<p className="text-xs text-muted-foreground">
{task.story_code && <span className="font-mono mr-1">{task.story_code}</span>}
{task.story_title}
</p>
</DialogHeader>
{task.description && (

View file

@ -7,6 +7,7 @@ import {
Sheet, SheetContent, SheetHeader, SheetTitle,
} from '@/components/ui/sheet'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import { CodeBadge } from '@/components/shared/code-badge'
import { claimStoryAction } from '@/actions/stories'
import { cn } from '@/lib/utils'
@ -20,6 +21,7 @@ export interface UnassignedStoryTask {
export interface UnassignedStory {
id: string
code: string | null
title: string
tasks: UnassignedStoryTask[]
}
@ -119,7 +121,10 @@ function ClaimStoryRow({
<div className="rounded-lg border border-border bg-surface-container overflow-hidden">
<div className="flex items-center gap-3 px-3 py-2.5">
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-foreground truncate">{story.title}</p>
<div className="flex items-start justify-between gap-2">
<p className="text-sm font-medium text-foreground truncate flex-1">{story.title}</p>
{story.code && <CodeBadge code={story.code} className="shrink-0 mt-0.5" />}
</div>
<p className="text-xs text-muted-foreground">
{story.tasks.length} {story.tasks.length === 1 ? 'taak' : 'taken'}
</p>