feat(sprint-5/etapa-3): heatmap gradiente 4 stops + modo percentil + localStorage + fix zoom
- colors.ts: gradiente continuo verde→amarillo→naranja→rojo (interpolación N-stops genérica) - Renombra modos: relative→percentile (rank-based), absolute→minmax - Hook useHeatmapMode(): persiste selección en localStorage con clave inq-roi:heatmap-mode - HeatmapLegend: barra de 4 stops, labels P0/P50/P100 en modo percentil - HeatmapModeToggle: etiquetas "Percentil" / "Min-max" - pdf-sections.ts: leyenda PDF con 4 stops interpolados - BpmnCanvas: controles de zoom movidos a esquina inferior izquierda (evita logo bpmn.io) - Tests: 528 unitarios pasan; E2E recalibrados con vecino más cercano (distancia euclidiana) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { formatCurrency, formatPercent } from '@/lib/format'
|
||||
import { heatmapLegendBounds, HEATMAP_LOW_HEX, HEATMAP_MID_HEX, HEATMAP_HIGH_HEX } from '@/lib/colors'
|
||||
import { formatCurrency } from '@/lib/format'
|
||||
import { heatmapLegendBounds, HEATMAP_LOW_HEX, HEATMAP_MID_HEX, HEATMAP_HIGH_MID_HEX, HEATMAP_HIGH_HEX } from '@/lib/colors'
|
||||
import type { HeatmapMode } from '@/lib/colors'
|
||||
import type { ActivitySimResult } from '@/domain/types'
|
||||
|
||||
@@ -12,8 +12,10 @@ interface HeatmapLegendProps {
|
||||
export function HeatmapLegend({ perActivity, mode, currency }: HeatmapLegendProps) {
|
||||
const bounds = heatmapLegendBounds(perActivity, mode)
|
||||
|
||||
// En modo percentile los extremos son rango (0 = más barata, 100 = más cara), no costo
|
||||
// literal — el percentil no es lineal respecto al costo real.
|
||||
function formatBound(value: number): string {
|
||||
if (bounds.unit === 'percent') return formatPercent(value, value % 1 === 0 ? 0 : 1)
|
||||
if (bounds.unit === 'rank') return `P${Math.round(value)}`
|
||||
return formatCurrency(value, currency)
|
||||
}
|
||||
|
||||
@@ -21,7 +23,7 @@ export function HeatmapLegend({ perActivity, mode, currency }: HeatmapLegendProp
|
||||
<div className="flex items-center gap-3 mt-3">
|
||||
<span className="text-xs text-slate-500 shrink-0">Bajo costo</span>
|
||||
<div className="flex-1 h-3 rounded-full" style={{
|
||||
background: `linear-gradient(to right, ${HEATMAP_LOW_HEX}, ${HEATMAP_MID_HEX}, ${HEATMAP_HIGH_HEX})`
|
||||
background: `linear-gradient(to right, ${HEATMAP_LOW_HEX}, ${HEATMAP_MID_HEX}, ${HEATMAP_HIGH_MID_HEX}, ${HEATMAP_HIGH_HEX})`
|
||||
}} />
|
||||
<span className="text-xs text-slate-500 shrink-0">Alto costo</span>
|
||||
<div className="h-4 border-l border-slate-200 mx-1" />
|
||||
|
||||
Reference in New Issue
Block a user