Files
SanatiLeads/components/analysis-timeline.tsx

83 lines
2.7 KiB
TypeScript

"use client"
import { CheckCircle2, AlertTriangle, Loader2 } from "lucide-react"
import { cn } from "@/lib/utils"
type TimelineItem = {
key: string
label: string
status: "pending" | "running" | "completed" | "failed"
detail?: string
}
function StatusIcon({ status }: { status: TimelineItem["status"] }) {
if (status === "completed") {
return <CheckCircle2 className="h-4 w-4 text-foreground" />
}
if (status === "failed") {
return <AlertTriangle className="h-4 w-4 text-destructive" />
}
if (status === "running") {
return <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
}
return <span className="h-2.5 w-2.5 rounded-full border border-muted-foreground/60" />
}
export function AnalysisTimeline({ items }: { items: TimelineItem[] }) {
if (!items.length) return null
return (
<div className="rounded-lg border border-border/60 bg-muted/20 p-4">
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Analysis timeline
</div>
<div className="mt-3 space-y-3">
{items.map((item, index) => {
const isPending = item.status === "pending"
const nextStatus = items[index + 1]?.status
const isStrongLine =
nextStatus &&
(item.status === "completed" || item.status === "running") &&
(nextStatus === "completed" || nextStatus === "running")
return (
<div key={item.key} className="relative pl-6">
<span
className={cn(
"absolute left-[6px] top-3 bottom-[-12px] w-px",
index === items.length - 1 ? "hidden" : "bg-border/40",
isStrongLine && "bg-foreground/60"
)}
/>
<div
className={cn(
"flex items-start gap-3 text-sm transition",
isPending && "scale-[0.96] opacity-60"
)}
>
<div className="mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-background shadow-sm">
<StatusIcon status={item.status} />
</div>
<div className="min-w-0">
<div
className={cn(
"font-medium",
item.status === "failed" && "text-destructive"
)}
>
{item.label}
</div>
{item.detail && (
<div className="text-xs text-muted-foreground">
{item.detail}
</div>
)}
</div>
</div>
</div>
)
})}
</div>
</div>
)
}