# Migration: Trainings-Einheit — Modal → Vollseiten-Editor

**Status:** Phase C abgeschlossen (Hub + Edit-Route produktiv)  
**Stand:** 2026-05-19  
**Bezug:** Architektur-Schuld A1 (`SCHULDEN_UND_REMEDIATION.md`), UX-Grundsatz Modals vs. Vollseiten

---

## 1. Ausgangslage

| Aspekt | Ist (Modal) | Soll (Vollseite) |
|--------|-------------|------------------|
| Bearbeiten / Neu | `TrainingPlanningUnitFormModal` über `TrainingPlanningPageRoot` | `TrainingUnitEditPage` unter eigener Route |
| Hub | Liste + Kalender auf `/planning` | unverändert — nur Übersicht & Kurzaktionen |
| Deep-Link | `/planning?unit={id}` (öffnet Modal, Query wird entfernt) | `/planning/units/{id}/edit` (bookmarkbar) |
| Vergleich | Rahmenprogramm, Modul, Vorlage, Run/Coach | gleiches Muster |

**Warum Modal historisch:** Frontend Phase 3 (0.8.131) — Extraktion aus God-Page, **kein** bewusstes UX-Zielbild.

---

## 2. Zielbild (verbindlich)

### 2.1 Routen

| Route | Zweck |
|-------|--------|
| `/planning` | Hub: Gruppe, Liste/Kalender, Import, Zuweisen, Löschen, Links „Bearbeiten“ |
| `/planning/units/new` | Neue Einheit (Query: `group`, `date`, optional `template`) |
| `/planning/units/:id/edit` | Bestehende Einheit bearbeiten (Query optional: `mode=debrief`) |
| `/planning/run/:unitId` | Durchführung (unverändert) |
| `/planning/run/:unitId/coach` | Coaching (unverändert) |

Implementierung: `frontend/src/utils/planningUnitRoutes.js` — **einzige** Quelle für Pfade und Rückkehr-Kontext (Drift-Schutz).

### 2.2 Was Modal bleibt (Hub + Editor)

| Dialog | Ort | Begründung |
|--------|-----|------------|
| Rahmen-Import | Hub | Mehrfachauswahl + Datums-Vorschläge |
| Trainer zuweisen | Hub | Kurzaktion aus Liste/Kalender |
| Rahmen-Session / Modul aus Liste | Hub | Aktion auf gespeicherter Einheit ohne Editor |
| Übungspicker, Modul einfügen, Peek | **Editor-Seite** | Kontext des Ablaufs |
| Rahmen übernehmen / Modul aus Editor | **Editor-Seite** | Nach Speichern des Ablaufs |
| Kombi-Ablauf bearbeiten | SectionsEditor (Sheet) | Fokussierter Sub-Dialog |

### 2.3 UI-Shell Editor

- `TrainingUnitFormShell.jsx` — reine Formular-UI (ohne Overlay), `page-form-shell` + `FormActionBar` (`variant="page"`).
- Kein `FormModalOverlay` / kein Scroll-Lock auf der Editor-Seite nötig.

### 2.4 Rückkehr zum Hub

Beim Navigieren vom Hub zum Editor wird `location.state.planningReturn` gesetzt (Gruppe, Ansicht, Monat, Datumsfilter).  
Abbrechen / Speichern & schließen → `/planning?…` mit wiederhergestellten Query-Parametern.

Legacy: `/planning?unit={id}` → Redirect auf `/planning/units/{id}/edit` (301/Replace via Router).

---

## 3. Code-Struktur (Ziel)

```
frontend/src/
├── utils/
│   ├── planningUnitRoutes.js          # Pfade, Return-State, Legacy-Redirect
│   ├── planningUnitRoutes.test.js     # Vitest
│   └── trainingUnitEditorCore.js      # Reine Payload-/Form-Helfer
│   └── trainingUnitEditorCore.test.js
├── hooks/
│   └── useTrainingUnitEditor.js       # Laden, Speichern, Form-State (Edit-Page)
├── components/planning/
│   ├── TrainingUnitFormShell.jsx      # Formular-UI (ex Modal-Inhalt)
│   └── TrainingPlanningPageRoot.jsx   # Hub only (~ weniger State)
└── pages/
    └── TrainingUnitEditPage.jsx       # Route-Container
```

**Soft-Limit (S1):** `TrainingUnitEditPage.jsx` delegiert an Hook + Shell; PageRoot verliert Modal-State.

---

## 4. Phasen & Abnahme

| Phase | Inhalt | Abnahme / Tests |
|-------|--------|-----------------|
| **A** | Doku, `planningUnitRoutes`, `trainingUnitEditorCore`, Vitest | `npm run test --prefix frontend` grün |
| **B** | `TrainingUnitFormShell`, `TrainingUnitEditPage`, Routen, Hub-Navigation, Modal entfernen | Playwright 14–15; Build grün |
| **C** | Hub liest Return-Query; Dashboard-Links direkt auf Edit-Route; PageRoot weiter entschlacken | Manuell + E2E |
| **D** (optional) | `useTrainingUnitEditor` weiter modularisieren; ungespeichert-Blocker wie Modul-Edit | S8 Checkliste |

### Definition of Done (Phase B)

- [x] Kein `TrainingPlanningUnitFormModal` mehr in Produktionspfad
- [x] `data-testid="planning-unit-form"` auf Editor-Seite
- [x] Speichern sendet identisches Payload wie zuvor (`buildTrainingUnitSavePayload`)
- [x] Split-Sessions / `phases`-PUT unverändert (`buildPlanPayloadForSave`)
- [x] Playwright 12–13 weiter grün; 14–15 neu
- [x] `docs/HANDOVER.md` + Roadmap aktualisiert

---

## 5. Risiken & Mitigation

| Risiko | Mitigation |
|--------|------------|
| Payload-Drift beim Speichern | Logik in `trainingUnitEditorCore.js` + Unit-Tests |
| Kontextverlust Hub | `planningReturn` in `planningUnitRoutes.js` + Hub-Query-Restore |
| Modul-Einfügen / Picker | Nur auf Edit-Page; gleiche Handler wie zuvor |
| Doppelte Einträge Deep-Link | Legacy-Redirect; Dashboard später auf neue URL |
| Große Edit-Page | Hook + Shell; PageRoot schrumpft |

---

## 6. Nicht-Ziele (dieser Sprint)

- Backend-API-Änderungen
- Virtualisierung der Einheitenliste
- Refactor `TrainingUnitSectionsEditor`
- Coach/Run-Flows

---

## 7. Pflege

Nach Abschluss Phase B: Eintrag in `UMSETZUNGSPLAN_ROADMAP.md` (Phase 3 Nachzug), `SCHULDEN_UND_REMEDIATION.md` A1 Fortschritt, `backend/version.py` CHANGELOG.
