diff --git a/ROADMAP.md b/ROADMAP.md index c83e7e5..4a28fe1 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -416,10 +416,12 @@ irrelevant und kann komplett raus." ## Ideen-Katalog (Rest) — bewusst offen -1. **Design 2.0** (kommt in eine frische Session, Commander-Entscheid): - `dark:`-Klassen statt Theme-Ternaries — Infrastruktur steht komplett, - reine mechanische Konvertierung pro Komponente. Der neue Anleitungs-Tab - gehört mit in den Feinschliff. +1. **Design 2.0** — an Gemini übergeben (24.07.2026). Vollständiges + Briefing: `docs/DESIGN-2.0-BRIEFING.md`. Arbeitsbranch: `design-2.0` + (deployt bewusst NICHT, nur `main` wird befördert). Kern: 428 + `theme === 'dark'`-Ternaries → Tailwind-`dark:` + UI-Primitives, + Optik-Modernisierung, ohne Funktions-/Text-Änderungen. Der neue + Anleitungs-Tab gehört mit in den Feinschliff. 2. **AI-Box als VAAPI-Transcode-Worker**: Ports sind offen, Compose steht (deploy/remote-transcode-worker.yml) — es fehlt nur der NFS/SMB-Export der Rippy-Ablage an die AI-Box (Infra-Entscheid auf der VM). diff --git a/docs/DESIGN-2.0-BRIEFING.md b/docs/DESIGN-2.0-BRIEFING.md new file mode 100644 index 0000000..6b8667d --- /dev/null +++ b/docs/DESIGN-2.0-BRIEFING.md @@ -0,0 +1,298 @@ +# Design 2.0 — Briefing (Übergabe an Gemini) + +> Dieses Dokument ist die vollständige Auftragsbeschreibung für den UI-Umbau +> „Design 2.0". Es ist so geschrieben, dass ein zweites KI-Modell (Gemini) +> eigenständig loslegen kann. Stand: 24.07.2026, vorbereitet von Claude. + +--- + +## 0. Auftrag in einem Satz + +Das Rippy-Web-UI von 428 handgeschriebenen `theme === 'dark' ? … : …`- +Ternaries auf ein **sauberes, token-basiertes Tailwind-`dark:`-System** +umstellen und dabei die Optik auf ein modernes, konsistentes „Design 2.0" +heben — **ohne** Funktion, API-Aufrufe, deutsche Texte oder die +Deploy-Kette anzufassen. + +--- + +## 1. Was Rippy ist (Kontext in 30 Sekunden) + +Rippy ist eine self-hosted Disc-Ripping-Maschine (CD/DVD/Blu-ray/4K-UHD): +Disc rein → automatisch erkannt → verlustfrei gerippt (MakeMKV) → +komprimiert (HandBrake) → Media-Server-fertig abgelegt. Alles Docker, +alles im Heimnetz. Das UI ist die einzige Bedienoberfläche. + +**Tech-Stack UI** (`docker/ui/`): +- React 18 + TypeScript + Vite +- TailwindCSS (`darkMode: 'class'`) +- lucide-react (Icons) +- Kein Router (Seitenwechsel über `useState` in `App.tsx`) +- State: lokale Hooks + Polling gegen die REST-API (`src/lib/api.ts`, + axios, `baseURL: '/api'`) + +**Sprach-Konvention (AGENTS.md Regel 4):** Variablen-/Funktionsnamen auf +Englisch, **alle Kommentare, UI-Texte und Docs auf Deutsch**. Der Betreiber +(„Commander") ist Nicht-Entwickler und liest alles. + +--- + +## 2. Der Kern des Problems + +Jede Komponente entscheidet Farben **zur Laufzeit per Ternary**: + +```tsx +// SO sieht es HEUTE ~428× aus: +
+``` + +Das ist der größte technische Schuldenberg des UI: +- **428 Ternaries** in 18 Dateien (Inventar unten) — jede Farbe doppelt + gepflegt, Copy-Paste-Fehler vorprogrammiert. +- Jede Komponente zieht dafür `const { theme } = useDarkMode()` — Rendering + hängt an einem Context-Wert, den es fast nie bräuchte. +- Wiederkehrende Farb-Mappings sind **mehrfach dupliziert** statt zentral: + `StatusBadge` (Dashboard), `getLevelColor` (Logs), `getTypeColor` + (DeviceDiscovery) definieren jeweils eigene Status→Farbe-Tabellen. + +### Warum das JETZT ein leichter Umbau ist + +Die Infrastruktur für den sauberen Weg **steht bereits vollständig**: +- `tailwind.config.js`: `darkMode: 'class'` ✅ +- `ThemeContext.tsx` setzt beim Umschalten `document.documentElement. + classList.add('dark')` — also `.dark` auf `` ✅ +- Damit funktionieren Tailwinds `dark:`-Varianten sofort überall. + +Konkret heißt Migration also fast immer nur: + +```tsx +// NACHHER — kein Ternary, kein useDarkMode nötig: +
+``` + +### Drei Altlasten, die mit aufgeräumt werden sollten + +1. **Tote CSS-Variablen** (`src/index.css`): Es gibt `:root { --bg-color … }` + und `[data-theme="dark"] { … }`. Der Dark-Block ist **toter Code** — + nichts setzt jemals `data-theme` (der Theme-Umschalter nutzt die + `.dark`-Klasse). Entweder die Variablen korrekt an `.dark` binden ODER + (empfohlen) ganz auf Tailwind-`dark:` setzen und die Variablen entfernen. +2. **Globale Transition** (`src/index.css`): `* { transition: + background-color .3s, color .3s, border-color .3s; }` lässt bei jedem + Theme-Wechsel die GESAMTE Seite animieren (Jank-Risiko) und macht die + überall verstreuten `transition-colors duration-300`-Klassen doppelt. + Auf einen bewussten, schmalen Transition-Ansatz reduzieren. +3. **Icon-Inkonsistenz**: Fast alles nutzt `lucide-react`, aber + `ConfirmDialog.tsx` nutzt Emoji (⚠️✅🤔) als „Icons". Vereinheitlichen. + +--- + +## 3. Empfohlener Weg (technisch) + +**Nicht** blind 428 Ternaries per Hand ersetzen — das ist fehleranfällig. +Stattdessen in zwei Schichten: + +### Schicht A — Wiederverwendbare Primitives (`src/components/ui/`) + +Ein kleines Set typisierter Bausteine, die das Design kapseln. Heute wird +jedes davon in jeder Datei neu zusammengeklöppelt: + +- `Card` / `CardHeader` — die `rounded-xl border bg-white dark:bg-slate-800`- + Kachel (kommt ~30× vor) +- `Button` (Varianten: primary / secondary / ghost / danger) +- `Badge` (Status/Typ-Pill mit zentraler Farbtabelle — löst die 3 Duplikate) +- `Input` / `Select` / `Toggle` (Formularfelder, heute inline-dupliziert) +- `Modal` (der `fixed inset-0 … backdrop-blur`-Rahmen — 4× dupliziert: + RipTargetModal, JobDetailModal, MetadataKorrektur, ConfirmDialog) +- `Section` / `PageHeader` (Seiten-Titel + Untertitel, überall gleich) + +Farbwelt/Status **einmal zentral** definieren (z. B. +`src/lib/design.ts`), damit Status→Farbe nur an EINER Stelle lebt: + +```ts +export const STATUS_STYLES = { + pending: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400', + processing: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', + transcoding: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400', + completed: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400', + failed: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400', + // Disc-Typen: cd=blue, dvd=purple, bluray=pink, uhd=amber +} as const +``` + +### Schicht B — Seiten/Komponenten auf die Primitives umstellen + +Datei für Datei die Ternaries durch `dark:`-Klassen bzw. die neuen +Primitives ersetzen. `const { theme } = useDarkMode()` fällt dabei in +fast allen Dateien weg (nur `App.tsx` braucht `toggleTheme` noch). + +### Optional als echtes „2.0": Tailwind-Theme-Tokens + +Statt roher `slate-*`/`indigo-*`-Klassen semantische Tokens in +`tailwind.config.js` (`theme.extend.colors`) definieren +(`surface`, `surface-muted`, `border-subtle`, `accent`, `text-primary`, +`text-muted` …) und diese nutzen. Das macht spätere Farb-Anpassungen zu +einer Ein-Zeilen-Änderung. **Kür, kein Muss** — die `dark:`-Umstellung +ist der Pflichtteil. + +--- + +## 4. Design-Richtung (Leitplanken, nicht Korsett) + +Die bestehende Farbwelt ist bereits kohärent — bitte **systematisieren und +verfeinern, nicht wild neu erfinden**. Referenz aus dem Ist-Zustand: + +- **Akzent/Primär:** Indigo (`indigo-600`), Verlauf `indigo-500 → purple-600` + (Logo, Buttons, aktive Nav) +- **Flächen:** hell `slate-50` (Seite) / `white` (Karten); dunkel + `slate-950`/`slate-900` (Seite) / `slate-800` (Karten) +- **Ränder:** `slate-200` hell / `slate-700` dunkel +- **Status:** amber=wartend/Warnung, blue=Bearbeitung/Info, + purple=Komprimieren, emerald=fertig/Erfolg, rose=Fehler; Disc-Typen: + cd=blue, dvd=purple, bluray=pink, **uhd=amber** (bewusst abgesetzt) +- **Typo:** system-sans (siehe `index.css`), Überschriften `font-bold` + +**Spielraum für 2.0** (gern, solange konsistent + zugänglich): +Abstände/Rhythmus vereinheitlichen, Karten-Schatten/Radien harmonisieren, +Empty-States aufwerten, Fokus-/Hover-Zustände konsistent, bessere +Dichte in den Tabellen, der neue **Anleitung**-Tab (`pages/Anleitung.tsx`) +darf visuell aufgewertet werden. Barrierefreiheit im Blick behalten +(Kontrast, Fokus-Ringe, `aria-*` wo sinnvoll). + +Es gibt eine `Skill`/Guideline „Web Interface Guidelines" — an modernen +Best-Practices orientieren. + +--- + +## 5. HARTE Regeln (nicht verhandelbar) + +1. **Nur UI, nur `docker/ui/src/`** (+ ggf. `tailwind.config.js`, + `index.css`, `index.html`). **Kein** Backend (`docker/api`, + `docker/worker`), **keine** API-Verträge, **keine** `docker-compose.yml`. +2. **Funktion bleibt 1:1.** Alle bestehenden Features, Flows, API-Calls, + Polling-Intervalle, Feldnamen im POST-Body bleiben exakt erhalten. Das + ist ein **Re-Skin + Refactor**, kein Feature-Umbau. Im Zweifel: + Verhalten unverändert lassen. +3. **Deutsch bleibt Deutsch.** Kein UI-Text wird übersetzt oder + umformuliert (außer offensichtliche Tippfehler). Kommentare Deutsch. +4. **Die CI-Ampel MUSS grün bleiben** (`.gitea/workflows/ci.yml`): bei + jedem Push laufen Ruff, pytest UND `npm run build` (Vite). Ein + TypeScript-/Build-Fehler = rot = nicht fertig. Nach JEDER umgestellten + Komponente lokal `npm run build` grün halten. +5. **`package-lock.json` committen**, falls neue Abhängigkeiten dazukommen + (die Ampel prüft Reproduzierbarkeit). Neue Runtime-Deps sparsam — das + Ziel ist weniger Code, nicht mehr. +6. **AGENTS.md gelesen halten** (Repo-Wurzel) — die dortigen Regeln gelten. + +--- + +## 6. Datei-Inventar (Fahrplan, Stand 24.07.2026) + +Sortiert nach Aufwand. Zahlen = `theme === 'dark'`-Ternaries in der Datei. + +| Datei | Zeilen | Ternaries | Hinweis | +|---|---:|---:|---| +| `pages/Settings.tsx` | 860 | **128** | Größter Brocken; viele Tabs — evtl. in Unterkomponenten pro Tab zerlegen | +| `pages/Dashboard.tsx` | 504 | 44 | Enthält `StatusBadge`/`TypeBadge`/`ProgressBar`/`StatCard` → in Primitives heben | +| `components/DeviceDiscovery.tsx` | 381 | 43 | Disc-Karte + Laufwerks-Liste; `getTypeColor`/`getStatusColor` zentralisieren | +| `components/RipTargetModal.tsx` | 401 | 37 | Modal + Track-Tabelle + Serien-Felder | +| `pages/Logs.tsx` | 246 | 34 | `getLevelColor`/`getLevelIcon`/`getLevelLabel` → zentral | +| `components/StorageMounts.tsx` | 361 | 33 | Mounts + Ordner-Browser | +| `components/JobDetailModal.tsx` | 239 | 28 | Modal, Download-Liste | +| `components/FirstRunWizard.tsx` | 192 | 22 | Onboarding | +| `components/WorkerVerwaltung.tsx` | 214 | 18 | Worker-Liste + Anbinde-Befehle | +| `components/LiveLogSection.tsx` | 147 | 15 | Live-Log-Kachel | +| `components/MetadataKorrektur.tsx` | 145 | 10 | Korrektur-Popup | +| `pages/Anleitung.tsx` | 180 | 7 | Neu; darf visuell aufgewertet werden | +| `components/ConfirmDialog.tsx` | 83 | 6 | Emoji-Icons → lucide | +| `App.tsx` | 101 | 2 | Sidebar/Nav/Footer; behält `toggleTheme` | +| `context/ThemeContext.tsx` | 52 | 1 | Bleibt im Kern; ggf. `data-theme` synchron setzen, falls CSS-Variablen genutzt werden | +| `context/ToastContext.tsx` | 62 | 0 | Nutzt schon `dark:` teils — als Vorbild ansehen | + +**Gesamt: 428 Ternaries.** Bereits `dark:`-Klassen im Code: nur 7 — +d. h. `ToastContext` und Reste zeigen das Zielbild. + +**Empfohlene Reihenfolge:** erst Schicht A (Primitives + `design.ts`), +dann die kleinen Dateien (`ConfirmDialog`, `App`, `LiveLogSection`) als +Kalibrierung, dann die großen. `Settings.tsx` zuletzt (größter Nutzen aus +den dann fertigen Primitives). + +--- + +## 7. Arbeitsweise & Branch + +- **Auf einem eigenen Branch arbeiten** (angelegt: `design-2.0`). Wichtig: + Die Deploy-Kette befördert **nur `main`** automatisch auf `stable` und + von dort auf die Live-VM. Ein Feature-Branch lässt die Ampel laufen + (Feedback grün/rot), deployt aber NICHT — ideal für einen großen Umbau. + Erst wenn Design 2.0 fertig & abgenommen ist, wird der Branch nach `main` + gemerged. +- **Klein committen**, eine sinnvolle Einheit pro Commit (z. B. „Primitives: + Card + Button", dann „Dashboard auf Primitives umgestellt"). Commit-Text + Deutsch, WAS + WARUM. +- **Nach jeder Komponente**: `npm run build` muss grün sein. Nie einen + roten Zwischenstand pushen. +- Visuell gegenprüfen: hell UND dunkel testen (Theme-Umschalter oben in der + Sidebar). + +--- + +## 8. Verifikation (die exakten Befehle) + +```bash +cd docker/ui +npm ci # einmalig +npm run build # MUSS grün sein — das prüft auch die Ampel +``` + +Lokal ansehen (Dev-Server): +```bash +cd docker/ui && npm run dev +``` +Das UI erwartet die API unter `/api` (nginx-Proxy). Für reine Design- +Arbeit reicht der Dev-Server; leere Listen/Fehlerzustände sind normal ohne +laufendes Backend. Wer gegen echte Daten testen will: Das Live-System läuft +im Heimnetz (Zugang beim Commander erfragen). + +Die **komplette** Ampel (wie in CI) prüft zusätzlich Backend-Tests — die +sind von reiner UI-Arbeit nicht betroffen, müssen aber grün bleiben (nicht +anfassen). + +--- + +## 9. Definition of Done + +- [ ] `src/components/ui/`-Primitives existieren und werden genutzt +- [ ] Status/Typ/Level-Farben zentral (`src/lib/design.ts`), keine + duplizierten Farb-Mappings mehr +- [ ] `grep -rn "theme === 'dark'" src/` ergibt **~0** Treffer (idealerweise + nur noch in `ThemeContext`/`App` das Nötigste) +- [ ] Tote CSS-Variablen (`[data-theme="dark"]`) und globale `* { + transition }` bereinigt +- [ ] `ConfirmDialog` nutzt lucide statt Emoji +- [ ] Hell- UND Dunkelmodus überall konsistent, keine „weiße Karte im + Darkmode"-Ausrutscher +- [ ] `npm run build` grün; keine neuen TS-Fehler/Warnungen +- [ ] Keine funktionale Änderung (alle API-Calls/Flows identisch) +- [ ] Alle deutschen Texte unverändert +- [ ] Auf Branch `design-2.0`, sauber committet, bereit für Review/Merge + +--- + +## 10. Copy-Paste-Startprompt für Gemini + +> Du übernimmst „Design 2.0" für das Rippy-Web-UI (React + TypeScript + +> Vite + TailwindCSS, `darkMode: 'class'`). Lies zuerst +> `docs/DESIGN-2.0-BRIEFING.md` KOMPLETT — dort stehen Auftrag, harte +> Regeln, Datei-Inventar, empfohlener Weg und die Definition of Done. +> Arbeite ausschließlich in `docker/ui/`, auf dem Branch `design-2.0`. +> Kernauftrag: 428 `theme === 'dark' ? …`-Ternaries durch Tailwind-`dark:`- +> Klassen + wiederverwendbare UI-Primitives ersetzen und die Optik +> modernisieren — OHNE Funktion, API-Aufrufe oder deutsche Texte zu ändern. +> Halte nach jeder umgestellten Komponente `npm run build` grün. Beginne +> mit den UI-Primitives (`src/components/ui/`) und `src/lib/design.ts`, +> dann die kleinen Dateien, dann die großen (`Settings.tsx` zuletzt). +> Kommentare und Commit-Texte auf Deutsch.