mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
fix(settings): make delegated module rows read-only managed deep-links
The Module hub rendered live switches for the delegated keys cycle and coach, but the gate resolves those from their own sources (cycle from CycleProfile, coach from the operator flag + disableCoach), so a toggle wrote an inert entry to modulePreferencesJson, snapped back, and still fired a success toast. Render delegated modules as read-only rows that deep-link to their real control, strip delegated keys from the modules PATCH schema so no inert value is stored, drop the duplicate cycle control, and surface an operator-disabled state with the previously orphaned hint string.
This commit is contained in:
1 parent
7c8d82f565
commit
91d01d154a
14 files changed
+216
-36
No files matched your search
@@ -11,17 +11,33 @@
|
||||
* `strict()` rejects unknown keys outright rather than silently dropping
|
||||
* them, so a client gets a clear error instead of a no-op.
|
||||
*
|
||||
* Delegated keys (`cycle`, `coach`) are NOT accepted here: their
|
||||
* enabled-state is owned elsewhere (the cycle gate / `disableCoach` + the
|
||||
* operator assistant flag), so a value for them would land inert in
|
||||
* `modulePreferencesJson` and mislead — the Modules hub renders them as
|
||||
* read-only "managed in X" rows that deep-link to the real control. Omitting
|
||||
* them from the schema means a stale client sending `{ coach: false }` gets
|
||||
* a clear 422 instead of a silent no-op behind a green "saved" toast.
|
||||
*
|
||||
* The shared shape is reused by the OpenAPI registry so the wire
|
||||
* contract stays single-source.
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { MODULE_KEYS } from "@/lib/modules/registry";
|
||||
import { MODULE_KEYS, moduleDelegatesTo } from "@/lib/modules/registry";
|
||||
|
||||
/** Build `{ <toggleableKey>?: boolean }` from the canonical key list. */
|
||||
/**
|
||||
* The directly-owned (non-delegated) toggleable keys — the only keys this
|
||||
* PATCH surface may write into `modulePreferencesJson`.
|
||||
*/
|
||||
const WRITABLE_MODULE_KEYS = MODULE_KEYS.filter(
|
||||
(k) => moduleDelegatesTo(k) === undefined,
|
||||
);
|
||||
|
||||
/** Build `{ <writableKey>?: boolean }` from the directly-owned key list. */
|
||||
const moduleShape = Object.fromEntries(
|
||||
MODULE_KEYS.map((k) => [k, z.boolean().optional()]),
|
||||
) as Record<(typeof MODULE_KEYS)[number], z.ZodOptional<z.ZodBoolean>>;
|
||||
WRITABLE_MODULE_KEYS.map((k) => [k, z.boolean().optional()]),
|
||||
) as Record<(typeof WRITABLE_MODULE_KEYS)[number], z.ZodOptional<z.ZodBoolean>>;
|
||||
|
||||
/**
|
||||
* Partial module-preferences PATCH body. Every key is an optional
|
||||
|
||||
Reference in new issue
Block a user