refetch()}
/>
)
}
```
---
## 8. Mobile-Spezifische Navigation
### 8.1 Bottom Navigation (Mobile)
**Pattern:**
```
┌─────────────────────────────────────┐
│ │
│ (Content Area) │
│ │
├─────────────────────────────────────┤
│ 🏠 Home │ 📋 Übungen │ 📅 Plan │
└─────────────────────────────────────┘
```
**Implementation:**
```javascript
// MobileBottomNav.jsx
```
**CSS:**
```css
.mobile-bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background: var(--surface);
border-top: 1px solid var(--border);
display: flex;
justify-content: space-around;
z-index: 100;
}
@media (min-width: 768px) {
.mobile-bottom-nav {
display: none; /* Desktop nutzt Top-Nav */
}
}
```
### 8.2 Swipe-Navigation (Detail-Seite)
**Pattern:** Swipe left/right zwischen Übungen (gleicher Filter)
**Implementation:**
```javascript
// ExerciseDetailPage.jsx
const { exercises } = useExercisesList() // aus Context/Query
const currentIndex = exercises.findIndex(e => e.id === parseInt(exerciseId))
const swipeHandlers = useSwipeable({
onSwipedLeft: () => {
const nextExercise = exercises[currentIndex + 1]
if (nextExercise) navigate(`/exercises/${nextExercise.id}`)
},
onSwipedRight: () => {
const prevExercise = exercises[currentIndex - 1]
if (prevExercise) navigate(`/exercises/${prevExercise.id}`)
},
preventDefaultTouchmoveEvent: true,
trackMouse: false,
})
{/* Exercise Detail Content */}
```
---
## 9. Accessibility
### 9.1 Skip Links
**Pattern:**
```javascript
// App.jsx
Zum Hauptinhalt springen
{/* Content */}
```
**CSS:**
```css
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--accent);
color: white;
padding: 8px;
z-index: 1000;
}
.skip-link:focus {
top: 0;
}
```
### 9.2 Focus Management
**Pattern:** Bei Navigation → Focus auf Hauptüberschrift setzen
```javascript
// ExerciseDetailPage.jsx
const titleRef = useRef(null)
useEffect(() => {
titleRef.current?.focus()
}, [exerciseId])
{exercise.title}
```
### 9.3 ARIA Live-Region für Filter
**Pattern:**
```javascript
// ExercisesListPage.jsx
{exercises.length} Übungen gefunden
```
---
## 10. Testing-Strategie
### 10.1 Route-Tests (Playwright)
```javascript
// exercises.routing.spec.js
test('Navigation zu Detail-Seite funktioniert', async ({ page }) => {
await page.goto('/exercises')
const firstCard = page.locator('.exercise-card').first()
await firstCard.click()
await expect(page).toHaveURL(/\/exercises\/\d+/)
await expect(page.locator('h1')).toBeVisible()
})
test('Filter-State bleibt in URL erhalten', async ({ page }) => {
await page.goto('/exercises?focus_area=1')
await page.reload()
const url = new URL(page.url())
expect(url.searchParams.get('focus_area')).toBe('1')
})
```
### 10.2 Navigation-Guard-Tests
```javascript
test('Unsaved Changes Warning', async ({ page }) => {
await page.goto('/exercises/new')
await page.fill('[name="title"]', 'Test Übung')
page.on('dialog', dialog => {
expect(dialog.message()).toContain('ungespeicherte')
dialog.accept()
})
await page.goto('/exercises')
})
```
---
## 11. Route-Konfiguration (React Router)
### 11.1 Vollständige Route-Definitionen
```javascript
// App.jsx
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
function App() {
return (
{/* Exercises Routes */}
} />
} />
} />
} />
{/* Varianten: Bearbeitung inline in ExerciseFormPage, keine eigenen Routen */}
{/* Exercise Blocks Routes */}
} />
} />
} />
} />
{/* Admin Routes */}
}>
} />
} />
} />
{/* Redirects */}
} />
} />
)
}
```
---
**Version:** 1.1
**Letzte Änderung:** 2026-04-24
**Status:** REVIEWED - Pending Implementation
**Review-Änderungen:** Exercise Blocks Routes + Navigation hinzugefügt