# Cabinet Displays – Implementierungs-Status

> Konzept: siehe `00-entwicklungskonzept.md`. Diese Datei wird je Phase fortgeschrieben.

## Übersicht

| Phase | Inhalt | Status |
|---|---|---|
| **0** | Konzept-Freigabe | ✅ 11.05.2026 |
| **1** | Datenmodell + Daten-Migration | ✅ 11.05.2026 |
| **2** | API & Player (config + preview + module preview) | ✅ 12.05.2026 |
| **3** | Admin-UI: Displays-Liste mit Live/Entwurf | ✅ 12.05.2026 |
| **4** | Admin-UI: Entwurf-Editor (Iframe-Vorschau) | ✅ 12.05.2026 |
| **5** | Modul-Editor: 3-stufige Vorschau | ✅ 12.05.2026 |
| **6** | Umbenennung Versionen → Module + Onboarding | ✅ 12.05.2026 |
| **7** | Aufräumen + alte Pivot-Tabelle entfernen | ⏳ offen |

Legende: ✅ fertig · 🟡 in Arbeit · ⏳ offen · ⛔ blockiert

---

## Defaults aus §10 (Konzept-Freigabe vom 11.05.2026)

Der User hat das Konzept freigegeben. Da keine abweichende Wahl getroffen wurde, gelten die im Konzept empfohlenen Defaults:

1. **Test-Display:** genau 1 Datensatz per Seeder angelegt, weitere können bei Bedarf erstellt werden.
2. **Entwurf verwerfen:** löscht die Draft-Playlist. Beim erneuten Anlegen wird die Reihenfolge aus Live kopiert.
3. **Module bleiben *shared*:** Modul-Änderungen wirken sofort auf alle Displays, die das Modul live einsetzen. Modul-eigene Versionierung ist *out of scope*.
4. **Polling-Mechanismus** der Player (alle 60 s) reicht; kein Push-Refresh.

---

## Live-Roll-out Hinweise

Auf dem Live-Server reicht für jede Phase:

```bash
git pull
composer install --no-dev --optimize-autoloader   # falls neue Composer-Deps
php artisan migrate --force                       # bringt neue Migrations ein
php artisan config:cache                          # Caches frisch
php artisan view:clear
```

Alle strukturellen Änderungen liegen **ausschließlich** in `database/migrations/` als datierte Dateien vor – auf der Live-DB reicht `php artisan migrate --force`. Datenverlust gibt es nicht: bestehende Pivot-Daten aus `display_display_version` werden in die neue Struktur überführt.

---

## Phase 1 – Datenmodell

**Ziel:** neue Tabellen `display_playlists` + `display_playlist_items`, erweiterte `displays`-Spalten (`is_test`, `preview_token`), vollständige verlustfreie Migration der heutigen Pivot-Daten.

**Dateien:**
- `database/migrations/2026_05_11_*_create_display_playlists_table.php`
- `database/migrations/2026_05_11_*_create_display_playlist_items_table.php`
- `database/migrations/2026_05_11_*_add_test_flag_and_preview_token_to_displays_table.php`
- `database/migrations/2026_05_11_*_migrate_pivot_to_display_playlists.php`
- `app/Models/DisplayPlaylist.php`
- `app/Models/DisplayPlaylistItem.php`
- `app/Models/Display.php` (neue Relations, alte `versions()` bleibt kompatibel)
- `database/factories/DisplayPlaylistFactory.php`
- `database/factories/DisplayPlaylistItemFactory.php`
- `tests/Feature/DisplayPlaylistMigrationTest.php`

**Wichtig:** Die alte Tabelle `display_display_version` und die Relation `Display::versions()` bleiben in dieser Phase **erhalten** (Removal erst in Phase 7), damit keine bestehenden Funktionen brechen.

### Stand 11.05.2026 – ✅ abgeschlossen

#### Gelieferte Migrationen (Live-Reihenfolge)

| Reihenfolge | Datei | Zweck |
|---|---|---|
| 1 | `2026_05_11_113300_add_test_flag_and_preview_token_to_displays_table.php` | `displays.is_test` + `displays.preview_token` (unique) |
| 2 | `2026_05_11_113310_create_display_playlists_table.php` | Neue Tabelle für Live/Entwurfs-Bespielung pro Display |
| 3 | `2026_05_11_113320_create_display_playlist_items_table.php` | Geordnete Module pro Bespielung |
| 4 | `2026_05_11_113330_migrate_pivot_to_display_playlists.php` | Übernimmt bestehende Pivot-Daten als Published-Playlists (idempotent) |

Die Daten-Migration ist **idempotent** – wenn pro Display bereits eine Published-Playlist existiert, wird sie übersprungen. Die alte Pivot-Tabelle `display_display_version` bleibt erhalten.

#### Neue Modelle & Relations

- `App\Models\DisplayPlaylist` mit Scopes `published()`/`draft()`, Relation `modules()` (geordnet)
- `App\Models\DisplayPlaylistItem`
- `App\Models\Display` erweitert um `playlists()`, `livePlaylist()`, `draftPlaylist()`, `liveModules()`, `ensurePreviewToken()`
- `Display::versions()` ist als `@deprecated` markiert, bleibt aber funktional

#### Tests

```text
tests/Feature/DisplayPlaylistMigrationTest.php  – 11 passed
tests/Feature/DisplayListTest.php               – ok
tests/Feature/DisplayVersionTest.php            – ok
tests/Feature/DisplayVersionApiTest.php         – ok
tests/Feature/DisplayMediaTest.php              – ok
```

Insgesamt 67 grüne Tests rund um Displays (11 neu + 56 bestand). Keine Linter-Warnungen, Pint clean.

#### Roll-out auf Live

```bash
git pull
php artisan migrate --force
```

Reihenfolge stimmt durch die Timestamps automatisch. Daten-Migration ist idempotent, kann beliebig oft laufen.

---

## Phase 2 – API & Player

**Ziel:** bestehende Player-Konfiguration liest künftig aus der Published-Playlist. Zusätzlich gibt es öffentliche Vorschau-Endpunkte für Display-Entwürfe per Token und einzelne Module. Das JSON-Schema bleibt rückwärtskompatibel (`playlist[]`, `updated_at`).

### Stand 12.05.2026 – ✅ abgeschlossen

Geplante/aktuelle Dateien:
- `app/Services/DisplayPlaylistConfigBuilder.php`
- `app/Http/Controllers/Api/DisplayVersionApiController.php`
- `app/Http/Controllers/Api/DisplayPreviewController.php`
- `app/Http/Controllers/Api/ModulePreviewController.php`
- `routes/domains.php`
- `public/_cabinet/display/index.html`
- `tests/Feature/DisplayVersionApiTest.php`

Umsetzung:
- Live-Config: `GET /api/display/{display}/config` liest `livePlaylist`
- Live-Check: `GET /api/display/{display}/check` bezieht sich auf die Published-Playlist
- Draft-Preview: `GET /api/display/preview/{token}` liefert die Draft-Playlist
- Modul-Preview: `GET /api/display/module/{module}/preview` liefert ein Einzelmodul im Player-Schema
- Player-Preview-Seiten: `/preview/{token}` und `/preview/module/{module}`

#### Tests

```text
tests/Feature/DisplayVersionApiTest.php         – 13 passed
tests/Feature/DisplayPlaylistMigrationTest.php  – ok
```

Insgesamt 24 grüne Tests für Phase 2 und die Playlist-Grundlage. Pint clean.

#### Hinweis

In der lokalen Umgebung musste der alte Route-Cache einmal mit `php artisan route:clear` geleert werden, damit die neuen Preview-Routen sichtbar wurden. Für Live bleibt beim Roll-out `php artisan config:cache` bzw. ein frischer Route-/Config-Cache relevant.

---

## Phase 3 – Admin-UI: Displays-Liste mit Live/Entwurf

**Ziel:** Die Display-Liste zeigt pro physischem Display den Live-Stand und optionalen Entwurf nebeneinander. Entwürfe können aus Live angelegt, verworfen und veröffentlicht werden. Das Test-Display ist sichtbar hervorgehoben.

### Stand 12.05.2026 – ✅ abgeschlossen

Dateien:
- `app/Livewire/Admin/Cms/DisplayList.php`
- `resources/views/livewire/admin/cms/display-list.blade.php`
- `tests/Feature/DisplayListTest.php`

Umsetzung:
- Display-Karten zeigen `Live` und `Entwurf` als zwei getrennte Spalten
- Der globale Bearbeiten-Button im Display-Kopf wurde entfernt; Live und Entwurf haben jeweils eigene Bearbeiten-Buttons
- Die Live-Card zeigt die Player-URL direkt als kopierbares Feld; der API-Link ist weniger prominent unten rechts platziert
- Live-Spalte nutzt `livePlaylist.modules`
- Entwurf-Spalte nutzt `draftPlaylist.modules`
- Live-Bearbeitung speichert nur die Published-Playlist
- Entwurfs-Bearbeitung speichert nur die Draft-Playlist und erzeugt bei Bedarf den Preview-Token
- Die Modul-Auswahl im Bearbeiten-Dialog zeigt nur noch Module, die in der aktuell bearbeiteten Bespielung noch nicht enthalten sind
- Der Plus-Button fügt auch dann das erste verfügbare Modul hinzu, wenn der Select-Wert wegen des Platzhalters noch nicht explizit gesetzt wurde
- Aktion `Entwurf anlegen` kopiert den aktuellen Live-Stand und erzeugt bei Bedarf den Preview-Token
- Aktion `Veröffentlichen` ersetzt die Published-Playlist durch den Draft und synchronisiert die alte Pivot-Tabelle weiterhin kompatibel
- Aktion `Verwerfen` löscht die Draft-Playlist
- Test-Displays (`is_test`) werden in der Liste hervorgehoben
- Der bestehende Bearbeiten-Dialog pflegt die Live-Bespielung weiter und synchronisiert bis Phase 7 zusätzlich `display_display_version`

#### Tests

```text
tests/Feature/DisplayListTest.php  – 14 passed
```

Die neuen Tests decken Draft anlegen, verwerfen, veröffentlichen, getrennte Live-/Entwurfs-Bearbeitung, gefilterte Modul-Auswahl sowie die Darstellung von Live-/Entwurf-Modulen ab.

---

## Phase 4 – Admin-UI: Entwurf-Editor mit Iframe-Vorschau

**Ziel:** Beim Bearbeiten eines Entwurfs ist die Player-Vorschau direkt sichtbar. Moduländerungen im Entwurf werden sofort in die Draft-Playlist geschrieben und laden die Vorschau neu.

### Stand 12.05.2026 – ✅ abgeschlossen

Dateien:
- `app/Livewire/Admin/Cms/DisplayList.php`
- `resources/views/livewire/admin/cms/display-list.blade.php`
- `tests/Feature/DisplayListTest.php`

Umsetzung:
- Der Entwurfs-Editor zeigt rechts eine 9:16-Iframe-Vorschau
- Die Iframe-Vorschau sitzt dauerhaft unterhalb der Aktualisieren-Aktion, damit sie im Desktop-Modal nicht mit dem Formular überlappt
- Die Vorschau lädt `/preview/{token}` mit Cache-Bust-Parameter
- Hinzufügen, Entfernen und Sortieren von Modulen persistiert bei Draft-Bearbeitung sofort in `display_playlist_items`
- Nach jeder Moduländerung wird die Iframe-Vorschau per `wire:key` neu aufgebaut
- Vollbild-Vorschau ist aus dem Editor heraus verlinkt

#### Tests

```text
tests/Feature/DisplayListTest.php  – 21 passed
```

Die Tests decken das Rendern der Vorschau-URL und das sofortige Persistieren von Draft-Änderungen für Preview-Reloads ab.

---

## Phase 5 – Modul-Editor: 3-stufige Vorschau

**Ziel:** Module können beim Bearbeiten visuell geprüft werden: kleine Vorschau je Item, eingebettete Player-Vorschau und Vollbild-Vorschau.

### Stand 12.05.2026 – ✅ abgeschlossen

Dateien:
- `app/Livewire/Admin/Cms/DisplayVersionEditor.php`
- `resources/views/livewire/admin/cms/display-version-editor.blade.php`
- `resources/views/livewire/admin/cms/partials/version-editor-video.blade.php`
- `resources/views/livewire/admin/cms/partials/version-editor-b2in.blade.php`
- `resources/views/livewire/admin/cms/partials/version-editor-offers.blade.php`
- `tests/Feature/DisplayVersionTest.php`

Umsetzung:
- Modul-Editor zeigt eine 9:16-Iframe-Vorschau über `/preview/module/{module}`
- Vollbild-Vorschau ist direkt aus dem Editor verlinkt
- Das Item-Bearbeiten-Modal ist breiter und zeigt unterhalb der Aktualisieren-Aktion ebenfalls eine 9:16-Iframe-Vorschau
- `Aktualisieren` im Item-Bearbeiten-Modal schließt das Modal nicht mehr, sondern speichert den Inhalt und lädt die Iframe-Vorschau neu
- Die Modal-Aktionen stehen unterhalb der Iframe-Vorschau und bieten `Aktualisieren`, `Abbrechen` und `Schließen`
- Die Vorschau im Item-Bearbeiten-Modal nutzt eine eigene Item-Preview und zeigt nur den aktuell bearbeiteten Slide statt das komplette Modul
- Der Display-Player rendert seinen Viewport strikt als 9:16-Fläche und skaliert Slide-, Footer- und QR-Elemente proportional zur Player-Fläche
- Harte Player-Elemente wie B2in-Headerlogo/Claim/Footer/QR, Offers-Logo/Brandtext/QR-Labels und Video-Footer-QR-Label sind jetzt als Modul-Einstellungen im CMS pflegbar
- Die Modul-Meta-Einstellungen sind als sichtbarer Block unterhalb der Media-/Slide-Liste editierbar; Angebote vererben Footer-Claim und Web/QR-URL automatisch an alle Slides
- Logo-Alt-Text-Felder wurden aus den Modul-Meta-Einstellungen entfernt; Player nutzen weiterhin feste Fallback-Alt-Texte
- Video-Display unterstützt Mediathek-Upload-URLs wie `/storage/...` ohne Legacy-`assets/`-Prefix
- Die Display-Mediathek und der schnelle Media-Picker akzeptieren SVG-Dateien als Bild-Uploads
- Änderungen an Name, Einstellungen, Items, Reihenfolge und Aktiv-Status laden die Modul-Vorschau neu
- Video/Footer/Media/Slide-Listen zeigen Inline-Mini-Previews je Item; Slide-Previews sind größer dargestellt
- Einzelmodul-Vorschau nutzt weiterhin den Player aus Phase 2

---

## Phase 6 – Umbenennung Versionen → Module + Onboarding

**Ziel:** Die Admin-UI verwendet den fachlich korrekten Begriff „Module“. Alte URLs bleiben kompatibel und leiten weiter.

### Stand 12.05.2026 – ✅ abgeschlossen

Dateien:
- `routes/admin.php`
- `app/Livewire/Admin/Cms/DisplayVersionList.php`
- `resources/views/livewire/admin/cms/display-version-list.blade.php`
- `resources/views/livewire/admin/cms/display-version-editor.blade.php`
- `resources/views/livewire/admin/cms/display-dashboard.blade.php`
- `resources/views/components/layouts/app/sidebar.blade.php`
- `tests/Feature/DisplayVersionTest.php`

Umsetzung:
- Neue Routen: `admin/cms/display-modules` und `admin/cms/display-modules/{displayVersion}/edit`
- Neue Routennamen: `admin.cms.display-modules` und `admin.cms.display-module-edit`
- Alte `display-versions`-Routen bleiben erhalten und leiten per 301 auf die Modul-Routen weiter
- Sidebar, Dashboard, Listen- und Editor-Texte verwenden „Module“
- Technische Modell-/Klassennamen bleiben bis Phase 7 kompatibel bei `DisplayVersion`

#### Tests

```text
tests/Feature/DisplayVersionTest.php         – ok
tests/Feature/DisplayVersionApiTest.php      – ok
tests/Feature/DisplayListTest.php            – ok
tests/Feature/DisplayPlaylistMigrationTest.php – ok
```

Insgesamt 64 grüne Tests für Phasen 5/6 und die angrenzenden Display-Flows. Pint clean.

