/** * Utility functions for the application */ import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; /** * Merge Tailwind CSS classes with clsx */ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } /** * Format a number for display with proper precision */ export function formatNumber( value: number, options: { maxDecimals?: number; minDecimals?: number; notation?: 'standard' | 'scientific' | 'engineering' | 'compact'; } = {} ): string { const { maxDecimals = 6, minDecimals = 0, notation = 'standard', } = options; // Handle edge cases if (!isFinite(value)) return value.toString(); if (value === 0) return '0'; // Use scientific notation for very large or very small numbers const absValue = Math.abs(value); const useScientific = notation === 'scientific' || (notation === 'standard' && (absValue >= 1e10 || absValue < 1e-6)); if (useScientific) { return value.toExponential(maxDecimals); } // Format with appropriate decimal places const formatted = new Intl.NumberFormat('en-US', { minimumFractionDigits: minDecimals, maximumFractionDigits: maxDecimals, notation: notation === 'compact' ? 'compact' : 'standard', }).format(value); return formatted; } /** * Debounce function for input handling */ export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout | null = null; return function executedFunction(...args: Parameters) { const later = () => { timeout = null; func(...args); }; if (timeout) clearTimeout(timeout); timeout = setTimeout(later, wait); }; } /** * Parse a number input string */ export function parseNumberInput(input: string): number | null { if (!input || input.trim() === '') return null; // Remove spaces and replace comma with dot const cleaned = input.replace(/\s/g, '').replace(',', '.'); const parsed = parseFloat(cleaned); return isNaN(parsed) ? null : parsed; } /** * Get relative time from timestamp */ export function getRelativeTime(timestamp: number): string { const now = Date.now(); const diff = now - timestamp; const seconds = Math.floor(diff / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ago`; if (hours > 0) return `${hours}h ago`; if (minutes > 0) return `${minutes}m ago`; return 'just now'; }