Rebrand Hub+Flux
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-20 15:44:15 +02:00
parent 0a3e52d603
commit 9b47296cea
130 changed files with 9357 additions and 3345 deletions

View file

@ -5,6 +5,920 @@
---
## 2026-05-20 · Phase 6 · Auth-Cleanup ✅
Mit Phase 6 ist die hub-flux-Roadmap (Phase 06) **vollständig
abgeschlossen**. Schlanker Cleanup-Task ohne Risiko.
**Inventur** (Referenzen geprüft via `rg` über `resources/` + `routes/`):
| Datei | Status |
|---|---|
| `components/layouts/app/sidebar.blade.php` | aktiv (primäres Portal-Layout) |
| `components/layouts/auth/pressekonto.blade.php` | aktiv (6 Auth-Pages) |
| `components/layouts/auth.blade.php` | nur in `login-simple`/`test-simple` → weg |
| `components/layouts/auth/simple.blade.php` | Starter-Kit-Rest mit hardcoded `class="dark"` → weg |
| `components/layouts/auth/split.blade.php` | dito → weg |
| `components/layouts/auth/card.blade.php` | dito → weg |
| `components/layouts/app/header.blade.php` | nirgends referenziert → weg |
| `livewire/auth/login-simple.blade.php` | Debug-Page ohne Route → weg |
| `test-simple.blade.php` | Debug-Page ohne Route → weg |
**Gelöscht**: 7 Files, insgesamt ~17 KB Code
**Aktualisiert**: `_docs/FORTIFY-SANCTUM-SETUP.md` (Code-Beispiel
von `components.layouts.auth` auf `components.layouts.auth.pressekonto`).
**Side-Effect**: Portal-CSS-Bundle ist ~2.4 KB kleiner geworden
(422.62 KB statt 425.07 KB), weil weniger Klassen via Tailwind
JIT entdeckt werden.
**Validierung**:
- `php artisan view:clear && npm run build:portal` → grün
- `vendor/bin/pint --dirty --format agent` → passed
- Tests: 230/231 (nur der bekannte pre-existing
`ApiDocumentationTest`)
**Roadmap-Update**:
- `03-WEITERE-PHASEN.md` Phase 6 von „⚪ optional
(Auth-Konsolidierung)" auf „✅ abgeschlossen (Auth-Cleanup)"
umgestellt
- Status-Tabelle: Phase 6 ✅
- „Nächste Schritte" angepasst: kein hub-flux-Item mehr offen,
nur noch eigenständige Initiativen (Dark-Mode-Smoke-Test,
PM-Form-Wizard-Refactor, Web-Frontend-Block)
**Lesson**: Mit der Anti-Flash-Bridge aus Phase 5 wären die
hardcoded `class="dark"`-Layouts zu einer Stolperfalle für
Light-Mode-User geworden, sobald jemand sie reaktiviert hätte.
Cleanup zum richtigen Zeitpunkt.
Plan-Doc: `18-PHASE-6-AUTH-CLEANUP.md`
---
## 2026-05-20 · Phase 5 · Dark-Mode-Bugfixes (User-Findings)
Nach dem ersten visuellen Smoke-Test des Users zwei Folge-Fixes
geliefert, plus die Anti-Flash-Bridge:
### Fix 1 — Logo „presse" im Dark Mode
`components/web/brand-mark.blade.php`: Bei `variant="auto"` (Default)
wird die Name-Farbe jetzt über CSS-Custom-Property `--brand-mark-name-color`
mit Light-Mode-Fallback gesetzt. Im Portal-Dark-Mode setzt
`design-tokens.css` `.dark`-Block die Variable auf `#ffffff`. Hub-Frontend
ist Light-Only, dort bleibt die Variable undefiniert und der Marken-
Standardwert greift.
### Fix 2 — Navlist-Flackern beim Klick
`portal.css` Navlist-Item-Block:
- Hover im Dark Mode auf `var(--color-hub-soft)` (Light-Mode-Hover
`var(--color-bg)` ist dunkler als die Sidebar — wirkte als
„Eindrücken" statt Hervorheben)
- `:active`, `:focus` explizit auf `var(--color-hub-soft)` mit
`outline: none` → verhindert Browser-Default-Tap-Flash
- `-webkit-tap-highlight-color: transparent` für mobile Browser
- `:focus-visible` mit Hub-Ring für Tastatur-A11y bleibt erhalten
### Fix 3 — Anti-Flash-Bridge (FOLT bei `wire:navigate`)
Bei `wire:navigate` morpht Livewire das DOM, das neue HTML kommt
vom Server **ohne** `class="dark"` (Server kennt LocalStorage nicht).
Folge: kurzer weißer Theme-Flash, bis JS die Klasse wieder anhängt.
User hat das richtig diagnostiziert.
Lösung:
1. **JS-Bridge** in `partials/head.blade.php` +
`partials/admin-head.blade.php`: wrappt
`window.Flux.applyAppearance`, spiegelt den effektiv applizierten
Modus (bei `system` aus DOM-Klasse abgelesen → `dark`/`light`)
in ein `flux_appearance`-Cookie. Schreibt auch beim initialen
Page-Load.
2. **Server-Side Render**: `<html>`-Tag in
`components/layouts/app/sidebar.blade.php` und
`layouts/admin-master.blade.php` setzt `class="dark"`
direkt, basierend auf dem Cookie:
`@class(['dark' => request()->cookie('flux_appearance') === 'dark'])`
3. **Bonus**: hardcoded `class="dark"` aus `admin-master.blade.php`
raus (war Light-User-Bug-Falle).
Erstbesuch: einmaliger Flash (Cookie noch nicht gesetzt).
Alle weiteren Pageloads: kein Flash mehr.
### Latente Bug-Fixes nebenbei
- `customer/tokens.blade.php` Z. 137: `--color-ink-deep` Token war
nie definiert → durch `--color-panel-dark-2` ersetzt (konstant
dunkel in beiden Modi)
- `customer/security.blade.php` 2FA-QR: erklärender Kommentar für
`bg-white` (Scan-Tauglichkeit)
**Validierung**:
- Build, Pint, Tests: 230/231 (nur ApiDocumentationTest)
---
## 2026-05-20 · Phase 5 · Dark Mode ✅
Phase 5 (Dark Mode) ist abgeschlossen. Die meiste Arbeit war
faktisch schon in Phase 04 erledigt — die konsequente
Token-Disziplin zahlt sich jetzt voll aus.
**Was schon da war (Stand bei Phase-5-Start):**
- `shared/design-tokens.css` hat einen kompletten
`.dark { … }`-Block (Z. 182248) mit allen Surfaces,
Hub-Blau (heller), Bernstein (heller, mit konstantem
`--color-accent-warm`), Ink-Skala (invertiert),
Status-Farben, Bridge-Dots, Schatten und `color-scheme: dark`
- `portal.css` hat `@custom-variant dark (&:where(.dark, .dark *))`
+ Dark-Mode-Shadow-Overrides für Primary-Buttons
- `hub-components.css` ist 100 % token-basiert
- `panel-dark` nutzt `--color-panel-dark*` (konstant)
- `@fluxAppearance` in beiden Head-Partials integriert
- Switcher in Sidebar (Desktop + Mobile) +
`settings/appearance.blade.php`
**Was im Rahmen von Phase 5 gefixt wurde:**
1. **`customer/tokens.blade.php` Z. 137** — Token-Anzeige
nutzte ein nicht existentes `--color-ink-deep`. Damit war
der Code-Block bisher transparent (im Dark Mode wäre
`--color-ink` hell → weißer Text unlesbar). Umgestellt auf
`--color-panel-dark-2` (konstant dunkel, weißer Text in
beiden Modi korrekt).
2. **`customer/security.blade.php` Z. 270** — 2FA-QR-Code in
`bg-white`. Bewusst belassen (QR-Codes brauchen
schwarz-auf-weiß für Scan-Tauglichkeit), erklärender
Kommentar ergänzt.
**Was unkritisch ist (kein Fix):**
- Alle weiteren `bg-white` / `text-white`-Treffer in
`customer/dashboard.blade.php` sind im `panel-dark` Block
(konstant dunkel) oder auf `--color-accent` (Bernstein in
beiden Modi) — passt
- `admin/dashboard.blade.php` Quick-Action Hover
(`group-hover:bg-hub group-hover:text-white`) — Hub-Bg ist
in beiden Modi dunkel genug für weißen Text
- `customer/press-kits/show.blade.php` Logo-Bg `bg-white`
bewusst, weil Firmen-Logos einen weißen Bg brauchen
- Sidebar-`dark:bg-zinc-*` Helper aus dem Starter-Kit —
Zinc-Skala ist in `portal.css` auf warmes Buchpapier
gemapped, läuft
**Außerhalb Phase 5:**
- `shared-styles.css` hat `.dark .card`, `.dark .slider-*`,
`.dark .highlight-*`, `.dark .section-*` — diese sind für
den Web-Bereich (Hub-Frontend, presseecho,
businessportal24). `portal.css` importiert
`shared-styles.css` **nicht** — keine Kollision.
- Web-Frontend bleibt Light-Only (per Roadmap-Definition)
**Validierung:**
- Build: `npm run build:portal` → grün
- Pint: `vendor/bin/pint --dirty --format agent` → passed
- Tests: 230/231 (1 pre-existing `ApiDocumentationTest`, kein
Bezug zur UI-Migration)
**Empfehlung:** Im Browser einmal User-Menü →
Erscheinung → „Dunkel" + Dashboard/Listen/Detail/Security
(QR)/Tokens visuell durchklicken für den Smoke-Test (Pest
hat keine echte Rendering-Pipeline).
Roadmap-Update:
- `03-WEITERE-PHASEN.md` Phase 5 von „⚪ später" auf
„✅ abgeschlossen" gesetzt
- Status-Tabelle aktualisiert
- Empfehlungen verschoben: Phase 6 Auth-Cleanup +
manueller Smoke-Test nach oben
Plan-Doc: `17-PHASE-5-DARK-MODE.md`
---
## 2026-05-20 · Phase 4 · offiziell abgeschlossen ✅
Mit dem Abschluss von 4J ist Phase 4 (Listen/Detail-Pages
durchgehen) in allen 10 Sub-Päckchen 4A4J durch:
| ID | Bereich |
|---|---|
| 4A | Press-Releases Listen (Admin + Customer) |
| 4B | Press-Releases Detail/Show |
| 4C | Press-Releases Forms (create/edit) |
| 4D | Companies (Admin) |
| 4E | Profile/Settings (Admin + Customer) |
| 4F | Restliche Admin-Bereiche (12 Module) |
| 4G | Restliche Customer-Bereiche (5 Module) |
| 4H | Customer „Meine Pressemitteilungen" Mockup-Stil |
| 4I | Admin „Pressemitteilungen" — Patterns übertragen |
| 4J | Dashboard-PM-Listen mit 4H/4I-Patterns |
**Roadmap-Cleanup**:
- `03-WEITERE-PHASEN.md` Phase 4 von „🚧 iterativ" auf
„✅ komplett abgeschlossen" gesetzt
- Phase 2 + 3 (Customer- + Admin-Dashboard) waren faktisch
schon in Phase 1 umgesetzt — Status retroaktiv auf
✅ korrigiert (mit Hinweis auf 4J-Verfeinerung)
- Neuer „Gesamt-Status"-Block in `03-WEITERE-PHASEN.md`
mit Phasen-Tabelle, Sub-Päckchen-Tabelle und konkreten
Empfehlungen für die nächsten Schritte (Phase 5 Dark
Mode > Phase 6 Auth-Cleanup > Web-Frontend-Block als
eigene Roadmap)
- Erkenntnis: Das Mockup `Veröffentlichen Tailwind.html`
ist eine **Public-Facing-Landing-Page** von
businessportal24 (Web-Frontend), nicht ein
Backend-PM-Wizard. Gehört in den separaten
Web-Frontend-Block, nicht in Phase 4.
**Verifikationsstand**:
- 230/231 Tests grün (1 pre-existing
`ApiDocumentationTest`-Fail, unverändert seit 4D)
- Build (Portal) sauber: 424 KB CSS / 16 KB JS gzipped
- Pint sauber
- 16 Plan-Dokumente in `dev/frontend/hub-flux/`
(`00``16` + `PROGRESS.md` + `README.md`)
---
## 2026-05-20 · Phase 4J · Dashboard-PM-Listen mit 4H/4I-Patterns
- **Anlass**: Nach 4H/4I sahen die Voll-Listen exakt wie
das Mockup aus, aber die kompakten PM-Listen in den
Dashboards waren noch im alten Stand (Badge rechts,
Sub-Zeile ohne Portal). 4J schließt diese Inkonsistenz.
- **Befund**: Beide Dashboards waren bereits in Phase 1
großzügig Hub-styled (Page-Header, KPI-Reihe,
`<x-portal.stat-card>`, `<x-portal.hint-card>`,
`panel-dark` Brand-Bridge usw.) — die Roadmap-Status
„⚪ später" für Phase 2 + 3 waren also veraltet und
wurden im Zuge dieses Päckchens auf ✅ gesetzt.
- **Plan-Dokument**: `16-PHASE-4J-DASHBOARD-LISTS.md`.
### Customer-Dashboard (`customer/dashboard.blade.php`)
- Volt: `recent` Select um `portal` + `published_at`
erweitert
- `recent`-Liste:
- Portal-Pills (`pe`/`bp`) neben dem Badge (Both → beide
Pills)
- Sub-Zeile mit `PM-{id} · Firma · Datum`
- `published_at` als Primärdatum für veröffentlichte PMs
- Badge-Mapping erweitert (`muted` für archived/draft
statt `hub`)
### Admin-Dashboard (`admin/dashboard.blade.php`)
- `recentPRs`-Liste:
- Portal-Pills neben Badge (Both → beide Pills)
- Sub-Zeile mit `PM-{id} · Firma · User · Datum`
- Badge-Mapping mit `muted` für archived/draft
- `pendingReviews`-Liste (Review-Queue):
- Row-Tinting `is-row-warn` (gelblich) für alle Items
- Inline-Action „Prüfen →" rechts oben (Link zur
Show-Page, weil Admin-Dashboard Controller+Blade ist
und keine direkte Wire-Methode hat)
- Portal-Pills unter dem Titel
- Container von `<a>` zu `<div>` umgestellt, weil zwei
Links nebeneinander (Titel-Link + Inline-Action) sonst
HTML-invalid wären
- Hover-Underline auf Titel-Link für klare Klickbarkeit
### Tests/Verifikation
- `DashboardTest` (Customer) → 5/5 grün, 21 Assertions
- Volle Suite → 230/231 grün, 1 pre-existing Fail
(`ApiDocumentationTest`)
- `npm run build:portal` → grün (424 KB CSS, +0,2 KB)
- `vendor/bin/pint --dirty` → passed
### Dateien
- `dev/frontend/hub-flux/16-PHASE-4J-DASHBOARD-LISTS.md` (neu)
- `resources/views/livewire/customer/dashboard.blade.php`
- `resources/views/admin/dashboard.blade.php`
- `dev/frontend/hub-flux/PROGRESS.md` (dieser Eintrag)
- `dev/frontend/hub-flux/03-WEITERE-PHASEN.md` (4J +
Phase 2/3 retroaktiv auf ✅)
---
## 2026-05-20 · Phase 4I · Admin „Pressemitteilungen" auf Mockup-Patterns
- **Anlass**: Direktes Folgepäckchen zu 4H — die in der Customer-Liste
entwickelten Mockup-Patterns werden auf die zentrale
Admin-Pressemitteilungen-Liste übertragen (Editorial-Workflow).
- **Plan-Dokument**: `15-PHASE-4I-ADMIN-PRESS-RELEASES.md`.
### Volt-Komponente erweitert (`admin/press-releases/index.blade.php`)
- `pressReleaseStats()` um `rejected` + `archived` Counter
erweitert (zwei zusätzliche `selectRaw` im gleichen Statement,
weiter über `AdminPerformanceCache`)
- Neue Methoden: `setView($view)` (setzt Statusfilter +
resetPage), `resetFilters()` (kompletter Reset inkl.
Entity-Lookups)
### Markup auf Mockup-Stil
- **Saved-Views-Tabs**: 6 Tabs (Alle, In Prüfung,
Veröffentlicht, Entwürfe, Abgelehnt, Archiv) mit
Counter-Pillen, `is-active`-State spiegelt `$statusFilter`
- **Active-Chips** unter Filter-Panel: 8 Filter-Typen
(Suche, Status, Portal, Sprache, Kategorie, User, Firma,
Kontakt) mit Remove-Button + „Alle zurücksetzen"-Link
- **Tabelle umgestellt** (8 → 7 Spalten):
- Status + Inline-Action (Freigeben/Ablehnen für Review,
Archivieren für Published) — Inline-Actions sind
`flux:modal.trigger` für die bestehenden, test-kritischen
Modals
- Titel mit Sub-Zeile (PM-ID + Firma + Sprache, klickbar)
- Portal-Pills (presseecho/businessportal24, bei
`Portal::Both` beide nebeneinander)
- Kategorie (truncate)
- Datum mit Status-Kontext-Sub („veröffentlicht · HH:MM",
„eingereicht · HH:MM", …) und `published_at` als
Primärdatum wenn vorhanden
- Hits monospace
- Aktionen-Spalte rechts reduziert auf view + edit
(Status-Actions wandern in die Status-Zelle)
- **Row-Tinting**: review → `is-row-warn`,
rejected → `is-row-err`
- **Empty-State 2-stufig**: „mit Filter" → Reset-CTA,
„ohne Filter" → Anlegen-CTA
### Was unangetastet bleibt (Test-kritisch)
- `publish()`, `reject()`, `archive()`, `sort()`,
`with()`, alle `clearXFilter()`, `resetEntityFilters()`
- 3 Modals mit Strings „Pressemitteilung veröffentlichen?",
„Pressemitteilung ablehnen?", „Pressemitteilung
archivieren?" — werden weiter vom Markup gemountet,
jetzt zusätzlich via Inline-Action triggerbar
- Combobox-Lookups für User/Firma/Kontakt (Schema +
Verhalten unverändert)
### Pitfall + Fix
- `@php(...)` Inline-Form kompilierte zu `<?php($var = ...)`
ohne Whitespace → PHP-Syntax-Fehler trotz balancierter
Klammern. Workaround: alle drei Inline-`@php(...)` zu
Block-`@php ... @endphp` umgewandelt.
### Verifikation
- `npm run build:portal` → grün (424 KB CSS, +5 KB ggü. 4H)
- `vendor/bin/pint --dirty` → passed
- Gezielt: `AdminPressReleaseActionsTest` +
`PressReleaseWorkflowTest` → 16/16 grün, 52 Assertions
- Volle Suite: 230/231 grün, 1 pre-existing Fail
(`ApiDocumentationTest` — fehlende `docs/api/v1.yml`,
unverändert seit 4D), 3 skipped, 1212 Assertions
### Dateien
- `dev/frontend/hub-flux/15-PHASE-4I-ADMIN-PRESS-RELEASES.md` (neu)
- `resources/views/livewire/admin/press-releases/index.blade.php`
- `dev/frontend/hub-flux/PROGRESS.md` (dieser Eintrag)
- `dev/frontend/hub-flux/03-WEITERE-PHASEN.md` (4I-Eintrag)
---
## 2026-05-20 · Phase 4H · Customer „Meine Pressemitteilungen" auf Mockup
- **Anlass**: Nach Abschluss von 4F entschied sich der User
bewusst gegen die nächste Roadmap-Phase und für **detail-tief
in das wichtigste Customer-Arbeitstool** zu gehen. Vorlage:
`dev/frontend/tailwind_v3/User Pressemitteilungen presseportale.html`.
- **Plan-Dokument**: `14-PHASE-4H-PRESS-RELEASES-MOCKUP.md`.
### Hub-CSS erweitert (`resources/css/shared/hub-components.css`)
Neue Komponenten — alle aus Tokens, KEINE Hex-Literale:
- `.counter-strip` + `.seg` (mit `is-ok`, `is-warn`, `is-err`, `is-muted`) + `.sep`
- `.view-tabs` + `.view-tab` (mit `is-active`, `cnt`-Pille)
- `.filter-chip` (mit `is-active`, `caret`)
- `.active-chip` (mit `x`-Remove-Button)
- `.portal-pill` (mit `pe` + `bp` Dot-Varianten, nutzt
`--color-bridge-presseecho` / `--color-bridge-businessportal`)
- `.inline-action` (mit `warn` + `err` Varianten)
- `.is-row-warn` + `.is-row-err` (Row-Tinting via
`color-mix` aus Status-Soft-Token gegen Card-Background)
- `.empty-stage` + `.empty-ico` (mit `warm` + `err` Varianten)
+ `.empty-title` + `.empty-sub`
- `.badge.muted` (neue Variante neben `ok`, `warn`, `err`, `hub`)
### Volt-Komponente erweitert (`customer/press-releases/index.blade.php`)
- Aggregierte `statusCounts` (assoc) per `groupBy('status')`
über dieselbe `$base`-Query — eine zusätzliche SQL-Query
- Neue Properties: `$portalFilter`
- Neue Methoden: `setView($status)`, `resetFilters()`,
`updatedPortalFilter()`
- Daten an View: `statusCounts`, `portalOptions`
- Paginierung von 100 → 25 (sinnvoller für Mockup-Layout)
### Markup auf Mockup-Stil (~50 % → ~90 %)
- **Counter-Strip im Header**: dynamische Segmente werden nur
angezeigt, wenn Count > 0, mit semantisch eingefärbten
Zahlen (ok/warn/muted/err)
- **Kontext-Hinweis**: „Gefiltert auf :company" als kleine
Sub-Zeile, falls Firma-Kontext aktiv (Test-kompatibel!)
- **Saved-Views-Tabs**: 6 Tabs (Alle, Veröffentlicht,
Entwürfe, In Prüfung, Abgelehnt, Archiv) mit `cnt`-Pille,
klicken setzt `statusFilter` via `setView()`
- **Filter-Sektion**: Suche + Portal-Select + Firma-Select
(letzteres nur wenn `hasGlobalCompanyContext`)
- **Active-Chips**: entfernbare Anzeige aller aktiven Filter
(Status, Portal, Firma, Suche), mit `Alle zurücksetzen`-Link
- **Tabelle**:
- Status-Spalte mit Hub-Badge + Inline-Action „Zur Prüfung →"
für Drafts (ruft `submitForReview` mit `wire:confirm`)
- Titel mit Hub-Style-Link + PM-{id}-Sub
- Portal-Pills (eine oder zwei, abhängig vom Portal-Enum-Wert)
- Firma als Hub-Link oder „— keine —" italic
- Datum: Mono-Font + Sub mit Status-Kontext
(„veröffentlicht · 09:12", „eingereicht · 17:48" …)
- Row-Tint via `is-row-warn` (review) / `is-row-err`
(rejected) — dezent beim Hover
- **3-fach Empty-State**:
- `empty-search` (Suche ohne Treffer)
- `empty-filter` (Filter ohne Treffer, warm-Icon-Box)
- `empty-none` (gar keine PMs, mit 3-Schritt-Onboarding
01-Firma · 02-Verfassen · 03-Zur Prüfung)
- **Status-Aktionen-Legende**: `panel-warm` mit 5-Spalten-
Grid (Entwurf, In Prüfung, Veröffentlicht, Abgelehnt,
Archiviert) und einer Action-Liste je Status
### Was bewusst NICHT umgesetzt wurde
- **Bulk-Selection**: weggelassen (keine Bulk-Actions im
Backend → wäre nur Dekoration ohne Funktion)
- **Inline-Action „Grund ansehen →"** für Rejected: keine
`rejection_reason`-Spalte in `press_releases`-Tabelle
(Grund wird nur via E-Mail an Autor versendet)
- **Spalten- & Export-Buttons** im Header: keine Backend-
Implementierung, weggelassen
- **Modals und Bestätigungs-Flows**: bleiben FluxUI
- **Volt-Logik außerhalb der Erweiterungen**: unangetastet
### Tests & Hygiene
- **Erst-Fail**: `CustomerCompanyContextTest:79` rot, weil
„Gefiltert auf Alpha GmbH" im neuen Layout vom Counter-Strip
verdrängt wurde
- **Fix**: Kontext-Hinweis als zusätzliche kleine Sub-Zeile
unter dem Counter-Strip, immer sichtbar wenn Firma-Kontext
- **PR + Customer Tests**: 50/50 grün (199 Assertions)
- **Volle Suite**: 230 grün (1212 Assertions), 3 skipped,
1 fail = pre-existing `ApiDocumentationTest` (kein Bezug zu UI)
- **Build**: `npm run build:portal` clean
- **Pint**: `vendor/bin/pint --dirty``passed`
- **Lints**: keine Errors
### Status
- Plan-Status: ✅ Phase 4H **abgeschlossen**
- 03-WEITERE-PHASEN.md: 4H ergänzt als ✅
- Match zum Mockup: ≥ 90 %
### Übertragbar auf
- `admin/press-releases/index.blade.php` (Phase 4I als
natürliche Folgephase)
- `admin/users.blade.php`, `admin/contacts/index.blade.php`,
`admin/companies/index.blade.php` (Counter-Strip,
Saved-Views-Tabs, Filter-Chips wären überall sinnvoll)
---
## 2026-05-20 · Phase 4F · Restliche Admin-Bereiche
- **Anlass**: User „4f weiter" nach 4G. Siebtes (und letztes
großes) Päckchen aus Phase 4. Ziel: alle übrigen Admin-Pages
auf Hub-Stil, damit die komplette interne Strecke visuell
abgeschlossen ist.
- **Plan-Dokument**: `13-PHASE-4F-ADMIN-REST.md`.
Aufgrund des Umfangs (~7.500 Z. Blade) in 4 Sub-Päckchen
aufgeteilt.
### 4F-1 · Stammdaten & Switcher
- **`admin/presets/{index,create,edit}.blade.php`** +
`partials/form-fields.blade.php`: Page-Header
(„Admin Backend"-Pille, Eyebrow „Administration · Presets"),
Filter-Panel, Table-Panel mit Hub-Badges und Hub-Empty-State,
Forms in `article.panel`, Required-Marker auf
`text-[color:var(--color-err)]`.
- **`admin/categories/{index,create,edit}.blade.php`**:
Page-Header mit Aktion, KPI-Reihe mit
`<x-portal.stat-card>` (gesamt, aktiv, mit/ohne PMs),
Filter & Sort Panel, Category-Cards als `article.panel`,
Hub-Badges, Hub-Style innere Items, Danger-Zone mit linkem
roten Strip.
- **`admin/portal-switcher.blade.php`** (Sidebar):
Token-basierte Button-Farben mit `--color-bg-elev`,
`--color-bg-rule`, `--color-ink`, `--color-ink-2`,
`--color-ink-3`.
- **Tests**: `CategoryIndexPerformanceTest`,
`AdminCategoryManagementTest`,
`AdminPresetManagementTest` — alle grün.
### 4F-2 · Pressekontakte
- **`admin/contacts/index.blade.php`** (729 Z.): Page-Header
mit Action, KPI-Reihe (`<x-portal.stat-card>`),
Filter-Panel, Preset-Panel, Table-Panel mit Hub-Badges und
Hub-Empty-State, Hub-Style Flash-Boxen.
- **`admin/contacts/create.blade.php`** (275 Z.):
Page-Header mit „prefilled company"-Badge, Forms in
`article.panel`.
- **`admin/contacts/edit.blade.php`** (352 Z.):
Page-Header mit ID + Portal-Badge, Forms in
`article.panel`, Danger-Zone mit linkem roten Strip.
### 4F-3 · Operations & Finance
- **`admin/footer-codes/{index,create,edit}.blade.php`**:
Page-Header, KPI-Reihe, Filter-Panel, Table-Panel mit
Hub-Badges, Forms in `article.panel`, Category-Checkboxes
Hub-styled, Danger-Zone.
- **`admin/reports/slow-requests.blade.php`** +
`slow-requests-table.blade.php`: Page-Header,
Filter-Panel mit Reset-Button, KPI-Reihe, Top Routes/Paths
Panels, Slowest-Requests-Table, Frequent Slow Queries Table,
EXPLAIN Top Slow Queries Panel — alles Hub-styled.
- **`admin/invoices/index.blade.php`** (Legacy-Archiv):
Page-Header mit Archive-Badge, Warning-Box für „unmapped",
KPI-Reihe, Filter-Panel, Table-Panel mit Hub-Badges +
Pagination.
- **`admin/coupons/index.blade.php`** (Stub): Page-Header
„Vertagt"-Badge, Info-Panel mit Hub-Style List-Items.
- **`admin/payments/index.blade.php`** (Stub): Page-Header
„In Vorbereitung"-Badge, Info-Panel mit Hub-Style
List-Items + Rules.
- **Tests**: `AdminFooterCodeManagementTest`,
`AdminSlowRequestReportTest`,
`AdminSlowRequestLoggingTest`,
`AdminLegacyInvoiceArchiveTest` — alle grün.
### 4F-4 · User-Verwaltung
- **`admin/roles/{index,create,edit}.blade.php`**:
Page-Header (mit ID + System-Role-Badges in edit),
Warning-Box für System-Rollen, Forms in `article.panel`,
Table-Panel mit Hub-Badges + Empty-State.
- **`admin/newsletter/sync.blade.php`** (171 Z.):
Page-Header mit Sync-Status-Badge (active/deactivated),
Action-Buttons (Dry Run, Test-Sync) im Header, Hub-Style
Info/Success-Pillen für Notifications, KPI-Reihe mit
`<x-portal.stat-card>` (gesamt, bestätigt, ausstehend,
abgemeldet), Config-Details (Provider, Timeout, Endpoint)
als Definition-List in `article.panel`.
- **`admin/users.blade.php`** (939 Z.): Page-Header mit
Action „Benutzer anlegen", KPI-Reihe (gesamt, aktiv,
inaktiv), Filter-Panel mit Reset-Button, Table-Wrapper
als `article.panel` mit Hub-Empty-State. **Modal**
und alle Tabellen-Inhalte bewusst unangetastet — wegen
Test-Strings + Komplexität.
- **`admin/users/show.blade.php`** (239 Z.): Hub-Header mit
ID + Status-Badges, KPI-Reihe (Portal, Typ, Status, Login),
Rollen-Panel, Rechnungsadresse-Panel,
„Verknüpfte Firmen & Kontakte"-Panel als verschachtelte
Hub-Boxes.
- **`admin/users/create.blade.php`** (421 Z.): Hub-Header,
Forms in `article.panel` (Basisdaten, Rollenzuweisung,
Firmenverknüpfung, Rechnungsadresse), Action-Panel
am Ende.
- **`admin/users/edit.blade.php`** (1.224 Z.): Hub-Header
mit ID/Portal/Status-Badges, Notification als
Hub-Style Ok-Pill, Quick-Nav als Token-Pillen mit
Hover auf Hub-Blue, KPI-Reihe (Account, Legacy-Profil,
Verknüpfungen, Rechnungsadresse). Innere Sektionen
(`#account`, `#legacy-profile`, `#roles`,
`#company-links`, `#contact-links`, `#billing-address`)
bleiben `flux:card` (IDs für Quick-Nav, sehr großes File).
Footer-Action-Panel auf Hub umgestellt.
- **Tests**: `UserManagementTest`, `UserImpersonationTest`,
`UserList*Test` — 29 Tests / 270 Assertions grün.
### Bauplatz-Hygiene
- **Build**: `npm run build:portal` — sauber durch.
- **Pint**: `vendor/bin/pint --dirty``passed`.
- **Lints**: keine Linter-Errors in den editierten Blade-Files.
- **Pre-existing**: `ApiDocumentationTest` weiterhin rot, kein
Bezug zu UI-Styling (siehe frühere Phasen).
### Abgrenzung — was bewusst NICHT angefasst wurde
- Volt-Logik in allen Dateien (PHP, `mount`, `save`,
`with`, …).
- `<flux:input>`, `<flux:select>`, `<flux:checkbox>`,
`<flux:textarea>`, `<flux:field>`, `<flux:error>`,
`<flux:table.*>`, `<flux:button>`, `<flux:modal>`.
- Innere Sektionen von `users/edit.blade.php` mit ID-Ankern
(Quick-Nav-Targets) — diese bleiben `flux:card`, da
Footnote-Logik daran hängt und das File 1.224 Z. groß ist.
- Modal in `users.blade.php` und alle internen Bestätigungs-
Flows (Test-Strings).
- Test-relevante Strings überall.
### Status
- Plan-Status: ✅ Phase 4F **abgeschlossen**.
- 03-WEITERE-PHASEN.md: 4F auf ✅ aktualisiert.
---
## 2026-05-20 · Phase 4G · Customer Portal (Mein Bereich)
- **Anlass**: User „weiter 4G" nach 4E. Sechstes Päckchen aus
Phase 4: alle übrigen Customer-Pages auf Hub-Stil bringen,
damit die komplette User-sichtbare Strecke (Mein Bereich)
visuell abgeschlossen ist.
- **Plan-Dokument**: `12-PHASE-4G-CUSTOMER-PORTAL.md`.
- **Was umgebaut wurde**:
- **`customer/company-switcher.blade.php`** (Sidebar-Helper,
91 Z.): „Aktive Firma"-Label als `.badge hub dot`,
Portal-Suffix als Token-Eyebrow, „Keine Firma zugeordnet"
als `.badge warn`. `<flux:select>`, `Firma öffnen`-Button
und `route('me.press-kits.show', …)` bleiben — alles, was
der `CustomerCompanyContextTest` assertiert, ist erhalten.
- **`customer/bookings.blade.php`** (Coming-Soon, 52 Z.):
Hub-Page-Header („User Backend"-Pille,
„Mein Bereich · Finanzen"-Eyebrow, Warn-Pille
„In Vorbereitung"). Info-Box auf Hub-Soft-Token,
3 Feature-Panels mit Eyebrow + Beschreibung.
- **`customer/invoices.blade.php`** (194 Z.): Page-Header
mit Aktion „Rechnungsadresse im Profil pflegen". Hinweis
in eigenes `.panel`. 4 KPI-Cards (primary/muted/ok/warn).
Filter-Panel, Tabellen-Panel mit Hub-Badges (`ok dot`
für bezahlt, `warn dot` für offen), Empty-State als
Icon-Box. Pagination am Boden im Panel mit Top-Border.
Notification als Hub-Warn-Pille mit Icon.
- **`customer/tokens.blade.php`** (212 Z.): Hub-Page-Header
mit „API-Dokumentation"-Aktion. Flash-Boxen (success/warn)
in Token-Style. „Neuer Token"-Anzeige als eigenes Panel
mit linkem Warn-Strip (`border-left:3px solid
--color-warn`) + `.badge warn`-„Nur jetzt sichtbar". Form
in Panel mit Border-Top-getrenntem Submit-Bereich.
Tabelle in Panel mit Counter, Berechtigungen als
`.badge hub` (statt `flux:badge`), Empty-State als
Icon-Box.
- **`customer/press-kits/index.blade.php`** (119 Z.):
Hub-Page-Header. Filter-Panel. Karten-Grid mit
`.panel`-Karten: `.panel-head` mit Status-Badge
(`ok dot` / `err dot`), Body mit Slug, Portal/Rolle/
Footer-Badges, KPI-Boxen (Border + bg-elev), Footer
mit Border-Top + „Firma öffnen"-Button.
Empty-State als full-width Panel mit Hub-Icon-Box.
- **`customer/press-kits/show.blade.php`** (734 Z. → Polish):
Großes Detail-Cockpit komplett auf Hub:
- **Header**: Pillen-Reihe (User-Backend, Mein
Bereich · Firma, Aktiv/Inaktiv, Portal, Rolle, ggf.
Footer-Code-aus) + Logo-Box (oder Hub-Icon-Box) + H1
+ Slug. Aktionen rechts: Zurück, Stammdaten bearbeiten,
Neue PM.
- **Quick-Nav**: Anker-Links als pillen-artige
Hover-Buttons mit Bottom-Border.
- **4 KPI-Cards**: PMs (primary), Pressekontakte (ok),
Portal (muted), Deine Rolle (muted) — mit
`canManageCompany`-abhängiger Trend.
- **Stammdaten-Panel**: `.panel-head` mit Bearbeiten-
Button. Inline-Form als `bg-elev`-Block mit
Border-Top-getrennten Sections (Logo / Aktionen).
Daten-Liste als `<dl>` mit Token-Labels + Werten,
Website als Hub-Underline-Link.
- **Pressekontakte-Panel**: `.panel-head` mit Counter.
Inline-Form analog Stammdaten. Kontakt-Items als
`bg-elev`-Boxen mit Aktionen rechts. Empty-State als
gestrichelte Box. Flash-Messages
(„Pressekontakt wurde angelegt./aktualisiert./
gelöscht.") in Token-Success-Pille.
- **Pressemitteilungen-Panel**: Tabelle mit Hub-Status-
Badges (ok/warn/err/hub). Empty-State Hub-Icon-Box.
- **Abrechnung & Statistik**: 2 Panels nebeneinander
mit „In Vorbereitung"/„Später"-Warn-Pillen. Abrechnung
mit gestrichelter Hint-Box. Statistik mit
2 Token-Mini-Stats.
- **Was bewusst unverändert blieb**:
- Volt-PHP-Logik in allen Dateien (mount, saveCompany,
saveContact, deleteContact etc.).
- Flash-Strings („Stammdaten wurden gespeichert.",
„Pressekontakt wurde angelegt./aktualisiert./gelöscht.",
„Token wurde erstellt", „Token wurde widerrufen.",
„API-Tokens werden erst freigeschaltet" etc.) —
bleiben in Volt-PHP wie zuvor und erscheinen in den
neuen Hub-Pillen.
- Section-Headings „Abrechnung" und „Statistik" — Tests
assertieren genau diese Strings.
- Strings im Header („Alpha GmbH", „Firma öffnen",
`route('me.press-kits.show', …)`).
- FluxUI-Form-Komponenten (`flux:input`, `flux:select`,
`flux:textarea`, `flux:checkbox`, `flux:field`,
`flux:error`, `flux:table*`) — nur Wrapper-Markup
verändert.
- **Verifikation**:
- `php artisan view:clear`
- `npm run build:portal` ✓ — 418.11 kB CSS / 44.38 kB JS
(keine Größenänderung gegenüber 4E).
- `php artisan test --compact tests/Feature/{
CustomerPortalTest, CustomerCompanyContextTest,
PanelConsolidationTest}.php` →
**29 passed, 131 assertions**.
- Volle Suite: **230 passed, 3 skipped, 1 pre-existing
fail** (`ApiDocumentationTest` — fehlende
`docs/api/v1.yml`, war auch vor 4G/4E/4D rot).
- `vendor/bin/pint --dirty --format agent``passed`.
- **Resultat**:
- Mein-Bereich des Users ist visuell **vollständig** auf
Hub-Sprache.
- Sidebar-Nav (presse-kits, invoices, tokens, bookings)
läuft jetzt durchgängig im selben Vokabular wie Dashboard
+ Press-Releases.
- Detail-Cockpit `press-kits/show` ist das visuell
aufwendigste Customer-Page und stimmt jetzt mit Admin-
Detail-Show überein (Pillen-Header, KPI-Reihe, Panels,
Quick-Nav, Tabellen).
- **Nächste mögliche Päckchen**:
- **4F** Restliche Admin-Bereiche (contacts, categories,
presets, footer-codes, slow-requests, users).
- **press-release-images-manager** Komponente (kleiner
Cleanup aus 4C-Resten).
- **Phase 5** Dark-Mode-Konsolidierung.
---
## 2026-05-20 · Phase 4E · Profile & Settings
- **Anlass**: User „okay weiter" nach 4D. Fünftes Päckchen aus
Phase 4: alle Settings-Pages (Admin + Customer) auf Hub-Stil.
- **Plan-Dokument**: `11-PHASE-4E-PROFILE-SETTINGS.md`.
- **Zentraler Trick — Wrapper umgebaut**:
- **`resources/views/partials/settings-heading.blade.php`**:
Komplett neu als Hub-Page-Header (Pille „Admin Backend",
Eyebrow „Mein Konto · Einstellungen", H1 „Settings",
Subtitle).
- **`resources/views/components/settings/layout.blade.php`**:
Komplett neu als 2-Spalten-Grid mit Sidebar-Nav-`.panel`
(„Mein Konto"-Eyebrow + FluxUI-Navlist drin) und
Content-`.panel` mit `.panel-head` für Page-Heading +
Subheading im Body. Heading/Subheading-Slots der einzelnen
Settings-Pages werden so automatisch im Hub-Look gerendert.
- **Effekt**: `settings/appearance.blade.php` musste
**gar nicht** angefasst werden — übernimmt den Hub-Look
via Wrapper. Die anderen beiden brauchen nur
Save-Bar-Polish.
- **Was umgebaut wurde**:
- **`settings/profile.blade.php`**: Verification-Hinweis von
`<flux:text>`-Link auf Hub-Warn-Box (gelber Linker Strip,
Icon, Hub-Link für „re-send the verification email").
Save-Bar mit Border-Top + Token-`Saved.`-Pill.
Delete-Button-Section visuell durch Border-Top abgetrennt.
- **`settings/password.blade.php`**: Save-Bar gleicher Polish.
- **`settings/delete-user-form.blade.php`**: Das `mt-10`-Card
durch Hub-Danger-Box mit `border-l-[3px]
border-l-[color:var(--color-err)]`, „Danger Zone"-Eyebrow,
H3 + Subtitle + Trash-Button. Modal-Markup komplett
unverändert (Confirm-Password-Modal kommt aus FluxUI-Std.).
- **`customer/profile.blade.php`**: Page-Header („User
Backend"-Pille, „Mein Bereich · Profil"-Eyebrow,
„Mein Profil"-H1). Form in 3 Panels + Aktions-Panel:
Konto (Name/E-Mail/Sprache) · Profil (Anrede,
Vor-/Nachname, Telefon, Backlink, Checkboxen) ·
Rechnungsadresse (mit Warn-Hub-Box, wenn unvollständig).
Zugeordnete-Firmen als eigenes `.panel` mit Hub-Badges
(`ok` für Eigentümer, `hub` für Portal/Rolle).
- **`customer/security.blade.php`**: Page-Header. 4-spaltige
KPI-Reihe mit `.panel` + uppercase-Eyebrow + großer Wert +
Hub-Badge (E-Mail bestätigt? · 2FA aktiv? · Letzter Login +
IP · Sessions-Count). 2-Spalten-Grid für Passwort + E-Mail
in `.panel` mit `.panel-head`. 2FA-`.panel` mit
ok-Badge im Header wenn aktiv, Recovery-Codes mit
Hub-Bg-Boxes. Sessions-`.panel` mit Eintrags-Counter,
Empty-State als Hub-Icon-Box. **Alle Test-Strings
erhalten**: „Konto-Sicherheit", „Letzter Login",
„Aktive Sessions", „Passwort ändern", „E-Mail-Adresse
ändern", „Zwei-Faktor-Authentifizierung",
„Rechnungsadresse".
- **Tests**:
- Smoke: `Settings|CustomerProfileSecurity|
CustomerCompanyContext` → 33 passed (146 assertions).
- Volle Suite: 230 passed / 3 skipped /
1 pre-existing `ApiDocumentationTest`-Fail.
- **Build / Pint**: `npm run build:portal` ✓ (418 kB CSS),
`pint --dirty` ✓, keine Linter-Errors.
- **Bewusst NICHT angefasst**:
- Volt-Logik in allen Dateien.
- Confirm-User-Deletion-Modal-Markup
(`settings/delete-user-form.blade.php`).
- Fortify-2FA-Logik (Enable / Disable / Recovery-Codes-
Regenerate / QR-Generation).
- `<x-action-message>` Component-Wrapper — nur Slot-Inhalt.
- **Nächster Schritt** — Vorschlag:
- **4G** Customer-Bereiche (invoices, tokens, bookings,
company-switcher, me/press-kits/*) — Tests fordern
Strings, aber alle gut greifbar.
- **4F** Restliche Admin-Bereiche (contacts, categories,
presets, footer-codes, slow-requests, users) — größeres
Päckchen, sollte weiter unterteilt werden.
---
## 2026-05-20 · Phase 4D · Companies (admin)
- **Anlass**: User „okay weiter" nach 4C. Viertes Päckchen aus
Phase 4: alle vier Admin-Companies-Pages auf Hub-Stil.
- **Plan-Dokument**: `10-PHASE-4D-COMPANIES.md`.
- **Was umgebaut wurde**:
- **`admin/companies/index.blade.php`**: Hub-Page-Header
(„Admin Backend"-Pille, Eyebrow „Stammdaten · Firmen",
H1 „Firmen", Subtitle, CTA „Neue Firma" rechts) →
3 `<x-portal.stat-card>` (Gesamt/Aktiv/Inaktiv) →
Filter-`.panel` mit Combobox-Selects unverändert in der
Logik, nur Hülle getauscht → Tabelle in `.panel
overflow-hidden` mit `.panel-head` „Alle Firmen" +
Eintrags-Counter. Tabellen-Status/Portal/Count-Badges
auf Hub-Klassen (`badge ok|err|hub` + Dot) gesetzt.
Empty-State als Hub-Icon-Box.
- **`admin/companies/show.blade.php`**: Header mit
Status-, Portal- und ID-Pille; Logo-Box neben H1. KPI-Reihe
(3 stat-cards). Tabs „Überblick" / „Kontakte" als schlankes
Bottom-Border-Pattern (kein FluxUI-Tabs-Group nötig). Beide
Tab-Inhalte komplett in `.panel`-Sektionen mit `dl`-Layouts
bzw. Kontakt-Karten. Existing-Contact-Combobox bleibt
FluxUI; Wrapper auf Hub-`bg-elev`. Flash-Boxen
(success/error/info) auf Token-Pillen.
- **`admin/companies/edit.blade.php`**: Page-Header
(„ID"-Pille), 5 Form-Panels (Basisinformationen, Adresse,
Rechtliche Daten, Logo & Status, Aktionen). Required-Marker
auf `text-[color:var(--color-err)]`. Logo-Vorschau-Bild
nutzt Hub-Token-Border. „Logo wird beim Speichern entfernt"
auf Hub-Warn-Box (statt `flux:callout`).
**Delete-Confirm-Modal komplett unverändert.**
- **`admin/companies/create.blade.php`**: gleiches Schema
wie Edit, ohne Status-Pille und ohne Delete-Button. Forms
in 5 Panels strukturiert.
- **Tests**:
- Companies-Smoke: `UserManagement|PortalAssetManifest`
→ 25 passed (227 assertions).
- Volle Suite: 230 passed / 3 skipped /
1 vorbestehender Fail (`ApiDocumentationTest`
fehlende Datei `docs/api/v1.yml`, nicht durch Phase 4D
verursacht).
- **Build / Pint**: `npm run build:portal` ✓ (418 kB CSS,
44 kB JS), `vendor/bin/pint --dirty --format agent` ✓.
- **Bewusst NICHT angefasst**:
- Volt-Logik in allen vier Dateien.
- `deleteCompany`-Methode und ihr Confirm-Modal-Markup
(Test `UserManagementTest::admin can delete company`
prüft Redirect-Verhalten, nicht UI).
- `<flux:select variant="combobox">` (Kontakt-/User-Lookup)
und alle anderen `flux:field`/`flux:input`-Bausteine —
Token-Bridging trägt.
- Test-relevante Strings: „Firmen", „Portal", „Alle Portale",
„Presseecho", „Businessportal24", „/admin/companies/…".
- **Nächster Schritt (Phase 4E oder 4F)**:
- **4E** = Profile/Settings (`settings.*`, `me.profile`,
`me.security`) — eher klein, viele kleine Panels.
- **4F** = Restliche Admin-Bereiche (contacts/, categories/,
presets/, footer-codes/, slow-requests, …) — Päckchen-Größe.
---
## 2026-05-19 · Phase 4C · Press-Releases Forms (create / edit)
- **Anlass**: User-Freigabe „ja" nach 4B. Drittes Päckchen aus