mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
fix(vorsorge): key due status on the local calendar day
This commit is contained in:
1 parent
a1f5ed625c
commit
90a9407195
2 files changed
+74
-3
No files matched your search
@@ -136,6 +136,68 @@ describe("<VorsorgeSection> loading + empty", () => {
|
||||
expect(html).not.toContain("Log value");
|
||||
});
|
||||
|
||||
it("reads a same-day due time as 'today' (calendar-day delta, not rolling 24h)", () => {
|
||||
// v1.18.9 recon — a reminder whose nextDue falls on the SAME local
|
||||
// calendar day must read "Due today" with the green status hue, even when
|
||||
// the wall-clock gap to now exceeds the 24h a rolling delta would key on.
|
||||
// Anchor the due instant to local noon today so the floored calendar-day
|
||||
// delta is 0 regardless of the hour the suite runs.
|
||||
const todayNoon = new Date();
|
||||
todayNoon.setHours(12, 0, 0, 0);
|
||||
const reminder: MeasurementReminder = {
|
||||
id: "due-today",
|
||||
label: "Blood pressure check",
|
||||
measurementType: "BLOOD_PRESSURE_SYS",
|
||||
intervalDays: 7,
|
||||
rrule: null,
|
||||
anchorDate: null,
|
||||
endsOn: null,
|
||||
origin: "VORSORGE",
|
||||
nextDueAt: todayNoon.toISOString(),
|
||||
notifyHour: 9,
|
||||
location: null,
|
||||
lastSatisfiedAt: null,
|
||||
enabled: true,
|
||||
createdAt: "2030-01-01T00:00:00.000Z",
|
||||
updatedAt: "2030-01-01T00:00:00.000Z",
|
||||
} as MeasurementReminder;
|
||||
remindersMock.mockReturnValue({ data: [reminder], isLoading: false });
|
||||
const html = render(<VorsorgeSection />);
|
||||
expect(html).toContain("Due today");
|
||||
// The status hue is the discreet success colour, never a card-bg tint.
|
||||
expect(html).toContain("text-success");
|
||||
});
|
||||
|
||||
it("reads a prior-day due time as 'overdue' once the calendar day has passed", () => {
|
||||
// A reminder whose due CALENDAR day is before today reads "Overdue", with
|
||||
// the warning hue — a rolling-24h delta would mis-bucket a yesterday-evening
|
||||
// due viewed this morning as "today".
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
yesterday.setHours(20, 0, 0, 0);
|
||||
const reminder: MeasurementReminder = {
|
||||
id: "overdue",
|
||||
label: "Annual physical",
|
||||
measurementType: null,
|
||||
intervalDays: 365,
|
||||
rrule: null,
|
||||
anchorDate: null,
|
||||
endsOn: null,
|
||||
origin: "VORSORGE",
|
||||
nextDueAt: yesterday.toISOString(),
|
||||
notifyHour: 9,
|
||||
location: null,
|
||||
lastSatisfiedAt: null,
|
||||
enabled: true,
|
||||
createdAt: "2030-01-01T00:00:00.000Z",
|
||||
updatedAt: "2030-01-01T00:00:00.000Z",
|
||||
} as MeasurementReminder;
|
||||
remindersMock.mockReturnValue({ data: [reminder], isLoading: false });
|
||||
const html = render(<VorsorgeSection />);
|
||||
expect(html).toContain("Overdue by 1 days");
|
||||
expect(html).toContain("text-warning");
|
||||
});
|
||||
|
||||
it("translates a COACH-origin label i18n key and shows the neutral badge", () => {
|
||||
const reminder: MeasurementReminder = {
|
||||
id: "c1",
|
||||
|
||||
@@ -40,6 +40,7 @@ import {
|
||||
|
||||
import { useFormatters, useTranslations } from "@/lib/i18n/context";
|
||||
import { relativeCalendarDate } from "@/lib/i18n/relative-time";
|
||||
import { startOfLocalDayInTz } from "@/lib/tz/local-day";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { applyOrder, useModuleListPrefs } from "@/lib/module-list-prefs";
|
||||
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
||||
@@ -124,9 +125,17 @@ function relativeDueKey(
|
||||
now: number,
|
||||
): { key: string; days: number } {
|
||||
if (!nextDueAt) return { key: "nextDue.none", days: 0 };
|
||||
const due = new Date(nextDueAt).getTime();
|
||||
// Compare calendar-day deltas so "today" / "in 1 day" read cleanly.
|
||||
const deltaDays = Math.round((due - now) / DAY_MS);
|
||||
const due = new Date(nextDueAt);
|
||||
if (Number.isNaN(due.getTime())) return { key: "nextDue.none", days: 0 };
|
||||
// v1.18.9 (recon) — compare CALENDAR-day deltas in the user's local zone,
|
||||
// not a rolling-24h delta. A reminder due at 09:00 viewed the same evening
|
||||
// at 20:00 must still read "heute", and one whose due calendar-day is before
|
||||
// today must read "überfällig" — a raw `(due - now) / DAY_MS` round would
|
||||
// mis-bucket both. Floor each instant to its local day start (host-local zone
|
||||
// = the browser user's zone for this client component) before differencing.
|
||||
const dueDay = startOfLocalDayInTz(due, undefined).getTime();
|
||||
const nowDay = startOfLocalDayInTz(new Date(now), undefined).getTime();
|
||||
const deltaDays = Math.round((dueDay - nowDay) / DAY_MS);
|
||||
if (deltaDays < 0) return { key: "overdueByDays", days: Math.abs(deltaDays) };
|
||||
if (deltaDays === 0) return { key: "nextDue.today", days: 0 };
|
||||
if (deltaDays === 1) return { key: "nextDue.tomorrow", days: 1 };
|
||||
|
||||
Reference in new issue
Block a user