import { useEffect, useMemo, useState } from 'react'; import { cn } from '@/lib/utils'; export type EventStatus = 'soon' | 'upcoming' | 'live' | 'ended'; interface CountdownInfo { status: EventStatus; label: string; } function computeStatus(start: number, end?: number): CountdownInfo { const now = Date.now() / 1000; const effectiveEnd = end ?? start + 3 * 3600; // assume ~3h if no end if (now >= start && now < effectiveEnd) { return { status: 'live', label: 'Happening now' }; } if (now >= effectiveEnd) { return { status: 'ended', label: 'Ended' }; } const diff = start - now; const days = Math.floor(diff / 86400); const hours = Math.floor((diff % 86400) / 3600); const mins = Math.floor((diff % 3600) / 60); if (days >= 1) { return { status: days <= 3 ? 'soon' : 'upcoming', label: days === 1 ? 'Tomorrow' : `In ${days} days` }; } if (hours >= 1) { return { status: 'soon', label: `In ${hours}h ${mins}m` }; } if (mins >= 1) { return { status: 'soon', label: `In ${mins} min` }; } return { status: 'soon', label: 'Starting now' }; } /** * Live status pill for an event — the single most valuable at-a-glance signal: * "IN 3 DAYS" / "IN 2H 14M" / "🔴 HAPPENING NOW" / "ENDED". Ticks every 30s. */ export function EventCountdown({ start, end, className, }: { start: number; end?: number; className?: string; }) { const [tick, forceTick] = useState(0); // Re-render periodically so the countdown stays fresh without a heavy timer. useEffect(() => { const id = setInterval(() => forceTick((n) => n + 1), 30_000); return () => clearInterval(id); }, []); // `tick` is a dependency so the label actually recomputes on each interval. const info = useMemo(() => computeStatus(start, end), [start, end, tick]); const styles: Record = { live: 'bg-[#ff0040] text-white border-[#ff0040] animate-pulse', soon: 'bg-[#ccff00] text-black border-[#ccff00]', upcoming: 'bg-white/10 text-white border-white/20', ended: 'bg-white/5 text-gray-400 border-white/10', }; return ( {info.status === 'live' && ( )} {info.label} ); } /** Standalone helper to get just the status (for conditional styling). */ export function useEventStatus(start: number, end?: number): EventStatus { const [tick, forceTick] = useState(0); useEffect(() => { const id = setInterval(() => forceTick((n) => n + 1), 30_000); return () => clearInterval(id); }, []); return useMemo(() => computeStatus(start, end).status, [start, end, tick]); }