feat: MVP Fase 0 — Process Cost Platform v0.1.0

Plataforma completa de análisis de costos operativos basada en BPMN 2.0.

Funcionalidades incluidas:
- Import de archivos BPMN 2.0 por drag & drop + 3 procesos de ejemplo
- Visualización read-only del diagrama (bpmn-js)
- Configuración de actividades (costo, tiempo, recursos asignados)
- CRUD de recursos (rol, persona, sistema, equipo, insumo)
- Configuración global (moneda, overhead %, nombre, cliente)
- Motor de simulación determinístico agregado con propagación de gateways XOR/AND
- Reporte visual con mapa de calor en dos modos (relativo/absoluto)
- Gráficos: KPIs, top actividades, composición, costo por recurso
- Export PDF (jsPDF + html2canvas) y CSV (papaparse)
- Persistencia en IndexedDB (Dexie)
- 268 tests unitarios/integración + 6 E2E con Playwright
- Deploy: https://process-cost-platform.pages.dev

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-14 01:58:40 -03:00
commit bed161c92a
97 changed files with 19638 additions and 0 deletions

36
src/lib/format.ts Normal file
View File

@@ -0,0 +1,36 @@
export function formatCurrency(amount: number, currency = 'USD'): string {
return new Intl.NumberFormat('es-PY', {
style: 'currency',
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(amount)
}
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`
}
// 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' }),
}
}