mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
feat(settings): make medications a toggleable module
Medications graduated from the always-on core set (weight / blood pressure / pulse stay core) to an opt-out module. The surface gates off the resolved module map — the left-nav entry, the dashboard medication widget, and the dedicated Medikamente settings entry hide when the account turns the module off. The medication data routes stay exempt from the gate (same data-layer reasoning as mood / labs): an importer, a sync, and the user's ability to clean up entries keep working while the surface is hidden, and re-enabling finds the schedule and intake history intact. Wire the module-route gate inventory, the dashboard widget/summary maps, the PATCH allowlist, and the nav model; regenerate the OpenAPI contract for the new module key.
This commit is contained in:
1 parent
930c4a75dd
commit
559366e308
13 files changed
+119
-28
No files matched your search
@@ -318,7 +318,7 @@ describe("normalisePrefs — fail-open coercion", () => {
|
||||
});
|
||||
|
||||
describe("registry — core domains can never be disabled", () => {
|
||||
it("the four core domains are not toggleable module keys", () => {
|
||||
it("the three core domains are not toggleable module keys", () => {
|
||||
for (const core of CORE_DOMAIN_KEYS) {
|
||||
expect(isModuleKey(core)).toBe(false);
|
||||
expect(isCoreDomain(core)).toBe(true);
|
||||
@@ -327,10 +327,11 @@ describe("registry — core domains can never be disabled", () => {
|
||||
|
||||
it("a crafted core-domain key is inert (never read as a module)", () => {
|
||||
// `weight: false` in the blob can't matter: weight is not a ModuleKey,
|
||||
// so the gate never consults it. The resolver only ever runs for the
|
||||
// 11 declared toggleable keys.
|
||||
// so the gate never consults it. The resolver only runs for the declared
|
||||
// toggleable keys. v1.18.1 (D3) — medications graduated to a toggleable
|
||||
// module, so it IS a ModuleKey now (weight / bp / pulse stay core).
|
||||
expect(isModuleKey("weight")).toBe(false);
|
||||
expect(isModuleKey("medications")).toBe(false);
|
||||
expect(isModuleKey("medications")).toBe(true);
|
||||
});
|
||||
|
||||
it("every toggleable key is a known module and not a core domain", () => {
|
||||
|
||||
@@ -103,6 +103,15 @@ export const MODULE_KEYS = [
|
||||
"achievements",
|
||||
"coach",
|
||||
"insights",
|
||||
// v1.18.1 (D3) — medications graduated from the always-on CORE set to a
|
||||
// toggleable module. Weight / blood pressure / pulse stay CORE (the
|
||||
// measurement engine is never disableable); medications is now an opt-out
|
||||
// domain so an account that does not track meds can hide the surface.
|
||||
// SURFACE-gated (nav entry, dashboard medication widget, the dedicated
|
||||
// Medikamente settings entry) — the medication data-layer routes stay
|
||||
// exempt like mood/labs so an importer / sync / cleanup keeps working and
|
||||
// re-enabling finds the rows intact.
|
||||
"medications",
|
||||
"doctorReport",
|
||||
] as const;
|
||||
|
||||
@@ -119,7 +128,6 @@ export const CORE_DOMAIN_KEYS = [
|
||||
"weight",
|
||||
"bloodPressure",
|
||||
"pulse",
|
||||
"medications",
|
||||
] as const;
|
||||
|
||||
export type CoreDomainKey = (typeof CORE_DOMAIN_KEYS)[number];
|
||||
@@ -232,6 +240,12 @@ export const MODULE_REGISTRY: Readonly<Record<ModuleKey, ModuleDefinition>> =
|
||||
descriptionKey: "modules.insights.description",
|
||||
category: "intelligence",
|
||||
},
|
||||
medications: {
|
||||
key: "medications",
|
||||
labelKey: "modules.medications.label",
|
||||
descriptionKey: "modules.medications.description",
|
||||
category: "tracking",
|
||||
},
|
||||
doctorReport: {
|
||||
key: "doctorReport",
|
||||
labelKey: "modules.doctorReport.label",
|
||||
|
||||
Reference in new issue
Block a user