import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function formatDate(date: string | Date): string { return new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', }).format(new Date(date)) } export function formatNumber(num: number): string { return new Intl.NumberFormat('en-US').format(num) } export function formatCurrency(cents: number): string { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }).format(cents / 100) } export function formatBytes(bytes: number, decimals: number = 2): string { if (bytes === 0) return '0 Bytes' const k = 1024 const dm = decimals < 0 ? 0 : decimals const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] } export function getStatusColor(status: string): string { switch (status.toLowerCase()) { case 'active': return 'gt-status-active' case 'pending': return 'gt-status-pending' case 'deploying': return 'gt-status-deploying' case 'suspended': case 'terminated': case 'failed': return 'gt-status-suspended' default: return 'gt-status-pending' } } export function truncate(str: string, length: number): string { if (str.length <= length) return str return str.slice(0, length) + '...' } export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout return (...args: Parameters) => { clearTimeout(timeout) timeout = setTimeout(() => func(...args), wait) } }