"use client"; import { CheckIcon, ChevronDownIcon, CopyIcon, MapPinIcon, PackageCheckIcon, TruckIcon } from "lucide-react"; import { AnimatePresence, motion, useReducedMotion } from "motion/react"; import { useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; export interface TrackerStep { label: string; date?: string; } export interface CarrierEvent { id: string; time: string; day?: string; title: string; location?: string; } export interface OrderTrackerProps { orderId: string; carrier: string; trackingNumber?: string; steps: TrackerStep[]; current: number; eta: { title: string; detail?: string }; delivered?: { title: string; detail?: string }; events: CarrierEvent[]; visibleEvents?: number; className?: string; } export function OrderTracker({ orderId, carrier, trackingNumber, steps, current, eta, delivered, events, visibleEvents = 3, className, }: OrderTrackerProps) { const reduce = useReducedMotion(); const [expanded, setExpanded] = useState(false); const [copied, setCopied] = useState(false); const [celebrate, setCelebrate] = useState(0); const last = steps.length - 1; const isDelivered = current >= last; const prev = useRef(current); const copyTimer = useRef(undefined); useEffect(() => { if (current >= last && prev.current < last) setCelebrate((n) => n + 1); prev.current = current; }, [current, last]); useEffect(() => () => clearTimeout(copyTimer.current), []); const copy = async () => { if (!trackingNumber) return; try { await navigator.clipboard.writeText(trackingNumber); } catch {} setCopied(true); clearTimeout(copyTimer.current); copyTimer.current = window.setTimeout(() => setCopied(false), 1400); }; const ease = [0.23, 1, 0.32, 1] as const; const head = isDelivered && delivered ? delivered : eta; const shown = expanded ? events : events.slice(0, visibleEvents); const progress = Math.min(1, current / Math.max(1, last)); return (

Order {orderId}

{carrier} {trackingNumber && ( <> {" ยท "} {trackingNumber} )}

{trackingNumber && ( )}
{isDelivered ? : }

{head.title}

{head.detail &&

{head.detail}

}
    {steps.map((s, i) => { const done = i < current || isDelivered; const active = i === current && !isDelivered; return (
  1. {active && ( )} {done ? ( ) : active ? ( ) : null} {i === last && 0 && !reduce} />} {s.label} {s.date && {s.date}}
  2. ); })}

Updates from {carrier}

    {shown.map((e, i) => (
    {i < shown.length - 1 && }

    {e.title}

    {e.location && (

    {e.location}

    )}
    {e.day && {e.day}} {e.time}
    ))}
{events.length > visibleEvents && ( )}
); } function Burst({ run }: { run: boolean }) { if (!run) return null; const dots = Array.from({ length: 10 }, (_, i) => { const angle = (i / 10) * Math.PI * 2 + 0.3; const dist = 16 + (i % 3) * 5; return { x: Math.cos(angle) * dist, y: Math.sin(angle) * dist, tone: ["bg-success", "bg-amber-400", "bg-info", "bg-rose-400"][i % 4] }; }); return ( {dots.map((d, i) => ( ))} ); }