mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
feat(modules): direct on/off switches for the delegated Coach + Cycle rows
The Modules hub listed Coach and Cycle as read-only "manage in X" deep-links because their enabled-state is owned outside `modulePreferencesJson` (Coach in Coach settings, Cycle in the Account card). Give both a real switch like every other module, driving the SAME canonical state instead of a second copy: - Coach → `PATCH /api/auth/me/disable-coach` (`User.disableCoach`, inverted); the switch reads `!disableCoach`. - Cycle → `PATCH /api/auth/me/cycle-prefs` (`cycleTrackingEnabled`); the switch reads the resolved per-user gate. Precedence stays honest. A module the operator turned off server-wide can never be re-enabled by a per-user toggle, so the switch renders disabled with a "disabled server-wide" hint. For Coach the operator layer is BOTH the module-availability blob AND the assistant master flag (`flags.coach`); for Cycle it is the module-availability blob. Each delegated row keeps a small "manage" deep-link beside its switch, since the canonical surface carries more than on/off (Coach cadence/memory; cycle goal, predictions, lengths). Flipping either switch invalidates `authMe()` so every gated surface re-gates live; the cycle flip also evicts its own `cyclePrefs`/`cycle` reads, matching the canonical cycle card. Reuses the existing endpoints — no new route, no OpenAPI change.
This commit is contained in:
1 parent
421c407811
commit
8bc2f0f2ef
6 files changed
+337
-120
No files matched your search
@@ -79,10 +79,13 @@ export interface ModuleDefinition {
|
||||
*/
|
||||
optIn?: boolean;
|
||||
/**
|
||||
* For delegated modules only: where the real on/off control lives, so the
|
||||
* Modules hub can render a read-only "managed in X" row that deep-links to
|
||||
* the canonical control instead of a dead toggle. `href` is the in-app
|
||||
* link; `labelKey` names the destination ("Account", "Coach settings").
|
||||
* For delegated modules only: where the canonical settings surface lives.
|
||||
* The Modules hub renders a LIVE switch for these keys (driving the real
|
||||
* column — coach → `User.disableCoach`, cycle → `cycleTrackingEnabled`) and
|
||||
* keeps this as a small "manage" deep-link beside the switch, because that
|
||||
* surface carries more than on/off (Coach cadence/memory; cycle
|
||||
* goal/predictions/lengths). `href` is the in-app link; `labelKey` names the
|
||||
* destination ("Account", "Coach settings").
|
||||
*/
|
||||
managedAt?: { href: string; labelKey: string };
|
||||
}
|
||||
@@ -193,7 +196,8 @@ export const MODULE_REGISTRY: Readonly<Record<ModuleKey, ModuleDefinition>> =
|
||||
descriptionKey: "modules.cycle.description",
|
||||
category: "tracking",
|
||||
delegatesTo: "cycle",
|
||||
// The real on/off lives in the Account section's cycle-tracking card.
|
||||
// The hub switch drives `cycleTrackingEnabled`; the fuller cycle-tracking
|
||||
// card (goal, predictions, cycle lengths) lives in the Account section.
|
||||
managedAt: {
|
||||
href: "/settings/account#cycle-tracking",
|
||||
labelKey: "settings.sections.account.title",
|
||||
@@ -253,7 +257,8 @@ export const MODULE_REGISTRY: Readonly<Record<ModuleKey, ModuleDefinition>> =
|
||||
descriptionKey: "modules.coach.description",
|
||||
category: "intelligence",
|
||||
delegatesTo: "coach",
|
||||
// The real on/off lives in the dedicated Coach settings section.
|
||||
// The hub switch drives `User.disableCoach`; the dedicated Coach settings
|
||||
// section carries the rest (cadence, memory, activation copy).
|
||||
managedAt: {
|
||||
href: "/settings/coach",
|
||||
labelKey: "settings.sections.coach.title",
|
||||
|
||||
Reference in new issue
Block a user