mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
Settings now reads as nine groups: Account, Tracking, Arrangement, Notifications, Health profile, AI, Connections, Data and System. On a phone one button names the current section and opens the grouped list, replacing the strip of every section. What moved, every old address still working: - Sessions, trusted devices and security activity sit under Security; the privacy page anchors forward there. - Notifications holds every reminder kind: the Coach nudges and the checkup reminder switches joined, and a card names the reminders set where their subject lives (dose times, cycle reminders). - Arrangement holds order and view only. Mood tags, the labs biomarker catalog and on-device text recognition, and the injection sites live on module pages under /settings/modules/<id>, linked from each Modules row and from the module's own wrench. /settings/layout/mood redirects. - The timezone saves on change in the Display card, with a one-tap offer of the device zone. - Screening hints sit beside the life circumstances they come from. - System gains Preview features with the Topics switch. Duplicates: the Coach and MCP pages show their state and link to the one switch in Modules (turning MCP off keeps tokens), the Coach overlay shows the provider and model with a link to Settings > AI instead of a second set of selects, and the privacy page drops its copy of the export links. A guard walks every historical /settings address through the redirects and every forwarded anchor to a page that renders.
117 lines
4.5 KiB
TypeScript
117 lines
4.5 KiB
TypeScript
import type { JSX } from "react";
|
|
|
|
import type { ModuleKey } from "@/lib/modules/registry";
|
|
import { surfaceModule } from "@/lib/modules/surface";
|
|
import { DashboardSection } from "./dashboard-section";
|
|
import { InsightsSection } from "./insights-section";
|
|
import { MedicationsSection } from "./medications-section";
|
|
import { LabsSection } from "./labs-section";
|
|
import { IllnessSection } from "./illness-section";
|
|
import { DocumentsSection } from "./documents-section";
|
|
import { VorsorgeSection } from "./vorsorge-section";
|
|
|
|
/**
|
|
* v1.25.11 (#148) — single source of truth for the "Layout" (slug
|
|
* `layout`) hub + its per-module subpages.
|
|
*
|
|
* "How my app looks and is arranged" was scattered across several unrelated
|
|
* settings sections. The `layout` slug is the one front door. v1.25.7 stacked
|
|
* every module's view/sort surface inline on a single page; #148 splits that
|
|
* back into a HUB → SUBPAGE model: `/settings/layout` lists the modules as
|
|
* clickable rows, and each row opens `/settings/layout/<id>`, which renders
|
|
* ONLY that module's section (the same existing section component, verbatim)
|
|
* with a "← Layout" back-link.
|
|
*
|
|
* This module is intentionally NOT `"use client"`: the client hub
|
|
* (`layout-section.tsx`) AND the server subpage route
|
|
* (`app/settings/layout/[module]/page.tsx`, which reads `LAYOUT_GROUP_IDS` in
|
|
* `generateStaticParams()`) both consume it, so its array values must stay
|
|
* usable on the server. It holds references to the `"use client"` section
|
|
* components, which a server component renders as ordinary client boundaries.
|
|
*
|
|
* v1.44 — the hub holds order and view only ("Arrangement"). The mood tag
|
|
* management, the labs biomarker catalog and text recognition, and the
|
|
* injection sites moved to the module pages under Settings > Modules
|
|
* (`module-settings-pages.tsx`); `/settings/layout/mood` redirects there.
|
|
*
|
|
* Each module section keeps its module-gate: a disabled module's row / subpage
|
|
* does not render, read from the resolved `useAuth().user.modules` map (the
|
|
* same map the nav, the Modules hub, and the Insights pills gate off). The gate
|
|
* fails OPEN (`!== false`) so a stale `/me` payload never blanks an entry.
|
|
* Vorsorge (preventive-care reminders) is not a toggleable module, so it always
|
|
* shows.
|
|
*/
|
|
export interface LayoutGroup {
|
|
/** Stable id — the subpage path segment (`/settings/layout/<id>`). */
|
|
id: string;
|
|
/** i18n key under `settings.sections.layout.<slug>.title`. */
|
|
titleKey: string;
|
|
/** i18n key under `settings.sections.layout.<slug>.description`. */
|
|
descriptionKey: string;
|
|
Body: () => JSX.Element | null;
|
|
}
|
|
|
|
/**
|
|
* The module a layout group belongs to, from the one surface map
|
|
* (`settings-layout:<id>`), or `undefined` for a group that is always shown.
|
|
* The row and its sub-page render only while that module is on (fail-open,
|
|
* `!== false`).
|
|
*/
|
|
export function layoutGroupModule(id: string): ModuleKey | undefined {
|
|
return surfaceModule(`settings-layout:${id}`);
|
|
}
|
|
|
|
export const LAYOUT_GROUPS: ReadonlyArray<LayoutGroup> = [
|
|
{
|
|
id: "dashboard",
|
|
titleKey: "settings.sections.layout.dashboard.title",
|
|
descriptionKey: "settings.sections.layout.dashboard.description",
|
|
Body: DashboardSection,
|
|
},
|
|
{
|
|
id: "insights",
|
|
titleKey: "settings.sections.layout.insights.title",
|
|
descriptionKey: "settings.sections.layout.insights.description",
|
|
Body: InsightsSection,
|
|
},
|
|
{
|
|
id: "medications",
|
|
titleKey: "settings.sections.layout.medications.title",
|
|
descriptionKey: "settings.sections.layout.medications.description",
|
|
Body: MedicationsSection,
|
|
},
|
|
{
|
|
id: "labs",
|
|
titleKey: "settings.sections.layout.labs.title",
|
|
descriptionKey: "settings.sections.layout.labs.description",
|
|
Body: LabsSection,
|
|
},
|
|
{
|
|
id: "illness",
|
|
titleKey: "settings.sections.layout.illness.title",
|
|
descriptionKey: "settings.sections.layout.illness.description",
|
|
Body: IllnessSection,
|
|
},
|
|
{
|
|
id: "documents",
|
|
titleKey: "settings.sections.layout.documents.title",
|
|
descriptionKey: "settings.sections.layout.documents.description",
|
|
Body: DocumentsSection,
|
|
},
|
|
{
|
|
id: "vorsorge",
|
|
titleKey: "settings.sections.layout.vorsorge.title",
|
|
descriptionKey: "settings.sections.layout.vorsorge.description",
|
|
Body: VorsorgeSection,
|
|
},
|
|
];
|
|
|
|
/** Ordered list of the subpage path segments — server-safe for `generateStaticParams()`. */
|
|
export const LAYOUT_GROUP_IDS: readonly string[] = LAYOUT_GROUPS.map(
|
|
(group) => group.id,
|
|
);
|
|
|
|
export function isLayoutGroupId(value: string): boolean {
|
|
return LAYOUT_GROUP_IDS.includes(value);
|
|
}
|