import { Badge } from "@/components/reui/badge"
import {
Frame,
FrameHeader,
FramePanel,
} from "@/components/reui/frame"
import {
Timeline,
TimelineContent,
TimelineHeader,
TimelineIndicator,
TimelineItem,
TimelineSeparator,
TimelineTitle,
} from "@/components/reui/timeline"
import { cn } from "@/lib/utils"
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import { Spinner } from "@/components/ui/spinner"
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'
const pipelineSteps = [
{
id: 1,
title: "Source Code Checkout",
duration: "12s",
status: "completed",
description: "Successfully fetched latest changes from the main branch.",
user: {
name: "Alex Johnson",
avatar:
"https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=96&h=96&dpr=2&q=80",
},
},
{
id: 2,
title: "Dependency Installation",
duration: "1m 45s",
status: "completed",
description: "All npm packages installed and cached for future builds.",
user: {
name: "Sarah Chen",
avatar:
"https://images.unsplash.com/photo-1519699047748-de8e457a634e?w=96&h=96&dpr=2&q=80",
},
},
{
id: 3,
title: "Unit & Integration Tests",
duration: "Running",
status: "active",
description: "Running 142 test suites across the entire codebase...",
user: {
name: "Michael Rodriguez",
avatar:
"https://images.unsplash.com/photo-1584308972272-9e4e7685e80f?w=96&h=96&dpr=2&q=80",
},
},
{
id: 4,
title: "Production Build",
duration: "Pending",
status: "pending",
description: "Optimizing assets and generating static site pages.",
user: {
name: "Emma Wilson",
avatar:
"https://images.unsplash.com/photo-1485893086445-ed75865251e0?w=96&h=96&dpr=2&q=80",
},
},
]
function StatusIcon({ status }: { status: string }) {
if (status === "completed")
return (
<CheckIcon className="size-3.5" />
)
if (status === "active") return <Spinner className="size-3.5" />
return (
<CircleIcon className="size-3.5" />
)
}
function StatusBadge({
status,
duration,
}: {
status: string
duration: string
}) {
const variant =
status === "completed"
? "success-light"
: status === "active"
? "info-light"
: "warning-light"
return (
<Badge variant={variant} size="sm">
{duration}
</Badge>
)
}
export function Pattern() {
return (
<div className="w-full max-w-lg">
<Timeline defaultValue={3}>
{pipelineSteps.map((step) => (
<TimelineItem key={step.id} step={step.id} className="ms-10 pb-10">
<TimelineHeader>
<TimelineSeparator className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-7" />
<div className="flex items-center gap-2">
<TimelineTitle className="text-sm font-semibold">
{step.title}
</TimelineTitle>
<StatusBadge status={step.status} duration={step.duration} />
</div>
<TimelineIndicator
className={cn(
"bg-muted text-muted-foreground group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground flex size-6 items-center justify-center border-none group-data-[orientation=vertical]/timeline:-left-7",
step.status === "active" && "ring-primary/20 ring-2"
)}
>
<StatusIcon status={step.status} />
</TimelineIndicator>
</TimelineHeader>
<TimelineContent className="mt-2">
<Frame stacked dense spacing="sm">
<Collapsible defaultOpen className="group/collapsible">
<CollapsibleTrigger className="flex w-full">
<FrameHeader className="flex grow flex-row items-center justify-between gap-2">
<div className="flex items-center gap-2">
<Avatar className="size-5">
<AvatarImage
src={step.user.avatar}
alt={step.user.name}
/>
<AvatarFallback>
{step.user.name.charAt(0)}
</AvatarFallback>
</Avatar>
<span className="text-muted-foreground text-xs font-medium">
{step.user.name}
</span>
</div>
<ChevronRightIcon className="text-muted-foreground size-4 transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</FrameHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<FramePanel>
<p className="text-muted-foreground text-sm leading-relaxed">
{step.description}
</p>
</FramePanel>
</CollapsibleContent>
</Collapsible>
</Frame>
</TimelineContent>
</TimelineItem>
))}
</Timeline>
</div>
)
}