mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
feat(coach): evidence-based cadence suggestions with one-tap in-chat reminder
The Coach can append a ---SUGGEST-REMINDER--- sentinel to propose a measurement cadence (weight daily, the ESH/AHA 7-2-2 home-BP protocol, structured glucose). The server resolves the cadence from a closed catalog and emits an additive 'suggestion' SSE frame the chat renders as a one-tap action card; accepting it creates a MeasurementReminder with origin COACH through the same engine the Vorsorge surface uses (server-authoritative schedule, finite course window self-expires via endsOn). Non-naggy by construction: a frequency-cap cooldown, dismissal memory, a master opt-out under Coach settings, and an explicit 'I measure enough' stop path, all in the coach-prefs blob. Triple dedup at suggest, render, and create so a cadence is never double-suggested or double-created, and suggestions for a disabled module never surface. RHR/HRV stay passive -- the Coach surfaces the baseline, it never nudges to 'go measure' them. The reminder DTO now echoes origin and endsOn for the iOS client.
This commit is contained in:
1 parent
b6796eee96
commit
12f4bc24e8
29 files changed
+1538
-9
No files matched your search
@@ -296,6 +296,42 @@ export function CoachPrefsSection({ isAuthenticated }: CoachPrefsSectionProps) {
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* v1.18.1 (Workstream C) — cadence-suggestion opt-out. The
|
||||
Coach offers an occasional, evidence-based reminder to
|
||||
measure a metric more regularly; this is the master switch
|
||||
for that surface. Off ⇒ no suggestion cards ever surface. */}
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="flex flex-col gap-1">
|
||||
<Label
|
||||
htmlFor="coach-prefs-reminder-suggestions"
|
||||
className="cursor-pointer text-xs font-medium"
|
||||
>
|
||||
{t("coach.settings.reminderSuggestionsLabel")}
|
||||
</Label>
|
||||
<p className="text-muted-foreground text-[11px] leading-relaxed">
|
||||
{t("coach.settings.reminderSuggestionsDescription")}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="coach-prefs-reminder-suggestions"
|
||||
data-slot="coach-prefs-reminder-suggestions"
|
||||
checked={draft.reminderSuggestions?.enabled ?? true}
|
||||
onCheckedChange={(next) =>
|
||||
setDraft((prev) => ({
|
||||
...prev,
|
||||
reminderSuggestions: {
|
||||
enabled: next,
|
||||
stopped: prev.reminderSuggestions?.stopped ?? false,
|
||||
dismissedCadences:
|
||||
prev.reminderSuggestions?.dismissedCadences ?? [],
|
||||
lastSuggestedAt:
|
||||
prev.reminderSuggestions?.lastSuggestedAt ?? null,
|
||||
},
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-4 flex justify-end pl-7">
|
||||
|
||||
Reference in new issue
Block a user