diff --git a/messages/de.json b/messages/de.json index 46d82bfcf..126aa9ae4 100644 --- a/messages/de.json +++ b/messages/de.json @@ -169,6 +169,7 @@ "admin": "Admin-Konsole", "logout": "Abmelden", "login": "Anmelden", + "about": "Über HealthLog", "notifications": "Benachrichtigungs-Center", "theme": "Darstellung", "themeSystem": "System", diff --git a/messages/en.json b/messages/en.json index be8e9b1a4..c21da9302 100644 --- a/messages/en.json +++ b/messages/en.json @@ -169,6 +169,7 @@ "admin": "Admin Console", "logout": "Sign out", "login": "Sign in", + "about": "About HealthLog", "notifications": "Notification Center", "theme": "Appearance", "themeSystem": "System", diff --git a/messages/es.json b/messages/es.json index 8bae79507..928be76ba 100644 --- a/messages/es.json +++ b/messages/es.json @@ -169,6 +169,7 @@ "admin": "Admin Console", "logout": "Sign out", "login": "Iniciar sesión", + "about": "Acerca de HealthLog", "notifications": "Centro de notificaciones", "theme": "Apariencia", "themeSystem": "Sistema", diff --git a/messages/fr.json b/messages/fr.json index 7bf6538b5..73bec294d 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -169,6 +169,7 @@ "admin": "Admin Console", "logout": "Sign out", "login": "Se connecter", + "about": "À propos de HealthLog", "notifications": "Centre de notifications", "theme": "Apparence", "themeSystem": "Système", diff --git a/messages/it.json b/messages/it.json index 76af3a469..5cbe33c1f 100644 --- a/messages/it.json +++ b/messages/it.json @@ -169,6 +169,7 @@ "admin": "Admin Console", "logout": "Sign out", "login": "Accedi", + "about": "Informazioni su HealthLog", "notifications": "Centro notifiche", "theme": "Aspetto", "themeSystem": "Sistema", diff --git a/messages/pl.json b/messages/pl.json index f5f5b4cdc..1253d48d7 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -169,6 +169,7 @@ "admin": "Admin Console", "logout": "Sign out", "login": "Zaloguj się", + "about": "O HealthLog", "notifications": "Centrum powiadomień", "theme": "Wygląd", "themeSystem": "Systemowy", diff --git a/src/components/layout/sidebar-nav.tsx b/src/components/layout/sidebar-nav.tsx index 64ac1f994..9da47bdc9 100644 --- a/src/components/layout/sidebar-nav.tsx +++ b/src/components/layout/sidebar-nav.tsx @@ -8,6 +8,7 @@ import { ChevronsLeft, ChevronsRight, Home, + Info, Lightbulb, LogOut, Monitor, @@ -143,6 +144,17 @@ function SidebarUserSection({ collapsed }: { collapsed: boolean }) { {t("nav.notifications")} + {/* v1.4.33 IW7 — "About" used to live as its own Settings + section but the three small cards inside (identity / links / + update check) collectively get read once or twice a year, so + the top-level slot has been collapsed into this dropdown. The + route stays alive at `/settings/about`. */} + + + + {t("nav.about")} + + {themeIcon} diff --git a/src/components/layout/top-bar.tsx b/src/components/layout/top-bar.tsx index 0266cac5e..82195860e 100644 --- a/src/components/layout/top-bar.tsx +++ b/src/components/layout/top-bar.tsx @@ -3,6 +3,7 @@ import { Bell, ChevronDown, + Info, LogIn, LogOut, Monitor, @@ -82,6 +83,15 @@ export function TopBar() { {t("nav.notifications")} + {/* v1.4.33 IW7 — "About" folded out of Settings into the + user-card dropdown; mobile dropdown mirrors the + desktop sidebar so the entry shows up here too. */} + + + + {t("nav.about")} + + {themeIcon} diff --git a/src/components/settings/__tests__/settings-shell.test.tsx b/src/components/settings/__tests__/settings-shell.test.tsx index 74bb76f67..66385f056 100644 --- a/src/components/settings/__tests__/settings-shell.test.tsx +++ b/src/components/settings/__tests__/settings-shell.test.tsx @@ -80,9 +80,16 @@ describe("SETTINGS_SECTION_SLUGS", () => { }); describe("", () => { - it("renders every section link — once for the mobile strip and once for the desktop sidebar", () => { + it("renders every navigable section link — once for the mobile strip and once for the desktop sidebar", () => { const html = renderShell({ active: "account" }); - for (const slug of SETTINGS_SECTION_SLUGS) { + // v1.4.33 IW7 — the `about` slug is alive as a route + // (`/settings/about` still resolves and `generateStaticParams()` + // still emits the page) but it is hidden from the in-shell nav. + // The user-card dropdown owns the link now. Iterate the visible + // sections list, not the slug list, when asserting on rendered + // markup. + const navigableSlugs = SETTINGS_SECTIONS.map((section) => section.slug); + for (const slug of navigableSlugs) { const matches = html.match(new RegExp(`href="/settings/${slug}"`, "g")); // Two renders — mobile strip + desktop sidebar — guarantee the link // exists in both layouts. Tablet/desktop hide the strip with `md:`, @@ -90,6 +97,8 @@ describe("", () => { // before media queries resolve. expect(matches?.length ?? 0).toBe(2); } + // The hidden `about` slug must NOT appear in the in-shell nav. + expect(html).not.toContain('href="/settings/about"'); }); it("links use the correct `/settings/` href — regression guard against typos", () => { @@ -149,7 +158,10 @@ describe("", () => { // entry in the sidebar; the link must be present in both locales. expect(html).toContain('href="/settings/export"'); expect(html).toContain("Advanced"); - expect(html).toContain("About"); + // v1.4.33 IW7 — About is no longer in the settings nav; it lives + // in the sidebar user-card dropdown. Route `/settings/about` is + // still alive for direct links. + expect(html).not.toContain('href="/settings/about"'); }); it("resolves every section title via the i18n provider — German", () => { @@ -172,7 +184,9 @@ describe("", () => { // API & Tokens is identical in both locales (proper noun + ampersand) expect(html).toContain("API & Tokens"); expect(html).toContain("Erweitert"); - expect(html).toContain("Über"); + // v1.4.33 IW7 — "Über" (About) section removed from the in-shell + // nav, folded into the sidebar user-card dropdown ("Über HealthLog"). + expect(html).not.toContain('href="/settings/about"'); }); it("does NOT surface the raw key when a translation resolves — guards against missing JSON entries", () => { diff --git a/src/components/settings/settings-shell.tsx b/src/components/settings/settings-shell.tsx index 72b964f18..5214d3397 100644 --- a/src/components/settings/settings-shell.tsx +++ b/src/components/settings/settings-shell.tsx @@ -20,7 +20,6 @@ import { usePathname } from "next/navigation"; import { Bell, Download, - Info, KeyRound, Layers, LayoutDashboard, @@ -61,9 +60,19 @@ interface SettingsSection { } /** - * Source of truth for the section list. Order matches the in-app navigation - * order so the sidebar, mobile strip, and `generateStaticParams()` all line - * up. Don't reorder without updating tests. + * Source of truth for the section list that the settings shell renders + * in its sidebar + mobile chip-strip. Order matches the in-app + * navigation order. Don't reorder without updating tests. + * + * v1.4.33 IW7 — "About" was folded into the sidebar user-card + * dropdown (sidebar-nav.tsx -> "Über HealthLog" / "About HealthLog") + * because its three small cards (identity / links / update check) + * collectively read once or twice a year and didn't earn a top-level + * settings slot. The route `/settings/about` is still alive — the + * slug stays in `SETTINGS_SECTION_SLUGS` so `generateStaticParams()` + * keeps emitting the page — but it no longer appears in the in-page + * navigation. Direct links (the user-card dropdown, the public + * `/about` permalink) continue to resolve to the same component. */ export const SETTINGS_SECTIONS: readonly SettingsSection[] = [ { slug: "account", titleKey: "settings.sections.account.title", icon: User }, @@ -104,7 +113,6 @@ export const SETTINGS_SECTIONS: readonly SettingsSection[] = [ titleKey: "settings.sections.advanced.title", icon: Settings2, }, - { slug: "about", titleKey: "settings.sections.about.title", icon: Info }, ] as const; export interface SettingsShellProps {