mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
feat(medications): thread timeZone into cadence + compliance helpers
The W19e pure cadence + compliance helpers used `Date.setHours`, `getDay`, and `setHours(0, 0, 0, 0)` for every local-day boundary, window-time application, and streak day-key. Those methods read the host process's system time — every medication detail page on the cadence route returned values relative to whatever zone the server ran in (Europe/Berlin in prod, often UTC in CI), not the user's. A Tokyo user reading the same data saw their 08:00 window land at 16:00 wall-clock and the day-of-week filter ran off the Berlin weekday. Thread an optional IANA `timeZone` argument through `expandScheduleSlots`, `pairDoses`, `buildCadenceTimeline`, `computeNextDose`, `missedDoses`, and `complianceChips`. Every local operation now resolves through `Intl.DateTimeFormat`. When the argument is omitted the helpers fall back to system-local — every existing unit test (system-local by construction) keeps its assertions green. The cadence route resolves the user's zone via `resolveUserTimezone(user.id)` and forwards. Regression tests pin the 08:00 wall-clock contract across Berlin / Tokyo / Los Angeles and check that a "Mondays only" schedule lands on each zone's local Monday. Fix-O / code-H2.
This commit is contained in:
1 parent
701fd5f251
commit
2a65f2b179
5 files changed
+361
-50
No files matched your search
@@ -26,6 +26,7 @@ import {
|
||||
computeNextDose,
|
||||
} from "@/lib/medications/scheduling/cadence";
|
||||
import { complianceChips } from "@/lib/medications/scheduling/compliance";
|
||||
import { resolveUserTimezone } from "@/lib/tz/resolver";
|
||||
|
||||
type RouteParams = { params: Promise<{ id: string }> };
|
||||
|
||||
@@ -76,12 +77,21 @@ export const GET = apiHandler(
|
||||
// chart disagree on the bi-weekly grid.
|
||||
const anchor = med.createdAt;
|
||||
|
||||
// v1.4.25 W21 Fix-O — resolve the user's IANA zone so the cadence
|
||||
// helpers compute every local-day boundary, window-time application,
|
||||
// and streak day-key in the user's clock instead of the host's
|
||||
// system time. A Tokyo user reading the same medication gets the
|
||||
// same chip values as a Berlin user — the host-relative day flip
|
||||
// was a sneaky bug at the 08:00-Berlin / 16:00-Tokyo intersection.
|
||||
const userTz = await resolveUserTimezone(user.id);
|
||||
|
||||
const timeline = buildCadenceTimeline(
|
||||
med.schedules,
|
||||
events,
|
||||
asOf,
|
||||
windowDays,
|
||||
anchor,
|
||||
userTz,
|
||||
);
|
||||
const chips = complianceChips(
|
||||
med.schedules,
|
||||
@@ -89,8 +99,9 @@ export const GET = apiHandler(
|
||||
asOf,
|
||||
windowDays,
|
||||
anchor,
|
||||
userTz,
|
||||
);
|
||||
const next = computeNextDose(med.schedules, asOf, 14, anchor);
|
||||
const next = computeNextDose(med.schedules, asOf, 14, anchor, userTz);
|
||||
|
||||
annotate({
|
||||
action: {
|
||||
|
||||
Reference in new issue
Block a user