From 4a48cde0a0e175404ca9333bcc7efcfa6c5f6ee6 Mon Sep 17 00:00:00 2001 From: Takanori Nishida Date: Wed, 5 Aug 2026 14:18:00 +0000 Subject: [PATCH] fix(pulse): fmtHero renders negative amounts as unabridged digits fmtHero()'s magnitude thresholds (>= 1_000_000, >= 10_000, >= 1_000) are checked against the signed value, so any negative number fails every branch and falls through to the last one, which was written assuming n was already known-small. Net (Overall tab) commonly goes negative when spending exceeds income, so a K/M-abbreviated sibling KPI like "$2.1M" ends up next to "$-2,120,000" instead of "-$2.1M". Threshold on Math.abs(n) instead and prepend the sign once, before the currency symbol. Positive inputs are byte-identical (sign is the empty string); this only changes output for values that were already rendering as long unformatted digit strings. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01NVzLJHrJPj5Phmh1vaLUBV --- .../Observability/src/app/finances/page.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/LifeOS/install/LIFEOS/PULSE/Observability/src/app/finances/page.tsx b/LifeOS/install/LIFEOS/PULSE/Observability/src/app/finances/page.tsx index 3f70e0f8e2..877147b9ef 100644 --- a/LifeOS/install/LIFEOS/PULSE/Observability/src/app/finances/page.tsx +++ b/LifeOS/install/LIFEOS/PULSE/Observability/src/app/finances/page.tsx @@ -185,13 +185,20 @@ interface FinancesDataV2 { function fmtHero(dollars: number | null | undefined): string { const n = Number(dollars) || 0; - if (n >= 1_000_000) return `$${(n / 1_000_000).toFixed(1)}M`; - if (n >= 10_000) return `$${Math.round(n / 1000)}K`; - if (n >= 1_000) { - const k = n / 1000; - return k % 1 === 0 ? `$${k.toFixed(0)}K` : `$${k.toFixed(1)}K`; + // Threshold on magnitude, not the signed value — a negative net (a real, + // common case: this card renders red ink when spending exceeds income) + // otherwise misses every `>=` check above and falls through to the last + // branch's unabridged digit string (e.g. "$-2,120,000" next to a sibling + // KPI reading "$2.1M"). + const sign = n < 0 ? "-" : ""; + const abs = Math.abs(n); + if (abs >= 1_000_000) return `${sign}$${(abs / 1_000_000).toFixed(1)}M`; + if (abs >= 10_000) return `${sign}$${Math.round(abs / 1000)}K`; + if (abs >= 1_000) { + const k = abs / 1000; + return k % 1 === 0 ? `${sign}$${k.toFixed(0)}K` : `${sign}$${k.toFixed(1)}K`; } - return `$${Math.round(n).toLocaleString()}`; + return `${sign}$${Math.round(abs).toLocaleString()}`; } function fmtExact(dollars: number | null | undefined): string {