diff --git a/messages/de.json b/messages/de.json
index 395fc13e3..f56ff12c3 100644
--- a/messages/de.json
+++ b/messages/de.json
@@ -4121,6 +4121,10 @@
"note": "Kernbereich — immer aktiv"
},
"description": "Lege fest, was HealthLog für dich erfasst. Schalte einzelne Bereiche ein oder aus — die Navigation, Kacheln und Auswertungen passen sich sofort an."
+ },
+ "gesundheitsakte": {
+ "title": "Gesundheitsakte",
+ "description": "Vollständige Gesundheitsakte als PDF, FHIR R4 oder kombiniertes ZIP-Paket exportieren."
}
},
"profile": "Profil",
diff --git a/messages/en.json b/messages/en.json
index 61f6d3588..6e6ad8c2e 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -4121,6 +4121,10 @@
"note": "Core area — always on"
},
"description": "Choose what HealthLog tracks for you. Turn individual areas on or off — the navigation, tiles, and insights adapt right away."
+ },
+ "gesundheitsakte": {
+ "title": "Health record",
+ "description": "Export your full health record as PDF, FHIR R4, or a combined ZIP package."
}
},
"profile": "Profile",
diff --git a/messages/es.json b/messages/es.json
index b9f3b6c4e..4e180cd70 100644
--- a/messages/es.json
+++ b/messages/es.json
@@ -4121,6 +4121,10 @@
"note": "Área esencial — siempre activa"
},
"description": "Elige qué registra HealthLog por ti. Activa o desactiva áreas concretas: la navegación, los paneles y los análisis se adaptan al instante."
+ },
+ "gesundheitsakte": {
+ "title": "Historial médico",
+ "description": "Exporta tu historial médico completo como PDF, FHIR R4 o un paquete ZIP combinado."
}
},
"profile": "Perfil",
diff --git a/messages/fr.json b/messages/fr.json
index 2014175bc..26773b240 100644
--- a/messages/fr.json
+++ b/messages/fr.json
@@ -4121,6 +4121,10 @@
"note": "Domaine essentiel — toujours actif"
},
"description": "Choisissez ce que HealthLog suit pour vous. Activez ou désactivez chaque domaine : la navigation, les tuiles et les analyses s'adaptent aussitôt."
+ },
+ "gesundheitsakte": {
+ "title": "Dossier médical",
+ "description": "Exportez votre dossier médical complet au format PDF, FHIR R4 ou en paquet ZIP combiné."
}
},
"profile": "Profil",
diff --git a/messages/it.json b/messages/it.json
index 9c9d306b4..1ea49f7cc 100644
--- a/messages/it.json
+++ b/messages/it.json
@@ -4121,6 +4121,10 @@
"note": "Ambito di base — sempre attivo"
},
"description": "Scegli cosa registra HealthLog per te. Attiva o disattiva i singoli ambiti: navigazione, riquadri e analisi si adattano subito."
+ },
+ "gesundheitsakte": {
+ "title": "Cartella clinica",
+ "description": "Esporta la tua cartella clinica completa in PDF, FHIR R4 o in un pacchetto ZIP combinato."
}
},
"profile": "Profilo",
diff --git a/messages/pl.json b/messages/pl.json
index d4144723f..d9572696e 100644
--- a/messages/pl.json
+++ b/messages/pl.json
@@ -4121,6 +4121,10 @@
"note": "Obszar podstawowy — zawsze aktywny"
},
"description": "Wybierz, co HealthLog ma dla Ciebie śledzić. Włączaj i wyłączaj poszczególne obszary — nawigacja, kafelki i analizy dostosują się od razu."
+ },
+ "gesundheitsakte": {
+ "title": "Dokumentacja zdrowotna",
+ "description": "Wyeksportuj pełną dokumentację zdrowotną jako PDF, FHIR R4 lub łączony pakiet ZIP."
}
},
"profile": "Profil",
diff --git a/src/app/settings/[section]/page.tsx b/src/app/settings/[section]/page.tsx
index bc1193242..d8a0c6faa 100644
--- a/src/app/settings/[section]/page.tsx
+++ b/src/app/settings/[section]/page.tsx
@@ -8,6 +8,7 @@ import { AiSection } from "@/components/settings/ai-section";
import { ApiSection } from "@/components/settings/api-section";
import { DashboardSection } from "@/components/settings/dashboard-section";
import { ExportSection } from "@/components/settings/export-section";
+import { GesundheitsakteSection } from "@/components/settings/gesundheitsakte-section";
import { InsightsSection } from "@/components/settings/insights-section";
import { IntegrationsSection } from "@/components/settings/integrations-section";
import { LayoutSection } from "@/components/settings/layout-section";
@@ -29,8 +30,7 @@ import { SettingsShell } from "@/components/settings/settings-shell";
/**
* Dynamic settings section route. Each of the `SETTINGS_SECTION_SLUGS`
- * (14 today — 10 nav-visible sections plus the four routable-but-hidden
- * Layout child editors) is pre-rendered at build via
+ * is pre-rendered at build via
* `generateStaticParams()` so the URLs are
* statically known to Next.js, while the `dynamicParams = false` flag below
* tells the router to 404 (instead of attempting on-demand rendering) for any
@@ -61,6 +61,7 @@ const SECTION_COMPONENTS: Record<
mood: MoodSection,
thresholds: ThresholdsSection,
api: ApiSection,
+ gesundheitsakte: GesundheitsakteSection,
export: ExportSection,
advanced: AdvancedSection,
};
diff --git a/src/components/settings/__tests__/export-section.test.tsx b/src/components/settings/__tests__/export-section.test.tsx
index fffd2e24f..264277863 100644
--- a/src/components/settings/__tests__/export-section.test.tsx
+++ b/src/components/settings/__tests__/export-section.test.tsx
@@ -2,7 +2,6 @@
* v1.4.16 Phase B7 — Settings → Export section.
*
* The consolidated Export page surfaces:
- * - Health Record export panel (the page hero, v1.12)
* - Measurements CSV
* - Medications CSV (with optional intake-history toggle)
* - Mood CSV
@@ -12,10 +11,10 @@
* download/generate button. SSR-only smoke test — interaction is
* exercised by the e2e suite.
*
- * The health-record export takes the page hero. The doctor-report PDF
- * now lives under the health-record export and is no longer offered as
- * a separate card here. The four CSV/JSON tiles stay under a "Weitere
- * Export-Optionen" / "Other export options" sub-heading. Each component
+ * v1.18.0 (S5) — the full health-record export moved out to its own
+ * top-level "Gesundheitsakte" section; this page keeps only the generic
+ * CSV/JSON data-out paths under a "Weitere Export-Optionen" / "Other
+ * export options" sub-heading plus the import surface. Each component
* owns its own contract test; this suite pins the page-level shape.
*/
import { describe, expect, it, vi } from "vitest";
@@ -77,12 +76,11 @@ describe(" — SSR smoke", () => {
expect(html).not.toContain('data-testid="export-card-cycle"');
});
- it("mounts the health-record export panel as the page hero", () => {
+ it("no longer mounts the health-record export panel (moved to Gesundheitsakte)", () => {
const html = render();
- // v1.12 — the health-record export owns the hero treatment.
- expect(html).toContain('data-testid="health-record-export-panel"');
- expect(html).toContain("hero-gradient");
- expect(html).toContain("glow-purple");
+ // v1.18.0 (S5) — the full health-record export lives in its own
+ // top-level Gesundheitsakte section now, not on this page.
+ expect(html).not.toContain('data-testid="health-record-export-panel"');
});
it("no longer mounts a separate doctor-report card", () => {
@@ -130,7 +128,7 @@ describe(" — SSR smoke", () => {
expect(buttonMatches?.length ?? 0).toBe(4);
});
- it("German locale renders the DE heading + hero copy", () => {
+ it("German locale renders the DE heading + sub-heading copy", () => {
const html = render(, "de");
expect(html).toContain("Export");
expect(html).toContain("Weitere Export-Optionen");
diff --git a/src/components/settings/__tests__/gesundheitsakte-section.test.tsx b/src/components/settings/__tests__/gesundheitsakte-section.test.tsx
new file mode 100644
index 000000000..57ab31493
--- /dev/null
+++ b/src/components/settings/__tests__/gesundheitsakte-section.test.tsx
@@ -0,0 +1,54 @@
+/**
+ * v1.18.0 (S5) — Settings → Gesundheitsakte section.
+ *
+ * The full health-record export (PDF + FHIR R4 + zip package) lifted out
+ * of Export & Import into its own top-level home. SSR-only smoke test —
+ * interaction is exercised by the panel's own contract test + e2e.
+ */
+import { describe, expect, it, vi } from "vitest";
+import { renderToStaticMarkup } from "react-dom/server";
+
+vi.mock("next/navigation", () => ({
+ useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
+ usePathname: () => "/settings/gesundheitsakte",
+}));
+
+vi.mock("@tanstack/react-query", () => ({
+ useQuery: () => ({ data: null, isLoading: false, refetch: vi.fn() }),
+ useQueryClient: () => ({ invalidateQueries: vi.fn() }),
+ useMutation: () => ({ mutate: vi.fn(), isPending: false }),
+}));
+
+vi.mock("@/hooks/use-auth", () => ({
+ useAuth: () => ({
+ user: { id: "u1", role: "USER" },
+ isAuthenticated: true,
+ isLoading: false,
+ refetch: vi.fn(),
+ }),
+}));
+
+import { I18nProvider } from "@/lib/i18n/context";
+import { GesundheitsakteSection } from "../gesundheitsakte-section";
+
+function render(node: React.ReactElement, locale: "en" | "de" = "en") {
+ return renderToStaticMarkup(
+ {node},
+ );
+}
+
+describe(" — SSR smoke", () => {
+ it("renders the section description and the health-record panel", () => {
+ const html = render();
+ expect(html).toContain('id="settings-section-gesundheitsakte-title"');
+ expect(html).toContain('data-testid="health-record-export-panel"');
+ // Raw key never leaks past i18n.
+ expect(html).not.toContain("settings.sections.gesundheitsakte.");
+ });
+
+ it("German locale resolves without leaking the raw key", () => {
+ const html = render(, "de");
+ expect(html).toContain('data-testid="health-record-export-panel"');
+ expect(html).not.toContain("settings.sections.gesundheitsakte.");
+ });
+});
diff --git a/src/components/settings/__tests__/settings-shell.test.tsx b/src/components/settings/__tests__/settings-shell.test.tsx
index d83647fc4..644e9969a 100644
--- a/src/components/settings/__tests__/settings-shell.test.tsx
+++ b/src/components/settings/__tests__/settings-shell.test.tsx
@@ -67,6 +67,8 @@ describe("SETTINGS_SECTION_SLUGS", () => {
// 301-redirects to `/settings/notifications`.
// v1.18.0 — `modules` ("Was du trackst") sits right after `account` as
// the single front door for enabling/disabling secondary domains.
+ // v1.18.0 (S5) — `gesundheitsakte` (the full health-record export) lifts
+ // out of Export & Import into its own top-level entry, before `export`.
expect([...SETTINGS_SECTION_SLUGS]).toEqual([
"account",
"modules",
@@ -80,6 +82,7 @@ describe("SETTINGS_SECTION_SLUGS", () => {
"thresholds",
"ai",
"api",
+ "gesundheitsakte",
"export",
"advanced",
"about",
@@ -204,6 +207,9 @@ describe("", () => {
// The ampersand is HTML-escaped by React SSR — assert on the encoded
// form so we don't accidentally match a parser that double-escapes.
expect(html).toContain("API & Tokens");
+ // v1.18.0 (S5) — the health record is its own top-level entry.
+ expect(html).toContain('href="/settings/gesundheitsakte"');
+ expect(html).toContain("Health record");
// v1.4.16 phase B7: the consolidated Export section is a top-level
// entry in the sidebar; the link must be present in both locales.
expect(html).toContain('href="/settings/export"');
diff --git a/src/components/settings/export-section.tsx b/src/components/settings/export-section.tsx
index 6761a8daf..ea99c154e 100644
--- a/src/components/settings/export-section.tsx
+++ b/src/components/settings/export-section.tsx
@@ -9,18 +9,14 @@
* per export type, each with its own filter inputs and a clear
* "Download" / "Generate" button.
*
- * 1. Health Record export — hero panel at the top of the page
- * (PDF + FHIR R4 + zip package, see
- * ``)
- * 2. Measurements CSV — optional `since`/`until`
- * 3. Medications CSV — optional intake-history toggle
- * 4. Mood CSV — optional `since`/`until`
- * 5. Full JSON Backup — single-file user-scoped dump
+ * 1. Measurements CSV — optional `since`/`until`
+ * 2. Medications CSV — optional intake-history toggle
+ * 3. Mood CSV — optional `since`/`until`
+ * 4. Full JSON Backup — single-file user-scoped dump
*
- * v1.12 — the health-record export is the headline "data out" path; it
- * takes the page hero. The doctor-report PDF lives under the
- * health-record export now and is no longer offered as a separate card
- * here (it used to be a small secondary card at the bottom).
+ * v1.18.0 (S5) — the full health-record export (PDF + FHIR R4 + zip
+ * package) moved out to its own top-level "Gesundheitsakte" section. This
+ * page now keeps only the generic data export/import paths.
*
* Mobile-first: cards stack on `=md`.
*/
@@ -42,7 +38,6 @@ import { Button } from "@/components/ui/button";
import { DateInput } from "@/components/ui/date-input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
-import { HealthRecordExportPanel } from "@/components/settings/health-record-export-panel";
import { ImportPanel } from "@/components/settings/import-panel";
import { queryKeys } from "@/lib/query-keys";
import { useTranslations } from "@/lib/i18n/context";
@@ -87,15 +82,9 @@ export function ExportSection() {
- {/* v1.12 — full health-record export is now the page hero. PDF +
- FHIR R4 + a combined zip package, with grouped data-section
- toggles (collapsed by default) and a format switch. This is the
- headline "data out" path; it carries the primary visual weight. */}
-
-
- {/* v1.12 — secondary export options. The four CSV/JSON
- destinations live under a dedicated sub-heading.
- Mobile: single column. Desktop (md+): 2-column grid. */}
+ {/* v1.18.0 (S5) — the full health-record export moved to its own
+ top-level "Gesundheitsakte" section. This page keeps the generic
+ CSV/JSON data-out paths and the import surface. */}
+ );
+}
diff --git a/src/components/settings/section-placeholder.tsx b/src/components/settings/section-placeholder.tsx
index c09c9c459..977327aee 100644
--- a/src/components/settings/section-placeholder.tsx
+++ b/src/components/settings/section-placeholder.tsx
@@ -15,6 +15,7 @@ import {
Bell,
Blocks,
Download,
+ FileHeart,
Info,
KeyRound,
LayoutDashboard,
@@ -46,6 +47,7 @@ const SLUG_ICON: Record = {
thresholds: SlidersHorizontal,
ai: Sparkles,
api: KeyRound,
+ gesundheitsakte: FileHeart,
export: Download,
advanced: Settings2,
about: Info,
diff --git a/src/components/settings/section-slugs.ts b/src/components/settings/section-slugs.ts
index 5be9037d5..e943bb479 100644
--- a/src/components/settings/section-slugs.ts
+++ b/src/components/settings/section-slugs.ts
@@ -31,6 +31,9 @@
// canonical editors; reminder TYPES now live centrally in `notifications`,
// each row gated on its module. `/settings/reminders` 301-redirects to
// `/settings/notifications` (next.config.ts).
+// v1.18.0 (S5) — per-submodule settings split. `gesundheitsakte` (the full
+// health-record export, always available) lifts out of Export & Import into
+// its own top-level entry.
export const SETTINGS_SECTION_SLUGS = [
"account",
// v1.18.0 — `modules` ("Was du trackst") sits right after account: the
@@ -46,6 +49,7 @@ export const SETTINGS_SECTION_SLUGS = [
"thresholds",
"ai",
"api",
+ "gesundheitsakte",
"export",
"advanced",
"about",
diff --git a/src/components/settings/settings-shell.tsx b/src/components/settings/settings-shell.tsx
index 22a9a7e22..de7c0257b 100644
--- a/src/components/settings/settings-shell.tsx
+++ b/src/components/settings/settings-shell.tsx
@@ -21,6 +21,7 @@ import {
Bell,
Blocks,
Download,
+ FileHeart,
Info,
KeyRound,
LayoutDashboard,
@@ -116,6 +117,13 @@ export const SETTINGS_SECTIONS: readonly SettingsSection[] = [
},
{ slug: "ai", titleKey: "settings.sections.ai.title", icon: Sparkles },
{ slug: "api", titleKey: "settings.sections.api.title", icon: KeyRound },
+ // v1.18.0 (S5) — the full health record (PDF + FHIR R4 + zip package)
+ // earns its own home, lifted out of Export & Import. Always available.
+ {
+ slug: "gesundheitsakte",
+ titleKey: "settings.sections.gesundheitsakte.title",
+ icon: FileHeart,
+ },
{
slug: "export",
titleKey: "settings.sections.export.title",