1import { Link } from 'react-router-dom'
2import { MessageSquare, CircleDot, CircleCheck } from 'lucide-react'
3import { formatDistanceToNow } from 'date-fns'
4import { LabelBadge } from './LabelBadge'
5import { Status } from '@/__generated__/graphql'
6
7interface BugRowProps {
8 id: string
9 humanId: string
10 status: Status
11 title: string
12 labels: Array<{ name: string; color: { R: number; G: number; B: number } }>
13 author: { humanId: string; displayName: string; avatarUrl?: string | null }
14 createdAt: string
15 commentCount: number
16 /** Current repo slug, used to build /:repo/issues/:id and /:repo/user/:id links. */
17 repo: string | null
18 onLabelClick?: (name: string) => void
19}
20
21// Single row in the issue list. Shows status icon, title, labels, author and
22// comment count. Labels are clickable to filter the list by that label.
23export function BugRow({
24 humanId,
25 status,
26 title,
27 labels,
28 author,
29 createdAt,
30 commentCount,
31 repo,
32 onLabelClick,
33}: BugRowProps) {
34 const isOpen = status === Status.Open
35 const StatusIcon = isOpen ? CircleDot : CircleCheck
36
37 const issueHref = repo ? `/${repo}/issues/${humanId}` : `/issues/${humanId}`
38 const authorHref = repo ? `/${repo}/user/${author.humanId}` : `/user/${author.humanId}`
39
40 return (
41 <div className="flex items-start gap-3 border-b border-border px-4 py-3 last:border-0 hover:bg-muted/30">
42 <StatusIcon
43 className={
44 isOpen
45 ? 'mt-0.5 size-4 shrink-0 text-green-600 dark:text-green-400'
46 : 'mt-0.5 size-4 shrink-0 text-purple-600 dark:text-purple-400'
47 }
48 />
49
50 <div className="min-w-0 flex-1">
51 <div className="flex flex-wrap items-baseline gap-2">
52 <Link
53 to={issueHref}
54 className="font-medium text-foreground hover:text-primary hover:underline"
55 >
56 {title}
57 </Link>
58 {labels.map((label) => (
59 <LabelBadge key={label.name} name={label.name} color={label.color} onClick={onLabelClick} />
60 ))}
61 </div>
62 <p className="mt-0.5 text-xs text-muted-foreground">
63 #{humanId} opened {formatDistanceToNow(new Date(createdAt), { addSuffix: true })} by{' '}
64 <Link to={authorHref} className="hover:underline">
65 {author.displayName}
66 </Link>
67 </p>
68 </div>
69
70 {commentCount > 0 && (
71 <div className="flex shrink-0 items-center gap-1 text-xs text-muted-foreground">
72 <MessageSquare className="size-3.5" />
73 {commentCount}
74 </div>
75 )}
76 </div>
77 )
78}