feat: add production assurance dashboard flow

This commit is contained in:
thanhnv
2026-07-28 21:49:15 +07:00
parent ee5d1f7af5
commit cce3cbfd42
39 changed files with 1873 additions and 91 deletions
@@ -0,0 +1,42 @@
import type { HarnessGateStatus, HarnessTraceGraph } from '../../lib/api';
const TONE: Record<HarnessGateStatus, string> = {
queued: 'border-slate-200 bg-slate-100 text-slate-400',
running: 'border-blue-300 bg-blue-50 text-blue-700',
pass: 'border-emerald-300 bg-emerald-50 text-emerald-700',
warning: 'border-amber-300 bg-amber-50 text-amber-700',
blocked: 'border-rose-300 bg-rose-50 text-rose-700',
error: 'border-rose-300 bg-rose-50 text-rose-700',
skipped: 'border-slate-200 bg-slate-100 text-slate-400',
};
const MARK: Record<HarnessGateStatus, string> = {
queued: '○',
running: '●',
pass: '✓',
warning: '!',
blocked: '×',
error: '×',
skipped: '–',
};
export function AssuranceRail({ graph }: { graph: HarnessTraceGraph }) {
return (
<div className="overflow-x-auto pb-1">
<div className="flex min-w-[760px] items-center">
{graph.nodes.map((node, index) => (
<div key={node.id} className="flex min-w-0 flex-1 items-center">
<div className={`min-w-0 flex-1 rounded-xl border p-3 ${TONE[node.status]}`}>
<div className="flex items-center justify-between gap-2">
<span className="text-[10px] font-black uppercase tracking-[0.12em]">{node.title.split(' · ')[0]}</span>
<span className={`flex h-5 w-5 items-center justify-center rounded-full border border-current text-[10px] ${node.status === 'running' ? 'animate-pulse' : ''}`}>{MARK[node.status]}</span>
</div>
<div className="mt-2 truncate text-xs font-semibold">{node.title.split(' · ')[1]}</div>
</div>
{index < graph.nodes.length - 1 && <div className={`h-px w-3 shrink-0 ${node.status === 'pass' ? 'bg-emerald-300' : 'bg-slate-200'}`} />}
</div>
))}
</div>
</div>
);
}