TypeScript 97.6%
SQL 1.4%
JavaScript 0.5%
1import { clsx, type ClassValue } from "clsx";2import { twMerge } from "tailwind-merge";34export function cn(...inputs: ClassValue[]): string {5 return twMerge(clsx(inputs));6}78export function timeAgo(iso: string | Date): string {9 const d = typeof iso === "string" ? new Date(iso) : iso;10 const s = Math.max(0, (Date.now() - d.getTime()) / 1000);11 if (s < 60) return "just now";12 if (s < 3600) return `${Math.floor(s / 60)}m ago`;13 if (s < 86400) return `${Math.floor(s / 3600)}h ago`;14 if (s < 7 * 86400) return `${Math.floor(s / 86400)}d ago`;15 return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });16}1718export function countdown(iso: string | null): string {19 if (!iso) return "";20 const ms = new Date(iso).getTime() - Date.now();21 if (ms <= 0) return "now";22 const h = Math.floor(ms / 3600_000);23 const m = Math.floor((ms % 3600_000) / 60_000);24 const s = Math.floor((ms % 60_000) / 1000);25 return h > 0 ? `${h}h ${String(m).padStart(2, "0")}m` : `${m}m ${String(s).padStart(2, "0")}s`;26}2728export const VOLATILITY_LABEL: Record<string, string> = { low: "Relaxed", medium: "Balanced", high: "High", extreme: "Extreme" };29export const VOLATILITY_BARS: Record<string, number> = { low: 1, medium: 2, high: 3, extreme: 4 };30