import type { ContractPhase } from "../../lib/api";
interface PhaseProgressBarProps {
currentPhase: ContractPhase;
onPhaseClick?: (phase: ContractPhase) => void;
readonly?: boolean;
}
const phases: ContractPhase[] = ["research", "specify", "plan", "execute", "review"];
const phaseLabels: Record<ContractPhase, string> = {
research: "Research",
specify: "Specify",
plan: "Plan",
execute: "Execute",
review: "Review",
};
const phaseColors: Record<ContractPhase, { active: string; inactive: string; completed: string }> = {
research: {
active: "bg-purple-400 border-purple-400",
inactive: "bg-transparent border-purple-400/30",
completed: "bg-purple-400/50 border-purple-400/50",
},
specify: {
active: "bg-blue-400 border-blue-400",
inactive: "bg-transparent border-blue-400/30",
completed: "bg-blue-400/50 border-blue-400/50",
},
plan: {
active: "bg-cyan-400 border-cyan-400",
inactive: "bg-transparent border-cyan-400/30",
completed: "bg-cyan-400/50 border-cyan-400/50",
},
execute: {
active: "bg-yellow-400 border-yellow-400",
inactive: "bg-transparent border-yellow-400/30",
completed: "bg-yellow-400/50 border-yellow-400/50",
},
review: {
active: "bg-green-400 border-green-400",
inactive: "bg-transparent border-green-400/30",
completed: "bg-green-400/50 border-green-400/50",
},
};
export function PhaseProgressBar({
currentPhase,
onPhaseClick,
readonly = false,
}: PhaseProgressBarProps) {
const currentIndex = phases.indexOf(currentPhase);
return (
<div className="flex items-center gap-1">
{phases.map((phase, index) => {
const isActive = phase === currentPhase;
const isCompleted = index < currentIndex;
const colors = phaseColors[phase];
const colorClass = isActive
? colors.active
: isCompleted
? colors.completed
: colors.inactive;
const canClick = !readonly && onPhaseClick;
return (
<div key={phase} className="flex items-center">
{/* Phase node */}
<button
onClick={() => canClick && onPhaseClick(phase)}
disabled={readonly}
className={`
relative group flex flex-col items-center
${canClick ? "cursor-pointer" : "cursor-default"}
`}
>
{/* Circle */}
<div
className={`
w-3 h-3 rounded-full border-2 transition-all
${colorClass}
${canClick && !isActive ? "hover:scale-110" : ""}
`}
/>
{/* Label */}
<span
className={`
absolute top-4 font-mono text-[9px] uppercase tracking-wide whitespace-nowrap
${isActive ? "text-[#dbe7ff]" : "text-[#555]"}
${canClick && !isActive ? "group-hover:text-[#75aafc]" : ""}
`}
>
{phaseLabels[phase]}
</span>
</button>
{/* Connector line */}
{index < phases.length - 1 && (
<div
className={`
w-8 h-0.5 mx-1
${index < currentIndex ? "bg-[#3f6fb3]" : "bg-[rgba(117,170,252,0.15)]"}
`}
/>
)}
</div>
);
})}
</div>
);
}
export function PhaseProgressBarCompact({
currentPhase,
}: {
currentPhase: ContractPhase;
}) {
const currentIndex = phases.indexOf(currentPhase);
return (
<div className="flex items-center gap-0.5">
{phases.map((phase, index) => {
const isActive = phase === currentPhase;
const isCompleted = index < currentIndex;
const colors = phaseColors[phase];
return (
<div
key={phase}
className={`
w-2 h-2 rounded-full border
${isActive ? colors.active : isCompleted ? colors.completed : colors.inactive}
`}
title={phaseLabels[phase]}
/>
);
})}
</div>
);
}