fix(sleep,mood): pick the richest writer per night and show the whole note

Sleep nights collapse per writer instead of per source: several
HealthKit apps land behind the same source value, so a phone's coarse
awake and in-bed blocks could blend into or fully constitute a night
whose stages another writer had recorded. The winning writer per
session is the one with the most distinct granular stages, then the
user's source ladder, and its rows are kept whole. The device type is
threaded through every sleep read including the stage stacked bar, and
the sync overlap for late-arriving nights widens from one day to seven
so a night scored after the cursor passed is fetched on the next tick —
assembly is read-time, so affected nights heal without manual repair.
Mood notes expand to their full text in the list on desktop and touch,
replacing the hover-only tooltip, and the mood CSV export carries a
note column.
This commit is contained in:
Marc-André Bombeck committed 2026-06-11 21:52:52 +02:00
1 parent a664395021
commit 657f2323a3
18 files changed
+548 -86

No files matched your search

+1
View File
@@ -489,6 +489,7 @@ async function computeSleepStageBreakdown(
measuredAt: true,
sleepStage: true,
source: true,
deviceType: true,
},
});
+3
View File
@@ -704,6 +704,9 @@ async function sleepListResponse(
measuredAt: true,
sleepStage: true,
source: true,
// Writer-level collapse: two HealthKit apps behind one source (watch
// stages vs phone in-bed) must not blend into one night.
deviceType: true,
},
});
+3
View File
@@ -222,6 +222,9 @@ export const GET = apiHandler(async (request: NextRequest) => {
measuredAt: true,
sleepStage: true,
source: true,
// Writer-level collapse: two HealthKit apps behind one source
// (watch stages vs phone in-bed) must not blend into one night.
deviceType: true,
},
});
unit = "h";
+3
View File
@@ -105,6 +105,9 @@ export const GET = apiHandler(async (request: NextRequest) => {
measuredAt: true,
sleepStage: true,
source: true,
// Writer-level collapse: two HealthKit apps behind one source (watch
// stages vs phone in-bed) must not blend into one night.
deviceType: true,
},
});