PhaseDots: distinguish failed states with halo ring, STALLED tag, dashed connector

This commit is contained in:
Bhanu Prakash Sai Potteri 2026-05-23 15:00:38 +05:30
parent 19e1ddc0f8
commit f05ea4b23e

View File

@ -11,7 +11,7 @@ import {
ChevronLeft, ChevronRight, Search, ArrowUp, ArrowDown, X, RefreshCw, ChevronLeft, ChevronRight, Search, ArrowUp, ArrowDown, X, RefreshCw,
CheckCircle2, LogOut, Sparkles, Car, ClipboardList, PhoneOutgoing, CheckCircle2, LogOut, Sparkles, Car, ClipboardList, PhoneOutgoing,
CalendarCheck2, MessageSquareHeart, Trophy, ArrowLeft, ChevronDown, ChevronUp, CalendarCheck2, MessageSquareHeart, Trophy, ArrowLeft, ChevronDown, ChevronUp,
Plus, Plus, AlertTriangle,
} from "lucide-react"; } from "lucide-react";
import { import {
BarChart as RBarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, BarChart as RBarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid,
@ -76,28 +76,52 @@ function phaseIndexFor(state: string | null | undefined): number {
if (state === STATE_IDS.AWAITING_SCHEDULER_CALL || state === STATE_IDS.SCHEDULING_CALL_FAILED) return 1; if (state === STATE_IDS.AWAITING_SCHEDULER_CALL || state === STATE_IDS.SCHEDULING_CALL_FAILED) return 1;
return 0; return 0;
} }
function failedPhaseIndex(state: string | null | undefined): number {
if (state === STATE_IDS.SCHEDULING_CALL_FAILED) return 1;
if (state === STATE_IDS.FEEDBACK_CALL_FAILED) return 3;
return -1;
}
function PhaseDots({ state }: { state: string | null | undefined }) { function PhaseDots({ state }: { state: string | null | undefined }) {
const current = phaseIndexFor(state); const current = phaseIndexFor(state);
const failedAt = failedPhaseIndex(state);
return ( return (
<div className="mt-4 flex items-center gap-2.5 flex-wrap"> <div className="mt-4 flex items-center gap-2.5 flex-wrap">
{PHASES.map((label, i) => { {PHASES.map((label, i) => {
const reached = i <= current; const reached = i <= current;
const isFailed = i === failedAt;
return ( return (
<React.Fragment key={label}> <React.Fragment key={label}>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span <span
className="w-2.5 h-2.5 rounded-full shrink-0" className="w-2.5 h-2.5 rounded-full shrink-0"
style={ style={
reached isFailed
? { background: "#e31837", boxShadow: "0 0 0 2px rgba(227,24,55,0.35)" }
: reached
? { background: "#e31837" } ? { background: "#e31837" }
: { background: "transparent", border: "2px solid rgba(255,255,255,0.4)" } : { background: "transparent", border: "2px solid rgba(255,255,255,0.4)" }
} }
/> />
<span className={`text-[11px] font-semibold uppercase tracking-[0.08em] ${reached ? "text-white" : "text-white/50"}`}> <span className={`flex items-center gap-1 text-[11px] font-semibold uppercase tracking-[0.08em] ${reached ? "text-white" : "text-white/50"}`}>
{label} {label}
{isFailed && (
<span className="flex items-center gap-0.5 ml-0.5" style={{ color: "#ff8a9c" }} title="Stalled — call failed">
<AlertTriangle size={10} strokeWidth={2.5} />
<span className="text-[9.5px] tracking-[0.1em]">STALLED</span>
</span>
)}
</span> </span>
</div> </div>
{i < PHASES.length - 1 && <span className="w-5 h-px" style={{ background: "rgba(255,255,255,0.2)" }} />} {i < PHASES.length - 1 && (
<span
className="w-5 h-px"
style={
isFailed
? { background: "transparent", borderTop: "1px dashed rgba(227,24,55,0.55)" }
: { background: "rgba(255,255,255,0.2)" }
}
/>
)}
</React.Fragment> </React.Fragment>
); );
})} })}