Files
2026-09-29 15:19:10 +07:00

50 lines
1.8 KiB
TypeScript

import type { InsightJobStage } from '../../types/api.ts';
/** Phase 4 pipeline step indicator for async AI Insight generation. */
const STEPS: { stage: InsightJobStage; label: string; icon: string }[] = [
{ stage: 'grading', label: 'Evaluating CP 707 rules...', icon: 'fa-solid fa-scale-balanced' },
{ stage: 'retrieving', label: 'Fetching SOP guidelines...', icon: 'fa-solid fa-book-open' },
{
stage: 'synthesizing',
label: 'Synthesizing recommendations...',
icon: 'fa-solid fa-wand-magic-sparkles',
},
{ stage: 'saving', label: 'Saving insight...', icon: 'fa-solid fa-floppy-disk' },
];
const ORDER: InsightJobStage[] = ['queued', 'starting', ...STEPS.map((s) => s.stage), 'done'];
function stageIndex(stage: InsightJobStage | null): number {
if (!stage) return 0;
const i = ORDER.indexOf(stage);
return i < 0 ? 0 : i;
}
export default function InsightProgressSteps({ stage }: { stage: InsightJobStage | null }) {
const current = stageIndex(stage);
return (
<ol className="space-y-1.5 text-xs text-gray-600" aria-live="polite">
{STEPS.map((step, i) => {
const state = current > i ? 'done' : current === i ? 'active' : 'pending';
return (
<li
key={step.stage}
className={`flex items-center gap-2 ${state === 'pending' ? 'opacity-40' : ''}`}
>
<i
className={`${step.icon} ${
state === 'done' ? 'text-green-600' : 'text-blue-600'
} ${state === 'active' ? 'fa-spin' : ''}`}
aria-hidden="true"
/>
<span>{step.label}</span>
{state === 'done' && (
<i className="fa-solid fa-check text-green-600" aria-hidden="true" />
)}
</li>
);
})}
</ol>
);
}