From 67d88de3d528c21449517ed45b67916b5e6b5e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 1 Oct 2026 09:34:13 +0200 Subject: [PATCH] fix(glp1): file timeline side effects under the mood entry's own day The timeline grouped side effects by the UTC day of moodLoggedAt, so an evening entry west of UTC (or a morning one east of it) showed on the neighbouring day. The entry's stored date is already the writer's local day; group by that. --- .../glp1-timeline/__tests__/route.test.ts | 15 +++++++++++++++ src/app/api/insights/glp1-timeline/route.ts | 7 +++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/app/api/insights/glp1-timeline/__tests__/route.test.ts b/src/app/api/insights/glp1-timeline/__tests__/route.test.ts index 966d55e94..eeeee3c4b 100644 --- a/src/app/api/insights/glp1-timeline/__tests__/route.test.ts +++ b/src/app/api/insights/glp1-timeline/__tests__/route.test.ts @@ -54,6 +54,7 @@ function medication() { function moodDay(day: number, tags: string[]) { return { + date: `2026-04-${String(day).padStart(2, "0")}`, moodLoggedAt: new Date(Date.UTC(2026, 3, day, 9, 0, 0)), tags: JSON.stringify(tags), }; @@ -99,6 +100,20 @@ describe("GET /api/insights/glp1-timeline side-effect days", () => { ]); }); + it("files a side effect under the entry's own day, not its UTC day", async () => { + // Logged 2026-04-10 at 20:00 in Los Angeles: already the 11th in UTC. + const out = await timeline([ + { + date: "2026-04-10", + moodLoggedAt: new Date("2026-04-11T03:00:00.000Z"), + tags: JSON.stringify(["nausea"]), + }, + ]); + expect(out.entries).toEqual([ + { date: "2026-04-10T12:00:00Z", kind: "side-effect", tags: ["nausea"] }, + ]); + }); + it("recognises the chip label of every shipped locale", async () => { const out = await timeline([ moodDay(10, ["Übelkeit"]), diff --git a/src/app/api/insights/glp1-timeline/route.ts b/src/app/api/insights/glp1-timeline/route.ts index 513cb76ef..67af7ff9c 100644 --- a/src/app/api/insights/glp1-timeline/route.ts +++ b/src/app/api/insights/glp1-timeline/route.ts @@ -80,7 +80,7 @@ export const GET = apiHandler(async (request: NextRequest) => { deletedAt: null, moodLoggedAt: { gte: ninetyDaysAgo }, }, - select: { moodLoggedAt: true, tags: true }, + select: { date: true, tags: true }, orderBy: { moodLoggedAt: "desc" }, }); @@ -140,7 +140,10 @@ export const GET = apiHandler(async (request: NextRequest) => { const { matched, unresolvedCount } = matchGlp1SideEffectTags(mood.tags); unresolvedTagCount += unresolvedCount; if (matched.length === 0) continue; - const dayKey = mood.moodLoggedAt.toISOString().slice(0, 10); + // `date` is the day the entry belongs to in the writer's zone. The UTC + // day of `moodLoggedAt` moved an evening entry west of UTC (a morning + // one east of it) onto the neighbouring day. + const dayKey = mood.date; const existing = sideEffectByDay.get(dayKey) ?? []; for (const t of matched) { if (!existing.includes(t)) existing.push(t);