mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
fix(dashboard): paired-metric tiles drop to text-2xl so 131/85 stays visible (v1.4.49.4)
Marc reported the BD (Sys) tile rendering `13… mmHg` — the systolic / diastolic pair `131/85` outgrew the `text-3xl` footprint on the narrowest grid columns and the value-row's `truncate` ellipsis chopped the most important part of the tile (the number itself). The other tiles in the strip (weight, pulse, glucose, …) carry a single value that never threatens the column-width budget on its own, so they keep `text-3xl`. Only paired-metric tiles step down to `text-2xl`; `131/85 mmHg` at `text-2xl tabular-nums tracking-tight` is ~84 px wide vs ~140 px for the narrowest 2-column grid cell — fits with the unit and trend arrow at every viewport. `truncate` stays as a defence-in-depth safety net for outlier values. `cn()` arg ordering tightened so `tailwind-merge` keeps the explicit `leading-none`. Tailwind v4's `text-3xl` / `text-2xl` carry their own default `line-height`, and the last-wins dedup rule otherwise dropped `leading-none` and broke the W20a across-tile baseline alignment that `trend-card-baseline-alignment.test.tsx` pins. Also fixes a pre-existing date-boundary test flake: `src/app/api/medications/intake/__tests__/route.test.ts`'s `reads the rollup tier when coverage is present` computed `todayKey` from UTC components, but the route's `readMedicationCompliance` uses the user's timezone (Europe/Berlin in the test fixture). At every 22:00 — 24:00 UTC window — once the Berlin clock crossed midnight — the two computations diverged by one calendar day, the mock returned data for the wrong day, and `today.scheduled` came back zero instead of three. The test now derives `todayKey` from the same Berlin zone the route uses. Tests: 5270 unit + integration pass, lint clean, typecheck clean.
This commit is contained in:
1 parent
fe4060e84b
commit
49c9b425bb
4 files changed
+52
-6
No files matched your search
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.49.4] — 2026-05-24 — BD-tile number truncation + medication-compliance test tz drift
|
||||
|
||||
Marc reported the dashboard BD (Sys) tile rendering `"13… mmHg"` — the systolic / diastolic pair (`131/85`) was wider than the narrowest grid column and the value-row's `truncate` ellipsis chopped the most important part of the tile (the number itself).
|
||||
|
||||
### Fixed
|
||||
|
||||
- `src/components/charts/trend-card.tsx` — paired-metric tiles (BP systolic/diastolic) now render the value at `text-2xl` (one Tailwind step down from `text-3xl`). Single-value tiles (weight, pulse, glucose, …) keep `text-3xl` because their value never threatens the column-width budget on its own. The `truncate` class stays as a defence-in-depth safety net so an outlier value (e.g. `200/120 mmHg` plus a future trend caption) still clips gracefully rather than overflowing the card boundary.
|
||||
- `cn()` argument ordering tightened so `tailwind-merge` keeps the explicit `leading-none` — Tailwind v4's `text-3xl` / `text-2xl` carry their own default `line-height`, and the last-wins dedup rule would otherwise drop the explicit `leading-none` and break the W20a across-tile baseline alignment. The `<TrendCard>` baseline-alignment tests pin the contract.
|
||||
- `src/app/api/medications/intake/__tests__/route.test.ts` (one pre-existing test) computed its `todayKey` from UTC date components but the route's `readMedicationCompliance` uses the user's timezone (Europe/Berlin in the test fixture). At every nightly 22:00 — 24:00 UTC window — once the Berlin clock crossed midnight — the two computations diverged by one calendar day and the rollup-tier read returned zero for "today". The test now derives `todayKey` from the same `Europe/Berlin` zone the route uses; the assertion stays the same.
|
||||
|
||||
## [1.4.49.3] — 2026-05-23 — Full i18n call-site audit + 28 stale missing keys filled
|
||||
|
||||
Marc reported additional raw key strings (`notifications.eventMoodReminder`, `notifications.eventMoodReminderDesc`) reaching the UI after v1.4.49.2 had landed the relative-time fix. The narrow `{count}`-call audit that drove v1.4.49.2 had missed every dynamic key construction; the full exhaustive sweep below picked up 28 keys called from real code that had never existed in any locale bundle.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "healthlog",
|
||||
"version": "1.4.49.3",
|
||||
"version": "1.4.49.4",
|
||||
"description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.",
|
||||
"license": "AGPL-3.0-only",
|
||||
"homepage": "https://healthlog.dev",
|
||||
|
||||
@@ -363,12 +363,26 @@ describe("v1.4.39 W-MED — compliance rollup read swap", () => {
|
||||
// runs. The pre-fix shape hard-coded `2026-05-18`, which fell out
|
||||
// of the trailing-7-day window on every subsequent wall-clock
|
||||
// day and silently shifted the body.data tail off the seed.
|
||||
//
|
||||
// v1.4.49.4 — compute todayKey in the SAME zone the route uses
|
||||
// (`readMedicationCompliance` → `userDayKey(now, safeTz)`), not in
|
||||
// UTC. SESSION_OK carries no `timezone`, so the route falls
|
||||
// through to `DEFAULT_TIMEZONE = "Europe/Berlin"`. The pre-fix
|
||||
// UTC computation diverged from the route's Berlin computation by
|
||||
// one calendar day during the 22:00-24:00 UTC window every night,
|
||||
// causing the test to fail deterministically once the clock
|
||||
// crossed midnight Berlin while still on the previous UTC day.
|
||||
const todayKey = (() => {
|
||||
const now = new Date();
|
||||
const y = now.getUTCFullYear();
|
||||
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
|
||||
const d = String(now.getUTCDate()).padStart(2, "0");
|
||||
return `${y}-${m}-${d}`;
|
||||
const fmt = new Intl.DateTimeFormat("en-CA", {
|
||||
timeZone: "Europe/Berlin",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
});
|
||||
// `en-CA` short-date format is `YYYY-MM-DD`, matching the
|
||||
// route's `userDayKey` output (see `src/lib/tz/resolver.ts`).
|
||||
return fmt.format(now);
|
||||
})();
|
||||
vi.mocked(prisma.medicationComplianceRollup.findMany).mockResolvedValue([
|
||||
{ day: todayKey, scheduled: 3, taken: 2, skipped: 1 },
|
||||
|
||||
@@ -268,7 +268,29 @@ export function TrendCard({
|
||||
className="mt-2 flex min-w-0 items-baseline gap-x-1.5"
|
||||
data-slot="trend-card-value-row"
|
||||
>
|
||||
<span className="min-w-0 truncate text-3xl leading-none font-semibold tracking-tight tabular-nums">
|
||||
<span
|
||||
className={cn(
|
||||
"min-w-0 truncate font-semibold tracking-tight tabular-nums",
|
||||
// v1.4.49.4 — paired values (BP systolic/diastolic) render
|
||||
// as `131/85` and outgrow the `text-3xl` footprint on the
|
||||
// narrowest grid columns, ellipsis-clipping to "13…" on the
|
||||
// dashboard. The truncate stays as a defence-in-depth safety
|
||||
// net, but paired tiles drop one font step (text-3xl →
|
||||
// text-2xl) so the full pair stays visible at every column
|
||||
// width. Single-value tiles (weight, pulse, glucose, …)
|
||||
// keep text-3xl because their value never threatens the
|
||||
// budget on its own.
|
||||
secondary ? "text-2xl" : "text-3xl",
|
||||
// `leading-none` must come AFTER the font-size class in the
|
||||
// cn() arg list. Tailwind v4 `text-3xl` / `text-2xl` ship
|
||||
// their own default `line-height`, so `twMerge` would
|
||||
// otherwise drop the explicit `leading-none` per the
|
||||
// last-wins rule and break the W20a across-tile baseline
|
||||
// alignment (digits line up at the same y-coordinate
|
||||
// across every tile in the strip).
|
||||
"leading-none",
|
||||
)}
|
||||
>
|
||||
{latest !== null ? renderPair(latest, secondary?.latest) : "—"}
|
||||
</span>
|
||||
<span className="text-muted-foreground shrink-0 text-sm tabular-nums">
|
||||
|
||||
Reference in new issue
Block a user