59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { ChevronUpIcon } from '@heroicons/react/20/solid'
|
|
import type { VoteState } from '@/types/changelog'
|
|
|
|
export function RoadmapItem({
|
|
id,
|
|
title,
|
|
description,
|
|
status,
|
|
vote,
|
|
onVote,
|
|
}: {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
status: 'planned' | 'in-progress'
|
|
vote: VoteState
|
|
onVote: (id: string) => void
|
|
}) {
|
|
const statusBadgeClass =
|
|
status === 'in-progress'
|
|
? 'border-amber-500/25 bg-amber-500/10 text-amber-400'
|
|
: 'border-zinc-700 bg-zinc-800/40 text-zinc-500'
|
|
|
|
return (
|
|
<div className="grid grid-cols-[52px_1fr_auto] items-center gap-4 rounded-xl border border-zinc-800/60 bg-zinc-950/60 p-5">
|
|
{/* Upvote button */}
|
|
<button
|
|
onClick={() => onVote(id)}
|
|
disabled={vote.loading}
|
|
title={vote.voted ? 'Remove vote' : 'Upvote'}
|
|
className={[
|
|
'flex h-[52px] w-11 flex-col items-center justify-center gap-0.5 rounded-lg border text-xs font-bold transition-colors disabled:opacity-50',
|
|
vote.voted
|
|
? 'border-amber-500/40 bg-amber-500/10 text-amber-400'
|
|
: 'border-zinc-700 text-zinc-500 hover:border-amber-500/40 hover:text-amber-400',
|
|
].join(' ')}
|
|
>
|
|
<ChevronUpIcon className="h-4 w-4" />
|
|
<span>{vote.count}</span>
|
|
</button>
|
|
|
|
{/* Content */}
|
|
<div>
|
|
<p className="text-sm font-semibold text-zinc-200">{title}</p>
|
|
<p className="mt-1 text-xs leading-relaxed text-zinc-500">{description}</p>
|
|
</div>
|
|
|
|
{/* Status badge */}
|
|
<span
|
|
className={`rounded-full border px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider ${statusBadgeClass}`}
|
|
>
|
|
{status === 'in-progress' ? 'In Progress' : 'Planned'}
|
|
</span>
|
|
</div>
|
|
)
|
|
}
|