mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
feat(medications): cadence-aware dose-state windows + miss-counting engine
Thread the auto_missed flag through the cadence timeline so a forgotten dose pairs to a missed slot (against the rate) rather than a neutral skip; a deliberate user skip stays excluded. This unifies the skip semantics across every compliance surface: user skip = excluded, forgotten = missed. Add a per-dose grace/miss window model the card will render: deriveDoseStatus derives on_time_window / overdue / missed / taken_on_time / taken_late / skipped / upcoming from the target instant, cadence family, and now. Daily/intraday uses minute-scale windows (on-time +/-60min, overdue to +240min, capped at the next dose); weekly/rolling uses the clinical 4-day rule (on-time +/-1 day, overdue to +4 days). Defaults are centralised named constants for later per-medication configurability. Surface taken / expected / missed counts on each compliance-display row so the card can show the trustworthy 'taken / expected . rate%' triple, and pin a single now through the per-medication compliance route so the two windows can't straddle a day boundary on a slow request.
This commit is contained in:
1 parent
29fa982e11
commit
cb239c2803
4 files changed
+489
-12
No files matched your search
@@ -113,6 +113,9 @@ export const GET = apiHandler(
|
||||
takenAt: e.takenAt,
|
||||
skipped: e.skipped,
|
||||
scheduledFor: e.scheduledFor,
|
||||
// v1.15.9 — a forgotten dose the auto-miss cron flipped counts as a
|
||||
// miss, not a neutral skip.
|
||||
autoMissed: e.autoMissed,
|
||||
}));
|
||||
|
||||
const createdAt = medication.createdAt;
|
||||
@@ -131,7 +134,14 @@ export const GET = apiHandler(
|
||||
userTz,
|
||||
);
|
||||
|
||||
// v1.15.9 — pin a single `now` and thread it into every cadence
|
||||
// computation. The two `calculateCompliance` calls + the display windows
|
||||
// can otherwise straddle a day boundary on a slow request, so a dose
|
||||
// would count in one window and not the next within the same response.
|
||||
const now = new Date();
|
||||
|
||||
const compliance7 = calculateCompliance(mapped, medication.schedules, 7, createdAt, {
|
||||
now,
|
||||
medicationContext,
|
||||
});
|
||||
const compliance30 = calculateCompliance(
|
||||
@@ -139,7 +149,7 @@ export const GET = apiHandler(
|
||||
medication.schedules,
|
||||
30,
|
||||
createdAt,
|
||||
{ medicationContext },
|
||||
{ now, medicationContext },
|
||||
);
|
||||
|
||||
// v1.8.6 — the two-row compliance display. The card always shows two
|
||||
@@ -152,10 +162,10 @@ export const GET = apiHandler(
|
||||
mapped,
|
||||
medication.schedules,
|
||||
medicationContext,
|
||||
{ now },
|
||||
);
|
||||
|
||||
// Build daily compliance map for heatmap/line chart (90 days)
|
||||
const now = new Date();
|
||||
const dailyCompliance: Record<string, DailyComplianceEntry> = {};
|
||||
|
||||
for (let d = 0; d < 90; d++) {
|
||||
|
||||
Reference in new issue
Block a user