diff --git a/backend/version.py b/backend/version.py
index ac2ca16..168a3ce 100644
--- a/backend/version.py
+++ b/backend/version.py
@@ -1,6 +1,6 @@
# Shinkan Jinkendo Version Information
-APP_VERSION = "0.8.69"
+APP_VERSION = "0.8.70"
BUILD_DATE = "2026-05-10"
DB_SCHEMA_VERSION = "20260508049"
@@ -29,6 +29,13 @@ MODULE_VERSIONS = {
}
CHANGELOG = [
+ {
+ "version": "0.8.70",
+ "date": "2026-05-10",
+ "changes": [
+ "Compliance P-01b: Einstellungen/Rechtliches (/settings/legal) fuer mobile/PWA-Darstellung; Hub mit Links zu Impressum, Datenschutz, Nutzungsbedingungen, Medienrichtlinie",
+ ],
+ },
{
"version": "0.8.69",
"date": "2026-05-10",
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 6067359..348833d 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -38,6 +38,7 @@ import AdminHomeRedirect from './components/AdminHomeRedirect'
import PlatformAdminRoute from './components/PlatformAdminRoute'
import MediaLibraryPage from './pages/MediaLibraryPage'
import LegalPage from './pages/LegalPage'
+import SettingsLegalPage from './pages/SettingsLegalPage'
import ActiveClubSwitcher from './components/ActiveClubSwitcher'
import InactiveMembershipBanner from './components/InactiveMembershipBanner'
import './app.css'
@@ -183,6 +184,7 @@ function AppRoutes() {
} />
} />
} />
+ } />
} />
} />
diff --git a/frontend/src/pages/AccountSettingsPage.jsx b/frontend/src/pages/AccountSettingsPage.jsx
index 67375ae..047e515 100644
--- a/frontend/src/pages/AccountSettingsPage.jsx
+++ b/frontend/src/pages/AccountSettingsPage.jsx
@@ -426,6 +426,10 @@ function AccountSettingsPage() {
Technische Systeminformationen
{' — App-Version, Build, Umgebung, Datenbankschema'}
+
+ Rechtliches
+ {' — Impressum, Datenschutz, Nutzungsbedingungen, Medienrichtlinie'}
+
)
}
diff --git a/frontend/src/pages/SettingsLegalPage.jsx b/frontend/src/pages/SettingsLegalPage.jsx
new file mode 100644
index 0000000..d1dc039
--- /dev/null
+++ b/frontend/src/pages/SettingsLegalPage.jsx
@@ -0,0 +1,66 @@
+import { Link } from 'react-router-dom'
+import { Scale } from 'lucide-react'
+
+const LEGAL_LINKS = [
+ { to: '/impressum', label: 'Impressum', description: 'Angaben zum Betreiber und Verantwortlichen' },
+ { to: '/datenschutz', label: 'Datenschutzerklärung', description: 'Verarbeitung personenbezogener Daten' },
+ { to: '/nutzungsbedingungen', label: 'Nutzungsbedingungen', description: 'Regeln für die Nutzung der Plattform' },
+ { to: '/medienrichtlinie', label: 'Medienrichtlinie', description: 'Urheberrecht, Rechte am eigenen Bild, Sichtbarkeit' },
+]
+
+function SettingsLegalPage() {
+ return (
+
+
+
+ ← Zurück zu Einstellungen
+
+
+
+
Rechtliches
+
+ Rechtstexte und Richtlinien der Plattform.
+ Die Inhalte befinden sich noch in redaktioneller Prüfung.
+
+
+
+ {LEGAL_LINKS.map((item, idx) => (
+
+
+
+
+ {item.label}
+
+
+ {item.description}
+
+
+
›
+
+ ))}
+
+
+ )
+}
+
+export default SettingsLegalPage
diff --git a/frontend/src/version.js b/frontend/src/version.js
index 31ceb7d..9ccbd2f 100644
--- a/frontend/src/version.js
+++ b/frontend/src/version.js
@@ -1,11 +1,12 @@
// Shinkan Jinkendo Frontend Version
-export const APP_VERSION = "0.8.69"
+export const APP_VERSION = "0.8.70"
export const BUILD_DATE = "2026-05-10"
export const PAGE_VERSIONS = {
LoginPage: "1.0.2",
LegalPage: "1.0.0",
+ SettingsLegalPage: "1.0.0",
Dashboard: "1.0.0",
AccountSettingsPage: "1.0.1",
ExercisesPage: "1.5.0", // Fokus +/- Regeln, nur ohne Fokusbereich; Filterprefs
diff --git a/tests/dev-smoke-test.spec.js b/tests/dev-smoke-test.spec.js
index 8a61fb7..c1fe24a 100644
--- a/tests/dev-smoke-test.spec.js
+++ b/tests/dev-smoke-test.spec.js
@@ -230,6 +230,59 @@ test('P-01: Login-Seite enthält Links zu allen vier Rechtstextseiten', async ({
console.log('✓ P-01: Login-Seite – alle vier Rechtstext-Links vorhanden');
});
+// P-01b: Rechtliches über Einstellungen (Mobile/PWA-Erreichbarkeit)
+
+test('P-01b: Einstellungen enthält Link zu Rechtliches', async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 844 });
+ await login(page);
+ await page.waitForLoadState('networkidle');
+
+ await page.goto('/settings');
+ await page.waitForLoadState('networkidle');
+
+ const link = page.locator('a[href="/settings/legal"]');
+ await expect(link).toBeVisible();
+
+ console.log('✓ P-01b: Einstellungen enthält Link zu /settings/legal');
+});
+
+test('P-01b: /settings/legal enthält Links zu allen vier Rechtstextseiten', async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 844 });
+ await login(page);
+ await page.waitForLoadState('networkidle');
+
+ await page.goto('/settings/legal');
+ await page.waitForLoadState('networkidle');
+
+ await expect(page.getByRole('heading', { level: 1 })).toContainText('Rechtliches');
+
+ for (const route of LEGAL_ROUTES) {
+ const link = page.locator(`a[href="${route.path}"]`);
+ await expect(link).toBeVisible();
+ }
+
+ console.log('✓ P-01b: /settings/legal – Überschrift + alle vier Rechtstext-Links vorhanden');
+});
+
+test('P-01b: Jeder Rechtstext-Link aus /settings/legal führt zur korrekten Route', async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 844 });
+ await login(page);
+ await page.waitForLoadState('networkidle');
+
+ for (const route of LEGAL_ROUTES) {
+ await page.goto('/settings/legal');
+ await page.waitForLoadState('networkidle');
+
+ await page.locator(`a[href="${route.path}"]`).click();
+ await page.waitForLoadState('networkidle');
+
+ expect(page.url()).toContain(route.path);
+ await expect(page.getByRole('heading', { level: 1 })).toContainText(route.label);
+
+ console.log(`✓ P-01b: ${route.label} – Link aus /settings/legal korrekt`);
+ }
+});
+
test('8. Keine kritischen Console-Fehler', async ({ page }) => {
const errors = [];
page.on('console', msg => {