mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Merge S3/S4 settings + sidebar nav into release/v1.19.1
S3: rename the settings nav entry label Layout to Dashboard across all six locales (route unchanged). S4: fix the main sidebar spine order to Medications, Vorsorge, Laborwerte, Krankheit, Insights, Coach, Achievements, with module gating preserved.
This commit is contained in:
commit
336c9224f4
10 files changed
+62
-49
No files matched your search
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Wähle, welche Erinnerungen du erhältst."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Layout",
|
||||
"title": "Dashboard",
|
||||
"description": "Lege fest, wie Dashboard und Insights aufgebaut und angeordnet sind.",
|
||||
"backToHub": "Zurück zu Layout & Personalisierung",
|
||||
"dashboard": {
|
||||
|
||||
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Choose which reminders you receive."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Layout",
|
||||
"title": "Dashboard",
|
||||
"description": "Arrange how the dashboard and insights are laid out.",
|
||||
"backToHub": "Back to Layout & Personalization",
|
||||
"dashboard": {
|
||||
|
||||
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Elige qué recordatorios recibes."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Diseño",
|
||||
"title": "Panel",
|
||||
"description": "Organiza cómo están dispuestos el panel y los análisis.",
|
||||
"backToHub": "Volver a Diseño y personalización",
|
||||
"dashboard": {
|
||||
|
||||
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Choisissez les rappels que vous recevez."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Disposition",
|
||||
"title": "Tableau de bord",
|
||||
"description": "Organisez la disposition du tableau de bord et des analyses.",
|
||||
"backToHub": "Retour à Disposition et personnalisation",
|
||||
"dashboard": {
|
||||
|
||||
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Scegli quali promemoria ricevere."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Layout",
|
||||
"title": "Cruscotto",
|
||||
"description": "Organizza la disposizione del cruscotto e degli approfondimenti.",
|
||||
"backToHub": "Torna a Layout e personalizzazione",
|
||||
"dashboard": {
|
||||
|
||||
+1
-1
@@ -3817,7 +3817,7 @@
|
||||
"subtitle": "Wybierz, które przypomnienia otrzymujesz."
|
||||
},
|
||||
"layout": {
|
||||
"title": "Układ",
|
||||
"title": "Pulpit",
|
||||
"description": "Ustal, jak rozłożone są pulpit i analizy.",
|
||||
"backToHub": "Powrót do Układ i personalizacja",
|
||||
"dashboard": {
|
||||
|
||||
@@ -50,9 +50,13 @@ describe("nav-model destination list", () => {
|
||||
expect(hrefs).toContain("/vorsorge");
|
||||
const vorsorge = NAV_DESTINATIONS.find((d) => d.href === "/vorsorge");
|
||||
expect(vorsorge?.tKey).toBe("nav.vorsorge");
|
||||
// Peer to Labs: sits in the clinical spine, before Insights.
|
||||
expect(hrefs.indexOf("/labs")).toBeLessThan(hrefs.indexOf("/vorsorge"));
|
||||
expect(hrefs.indexOf("/vorsorge")).toBeLessThan(hrefs.indexOf("/insights"));
|
||||
// v1.19.1 (S4) — the fixed spine is Medications → Vorsorge → Labs →
|
||||
// Illness → Insights, so Vorsorge sits after Medications and before Labs.
|
||||
expect(hrefs.indexOf("/medications")).toBeLessThan(
|
||||
hrefs.indexOf("/vorsorge"),
|
||||
);
|
||||
expect(hrefs.indexOf("/vorsorge")).toBeLessThan(hrefs.indexOf("/labs"));
|
||||
expect(hrefs.indexOf("/labs")).toBeLessThan(hrefs.indexOf("/insights"));
|
||||
});
|
||||
|
||||
it("does not list Recovery as a left-nav destination (it is an Insights pill)", () => {
|
||||
@@ -99,15 +103,17 @@ describe("nav-model utility tail (N-1 — one shared list)", () => {
|
||||
});
|
||||
|
||||
describe("visibleNavDestinations module gate", () => {
|
||||
it("includes Cycle (between Medications and Insights) only when its module is enabled", () => {
|
||||
it("includes Cycle (between Mood and Medications) only when its module is enabled", () => {
|
||||
// v1.18.0 — cycle is `requiresModule: "cycle"` and reads the delegated
|
||||
// `cycle` key from the same resolved module map every other gate uses.
|
||||
// v1.19.1 (S4) — cycle sits in the head block, after Mood and before the
|
||||
// fixed Medications → … → Achievements spine.
|
||||
const off = visibleNavDestinations({ cycle: false }).map((d) => d.href);
|
||||
const on = visibleNavDestinations({ cycle: true }).map((d) => d.href);
|
||||
expect(off).not.toContain("/cycle");
|
||||
expect(on).toContain("/cycle");
|
||||
expect(on.indexOf("/medications")).toBeLessThan(on.indexOf("/cycle"));
|
||||
expect(on.indexOf("/cycle")).toBeLessThan(on.indexOf("/insights"));
|
||||
expect(on.indexOf("/mood")).toBeLessThan(on.indexOf("/cycle"));
|
||||
expect(on.indexOf("/cycle")).toBeLessThan(on.indexOf("/medications"));
|
||||
});
|
||||
|
||||
it("drops a module-gated entry (mood / labs / coach / achievements / insights / medications) when its module is disabled", () => {
|
||||
|
||||
@@ -109,17 +109,18 @@ describe("<SidebarNav> cycle entry gate (v1.15.0 / v1.18.0 module map)", () => {
|
||||
expect(html).not.toContain('href="/cycle"');
|
||||
});
|
||||
|
||||
it("places the Cycle entry between Medications and Insights when enabled", () => {
|
||||
it("places the Cycle entry between Mood and Medications when enabled", () => {
|
||||
const html = render({ modules: { cycle: true } });
|
||||
const med = html.indexOf('href="/medications"');
|
||||
const mood = html.indexOf('href="/mood"');
|
||||
const cycle = html.indexOf('href="/cycle"');
|
||||
const insights = html.indexOf('href="/insights"');
|
||||
expect(med).toBeGreaterThan(-1);
|
||||
const med = html.indexOf('href="/medications"');
|
||||
expect(mood).toBeGreaterThan(-1);
|
||||
expect(cycle).toBeGreaterThan(-1);
|
||||
expect(insights).toBeGreaterThan(-1);
|
||||
// Cycle sits after Medications and before Insights in document order.
|
||||
expect(med).toBeLessThan(cycle);
|
||||
expect(cycle).toBeLessThan(insights);
|
||||
expect(med).toBeGreaterThan(-1);
|
||||
// v1.19.1 (S4) — Cycle sits after Mood and before Medications in document
|
||||
// order; Medications opens the fixed clinical/insight spine below it.
|
||||
expect(mood).toBeLessThan(cycle);
|
||||
expect(cycle).toBeLessThan(med);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ export interface NavDestination {
|
||||
* (after Medications) and is filtered out when the account gate is off;
|
||||
* the order is otherwise identical for both surfaces.
|
||||
*/
|
||||
// v1.19.1 (S4) — the clinical/insight spine below the dashboard/measurements/
|
||||
// mood/cycle head follows one fixed sequence, each entry directly below the
|
||||
// previous: Medications → Vorsorge → Labs → Illness → Insights → Coach →
|
||||
// Achievements. A disabled module simply drops out; the rest keep this order.
|
||||
export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
|
||||
{ href: "/", tKey: "nav.dashboard", icon: Home, tourId: "nav-dashboard" },
|
||||
{
|
||||
@@ -78,6 +82,13 @@ export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
|
||||
tourId: "nav-mood",
|
||||
requiresModule: "mood",
|
||||
},
|
||||
{
|
||||
href: "/cycle",
|
||||
tKey: "nav.cycle",
|
||||
icon: Droplets,
|
||||
tourId: "nav-cycle",
|
||||
requiresModule: "cycle",
|
||||
},
|
||||
{
|
||||
href: "/medications",
|
||||
tKey: "nav.medications",
|
||||
@@ -87,12 +98,23 @@ export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
|
||||
// module; the nav entry now drops when the account turns the module off.
|
||||
requiresModule: "medications",
|
||||
},
|
||||
// v1.17.1 — Vorsorge (preventive-care) gets a top-level nav home in the
|
||||
// clinical spine. It is a first-class tracking surface ("wann muss ich was
|
||||
// wo machen"), not pure configuration, so it belongs in the model both bars
|
||||
// render — not buried three taps deep under Settings → Reminders. The
|
||||
// Reminders hub still links to it; this is the direct front door.
|
||||
{
|
||||
href: "/cycle",
|
||||
tKey: "nav.cycle",
|
||||
icon: Droplets,
|
||||
tourId: "nav-cycle",
|
||||
requiresModule: "cycle",
|
||||
href: "/vorsorge",
|
||||
tKey: "nav.vorsorge",
|
||||
icon: Stethoscope,
|
||||
tourId: "nav-vorsorge",
|
||||
// v1.18.1 — deliberately NOT module-gated (no `requiresModule`). Unlike
|
||||
// labs / illness / cycle (opt-in clinical-spine verticals born off by
|
||||
// default), preventive-care reminders are a CORE surface available to
|
||||
// every account from birth: a reminder can target core vitals
|
||||
// (weight / BP / pulse) that are never behind a module toggle, and a
|
||||
// free-text "Großes Blutbild" reminder belongs to no module at all.
|
||||
// Gating the entry would orphan reminders the user can still create.
|
||||
},
|
||||
{
|
||||
href: "/labs",
|
||||
@@ -112,25 +134,6 @@ export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
|
||||
tourId: "nav-illness",
|
||||
requiresModule: "illness",
|
||||
},
|
||||
// v1.17.1 — Vorsorge (preventive-care) gets a top-level nav home in the
|
||||
// clinical spine, peer to Labs and Recovery. It is a first-class tracking
|
||||
// surface ("wann muss ich was wo machen"), not pure configuration, so it
|
||||
// belongs in the model both bars render — not buried three taps deep under
|
||||
// Settings → Reminders. The Reminders hub still links to it; this is the
|
||||
// direct front door so the customer knows where it lives.
|
||||
{
|
||||
href: "/vorsorge",
|
||||
tKey: "nav.vorsorge",
|
||||
icon: Stethoscope,
|
||||
tourId: "nav-vorsorge",
|
||||
// v1.18.1 — deliberately NOT module-gated (no `requiresModule`). Unlike
|
||||
// labs / illness / cycle (opt-in clinical-spine verticals born off by
|
||||
// default), preventive-care reminders are a CORE surface available to
|
||||
// every account from birth: a reminder can target core vitals
|
||||
// (weight / BP / pulse) that are never behind a module toggle, and a
|
||||
// free-text "Großes Blutbild" reminder belongs to no module at all.
|
||||
// Gating the entry would orphan reminders the user can still create.
|
||||
},
|
||||
// v1.18.0 — Workouts and Recovery both left the left-nav: each already
|
||||
// surfaces as an Insights tab-strip pill (`/insights/workouts` gated on
|
||||
// a workout row, `/insights/recovery` always present), so neither is a
|
||||
|
||||
@@ -284,9 +284,11 @@ describe("<SettingsShell>", () => {
|
||||
// `/notifications` inbox now shares the "Notifications" label.
|
||||
expect(html).toContain("Notifications");
|
||||
// v1.17.1 (F-2) — the dashboard + insights arrangement editors are
|
||||
// reached through one Layout hub entry. v1.18.1 (D6) — renamed to "Layout".
|
||||
// reached through one hub entry (route stays `/settings/layout`).
|
||||
// v1.19.1 (S3) — the nav label now reads "Dashboard" to match where
|
||||
// it leads; the route is unchanged.
|
||||
expect(html).toContain('href="/settings/layout"');
|
||||
expect(html).toContain(">Layout</a>");
|
||||
expect(html).toContain(">Dashboard</a>");
|
||||
// v1.18.1 (D4) — Channels + Sources are their own left-side entries.
|
||||
expect(html).toContain('href="/settings/channels"');
|
||||
expect(html).toContain('href="/settings/sources"');
|
||||
@@ -322,10 +324,11 @@ describe("<SettingsShell>", () => {
|
||||
// compound "Benachrichtigungs-Kanäle" wrapped). The `/notifications`
|
||||
// inbox now shares the "Benachrichtigungen" label.
|
||||
expect(html).toContain("Benachrichtigungen");
|
||||
// v1.17.1 (F-2) — the arrangement editors are reached through one
|
||||
// Layout hub entry. v1.18.1 (D6) — renamed to "Layout" in every locale.
|
||||
// v1.17.1 (F-2) — the arrangement editors are reached through one hub
|
||||
// entry (route stays `/settings/layout`). v1.19.1 (S3) — the nav label
|
||||
// reads "Dashboard" in every locale to match where it leads.
|
||||
expect(html).toContain('href="/settings/layout"');
|
||||
expect(html).toContain(">Layout</a>");
|
||||
expect(html).toContain(">Dashboard</a>");
|
||||
// v1.18.1 (D4) — Channels ("Kanäle") + Sources ("Quellen-Priorität")
|
||||
// are their own left-side entries.
|
||||
expect(html).toContain('href="/settings/channels"');
|
||||
|
||||
Reference in new issue
Block a user