Files
HealthLog/src/components/settings/coach-section.tsx
T
Marc-André Bombeck 5331528076 feat(coach): surface reminders in-app and add the action card
Add a "Your reminders" panel under Settings → Coach that lists the stored
reminders, highlights the due ones, and gives the user view, confirm,
done/dismiss, and delete control over their own memory. Light the Coach
launcher dot when a reminder is due, alongside the existing nudge signal.

Add the generic confirm-card component for the suggested-action frame: a
plain-text preview with a localized per-action heading and a single confirm
tap that posts the validated params to the build endpoint.

Translate the new copy in English and German.
2026-06-27 13:38:25 +02:00

71 lines
3.2 KiB
TypeScript

"use client";
/**
* v1.18.0 (S5) — Settings → Coach.
*
* The Coach preference cards moved out of the AI / Assistant section into
* their own dedicated entry so the AI section owns only provider / model /
* BYOK configuration. This section gathers the Coach-specific surface:
*
* 1. Disable Coach — the per-user opt-out (kept first so a user who
* wants the surface gone finds it immediately).
* 2. Coach preferences — tone, verbosity, data scope (`useCoachPrefs`).
* 3. Proactive nudge — the daily-nudge opt-out + per-group frequency
* (moved here from Settings → Benachrichtigungen in
* v1.18.6: it is a Coach setting, not a generic
* notification).
* 4. Coach memory — durable-fact review + forget controls.
*
* The nav entry is module-gated on `coach`. The preference + nudge + memory
* cards keep their own content gate on `!user.disableCoach` (mirrored from the
* old AI section): hiding the Coach hides its tuning + memory controls too.
*
* The "about me" context lives in the AI section, not here — the daily
* briefing reads it too, so it is not a Coach-only setting.
*
* v1.18.6 (W9) — the visible heading + subtitle now come from the shared
* `<SettingsSectionFrame>` in the route; this body is the Coach cards only.
*/
import { DisableCoachCard } from "@/components/settings/ai/disable-coach-card";
import { CoachMemorySection } from "@/components/settings/coach-memory-section";
import { CoachRemindersSection } from "@/components/settings/coach-reminders-section";
import { CoachNudgeCard } from "@/components/settings/coach-nudge-card";
import { CoachPrefsSection } from "@/components/settings/coach-prefs-section";
import { useAuth } from "@/hooks/use-auth";
import { useMounted } from "@/hooks/use-mounted";
export function CoachSection() {
const { isAuthenticated, user } = useAuth();
// Mirror the AI section's hydration-safe gating: the auth query can
// resolve before this boundary hydrates, so gate the child props on
// `useMounted()` to keep the hydration render matching the SSR HTML.
const mounted = useMounted();
const authed = mounted && isAuthenticated;
// The preference + memory cards ride the same content gate as the rest
// of the Coach surface: when the user has hidden the Coach there is no
// assistant to tune or remember anything. (`mounted`-gated so the SSR +
// hydration renders agree.)
const coachEnabled = !mounted || !user?.disableCoach;
return (
<div className="space-y-6">
<DisableCoachCard isAuthenticated={authed} />
{coachEnabled && <CoachPrefsSection isAuthenticated={authed} />}
{/* Proactive Coach nudge — moved here from Benachrichtigungen (v1.18.6).
Keeps the `#coach-nudge` anchor so existing deep links resolve. */}
{coachEnabled && (
<div id="coach-nudge" className="scroll-mt-28">
<CoachNudgeCard isAuthenticated={isAuthenticated} />
</div>
)}
{coachEnabled && <CoachMemorySection isAuthenticated={authed} />}
{coachEnabled && <CoachRemindersSection isAuthenticated={authed} />}
</div>
);
}