Files
inq-roi-simulador-web/src/lib/format.ts
Marcos Benítez c738bc5489
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Sprint 4 — Etapa 7B completada.
2026-06-19 00:20:27 -03:00

80 lines
2.5 KiB
TypeScript

export function formatCurrency(amount: number, currency = 'USD'): string {
return new Intl.NumberFormat('es-PY', {
style: 'currency',
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(amount)
}
// Precisión dinámica para costo/hora de recursos: evita que valores chicos
// (ej. licencias cloud a $0.037/h) se redondeen a $0.04 perdiendo la magnitud real.
export function formatCostPerHour(value: number, currency = 'USD'): string {
const symbol = currency === 'USD' ? '$' : currency
if (value === 0) return `${symbol}0`
let decimals: number
if (value >= 100) decimals = 0
else if (value >= 10) decimals = 1
else if (value >= 1) decimals = 2
else if (value >= 0.1) decimals = 3
else decimals = 4
// parseFloat recorta ceros sobrantes: toFixed(4) de 0.037 da "0.0370", queremos "0.037"
return `${symbol}${parseFloat(value.toFixed(decimals))}`
}
export function formatNumber(n: number, decimals = 1): string {
return new Intl.NumberFormat('es-PY', {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
}).format(n)
}
export function formatPercent(n: number, decimals = 1): string {
return `${formatNumber(n, decimals)}%`
}
export function formatMinutes(minutes: number): string {
if (minutes < 60) return `${Math.round(minutes)} min`
const h = Math.floor(minutes / 60)
const m = Math.round(minutes % 60)
return m > 0 ? `${h}h ${m}min` : `${h}h`
}
export function formatPayback(months: number): string {
if (Number.isNaN(months) || !isFinite(months)) {
return 'No recupera en horizonte'
}
if (months < 0) {
return 'Sin payback (costo aumenta)'
}
if (months === 0) {
return 'Inmediato'
}
if (months < 0.1) {
return '< 1 día'
}
if (months < 1) {
return `< 1 mes (${months.toFixed(2)} meses)`
}
if (months < 12) {
return `${months.toFixed(1)} meses`
}
if (months < 24) {
const years = (months / 12).toFixed(1)
return `${months.toFixed(1)} meses (~${years} años)`
}
return `${(months / 12).toFixed(1)} años`
}
// Formato de timestamp de simulación: "13 de mayo de 2026 a las 09:45"
// Locale explícito es-PY — nunca depende del locale del browser del cliente.
export function formatSimulationTimestamp(ts: number): { date: string; time: string } {
const d = new Date(ts)
return {
date: d.toLocaleDateString('es-PY', { day: '2-digit', month: 'long', year: 'numeric' }),
time: d.toLocaleTimeString('es-PY', { hour: '2-digit', minute: '2-digit' }),
}
}