maestro/ui/src/components/list/TaskListItem.tsx
oss-sync e00ea9fb0c
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (d8074a7)
2026-06-05 06:05:30 +00:00

69 lines
2.9 KiB
TypeScript

import { memo } from 'react';
import { LocalTask } from '../../api';
import { relativeTime, statusTone, formatStatusLabel } from '../../lib/utils';
interface LocalTaskListItemProps {
task: LocalTask;
active: boolean;
onClick: () => void;
}
export const LocalTaskListItem = memo(function LocalTaskListItem({ task, active, onClick }: LocalTaskListItemProps) {
const status = task.latestJob?.status ?? 'queued';
const tone = statusTone(status);
return (
<button
onClick={onClick}
className={`w-full text-left px-3 py-2.5 rounded-md border transition-colors ${
active
? 'border-accent/60 bg-accent-soft'
: 'border-hairline bg-canvas hover:bg-surface'
}`}
>
<div className="flex items-center justify-between gap-2 min-w-0">
<div className="flex items-center gap-1.5 min-w-0">
<span className="text-[10px] font-mono text-slate-400 tabular-nums">#{task.id}</span>
<span className="text-[13px] font-semibold text-slate-900 truncate">{task.title}</span>
</div>
<div className="flex-shrink-0 flex items-center gap-1.5">
{task.subtaskCount != null && task.subtaskCount > 0 && (
<span className="text-[10px] font-mono text-slate-400 tabular-nums">
{task.subtaskCompleted ?? 0}/{task.subtaskCount}
</span>
)}
<span
className="px-1.5 py-0.5 rounded text-[10px] font-medium border"
style={{ background: tone.bg, color: tone.fg, borderColor: 'transparent' }}
>
{formatStatusLabel(status)}
</span>
</div>
</div>
<div className="mt-1 text-2xs text-slate-500 truncate leading-snug">
{task.body.length > 80 ? `${task.body.slice(0, 80)}` : task.body}
</div>
<div className="mt-1.5 flex items-center gap-1.5 text-[10px]">
<span className="font-mono text-slate-400 tabular-nums">{relativeTime(task.updatedAt)}</span>
<span className="text-slate-300">·</span>
{task.ownerId ? (
<span className="text-slate-600">{task.ownerName ?? 'user'}</span>
) : (
<span className="text-slate-400">system</span>
)}
{task.visibility === 'private' && (
<span className="px-1 rounded text-[10px] font-medium bg-amber-50 text-amber-700 border border-amber-100" title="Private">private</span>
)}
{task.visibility === 'org' && (
<span className="px-1 rounded text-[10px] font-medium bg-blue-50 text-blue-700 border border-blue-100" title={`Shared with ${task.visibilityScopeOrgName ?? 'org'}`}>
{task.visibilityScopeOrgName ?? 'org'}
</span>
)}
{task.visibility === 'public' && (
<span className="px-1 rounded text-[10px] font-medium bg-emerald-50 text-emerald-700 border border-emerald-100" title="Public">public</span>
)}
</div>
</button>
);
});