# 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.