utils.ts•2.91 kB
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function formatTimestamp(timestamp: string | Date): string {
if (!timestamp) return 'N/A'
try {
const date = new Date(timestamp)
return date.toLocaleString()
} catch {
return String(timestamp)
}
}
export function formatRelativeTime(timestamp: string | Date): string {
if (!timestamp) return 'N/A'
try {
const date = new Date(timestamp)
const now = new Date()
const diff = now.getTime() - date.getTime()
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 `${seconds}s ago`
} catch {
return String(timestamp)
}
}
export function getStatusVariant(status: string): "default" | "success" | "warning" | "destructive" {
switch (status.toLowerCase()) {
case 'completed':
case 'online':
case 'active':
return 'success'
case 'pending':
case 'in_progress':
return 'warning'
case 'failed':
case 'error':
case 'offline':
return 'destructive'
default:
return 'default'
}
}
export function debounce<T extends (...args: unknown[]) => unknown>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout
return (...args: Parameters<T>) => {
clearTimeout(timeout)
timeout = setTimeout(() => func(...args), wait)
}
}
export function throttle<T extends (...args: unknown[]) => unknown>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean
return (...args: Parameters<T>) => {
if (!inThrottle) {
func(...args)
inThrottle = true
setTimeout(() => inThrottle = false, limit)
}
}
}
export function generateId(): string {
return Math.random().toString(36).substr(2, 9)
}
export function truncateText(text: string, maxLength: number): string {
if (text.length <= maxLength) return text
return text.slice(0, maxLength - 3) + '...'
}
export function capitalizeFirst(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1)
}
export function formatBytes(bytes: number, decimals = 2): string {
if (bytes === 0) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}
export function isValidUrl(string: string): boolean {
try {
new URL(string)
return true
} catch {
return false
}
}