diff --git a/messages/de.json b/messages/de.json index 9690017a4..f0ac137eb 100644 --- a/messages/de.json +++ b/messages/de.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Hypertonie Grad 1", "hypertensionGrade2": "Hypertonie Grad 2", "hypertensionGrade3": "Hypertonie Grad 3", - "bradycardia": "Bradykardie", + "belowTypicalRange": "Unter dem typischen Bereich", "elevated": "Erhöht", - "tachycardia": "Tachykardie", + "aboveTypicalRange": "Über dem typischen Bereich", "significantlyLow": "Deutlich niedrig", "slightlyLow": "Leicht niedrig", "onTarget": "Im Zielbereich", diff --git a/messages/en.json b/messages/en.json index 024f48eb3..506d46265 100644 --- a/messages/en.json +++ b/messages/en.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Hypertension Grade 1", "hypertensionGrade2": "Hypertension Grade 2", "hypertensionGrade3": "Hypertension Grade 3", - "bradycardia": "Bradycardia", + "belowTypicalRange": "Below typical range", "elevated": "Elevated", - "tachycardia": "Tachycardia", + "aboveTypicalRange": "Above typical range", "significantlyLow": "Significantly low", "slightlyLow": "Slightly low", "onTarget": "On target", diff --git a/messages/es.json b/messages/es.json index 0c376d378..edc3a2ed5 100644 --- a/messages/es.json +++ b/messages/es.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Hipertensión grado 1", "hypertensionGrade2": "Hipertensión grado 2", "hypertensionGrade3": "Hipertensión grado 3", - "bradycardia": "Bradicardia", + "belowTypicalRange": "Por debajo del rango típico", "elevated": "Elevado", - "tachycardia": "Taquicardia", + "aboveTypicalRange": "Por encima del rango típico", "significantlyLow": "Significativamente bajo", "slightlyLow": "Ligeramente bajo", "onTarget": "En rango objetivo", diff --git a/messages/fr.json b/messages/fr.json index f2e8009e9..49c4f7b9e 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Hypertension grade 1", "hypertensionGrade2": "Hypertension grade 2", "hypertensionGrade3": "Hypertension grade 3", - "bradycardia": "Bradycardie", + "belowTypicalRange": "En dessous de la plage habituelle", "elevated": "Élevé", - "tachycardia": "Tachycardie", + "aboveTypicalRange": "Au-dessus de la plage habituelle", "significantlyLow": "Nettement bas", "slightlyLow": "Légèrement bas", "onTarget": "Dans la plage cible", diff --git a/messages/it.json b/messages/it.json index 03d0645d5..5ce77c180 100644 --- a/messages/it.json +++ b/messages/it.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Ipertensione grado 1", "hypertensionGrade2": "Ipertensione grado 2", "hypertensionGrade3": "Ipertensione grado 3", - "bradycardia": "Bradicardia", + "belowTypicalRange": "Sotto il range tipico", "elevated": "Elevato", - "tachycardia": "Tachicardia", + "aboveTypicalRange": "Sopra il range tipico", "significantlyLow": "Significativamente basso", "slightlyLow": "Lievemente basso", "onTarget": "Nel range obiettivo", diff --git a/messages/pl.json b/messages/pl.json index 63cefc5e2..1577380ca 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -6649,9 +6649,9 @@ "hypertensionGrade1": "Nadciśnienie 1 stopnia", "hypertensionGrade2": "Nadciśnienie 2 stopnia", "hypertensionGrade3": "Nadciśnienie 3 stopnia", - "bradycardia": "Bradykardia", + "belowTypicalRange": "Poniżej typowego zakresu", "elevated": "Podwyższone", - "tachycardia": "Tachykardia", + "aboveTypicalRange": "Powyżej typowego zakresu", "significantlyLow": "Znacząco niskie", "slightlyLow": "Lekko niskie", "onTarget": "W zakresie docelowym", diff --git a/src/components/targets/__tests__/target-status-pill.test.tsx b/src/components/targets/__tests__/target-status-pill.test.tsx index f1ef31eb4..f2f60a402 100644 --- a/src/components/targets/__tests__/target-status-pill.test.tsx +++ b/src/components/targets/__tests__/target-status-pill.test.tsx @@ -33,7 +33,14 @@ describe("statusGroupForCategory", () => { it("paints far-out categories red", () => { expect(statusGroupForCategory("Hypertension Grade 3")).toBe("out"); expect(statusGroupForCategory("Significantly elevated")).toBe("out"); - expect(statusGroupForCategory("Tachycardia")).toBe("out"); + }); + + it("falls back to amber for the resting-pulse bands (no clinical-verdict red)", () => { + // v1.29.6 — "Below typical range" / "Above typical range" replaced the + // diagnosis-shaped "Bradycardia" / "Tachycardia" categories and no + // longer paint the pill destructive-red. + expect(statusGroupForCategory("Below typical range")).toBe("near"); + expect(statusGroupForCategory("Above typical range")).toBe("near"); }); it("falls back to amber for caution + unmapped categories", () => { diff --git a/src/components/targets/target-status-pill.tsx b/src/components/targets/target-status-pill.tsx index d2272572d..57e05fcc9 100644 --- a/src/components/targets/target-status-pill.tsx +++ b/src/components/targets/target-status-pill.tsx @@ -51,9 +51,9 @@ const STATUS_CATEGORY_KEY: Record = { "Hypertension Grade 1": "hypertensionGrade1", "Hypertension Grade 2": "hypertensionGrade2", "Hypertension Grade 3": "hypertensionGrade3", - Bradycardia: "bradycardia", + "Below typical range": "belowTypicalRange", Elevated: "elevated", - Tachycardia: "tachycardia", + "Above typical range": "aboveTypicalRange", "Significantly low": "significantlyLow", "Slightly low": "slightlyLow", "On target": "onTarget", @@ -128,6 +128,13 @@ export function statusGroupForCategory( "Moderately active", "Essential", ]); + // Note: "Below typical range" / "Above typical range" (resting pulse, + // v1.29.6) are deliberately absent from both sets — they fall through to + // the default "near" (amber) group below, same as "Elevated" already + // does. The prior "Bradycardia" / "Tachycardia" categories painted this + // pill destructive-red, a diagnosis-shaped verdict that contradicted the + // calmer, neutral framing the interpretation layer uses for the identical + // signal (see `insight-interpretation.ts` → `RESTING_HEART_RATE`). const redCategories = new Set([ "Obesity Grade III", "Hypertension Grade 3", @@ -135,8 +142,6 @@ export function statusGroupForCategory( "Significantly low", "Far too short", "Far too long", - "Tachycardia", - "Bradycardia", "Low", "High", "Fluctuating", diff --git a/src/lib/analytics/classifications.ts b/src/lib/analytics/classifications.ts index 293a4d27d..773d20872 100644 --- a/src/lib/analytics/classifications.ts +++ b/src/lib/analytics/classifications.ts @@ -101,9 +101,25 @@ export interface PulseClassification { severity: "info" | "normal" | "warning" | "danger"; } +/** + * v1.29.6 — dropped the bare clinical-diagnosis nouns ("Bradycardia" / + * "Tachycardia"). This is the same resting-pulse signal the interpretation + * layer (`insight-interpretation.ts` → `RESTING_HEART_RATE`) already frames + * neutrally ("below the standard resting range (common in trained hearts)", + * valence *neutral*) — a trained user at 55 bpm resting must not read a + * diagnosis-shaped verdict on one surface and a calm contextual band on the + * other. Category wording now mirrors that framing (and the "typical range" + * phrasing this codebase already uses in `pulse-targets.ts`); the < 60 band + * keeps its existing non-danger "info" tone, and the > 120 band steps down + * from destructive/"danger" to warning/amber — still flagged, never a verdict. + */ export function classifyPulse(bpm: number): PulseClassification { if (bpm < 60) { - return { category: "Bradycardia", color: "var(--info)", severity: "info" }; + return { + category: "Below typical range", + color: "var(--info)", + severity: "info", + }; } if (bpm <= 100) { return { category: "Normal", color: "var(--success)", severity: "normal" }; @@ -116,9 +132,9 @@ export function classifyPulse(bpm: number): PulseClassification { }; } return { - category: "Tachycardia", - color: "var(--destructive)", - severity: "danger", + category: "Above typical range", + color: "var(--warning)", + severity: "warning", }; }