46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { clsx, type ClassValue } from "clsx"
|
|
import { twMerge } from "tailwind-merge"
|
|
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return twMerge(clsx(inputs))
|
|
}
|
|
|
|
export function formatUptime(seconds: number): string {
|
|
const h = Math.floor(seconds / 3600)
|
|
const m = Math.floor((seconds % 3600) / 60)
|
|
if (h === 0) return `${m}m`
|
|
return `${h}h ${m}m`
|
|
}
|
|
|
|
export function formatMins(mins: number | null): string {
|
|
if (mins === null) return '—'
|
|
if (mins < 1) return '<1m'
|
|
const d = Math.floor(mins / 1440)
|
|
const h = Math.floor((mins % 1440) / 60)
|
|
const m = Math.floor(mins % 60)
|
|
const parts: string[] = []
|
|
if (d) parts.push(`${d}d`)
|
|
if (h) parts.push(`${h}h`)
|
|
parts.push(`${m}m`)
|
|
return parts.join(' ')
|
|
}
|
|
|
|
export function formatPrice(price: number | null, currency: string, priceUsd: number | null): string {
|
|
if (price === null) return '—'
|
|
const sym: Record<string, string> = {
|
|
USD: '$', GBP: '£', EUR: '€', JPY: '¥', CAD: 'CA$', AUD: 'A$',
|
|
}
|
|
const s = sym[currency] ?? currency + ' '
|
|
return `${s}${price % 1 === 0 ? price.toLocaleString() : price.toFixed(2)}`
|
|
}
|
|
|
|
export function timeAgo(isoString: string | null): string {
|
|
if (!isoString) return 'never'
|
|
const diff = Math.floor((Date.now() - new Date(isoString).getTime()) / 1000)
|
|
if (diff < 10) return 'just now'
|
|
if (diff < 60) return `${diff}s ago`
|
|
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`
|
|
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`
|
|
return `${Math.floor(diff / 86400)}d ago`
|
|
}
|