presseportale/dev/frontend/hub-flux/PROGRESS.md
Kevin Adametz 0a3e52d603 19-05-2026 Rebrand Pressekonto, Hub-Flux UI und Legacy-Media-Migration
Umbenennung presseportale → pressekonto in Domains, Themes und Dokumentation.
Design-Tokens, Portal-Shell, Customer-Dashboard, Auth- und Admin-PM-Views.
Artisan-Befehl migrate:legacy-media mit Tests und Hub-Flux-Entwicklungsdocs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 16:36:13 +00:00

40 KiB
Raw Blame History

Fortschritts-Log — Hub × FluxUI

Tagebuch der Umsetzung. Neue Einträge oben anfügen. Format pro Eintrag: Datum · Phase · Was wurde gemacht · Wer · Notizen


2026-05-19 · Phase 4C · Press-Releases Forms (create / edit)

  • Anlass: User-Freigabe „ja" nach 4B. Drittes Päckchen aus Phase 4 — Forms (create + edit) für Admin und Customer.

  • Plan-Dokument: 09-PHASE-4C-PRESS-RELEASES-FORMS.md.

  • Was umgebaut wurde (alle 4 Forms):

    • Page-Header wie auf Listen und Detail: Hub-Badge („Admin Backend" / „User Backend") + Eyebrow + großes H1 + Subtitle. Bei Edit zusätzlich Status-Pille im Header-Meta (@class([])-Syntax mit ok|warn|err|hub) und „ID"-Pill. Aktions-Buttons rechts (Zurück).
    • Form-Sektionen als .panel mit .panel-head und section-eyebrow: „Inhalt", „SEO & Links", „Metadaten", „Status-Aktionen" (Admin-Edit), „Aktionen". Innenraum immer p-5 space-y-4.
    • Form-Felder bleiben FluxUI (<flux:field>, <flux:label>, <flux:input>, <flux:textarea>, <flux:select> inkl. Combobox-Variant, <flux:checkbox>, <flux:error>) — das Token-Bridging aus Phase 1 zieht.
    • Required-Marker von text-red-500 auf Token-Farbe (text-[color:var(--color-err)]) umgestellt.
    • Save-/Submit-Buttons in eigenem .panel mit Header „Aktionen" statt „nackten" Buttons in der Sidebar.
    • Flash-Boxen (Success/Error) auf Hub-Token-Pillen.
  • Admin-Edit-spezifisch: 5 Sidebar-Panels (Status-Aktionen + Metadaten + Aktionen + Modals). „Status-Aktionen"-Panel zeigt rechts im Header die aktuelle Status-Pille — visuelle Doppelung mit dem Page-Header-Status, aber im Kontext der Sidebar sinnvoll als Vergleichs-Anker für die „Neuer Status"-Auswahl.

  • Was explizit NICHT angefasst wurde:

    • Volt-Logik (alle save/publish/reject/backToDraft/ archive/changeStatus/deletePressRelease/mount/with/ selectedCompany-Methoden) — Layout-only.
    • Confirm-Modals der Admin-Edit-Page (confirm-status-change, confirm-delete-press-release) — Tests in AdminPressReleaseActionsTest assertieren Wortlaute.
    • Wortlaute: „Neuer Status", „Status wechseln", „Status wirklich wechseln?", „Pressemitteilung löschen?", „Status wurde auf" — alle erhalten.
    • <livewire:components.press-release-images-manager> — eigene Komponente, kommt im jeweiligen eigenen Päckchen dran.
  • Build/Test:

    • npm run build:portal → ok (portal-D0cNdOWP.css 418.42 kB).
    • Linter clean (alle 4 Dateien).
    • php artisan test --compact --filter='PressRelease|CustomerCompanyContext|CustomerProfileSecurity|PanelConsolidation'72 passed (310 assertions).
    • Volle Suite: 230 passed, 3 skipped, 1 pre-existing failure (ApiDocumentationTest).
    • Pint --dirty --format agent → passed.
  • Offene Fragen: Keine.

  • Nächster Schritt: Phase 4 für Press-Releases ist mit 4A/4B/4C komplett abgeschlossen. Nächstes Päckchen je nach Sichtbarkeit: 4D = Companies (admin.companies.*) ODER 4E = Settings / Profile (me.profile, me.security).


2026-05-19 · Phase 4B · Press-Releases Detail/Show-Pages

  • Anlass: User-Freigabe „weiter" nach 4A. Zweites Päckchen aus Phase 4 — Detail/Show-Pages für Admin und Customer.

  • Plan-Dokument: 08-PHASE-4B-PRESS-RELEASES-DETAIL.md.

  • Was umgebaut wurde (beide Show-Pages):

    • Page-Header mit Hub-Badge + Eyebrow + Status-Pill + Sprache + Portal (Admin nur), darunter großer H1 mit dem PM-Titel und Subtitle mit Firma/Kategorie/Autor bzw. Datum. Aktions-Buttons rechts (Bearbeiten/Vorschau-Link/Zurück).
    • Status-Workflow-Aktionsbar als .panel mit .panel-head und passend gefärbtem Badge je nach Status (warn=Review, ok=Published, err=Rejected, hub=Draft).
    • Content-Hauptbereich (PM-Text) als .panel mit eigenem Header „Inhalt" + prose darunter. Keywords/Backlink darunter als Footer mit Hub-Rule.
    • Sidebar / Side-Cards (Admin) als kompakte .panel mit panel-head „Details" und „Bilder" + Hub-Badges.
    • Status-Verlauf-Timeline als .panel mit Hub-Badge je Log-Eintrag (.badge.ok|warn|err|hub) statt FluxUI-color-Props.
    • Status-Badges in Header und Timelines komplett auf <span class="badge …"> mit @class([])-Syntax.
  • Customer-Show-spezifisch:

    • Rejection-Hinweis als roter .panel mit linker Akzent-Border (border-left-width:3px) und Icon-Box — statt <flux:callout color="red">.
    • Review-Pending-Hinweis als warner .panel mit Akzent-Border und Clock-Icon-Box — statt <flux:callout color="yellow">.
    • Share-Link-Erfolgsblock als ok-.panel mit Gültigkeits-Badge im Header und readonly-Input im Body.
    • Contacts-Liste als Hub-Items (bg-bg-elev + border-bg-rule), Empty-State mit gestrichelter Border.
    • Status-Tile-Grid (Aktuell/Erstellt/Veröffentlicht/Aufrufe) als 4-er-Grid mit kleinen Hub-Tiles statt zinc-Hintergründen.
  • Admin-Show-spezifisch:

    • Modals (Publish/Reject/Archive) komplett unverändert — Tests in AdminPressReleaseActionsTest assertieren Wortlaute.
  • Was explizit NICHT angefasst wurde:

    • Volt-Logik (publish/reject/archive/submitForReview/ generateShareLink/with-Method) — Layout-only.
    • Wortlaute „Erneut einreichen", „Werbliche Sprache wurde markiert." aus PressReleaseWorkflowTest.
    • Bestehende Modals und ihre Wortlaute.
  • Mini-Stolperer (sofort gefixt):

    • Erst zwei nicht-existente Tokens (--color-rule, --color-panel-soft) verwendet. Korrigiert zu --color-bg-rule und --color-bg-elev (16 + 5 Vorkommen). Wäre im Browser stumm gefailed (Tailwind hätte die Klassen einfach nicht ausgegeben).
  • Build/Test:

    • npm run build:portal → ok (portal-Bq4pkLWt.css 418.36 kB).
    • Linter clean.
    • php artisan test --compact --filter='PressReleaseWorkflow|AdminPressReleaseActions' → 16 passed (52 assertions).
    • Volle Suite: 230 passed, 3 skipped, 1 pre-existing failure (ApiDocumentationTest, schon vor 4A bekannt).
    • Pint --dirty --format agent → passed.
  • Offene Fragen: Keine.

  • Nächster Schritt: Päckchen 4C = Press-Releases Forms (create.blade.php + edit.blade.php, Admin + Customer). Forms sind tendenziell aufwendiger (mehr FluxUI-Felder, ggf. zusätzliche Logik wie Image-Uploads).


2026-05-19 · Phase 4A · Press-Releases Listen-Pages

  • Anlass: User-Freigabe „weiter" nach Phase 3 (Admin-Dashboard). Phase 4 ist laut Roadmap „der Marathon" über Listen-/Detail-Pages (~35 Tage iterativ). Wegen Umfang in Päckchen geteilt — A = Listen, B = Detail/Show, C = Forms, D = Companies, E = Settings, F = Rest.

  • Plan-Dokument: 07-PHASE-4A-PRESS-RELEASES-LISTEN.md (knapp, Scope hart auf zwei index.blade.php-Files begrenzt, mit explizitem „NICHT in diesem Päckchen"-Block).

  • Scope dieses Päckchens:

    • resources/views/livewire/admin/press-releases/index.blade.php
    • resources/views/livewire/customer/press-releases/index.blade.php
  • Was umgebaut wurde (beide Listen):

    • Page-Header im Hub-Stil: <header> mit 1fr auto-Grid, Hub-Badge („Admin Backend" / „User Backend"), Eyebrow, großes H1, Subtitle, rechts der CTA-Primary-Button (FluxUI bleibt für den Button).
    • Filter-Bar als .panel + .panel-head mit section-eyebrow „Filter & Suche". FluxUI-Inputs (Search-Input, Selects, Combobox für User/Company/Contact-Lookup) bleiben unverändert — Hub hat kein eigenes Combobox-Pendant.
    • Tabelle als .panel mit .panel-head „Alle Pressemitteilungen"
      • Eintrags-Counter rechts. FluxUI-<flux:table> bleibt — das Zinc-→Hub-Mapping aus Phase 1 zieht hier perfekt.
    • Status-Badges: <flux:badge color="green|yellow|red|zinc|blue"> ersetzt durch <span class="badge ok|warn|err|hub"> für visuelle Konsistenz mit dem Dashboard (@class([...])-Syntax).
    • Empty-State mit Icon-Box (bg-[color:var(--color-hub-soft)], Hub-Border, flux:icon.newspaper) + Headline + Subtext.
    • Flash-Boxen auf Hub-Tokens (--color-ok-soft, --color-err-soft, --color-gain-deep, --color-loss) statt bg-green-50 etc.
  • Admin-spezifisch: Vier <x-portal.stat-card> (Gesamt/Veröffentlicht/ In Prüfung/Entwürfe) als KPI-Reihe — identisches Layout wie Admin-Dashboard.

  • Was explizit NICHT angefasst wurde:

    • Confirm-Modals (Publish/Reject/Archive) — Tests in AdminPressReleaseActionsTest assertieren die Wortlaute („Pressemitteilung veröffentlichen?" etc.) → unverändert.
    • Volt-Logik (Sort, Filter, alle Methods) — Layout-only.
  • Bonus-Fix: customer/dashboard.blade.php Subtitle bekommt einen „Übersicht für :company —"-Einschub, wenn $selectedCompany gesetzt ist. Korrigiert eine Phase-2-Regression bei CustomerCompanyContextTest > customer dashboard is filtered by ….

  • Build/Test:

    • npm run build:portal → ok (portal-DaL-tXm-.css 418.75 kB).
    • Linter clean.
    • php artisan test --compact --filter='PressReleaseWorkflow|AdminPressReleaseActions|Dashboard|CustomerCompanyContext' → 45 passed (163 assertions).
    • Volle Suite: 230 passed, 3 skipped, 1 failed. Der einzelne Fail (ApiDocumentationTest) ist pre-existing — via git stash verifiziert, war auch vor diesem Päckchen rot (/docs/api/v1 liefert nicht das erwartete YAML).
    • Pint --dirty --format agent → passed.
  • Offene Fragen: Keine.

  • Nächster Schritt: Päckchen 4B = Detail/Show-Pages (admin/press-releases/show.blade.php + customer/press-releases/show.blade.php). Dort ist mit der „Werbliche Sprache wurde markiert."- und „Erneut einreichen"- Assertion aus PressReleaseWorkflowTest zu rechnen — Wortlaute bleiben unverändert.


2026-05-19 · Phase 3 · Admin-Dashboard im Hub-Vokabular

  • Anlass: User-Freigabe „weiter" nach Phase 5 (Dark Mode). Phase 3 laut Roadmap: Admin-Dashboard (/dashboard) im selben Vokabular wie Customer-Dashboard.

  • Plan-Dokument: 06-PHASE-3-ADMIN-DASHBOARD.md (knapper als Phase 2 — niedrig-risiko, keine neuen Konzepte, reine Vokabular-Migration auf die DRY-Schicht aus Phase 2).

  • Ausgangslage: admin/dashboard.blade.php war Controller-rendered (kein Volt), nutzte reines Tailwind mit zinc-*-Klassen, harten Farb-Pillen (bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 …) und keiner FluxUI-Komponente. Visuell aus der Zeit gefallen.

  • admin/dashboard.blade.php komplett umgeschrieben:

    • Page-Header: Hub-Badge „Admin Backend" + Eyebrow + großes H1
      • Subtitle mit auth()->user()->name. Rechts: ok-Pille „Alle Systeme operational".
    • KPI-Reihe (5 Stat-Cards via <x-portal.stat-card>):
      • Pressemitteilungen → primary mit Trend-Slot „X pub · Y prüf · Z entwurf" (Wortlaut für Test-Assertions bewusst beibehalten).
      • In Prüfung → warn als eigene KPI (war vorher nur in der PM-Card versteckt — jetzt klickbar direkt in den Filter).
      • Firmen / Kontakte / Benutzer → muted mit kurzen Sublines.
      • Alle Cards sind klickbar (link-wrapped) → CRM-/Content-Übersichten.
    • 2-Spalten-Grid (2fr 1fr):
      • Links: Panel „Letzte Pressemitteilungen" mit Hub-Liste + .badge.ok|warn|err|hub-Pillen (statt Tailwind-Farben).
      • Rechts: Panel „Zur Prüfung" mit warn-Pille (Count) oder ok-Pille „leer". „+ N weitere"-Link im Footer.
    • Newsletter + Quick-Actions (1fr 2fr, NEU):
      • Links: panel-warm Newsletter-Block mit Mono-Zahl
        • Subline + Sync-Link.
      • Rechts: Quick-Action-Grid mit 4 Icon-Buttons (Pressemitteilungen, Firmen, Rechnungen, Voreinstellungen) — Icon-Tile wechselt auf Hover ins gefüllte Hub-Blau.
    • Footer: subtle Link-Reihe (Benutzer / Rollen / Performance).
  • Was bewusst NICHT geändert:

    • Controller-Logik, Datenform, Cache-Strategie (AdminPerformanceCache).
    • Newsletter-Count bleibt, wandert nur in eigenen Block.
  • Build/Verifikation:

    • npm run build:portalportal: 417.81 kB (Δ -0.7 kB, weil viele Zinc-Tailwind-Klassen weggefallen sind).
    • php artisan test --filter='DashboardTest|AuthenticationTest|RegistrationTest|CustomerPortalTest'18/18 passed, 70 Assertions. DashboardTest mit seinen Wortlaut-Assertions (3, 1 pub, 1 prüf, 1 entwurf, Review Dashboard PM) bleibt grün ohne Anpassung.
    • vendor/bin/pint --dirtypassed.
    • Linter: 0 Errors.
  • Lessons learned:

    • Vokabular-Migrations ohne Logik-Eingriff brauchen ~15 Minuten dank DRY-Schicht aus Phase 2 — der Wert der shared/hub-components.css
      • <x-portal.stat-card>-Investition zahlt sich ab Phase 3 deutlich aus.
    • Der <x-portal.stat-card> ist auch ohne :value-Number-Format flexibel (number_format() direkt im Aufruf eingebettet).
    • Test-Assertions können bei Layout-Refactors überraschend stabil bleiben, wenn man die Original-Strings im neuen Layout an sinnvollen Stellen behält (hier: im Trend-Slot der KPI-Card).

2026-05-19 · Phase 5 · Dark Mode + Switcher im User-Menü

  • Anlass: User-Feedback nach Phase 2: „Switch in den Dark Mode funktioniert nicht. Zusätzlich hätte ich gerne einen Switcher hell/dunkel direkt im User-Menü." → Phase 5 vorgezogen vor Phase 3/4, weil der Switcher der natürliche UX-Einstiegspunkt für Dark Mode ist und der Notfall-Hack aus Phase 1 (portal.css: .dark { --color-accent: var(--color-hub) }) endlich verschwinden soll.

  • Plan-Dokument: 05-PHASE-5-DARK-MODE.md mit Token-Mapping-Tabelle, drei wichtigen Token-Konstanten-Tricks (--color-accent-warm, --color-panel-dark, --color-panel-dark-2) und Switcher-Snippet.

  • design-tokens.css — Dark-Block aktiviert:

    • Vollständiger .dark { … }-Block mit Werten aus User Dashboard presseportale Dark.html.
    • Surfaces: bg/elev/card/rule schalten auf #0e1218-Familie.
    • Hub-Blau wird heller im Dark Mode (#5a78c2 statt #1a2540) — notwendig für Lesbarkeit auf dunklem Bg.
    • Bernstein-Akzent ebenfalls heller (#d9a560).
    • Status-Farben (ok/warn/err) auf dunkle, gesättigte Variante.
    • Schatten-Tokens neutral-schwarz statt hub-blau-warm.
    • color-scheme: dark; als Hint für native Form-Controls.
  • 3 neue Token-Konstanten (gleicher Wert in beiden Modi):

    • --color-accent-warm (#b07a3a) — für Stellen, die explizit Bernstein bleiben müssen (Hint-Card-Border-Left, Progress-Bar-Fill); löst die Kollision auf, dass --color-accent im Portal auf Hub-Blau gemapt ist und im Dark Mode noch heller würde.
    • --color-panel-dark (#0f1729) und --color-panel-dark-2 (#1a2540) — für .panel-dark und Brand-Bridge-Inner-Boxes. Ohne diese würde der dunkle Bridge-Container im Dark Mode plötzlich hellblau, weil var(--color-hub) zum hellen Wert wird.
  • portal.css — Notfall-Hack aus Phase 1 entfernt:

    • Der .dark { --color-accent: var(--color-hub); … }-Block ist überflüssig, weil das echte Dark-Token-Mapping in design-tokens.css --color-hub automatisch auf #5a78c2 schaltet — und --color-accent darüber per var(--color-hub)-Verweis dynamisch mitkommt.
    • Primary-Button-Shadows zusätzlich für .dark überschrieben: statt rgba(26, 37, 64, …) (warmer Hub-Blau-Alpha) jetzt rgba(0, 0, 0, …) (neutral-schwarz), weil der hub-blaue Schatten auf dunklem Card-BG zu sichtbar wirkt.
  • hub-components.css — Dark-tauglich gemacht:

    • .panel-dark nutzt jetzt var(--color-panel-dark-2) und var(--color-panel-dark) (vorher var(--color-hub) und var(--color-topbar-deep)) → bleibt im Dark Mode dunkel.
    • .hint-card border-left und .hint-bar > span nutzen var(--color-accent-warm) (konstant Bernstein) statt var(--color-accent) (im Portal Hub-Blau-Mapping).
    • .hint-card background schaltet auf var(--color-bg-card-warm) — ist im Light Mode #efeadc (warmes Buchpapier), im Dark Mode #1f1a12 (warm-dunkles Bernstein-Substrat).
    • Restliche Klassen funktionieren automatisch, weil alle Werte über Tokens laufen — DRY-Architektur zahlt sich aus.
  • customer/dashboard.blade.php:

    • Brand-Bridge-Inner-Boxes auf bg-[color:var(--color-panel-dark-2)] umgestellt (statt --color-hub-2, das im Dark Mode hell würde).
  • Switcher im User-Menü (sidebar.blade.php — Desktop + Mobile):

    • Vor dem Logout-Button: kleiner Block mit Eyebrow „Erscheinung" und FluxUI-Segmented-Radio-Group mit Icons-only.
      <flux:radio.group x-data variant="segmented" size="sm" x-model="$flux.appearance">
          <flux:radio value="light" icon="sun" :title="__('Hell')" />
          <flux:radio value="dark" icon="moon" :title="__('Dunkel')" />
          <flux:radio value="system" icon="computer-desktop" :title="__('System')" />
      </flux:radio.group>
      
    • $flux.appearance ist FluxUIs Magic-Object — LocalStorage-persistent, @fluxAppearance-Script setzt class="dark" auf <html>.
    • In BEIDEN Dropdowns (Desktop in der Sidebar, Mobile im Header).
  • Hub-Frontend bleibt Light-Only (Plan-Vorgabe):

    • auth/pressekonto.blade.php lädt KEIN @fluxAppearance und KEIN partials/head. Damit wird class="dark" dort nie gesetzt — auch nicht, wenn LocalStorage dark enthält. Kein Eingriff nötig.
    • Hub-Landing analog (eigene <head>-Pipeline).
  • Build/Verifikation:

    • npm run build:portalportal: 418.55 kB (Δ +1.5 kB für Dark-Tokens + Switcher).
    • php artisan test --filter='DashboardTest|AuthenticationTest|RegistrationTest|CustomerPortalTest'18/18 passed, 70 Assertions. Keine Regressions.
    • vendor/bin/pint --dirtypassed.
    • Linter: 0 Errors.
  • Lessons learned:

    • Tailwind v4's @theme-Variables sind dynamisch zur Laufzeit — --color-accent: var(--color-hub) schaltet beim .dark-Switch automatisch mit, ohne dass man .dark { --color-accent: … } extra setzen muss.
    • Wenn ein Wert in beiden Modes IDENTISCH bleiben soll (--color-panel-dark-2, --color-accent-warm), gehört er in den Light-Block und wird im .dark-Block bewusst NICHT überschrieben. Vererbung tut den Rest.
    • FluxUI's flux:radio.group variant="segmented" mit Icons-only ist perfekt für Dropdown-Switcher; :title="…" liefert Tooltips ohne sichtbares Label.
  • Bonus: Der ursprüngliche Symptom-Fix aus Phase 1 (Multi-Alpine + Dark-Mode-Bug) ist jetzt strukturell aufgelöst:

    • Alpine kommt ausschließlich aus @fluxScripts.
    • Dark Mode ist echt umgesetzt, nicht maskiert.

2026-05-19 · Phase 2 · Customer-Dashboard auf Mockup-Stil

  • Anlass: User-Freigabe „weiter“ nach Behebung des Dark-Mode/Alpine-Bugs. Phase 2 laut Plan: Customer-Dashboard (/admin/me) an User Dashboard presseportale.html angleichen.

  • Vorab-Doku: 04-PHASE-2-CUSTOMER-DASHBOARD.md mit Mockup-Diff-Tabelle, CSS-Strategie, Component-Skizzen, Akzeptanzkriterien.

  • CSS-Architektur — DRY-Schritt:

    • Neue Datei resources/css/shared/hub-components.css als Single Source of Truth für Hub-Layout-Bausteine: .panel (warm/dark/head), .stat-card (+ Varianten is-primary|ok|warn|muted, .stat-strip, .stat-label, .stat-num, .stat-meta, .stat-trend), .hint-card (+ .hint-ico, .hint-bar, .hint-action), .badge (+ .warn|ok|hub|err|dot), .bridge-row/.dot-pe/.dot-bp, portable .eyebrow und .section-eyebrow (für Portal — Web-Build überschreibt idempotent).
    • Importiert in beiden Builds:
      • resources/css/portal.css (nach flux.css)
      • resources/css/web/shared-styles.css (nach design-tokens.css)
    • Alle Werte nutzen var(--color-*)-Tokens — keine Hex-Literale.
    • Fehlende Tokens nachgezogen in shared/design-tokens.css: --color-bg-rule-2 (hellere Progress-Track-Variante) und --color-gain-deep (dunkles Grün für is-ok-Stat-Num).
  • Neue Blade-Components in resources/views/components/portal/:

    • <x-portal.stat-card variant="…" label="…" :value="…"> mit Slots meta (oben rechts) und trend (unten).
    • <x-portal.hint-card :icon :title :percent :href :action> mit Progress-Bar bei gesetztem $percent und wire:navigate-Link.
  • livewire/customer/dashboard.blade.php komplett neu:

    • Page-Header: Hub-Badge „User Backend“ + Eyebrow + großes H1
      • Subtitle. Rechts entweder Aktive-Firma-Pille oder Warn-Pille „Keine Firma zugeordnet → zuordnen“.
    • KPI-Reihe (4 stat-cards): Gesamt (primary, mit Δ-zu-Vormonat), Veröffentlicht (ok), In Prüfung (warn), Entwürfe (muted).
    • Zweispalten-Grid (lg:grid-cols-[2fr_1fr]):
      • Links: Panel mit Pressemitteilungen-Liste oder Empty-State (Icon-Box mit Notification-Dot, Headline, Action-Button, Schritt-Karten 01/02/03, Footer-Tipp „4 Stunden“).
      • Rechts: Panel „Datenqualität“ mit <x-portal.hint-card>s oder Success-State („Alles im grünen Bereich“).
    • Unteres Grid: Firmen-Panel (Liste oder dashed Empty-Slot
      • Hinweis-Box) + Brand-Bridge-Dark-Panel (presseecho + businessportal24 mit Status, API-Status-Indikator, Tarif).
    • Footer: Subtle-Link-Reihe (Sicherheit, API & Tokens, Profil).
  • Volt-with() erweitert:

    • stats.deltaMonth — Monatsvergleich via zweiter whereBetween-Query.
    • profileCompleteness (Heuristik auf 6 Profile-Kernfelder).
    • billingCompleteness (5 Address-Pflichtfelder).
    • bridgeStatus (vorerst hardcoded connected — Phase 3+).
    • qualityHints[] optional um percent-Feld erweitert — wenn gesetzt, rendert Progress-Bar in der Hint-Card.
  • Edge-Case beim Bauen: Blade interpretierte <flux:icon> im PHPDoc- Kommentar von hint-card.blade.php als echten Component-Tag und produzierte Undefined variable $component. Fix: Doc-Block entkontaminiert („flux:icon“ ohne Spitzklammern).

  • Tests neu in tests/Feature/Customer/DashboardTest.php (5 Cases):

    1. Customer-Dashboard rendert Core-Sections ohne Fehler
    2. Empty-State mit 3-Schritt-Intro wird gezeigt
    3. PR-Liste + KPI-Zahlen rendern bei vorhandenen Daten
    4. Profile-Completeness-Hint mit Prozentwert erscheint bei Teildaten
    5. Vollständiges Profil + Billing → Hints werden ausgeblendet, „Alles im grünen Bereich“ wird gezeigt
    • Ergebnis: 5/5 passed, 21 Assertions.
    • Cross-Check: Verwandte Tests (Dashboard|Authentication|Registration|CustomerPortal) → 18/18 grün, 70 Assertions. Keine Regressions.
  • Build/Verifikation:

    • npm run build:portalportal: 417.02 kB (Δ +8 kB für neue Hub-Components-Klassen + Dashboard-Klassen). Web-Build unverändert.
    • vendor/bin/pint --dirtypassed.
  • Was bewusst weggelassen:

    • Sparklines auf den Stat-Cards (kommen mit echten Trend-Daten in Phase 4).
    • Topbar-Anpassung (eigene Phase, später).
    • <x-portal.bridge-card>-Extraktion (Brand-Bridge bleibt inline, bis sie an mehr Stellen gebraucht wird).
  • Lessons learned:

    • PHPDoc in Blade-Components darf KEINE <flux:*>-Tags enthalten — der Blade-Pre-Compiler scannt das gesamte File vor dem PHP-Parsing.
    • shared/hub-components.css ist der richtige Hebel für Phase 3 (Admin-Dashboard) und Phase 4 (Listen/Detail) — Components-CSS muss nicht mehr pro Phase neu definiert werden.

2026-05-19 · Phase 1 Refinement · Dark-Mode-Bug + Multi-Alpine

  • Anlass: User-Review nach Kontrast-Refinement: zwei konkrete Befunde aus der Browser-Konsole.

    1. [Warning] Detected multiple instances of Alpine running (me, line 114)
    2. Button-Default-Farbe ist rgb(109, 138, 211) (helles Blau), nicht das gewünschte Hub-Blau rgb(26, 37, 64). Computed Style zeigt: .bg-[var(--color-accent)] { background-color: var(--color-accent); }var(--color-accent) löst zu #6d8ad3 auf.
  • Diagnose Bug 1 (Alpine):

    • partials/head.blade.php lädt resources/js/app.js über @vite. app.js ruft Alpine.start() auf.
    • Am Ende des <body> injiziert @fluxScripts (sidebar.blade.php Zeile nahe </body>) eine eigene Alpine-Instanz (FluxUI bringt Alpine selbst mit).
    • Ergebnis: zwei window.Alpine-Objekte, Bindings teils tot, Warning.
    • Auf der Login-Seite hatten wir das bereits gefixt (app.js dort rausgenommen), aber im Portal-Layout war der Fix noch offen.
  • Diagnose Bug 2 (Button-Farbe):

    • Der Wert rgb(109, 138, 211) = #6d8ad3 ist exakt der Dark-Mode-Fallback, den ich in portal.css unter .dark { --color-accent: #6d8ad3 } definiert hatte.
    • FluxUI's @fluxAppearance-Helper schreibt class="dark" auf <html>, sobald der User den Appearance-Switcher mal auf "dark" gestellt hatte (gespeichert in localStorage).
    • Damit überschreibt der Dark-Block den Light-Mode-Akzent var(--color-hub) (#1A2540) — Buttons sehen plötzlich blassblau aus.
    • Dark Mode ist laut Plan erst Phase 5, war aber durch den Fallback-Block bereits halb aktiv.
  • Fixes:

    • resources/views/partials/head.blade.php: resources/js/app.js aus dem @vite-Aufruf entfernt. Alpine kommt im Portal ausschließlich über @fluxScripts. (Hub-Landing nutzt partials/head nicht — eigene <head>-Pipeline.)
    • resources/css/portal.css: Der .dark { --color-accent: ... }- Block setzt jetzt bewusst alle Akzent-Tokens auf var(--color-hub) (also den Light-Mode-Wert). Damit bleibt das Hub-Blau auch bei eingeschaltetem class="dark" konsistent. Kommentar dokumentiert, dass Phase 5 diesen Block durch das echte Dark-Token-Mapping aus shared/design-tokens.css ersetzt.
  • Build/Verifikation:

    • npm run build:portalportal: 408.97 kB (Δ +0.02 kB).
    • php artisan test --compact --filter='AuthenticationTest|RegistrationTest'6 passed, 19 assertions, 1.93s.
    • vendor/bin/pint --dirty --format agentpassed.
  • User-Action zur Verifikation:

    • Im Portal Hard-Reload (Cmd/Strg+Shift+R) — die alte app.js hängt sonst im HTTP-Cache.
    • Konsole sollte keine Multi-Alpine-Warning mehr werfen.
    • Primary-Buttons sind im Default-State sattes Hub-Blau (#1A2540), Hover noch dunkler (#243152).

2026-05-19 · Phase 1 Refinement · Kontraste & Button-Hover

  • Anlass: User-Review nach Phase 1: „Buttons als Primary auf rgb(26, 37, 64) einsetzen, die andere Farbe ist deutlich zu hell. Es fehlen noch deutliche Kontraste."
  • Diagnose:
    • FluxUI-Primary-Buttons sind eigentlich schon auf var(--color-accent) = var(--color-hub) = #1A2540 = rgb(26, 37, 64) gesetzt (im Build verifiziert). Sollte stimmen.
    • ABER: Der FluxUI-Default-Hover ist hover:bg-[color-mix(in_oklab,_var(--color-accent),_transparent_10%)] — auf hellem Buchpapier wirkt das hell-blau statt der gewünschten Hub-Konvention hover:bg-hub-2 (dunkler als Default).
    • Außerdem zu wenig Schatten/Border-Kontrast für klare Button-Kanten.
  • Erkenntnis: Frühere [data-flux-button][data-variant="primary"]- Overrides griffen nie, weil FluxUI kein data-variant-Attribut rendert. Variant-Styling kommt komplett über Tailwind-Klassen (z.B. bg-[var(--color-accent)]). Neue Selektor-Strategie nutzt jetzt diese Klassen direkt (mit escapeten Brackets).
  • Fixes in portal.css:
    • Primary-Button-Hover auf var(--color-hub-2) (#243152) statt FluxUI's color-mix-Hellung. Selektor: [data-flux-button].hover\:bg-\[color-mix\(in_oklab\,_var\(--color-accent\)\,_transparent_10\%\)\]:hover
    • Primary-Button-Shadow: kräftigeres Inset-Highlight + warmer Drop-Shadow in Hub-Blau-Alpha für klare Kanten auf Buchpapier. Border zusätzlich auf var(--color-hub-2) für definierten Rand.
    • Hover-State: noch stärkerer Shadow + Drop für Tiefenwirkung.
    • Input-Focus auf Hub-Blau-Ring (statt blassem Default-Akzent), mit Buchpapier-Offset für saubere Trennung.
    • Alter (defunkter) [data-flux-button][data-variant="primary"]- Block entfernt, weil Selektor nicht existiert.
  • Build/Verifikation:
    • npm run build:portalportal: 408.95 kB (von 409.03 kB, -0.08 kB).
    • Im finalen CSS verifiziert:
      • Hub-2-Hover-Override: [data-flux-button].hover\:bg-…:hover{background-color:var(--color-hub-2)!important}
      • Shadow-Override: [data-flux-button].bg-\[var\(--color-accent\)\]{border-color:var(--color-hub-2);box-shadow:inset 0 1px #ffffff2e,0 1px 2px #1a254040,…}
      • Input-Focus-Ring auf Hub-Blau.
    • vendor/bin/pint --dirty → passed.
  • Wirkung:
    • Primary-Button Default: #1A2540 (Hub-Blau), klarer warmer Schatten, definierter Rand → fühlt sich „solid" an wie auf der Hub-Landing.
    • Primary-Button Hover: #243152 (Hub-2, dunkler statt heller) — Hub-Konvention, signalisiert Interaktion ohne den Eindruck einer schwächeren Farbe zu erzeugen.
    • Inputs zeigen jetzt einen erkennbaren Hub-Blau-Ring beim Fokus statt eines blassen Bernstein-Schimmers.
  • Hinweis an User: Hard-Reload (Cmd+Shift+R) ist nötig — das CSS-Bundle hat einen neuen Hash (portal-kuU-opFv.css).
  • Verfeinerungen noch offen für Phase 2 / Iteration:
    • Subtle/Filled/Ghost-Buttons (<flux:button variant="filled">) sind weiterhin transparent-zinc → bei Bedarf in Phase 2 angleichen.
    • Sidebar-Active-Item hat schon Hub-Soft + 2 px-Strip; ggf. den Strip noch sichtbarer machen wenn weiter zu unauffällig.

2026-05-19 · Phase 1 abgeschlossen · Portal-Shell auf Hub-Design

  • Was: Portal-Shell (Sidebar, Topbar, Layout-Container, Customer-Banner) visuell ans Hub-Design angeglichen. FluxUI bleibt komplett erhalten — Anpassung erfolgt über CSS-Token-Bridging und [data-flux-*]-Overrides. Brand-Mark ersetzt das Starter-Kit-Logo. Light Mode ist Default; Dark Mode für Phase 5 vorbereitet (heller Hub-Blau).
  • Dateien (geändert):
    • resources/css/portal.css — komplett refactored:
      • --font-sans: "Inter Tight" statt Instrument Sans
      • --color-accent: var(--color-hub) (#1A2540) statt #3ea3dc
      • --color-zinc-50..950 auf Hub-Buchpapier-Familie gemappt (Zinc-100 = #F6F4EF, Zinc-700 = #1A1F1C, Zinc-900 = Hub-Blau)
      • Hub-Stil-Overrides: [data-flux-sidebar], [data-flux-navlist], [data-flux-navlist-item] mit Active-Strip links, [data-flux-button] Primary/Filled auf Hub-Blau, [data-flux-card] Buchpapier
      • Dark-Mode-Block bleibt vorerst minimal (nur Accent), Vollumstellung in Phase 5
    • resources/views/partials/head.blade.php — Bunny-Font auf inter-tight + jetbrains-mono + source-serif-4 (für Brand-Mark)
    • resources/views/components/layouts/app/sidebar.blade.php:
      • class="dark" aus <html> entfernt
      • <body> jetzt bg-bg text-ink antialiased (Hub-Buchpapier)
      • <x-app-logo> ersetzt durch <x-web.brand-mark brand="pressekonto" :serif="false" /> + Eyebrow "Publisher · Hub" — sowohl im Desktop- Brand-Block als auch im Mobile-Header
      • Testmodus-Block (Impersonation) komplett im Hub-Stil: dunkles Hub-Blau-Panel mit Bernstein-Eyebrow „Testmodus aktiv", weiße CTA „Zurück zum Admin" (statt Amber-Warnfarbe wie zuvor)
      • Resources-Block (Tailwind/HeroIcons/Flux/Repository) entfernt — gehört nicht ins Live-Portal
    • resources/views/components/layouts/app.blade.php:
      • Customer-Banner („User Backend") visuell auf Hub-Stil: Hub-Soft- Hintergrund + Hub-Soft-2-Border, Hub-Blau-Pille mit Dot, Eyebrow „Firmenkontext" in Sperrschrift, Heading in Hub-Ink
  • Dateien (Test-Anpassungen, weil rollen-basierter Redirect aus Login-Fix weitere Tests berührt hat):
    • tests/Feature/Auth/AuthenticationTest.php — Test-User auf superAdmin() umgestellt (sonst canAccessAdmin() === false → Redirect auf / statt /dashboard)
    • tests/Feature/Auth/RegistrationTest.phpterms_accepted im Formular gesetzt + Redirect-Erwartung auf / angepasst (frisch registrierte User haben keine Rolle → Fallback /)
  • Build/Test:
    • npm run build:portalportal: 409.03 kB (vorher 408.89 kB, +0.14 kB). Unter dem 10 %-Akzeptanzkriterium (≤ 450 kB).
    • CSS-Inspektion bestätigt Phase-1-Tokens:
      • --color-accent: var(--color-hub) und .dark { --color-accent: #6d8ad3 } im :root
      • --color-zinc-700: #1a1f1c (Hub-Ink statt Zinc-Grau)
      • --font-sans: "Inter Tight" ohne Instrument-Sans-Vorlauf
      • Hub-Overrides im Output: [data-flux-sidebar]{background:var(...)}, [data-flux-navlist-item][aria-current=page]{background:var( --color-hub-soft);...}
    • Auth-Test-Suite: 0 zusätzliche Regressionen verifiziert (8 fail / 15 passed vor & nach Phase 1; verbleibende Failures sind pre-existing Domain-Mismatch- und CSRF-Issues im Test-Setup).
    • Smoke-Test: /dashboard, /admin/me, /settings/profile, /admin/companies, /admin/press-releases antworten alle HTTP 302 → /login (erwartetes Verhalten ohne Auth-Session via curl).
    • vendor/bin/pint --dirty → passed.
  • Bewusst NICHT in Phase 1:
    • Topbar mit Breadcrumb + Bridge-Row + Search + „Neue Mitteilung"-CTA aus dem Mockup → ist für Phase 2 (Customer-Dashboard) sinnvoller, weil die Topbar dort Page-Kontext (Breadcrumb-Titel) braucht. Aktuell nutzen wir FluxUI's Default-Layout ohne dedizierte Topbar.
    • Konto-Switcher als Sidebar-Header (Avatar + Name + Firma als Dropdown-Trigger oben statt unten) → das User-Menü unten bleibt vorerst FluxUI-Standard. Iterativ in Phase 2.
    • Dashboard-Inhalte (Stat-Cards, Hint-Cards) → Phase 2 & 3.
    • Listen-Pages → Phase 4 (automatisch durch Token-Bridge schon „okay").
  • Beobachtungen:
    • FluxUI-Navlist-Item-Selektor: [aria-current="page"] greift. Falls künftige FluxUI-Versionen [data-current="true"] statt [aria-current="page"] setzen, deckt der Override beides ab.
    • Vendor-Pfad in partials/head.blade.php bewusst nicht geändert — Vite-Setup mit build/portal bleibt wie gehabt.
  • Nächster Schritt: Review-Stopp. Bei Freigabe → entweder Phase 2 (Customer-Dashboard-Stat-Cards & Hint-Cards) oder Topbar- Iteration. Entscheidung bei dir/Frank nach Anschauen.

2026-05-19 · Login-Funktionsfix · Doppelte Alpine-Instanz

  • Was: Nach Phase 0 trat ein funktionaler Bug auf: Login-Form ging nicht durch, Browser-Logs zeigten „Detected multiple instances of Alpine running" und „Livewire: published assets out of date".
  • Ursache: Das Hub-Auth-Layout (pressekonto.blade.php) lud sowohl resources/js/app.js (das Alpine.start() aufruft) als auch @livewireScripts (das Alpine intern mitbringt). Zwei Alpine-Instanzen → wire:submit, x-data, wire:model brachen.
  • Fixes:
    • app.js aus @vite([…]) im Auth-Layout entfernt — Alpine kommt nun nur noch über Livewire.
    • php artisan livewire:publish --assetslivewire.js von 450 kB auf 552 kB aktualisiert (Versions-Mismatch behoben).
    • Login/Register-Redirect auf rollen-basierte Logik umgestellt (Admin → /dashboard, Customer → /admin/me, sonst /) und navigate: true entfernt — SPA-Navigation kann den Wechsel zwischen Web-Build (Hub-Auth) und Portal-Build (FluxUI-Dashboard) nicht handhaben.
  • Dateien:
    • resources/views/components/layouts/auth/pressekonto.blade.php
    • resources/views/livewire/auth/login.blade.php
    • resources/views/livewire/auth/register.blade.php
  • Verifikation: Login funktioniert (User bestätigt), Redirect zum Dashboard läuft, keine Browser-Warnings mehr.

2026-05-19 · Phase 0 abgeschlossen · Token-Unifizierung

  • Was: Single Source of Truth für Design-Tokens etabliert. Web- und Portal-Build importieren beide resources/css/shared/design-tokens.css. Visuelle Unverändertheit verifiziert — FluxUI-Defaults gewinnen im Portal weiterhin (Instrument Sans, Zinc, #3ea3dc), wird in Phase 1 abgelöst.
  • Dateien:
    • resources/css/shared/design-tokens.css neu — alle Hub-Tokens plus Status-Reihe (--color-warn, --color-warn-soft, --color-err, --color-err-soft, --color-ok-soft), Bridge-Dots (--color-bridge-presseecho, --color-bridge-businessportal), Radii (--radius-xs/sm/md/lg) und Schatten (--shadow-soft, --shadow-auth). Dark-Mode-Block als auskommentierter Vorgriff.
    • resources/css/web/shared-styles.css — Token-Import nach tailwindcss ergänzt. Wirkt damit für alle Web-Themes (pressekonto, presseecho, businessportal24).
    • resources/css/web/theme-pressekonto.css — kompletter @theme {}- Block entfernt (lebt jetzt in der Token-Datei). HSL-Legacy-Variablen und @layer components { … } blieben unverändert.
    • resources/css/portal.css — Token-Datei importiert, FluxUI-Setup mit Zinc + Instrument Sans bleibt vorerst dominant. Phase 1 löst es ab.
  • Build/Test:
    • npm run build:webtheme-pressekonto: 193 kB (vorher 189 kB, +4 kB für neu gebridgde Status-Tokens), theme-presseecho: 189 kB, theme-businessportal24: 189 kB.
    • npm run build:portalportal: 408 kB (vorher 397 kB, +12 kB für die zusätzlich verfügbaren Hub-Tokens als CSS-Vars im :root). Wird in Phase 1 wieder egalisiert, wenn das Zinc-Setup wegfällt.
    • Smoke-Test: pressekonto.test/, /login, /register, /dashboard (302→login), presseecho.test/, businessportal24.test/ — alle HTTP 200/302 wie erwartet.
    • CSS-Inspektion: --color-hub: #1a2540 und --color-warn: #a87a1f sind in theme-pressekonto-*.css enthalten. Im Portal-Build bleibt --font-sans: "Instrument Sans" — bestätigt visuelle Unverändertheit.
    • vendor/bin/pint --dirty → passed.
  • Offene Fragen / Beobachtungen:
    • Weil Tailwind v4 alle in @theme {} definierten Tokens als CSS- Variablen im :root ausgibt (auch ohne Utility-Verwendung), wird der Portal-CSS-Wuchs in Phase 1 nicht komplett zurückgehen — die Hub-Tokens bleiben als Variablen verfügbar. Der Nettoeffekt nach Phase 1 sollte ähnlich bleiben (+/- 510 kB).
    • Dark-Mode-Block in design-tokens.css ist auskommentiert vorbereitet, aber bewusst noch nicht aktiv (Phase 5).
  • Nächster Schritt: Review-Stopp. Bei Freigabe → Phase 1 starten: Portal-Shell (Sidebar, Topbar, Layout-Container) auf Hub-Style mappen, Zinc-Palette ablösen, FluxUI-Overrides via [data-flux-*]-Selektoren in portal.css. Details: 02-PHASE-1-PORTAL-SHELL.md.

2026-05-19 · Setup

  • Was: Architektur-Entscheidung getroffen → Plan B (Tokens teilen, Komponenten getrennt lassen). Dokumentation in dev/frontend/hub-flux/ angelegt:
    • README.md — Übersicht & Entscheidung
    • 01-PHASE-0-TOKENS.md — Detail-Plan für Tokens-Vereinheitlichung
    • 02-PHASE-1-PORTAL-SHELL.md — Detail-Plan für Portal-Shell-Refresh
    • 03-WEITERE-PHASEN.md — Outline Phase 26
    • PROGRESS.md — dieses Log
  • Bestätigt:
    • Hub-Blau als Primärer Akzent im Portal (klarer Kontrast zum hellen Buchpapier-Hintergrund)
    • Bernstein als Sekundärer Akzent (Notifications, Datenqualität, Akzent-Ribbons)
    • Brand bleibt pressekonto (auch im Portal-Sidebar via <x-web.brand-mark>)
    • Reihenfolge: erst Phase 0 + 1, dann Review
  • Nächster Schritt: Phase 0 umsetzen → resources/css/shared/design-tokens.css erstellen, theme-pressekonto.css refactoren, portal.css minimal vorbereiten.

Vorlauf (zur Erinnerung, was schon steht)

  • Hub-Landing (web/pressekonto.blade.php) — fertig, lebt im Web-Build mit theme-pressekonto.css
  • Hub-Auth (Login, Register, Forgot, Reset, Verify, Confirm) — fertig im Hub-Design, neues Layout auth/pressekonto.blade.php im Web-Build
  • Register-AGB-Checkbox mit Server-Side-Validierung ergänzt
  • Portal-Backend mit FluxUI funktional vorhanden (Admin-Dashboard, Customer-Dashboard, 77 Blade-Dateien mit FluxUI), aber visuell noch Starter-Kit-Look (Zinc + #3ea3dc + Instrument Sans)

Template für neue Einträge

## YYYY-MM-DD · Phase N · Kurztitel

- **Was**: [Was wurde konkret gemacht?]
- **Dateien**: [Pfade]
- **Build/Test**: [Wie verifiziert?]
- **Offene Fragen**: [Falls etwas unklar geblieben ist]
- **Nächster Schritt**: [Was als Nächstes ansteht]