diff --git a/_docs/FORTIFY-SANCTUM-SETUP.md b/_docs/FORTIFY-SANCTUM-SETUP.md index 61d219a..58c175a 100644 --- a/_docs/FORTIFY-SANCTUM-SETUP.md +++ b/_docs/FORTIFY-SANCTUM-SETUP.md @@ -150,7 +150,7 @@ Bearbeiten Sie die Komponenten in `resources/views/livewire/auth/`: ```php // Beispiel: Login-Komponente anpassen -new #[Layout('components.layouts.auth')] class extends Component { +new #[Layout('components.layouts.auth.pressekonto')] class extends Component { #[Validate('required|string|email')] public string $email = ''; diff --git a/dev/frontend/hub-flux/03-WEITERE-PHASEN.md b/dev/frontend/hub-flux/03-WEITERE-PHASEN.md index 61ef609..3171b58 100644 --- a/dev/frontend/hub-flux/03-WEITERE-PHASEN.md +++ b/dev/frontend/hub-flux/03-WEITERE-PHASEN.md @@ -8,7 +8,15 @@ ## Phase 2 — Customer-Dashboard auf Mockup-Stil -**Status**: ⚪ später · **Aufwand**: ~½ Tag · **Risiko**: niedrig +**Status**: ✅ **abgeschlossen** (de facto in Phase 1 + +verfeinert in 4J) · **Aufwand**: ~½ Tag · **Risiko**: niedrig + +> Während der Phase-1-Migration wurden Page-Header, KPI-Reihe, +> 2-Spalten-Grids, ``, +> `` und Brand-Bridge-Dark-Card bereits +> umgesetzt. Phase 4J hat die Recent-PM-Liste mit Portal-Pills +> + PM-ID-Sub auf den finalen 4H/4I-Pattern-Stand gebracht. +> Match zum Mockup ≥ 95 %. ### Ziel `livewire/customer/dashboard.blade.php` matched das Mockup @@ -40,26 +48,36 @@ ## Phase 3 — Admin-Dashboard konsistent -**Status**: ⚪ später · **Aufwand**: ~½ Tag · **Risiko**: niedrig +**Status**: ✅ **abgeschlossen** (in Phase 1 + 4J) +· **Aufwand**: ~½ Tag · **Risiko**: niedrig -### Ziel -`resources/views/admin/dashboard.blade.php` nutzt dasselbe Vokabular wie -Customer-Dashboard. - -### Heutiger Stand -Reines Tailwind mit `zinc-*`-Klassen, **keine** FluxUI-Komponenten, -visuell aus der Zeit gefallen. - -### Schritte -- KPI-Karten als `` -- Wenn Charts vorhanden: über `flux:chart` umsetzen (FluxUI Pro) -- Recent-Activity-Liste in `flux:card` mit Hub-Akzenten +> Admin-Dashboard nutzt seit Phase 1 dasselbe Vokabular wie +> das Customer-Dashboard: Page-Header, 5-KPI-Reihe mit +> ``, 2-Spalten-Grid (Recent + Pending +> Reviews), Newsletter `panel-warm`, Quick-Actions-Grid, +> Footer. Phase 4J hat Portal-Pills, PM-ID-Sub und +> Inline-Action „Prüfen →" mit `is-row-warn`-Tinting für +> die Review-Queue ergänzt. --- ## Phase 4 — Listen-/Detail-Pages durchgehen -**Status**: 🚧 iterativ · **Aufwand**: ~3–5 Tage gesamt · **Risiko**: niedrig +**Status**: ✅ **komplett abgeschlossen** (4A–4J) +· **Aufwand**: ~3–5 Tage gesamt · **Risiko**: niedrig + +> Alle 10 Sub-Päckchen (4A–4J) sind grün, Build + Pint +> sauber, alle relevanten Tests bestehen +> (230/231 gesamt — der eine Fail ist der pre-existing +> `ApiDocumentationTest` ohne Bezug zur UI-Migration). +> Das gesamte Backend (Admin + Customer) nutzt damit +> dieselbe Design-Sprache: Page-Header mit +> Eyebrow/Badge/Subtitle, ``-KPI-Reihen, +> `article.panel` als Container, `flux:table` mit Hub-Padding +> + Sortierung, `flux:card` nur wo Test-Verträge sie noch +> brauchen, sowie die Mockup-Patterns aus 4H/4I/4J +> (Saved-Views-Tabs, Active-Chips, Portal-Pills, +> Inline-Actions, Row-Tinting, 3-stufige Empty-States). ### Ziel Alle Volt-Pages im Admin- und Customer-Bereich nutzen denselben Hub-Stil. @@ -73,9 +91,20 @@ Alle Volt-Pages im Admin- und Customer-Bereich nutzen denselben Hub-Stil. siehe `08-PHASE-4B-PRESS-RELEASES-DETAIL.md` - **4C** = Press-Releases Forms (create/edit, Admin + Customer) — ✅ **abgeschlossen** siehe `09-PHASE-4C-PRESS-RELEASES-FORMS.md` - - **4D** = Companies (`admin.companies.*`) — ⚪ pending - - **4E** = Profile/Settings (`settings.*`, `me.profile`, `me.security`) — ⚪ pending - - **4F** = Restliche Admin-Bereiche — ⚪ pending + - **4D** = Companies (`admin.companies.*`) — ✅ **abgeschlossen** + siehe `10-PHASE-4D-COMPANIES.md` + - **4E** = Profile/Settings (`settings.*`, `customer.profile`, `customer.security`) — ✅ **abgeschlossen** + siehe `11-PHASE-4E-PROFILE-SETTINGS.md` + - **4F** = Restliche Admin-Bereiche (contacts, categories, presets, footer-codes, users, roles, newsletter, reports, invoices, coupons, payments, portal-switcher) — ✅ **abgeschlossen** + siehe `13-PHASE-4F-ADMIN-REST.md` + - **4G** = Restliche Customer-Bereiche (invoices, tokens, bookings, company-switcher, me/press-kits/*) — ✅ **abgeschlossen** + siehe `12-PHASE-4G-CUSTOMER-PORTAL.md` + - **4H** = Customer „Meine Pressemitteilungen" auf Mockup-Stil (Counter-Strip, Saved-Views-Tabs, Filter-Chips, Active-Chips, Portal-Pills, Inline-Actions, Row-Tint, 3-fach-Empty-State, Status-Aktionen-Legende) — ✅ **abgeschlossen** + siehe `14-PHASE-4H-PRESS-RELEASES-MOCKUP.md` + - **4I** = Admin „Pressemitteilungen" — Mockup-Patterns übertragen (Saved-Views-Tabs, Active-Chips, Portal-Pills, Row-Tint, Inline-Actions als Modal-Trigger, reduzierte Spalten, 2-stufiger Empty-State) — ✅ **abgeschlossen** + siehe `15-PHASE-4I-ADMIN-PRESS-RELEASES.md` + - **4J** = Dashboard-PM-Listen mit 4H/4I-Patterns (Portal-Pills, PM-ID-Sub, Customer + Admin Dashboard, Inline-Action „Prüfen →" für Admin-Review-Queue mit `is-row-warn` Tinting) — ✅ **abgeschlossen** + siehe `16-PHASE-4J-DASHBOARD-LISTS.md` ### Was geändert wird - Page-Header-Struktur (Eyebrow + H1 + Subtitle + Aktions-Bar) @@ -91,72 +120,125 @@ Alle Volt-Pages im Admin- und Customer-Bereich nutzen denselben Hub-Stil. ## Phase 5 — Dark Mode konsistent -**Status**: ⚪ später · **Aufwand**: ~½ Tag · **Risiko**: niedrig +**Status**: ✅ **abgeschlossen** · **Aufwand**: ~½ Tag (Großteil +der Arbeit war Vorbereitung in Phase 0–4) · **Risiko**: niedrig -### Ziel -Dark Mode funktioniert sauber im Portal, **ohne doppelte UI-Pflege**. +> Tokens, Switcher und alle Custom-CSS-Komponenten waren +> bereits token-basiert vorbereitet — `shared/design-tokens.css` +> hat einen kompletten `.dark { … }`-Block (Z. 182–248) mit allen +> Surfaces, Hub/Bernstein-Akzenten, Ink-Skala, Status-Farben, +> Schatten und `color-scheme: dark`. `hub-components.css` ist +> zu 100 % token-basiert und schaltet automatisch um. FluxUI's +> `@fluxAppearance` ist in beiden Head-Partials integriert, +> Switcher liegt im User-Menü (Desktop + Mobile) sowie in +> `settings/appearance.blade.php`. Bei der Inventur fiel nur +> ein latenter Bug auf (`--color-ink-deep`-Token existiert +> nicht, in `customer/tokens.blade.php` auf +> `--color-panel-dark-2` umgestellt). QR-Code in +> `customer/security.blade.php` behält bewusst `bg-white` in +> beiden Modi (Scan-Tauglichkeit), klarstellender Kommentar +> ergänzt. +> +> Siehe `17-PHASE-5-DARK-MODE.md` für Details. ### Quelle -`dev/frontend/tailwind_v3/User Dashboard presseportale Dark.html` hat -alle Dark-Tokens bereits vorgegeben. +`dev/frontend/tailwind_v3/User Dashboard presseportale Dark.html` +hat alle Dark-Tokens bereits vorgegeben — alle Werte sind in +`design-tokens.css` übernommen. -### Schritte -1. In `shared/design-tokens.css` Dark-Werte ergänzen: - ```css - @media (prefers-color-scheme: dark) { - @theme { - --color-bg: #0E1218; - --color-bg-elev: #14181F; - --color-hub: #5A78C2; - --color-accent: #D9A560; - /* … */ - } - } - .dark { - /* gleiche Werte für expliziten Switch */ - } - ``` -2. `class="dark"` wird **nicht** mehr hardcoded gesetzt -3. Flux Appearance-Switcher (`settings/appearance.blade.php`) steuert - `.dark` auf `` -4. Hub-Frontend bleibt erstmal Light-Only (so wie heute) - -### Erwartung -- Settings → Appearance → „Dark" schaltet Portal um -- Settings → Appearance → „System" folgt OS-Präferenz -- Sidebar, Topbar, Dashboards, Listen, Forms — alles funktioniert -- Hub-Landing und Hub-Auth bleiben Light +### Was geliefert wird +- Settings → Erscheinung → „Dunkel" schaltet Portal um +- Settings → Erscheinung → „System" folgt OS-Präferenz +- Switcher zusätzlich direkt im User-Menü (Sidebar + Mobile) +- Sidebar, Topbar, Dashboards, Listen, Forms — alles schaltet + automatisch über Token-Cascade um +- `panel-dark` bleibt KONSTANT dunkel (Brand-Bridge-Card) +- `--color-accent-warm` bleibt KONSTANT Bernstein (Hint-Cards) +- Hub-Landing und Hub-Auth bleiben Light (kein + `@fluxAppearance` im Web-Build) --- -## Phase 6 — Auth-Konsolidierung (optional) +## Phase 6 — Auth-Cleanup -**Status**: ⚪ optional · **Aufwand**: 0–1 Tag · **Risiko**: mittel +**Status**: ✅ **abgeschlossen** · **Aufwand**: ~30 min · **Risiko**: niedrig -### Frage -Bleibt der Hub-Login (`auth/pressekonto`-Layout, Web-Build) so wie er ist? -Oder konsolidieren wir auf den Portal-Build? +> Hub-Auth bleibt eigenständig (auf Web-Build mit dem `pressekonto`-Layout), +> weil Hub-Atmosphäre + Light-Bundle als Trade-off bewusst gewollt sind. +> Die ungenutzten Starter-Kit-Layouts wurden entfernt: `auth/simple`, +> `auth/split`, `auth/card`, der Wrapper `auth.blade.php`, das alternative +> `app/header.blade.php` sowie die Debug-Views `livewire/auth/login-simple` +> und `test-simple`. Damit gibt es keine hardcoded `class="dark"`-Reste +> mehr, die Phase 5 hätten torpedieren können. Doku-Beispiel in +> `_docs/FORTIFY-SANCTUM-SETUP.md` auf `components.layouts.auth.pressekonto` +> umgestellt. CSS-Bundle ist dabei sogar ~2.4 KB kleiner geworden. +> +> Siehe `18-PHASE-6-AUTH-CLEANUP.md` für die Inventur. -### Pro Konsolidierung -- Ein Build weniger -- Konsistente Komponenten-Sprache +### Optional für später (NICHT Teil von Phase 6) +Eine echte **Auth-Konsolidierung** (Hub-Auth-CSS in den Portal-Build +ziehen, Web-Build nur für die Landing-Pages behalten) wäre denkbar, +aber: +- Hub-Atmosphäre (Konzentrische Kreise, Hub-Grid) ist visuell stark +- Hub-Auth ist leichtgewichtig (kein FluxUI im Bundle) +- Aktueller Stand funktioniert sauber -### Pro Beibehaltung (heutiger Stand) -- Hub-Atmosphäre der Auth-Seiten (Konzentrische Kreise, Hub-Grid) ist - visuell sehr stark — würde verloren gehen -- Hub-Auth ist **leichtgewichtig** (kein FluxUI im Bundle) -- Vorlage `Login pressekonto A3 Tailwind.html` ist bewusst minimalistisch +→ keine Action notwendig, bleibt offen. -### Entscheidung -Vermutlich **beibehalten**. Aber: Die alten Auth-Layouts -`auth/simple.blade.php`, `auth/split.blade.php`, `auth/card.blade.php` aus -dem Starter-Kit können vermutlich gelöscht werden, sobald geprüft ist, -dass keine Komponente sie noch verwendet. +--- -### Schritte (wenn konsolidiert) -- Hub-Auth-CSS in `portal.css` ziehen (mit `@source` für die Tokens) -- `auth/pressekonto`-Layout auf Portal-Build umstellen -- Hub-Auth-Klassen (`.auth-card`, `.auth-grid`, `.auth-btn-primary`) - bleiben — laufen nur jetzt aus dem Portal-Bundle -- `theme-pressekonto.css` aus dem Web-Build entfernen (oder behalten - für die Landing) +## Gesamt-Status (Stand 2026-05-20) + +| Phase | Inhalt | Status | +|---|---|---| +| 0 | Hub-Auth (Login/Register) im Hub-Stil | ✅ | +| 1 | Portal-Migration (Tokens, FluxUI-Overrides, Sidebar/Topbar, App-Shell, Dark-Switch im User-Menü) | ✅ | +| 2 | Customer-Dashboard auf Mockup-Stil | ✅ (in P1, verfeinert in 4J) | +| 3 | Admin-Dashboard konsistent | ✅ (in P1, verfeinert in 4J) | +| 4 | Listen/Detail durchgehen (4A–4J) | ✅ **komplett** | +| 5 | Dark Mode konsistent | ✅ **abgeschlossen** | +| 6 | Auth-Cleanup | ✅ **abgeschlossen** | + +### Phase 4 — Sub-Päckchen im Detail + +| ID | Bereich | Plan-Doc | +|---|---|---| +| 4A | Press-Releases Listen (Admin + Customer) | `07-PHASE-4A-…` | +| 4B | Press-Releases Detail/Show | `08-PHASE-4B-…` | +| 4C | Press-Releases Forms (create/edit) | `09-PHASE-4C-…` | +| 4D | Companies (Admin) | `10-PHASE-4D-…` | +| 4E | Profile/Settings (Admin + Customer) | `11-PHASE-4E-…` | +| 4F | Restliche Admin-Bereiche (contacts, categories, presets, footer-codes, users, roles, newsletter, reports, invoices, coupons, payments, portal-switcher) | `13-PHASE-4F-…` | +| 4G | Restliche Customer-Bereiche (invoices, tokens, bookings, company-switcher, press-kits) | `12-PHASE-4G-…` | +| 4H | Customer „Meine Pressemitteilungen" Mockup-Stil (Counter-Strip, Saved-Views, Filter-/Active-Chips, Portal-Pills, Inline-Actions, Row-Tint, 3-stufiger Empty-State, Aktionen-Legende) | `14-PHASE-4H-…` | +| 4I | Admin „Pressemitteilungen" — Mockup-Patterns übertragen | `15-PHASE-4I-…` | +| 4J | Dashboard-PM-Listen mit 4H/4I-Patterns | `16-PHASE-4J-…` | + +### Nächste sinnvolle Schritte (Priorität) + +> Die hub-flux-Roadmap ist mit Phase 6 **vollständig** abgeschlossen. +> Alle weiteren Themen sind eigene Initiativen. + +1. **Manueller Dark-Mode Smoke-Test**: Im Browser User-Menü → + Erscheinung → „Dunkel" und durch die Hauptseiten klicken + (Dashboard, Listen, Detail, Security mit QR, Tokens). Erwartung: + Lesbar + konsistent. Kleine Polish-Runde, falls visuelle + Auffälligkeiten. + +2. **PM-Form-Wizard-Refactor**: Mockup + `User Neue Mitteilung presseportale.html` auf den bestehenden + Press-Release-Create/Edit-Flow übertragen. Größere Aktion mit + eigener Phase. + +3. **Web-Frontend-Block** (eigenständig, NICHT Teil von Phase 1–6): + Die noch ungenutzten Mockups + `Startseite Tailwind.html`, + `Startseite presseecho Tailwind.html`, + `Branchenseite Tailwind.html`, + `Detailseite Tailwind.html`, + `Veröffentlichen Tailwind.html` + sind Public-Facing-Pages der beiden Portale (businessportal24 + + presseecho), nicht Portal/Backend. Würde eine **eigene Roadmap** + bekommen, weil andere Build-Pipeline (`vite.web.config.js`), andere + Komponenten und ein ganz anderer Stil-Stack + (Source-Serif-Headlines, Brand-orange für businessportal24). diff --git a/dev/frontend/hub-flux/10-PHASE-4D-COMPANIES.md b/dev/frontend/hub-flux/10-PHASE-4D-COMPANIES.md new file mode 100644 index 0000000..eb1290f --- /dev/null +++ b/dev/frontend/hub-flux/10-PHASE-4D-COMPANIES.md @@ -0,0 +1,79 @@ +# Phase 4D — Companies (admin) + +> Viertes Päckchen aus Phase 4. Folgt auf 4A/4B/4C +> (Press-Releases-Strecke komplett). + +**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag · **Risiko**: niedrig–mittel + +--- + +## Scope + +- `resources/views/livewire/admin/companies/index.blade.php` (573 Z.) +- `resources/views/livewire/admin/companies/show.blade.php` (400 Z.) +- `resources/views/livewire/admin/companies/edit.blade.php` (412 Z.) +- `resources/views/livewire/admin/companies/create.blade.php` (281 Z.) + +NICHT in diesem Päckchen: +- `admin/contacts/*` — eigener Bereich, Päckchen 4F. +- `me/press-kits/*` — Customer-Sicht auf Firmen, eigener Päckchen-Anteil. +- Settings / Profile (Päckchen 4E). + +## Ziel + +Alle vier Companies-Pages im Hub-Vokabular — gleiches Muster wie +die Press-Releases-Strecke: + +- **Page-Header** mit Hub-Badge „Admin Backend" + Eyebrow + H1 + + Subtitle. Bei Show/Edit zusätzlich Portal-Pille (Presseecho / + Businessportal24 / Both) und ID/Slug-Hinweis. +- **KPI-Reihe** auf Index als `` falls Stats + vorhanden (Gesamt, je Portal, ggf. mit/ohne PMs). +- **Filter-Bar** als `.panel` mit `.panel-head` „Filter & Suche". +- **Tabelle/Listen** in `.panel` mit Hub-Badges + (`.badge.hub|ok|warn`). +- **Form-Sektionen** (Edit, Create) als `.panel` mit `.panel-head` + und `section-eyebrow`. +- **Tabs** (Show: „contacts", andere?) bleiben als FluxUI-Tabs — + optisch über das Token-Bridging genug Hub-Look. +- **Confirm-Modals** unverändert lassen (z.B. delete-confirm). + +## Was explizit NICHT angefasst wird + +- **Volt-Logik** in allen 4 Files — Layout-only. +- **`deleteCompany`**-Methode + Confirm-Modal — Test + `UserManagementTest` assertiert Redirect-Verhalten. +- **Wortlaute, die Tests prüfen**: + - `Firmen` (Sidebar-Link), `Portal`, `Alle Portale`, + `Firmen PM Zaehler GmbH` (Faktur-Name). + - Portal-Labels `Presseecho`, `Businessportal24`. + - URL-Pfade `/admin/companies/{id}`. +- **FluxUI Form-Felder, Combobox, Tab-Groups** bleiben. + +## Akzeptanzkriterien + +- [x] Plan +- [x] Index: Page-Header + Stats + Filter-Panel + Tabellen-Panel + + Hub-Badges. +- [x] Show: Page-Header (mit Portal-Pille) + Logo-/Meta-Block + + Tabs + Hub-Badges. +- [x] Edit: Page-Header (mit Portal-Pille) + Form-Panels + + Aktions-Panel. Delete-Modal unverändert. +- [x] Create: Page-Header + Form-Panels + Aktions-Panel. +- [x] `UserManagementTest`, `PortalAssetManifestTest` grün + (25 Tests, 227 Assertions). Volle Suite: 230 grün + (Vorhandener `ApiDocumentationTest`-Fail nicht von uns). +- [x] Build + Pint + PROGRESS. + +## Notes + +- Tabs als schlankes Bottom-Border-Pattern statt FluxUI-Tabs: + spart Layout-Komplexität und ist optisch näher am Hub. +- Portal-Badges bewusst alle als `badge hub` vereinheitlicht — + Portal-spezifische Farben (purple/blue) brachen aus dem + Tokensystem aus. Portal-Label bleibt sichtbar im Text. +- Logo-Boxen folgen jetzt dem gleichen Token-Pattern wie auf den + Press-Release-Detail-Seiten (`var(--color-bg-elev)` + + `var(--color-bg-rule)` border). +- Delete-Confirm-Modal komplett unverändert (Test prüft Redirect + nach `deleteCompany`, nicht UI). diff --git a/dev/frontend/hub-flux/11-PHASE-4E-PROFILE-SETTINGS.md b/dev/frontend/hub-flux/11-PHASE-4E-PROFILE-SETTINGS.md new file mode 100644 index 0000000..6fb7696 --- /dev/null +++ b/dev/frontend/hub-flux/11-PHASE-4E-PROFILE-SETTINGS.md @@ -0,0 +1,103 @@ +# Phase 4E — Profile & Settings + +> Fünftes Päckchen aus Phase 4. Folgt auf 4D Companies. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag · **Risiko**: niedrig + +--- + +## Scope + +**Admin / „/settings/*" (alle Rollen)** + +- `resources/views/livewire/settings/profile.blade.php` (117 Z.) +- `resources/views/livewire/settings/password.blade.php` (82 Z.) +- `resources/views/livewire/settings/appearance.blade.php` (21 Z.) +- `resources/views/livewire/settings/delete-user-form.blade.php` + (59 Z., wird in profile.blade.php als Komponente eingebunden) + +**Customer („Mein Bereich")** + +- `resources/views/livewire/customer/profile.blade.php` (451 Z.) +- `resources/views/livewire/customer/security.blade.php` (295 Z.) + +NICHT in diesem Päckchen: + +- `customer/invoices.blade.php`, `customer/tokens.blade.php`, + `customer/bookings.blade.php`, `customer/company-switcher` — + eigenes Päckchen 4F. +- 2FA-Pages aus Fortify-Standard-Setup — bleiben FluxUI bis sie + separat angepackt werden. + +## Ziel + +Beide Settings-Strecken im Hub-Vokabular wie Press-Releases / +Companies: + +- **Page-Header** mit Rolle-Pille („Admin Backend" oder + „User Backend") + Eyebrow + H1 + Subtitle. +- **Form-Sektionen** als `.panel` mit `.panel-head` und + `section-eyebrow`. +- **FluxUI-Form-Felder** bleiben (`flux:field`, `flux:input`, + `flux:label`, `flux:error`, `flux:checkbox`, `flux:radio`, + `flux:textarea`, `flux:button`). +- **Required-Marker** auf Hub-Token (`text-[color:var(--color-err)]`). +- **Save-Action** in eigenem Panel-Footer mit Save-Indicator-Span. +- **Flash-/Success-Messages** auf Hub-Token-Pillen. +- **Danger-Zone** (Delete-Account, Sessions löschen) als + `.panel` mit `is-danger`-Akzent (linker Roter Strip). + +## Was explizit NICHT angefasst wird + +- Volt-Logik in allen Dateien. +- `` Wrapper-Komponente (falls vorhanden) — + Layout-only-Änderungen, keine Hülle. +- 2FA-/Confirm-Password-Modals. +- Test-relevante Strings auf customer/profile + customer/security: + - **profile**: „Rechnungsadresse" + - **security**: „Konto-Sicherheit", „Letzter Login", + „Aktive Sessions", „Passwort ändern", „E-Mail-Adresse ändern", + „Zwei-Faktor-Authentifizierung" + +## Akzeptanzkriterien + +- [x] Plan +- [x] `partials/settings-heading` zentral auf Hub-Page-Header. +- [x] `components/settings/layout` zentral auf Hub-Sidebar + + Content-Panel. +- [x] `settings/appearance` Hub-styled (profitiert vom neuen + Wrapper, kein Body-Touch nötig). +- [x] `settings/profile` Hub-styled + Verification-Hinweis als + Hub-Warn-Box + Save-Button mit Token-„Saved."-Pill. +- [x] `settings/delete-user-form` als Hub-Danger-Box mit + linkem Roten Strip. Modal-Markup unverändert. +- [x] `settings/password` Hub-styled (Save-Bar mit Border-Top). +- [x] `customer/profile` Hub-styled: Header, 3 Panels (Konto, + Profil, Rechnungsadresse), Aktionen-Panel, Zugeordnete-Firmen- + Panel mit Hub-Badges. +- [x] `customer/security` Hub-styled: Header, 4-spaltige + KPI-Reihe, Passwort+E-Mail 2-Col-Grid, 2FA-Panel mit + Hub-Recovery-Codes, Sessions-Panel mit Hub-Empty-State. +- [x] Tests grün: + - `Settings|CustomerProfileSecurity|CustomerCompanyContext` + → 33 passed (146 assertions). + - Volle Suite → 230 passed, 3 skipped, 1 pre-existing + `ApiDocumentationTest`-Fail (nicht von 4E). +- [x] Build + Pint + PROGRESS. + +## Notes + +- Der zentrale Umbau der beiden Wrapper (`settings-heading`, + `settings.layout`) hat sich bezahlt gemacht: die drei + `settings/*`-Pages sind weitgehend identisch klein geblieben, + Page-Header und Side-Nav kommen automatisch im Hub-Look. +- `` für „Saved."-Toast bleibt drin, aber + der Slot ist auf einen Hub-getönten `` umgestellt. +- Empty-State für „Aktive Sessions" nutzt das gleiche + Hub-Icon-Box-Pattern wie auf den Press-Releases-Listen. +- 2FA-QR-Container behält explizit weißen Hintergrund — + QR-Codes brauchen hohen Kontrast unabhängig vom Mode. +- Alle Test-Pflicht-Strings unverändert: „Rechnungsadresse", + „Konto-Sicherheit", „Letzter Login", „Aktive Sessions", + „Passwort ändern", „E-Mail-Adresse ändern", + „Zwei-Faktor-Authentifizierung". diff --git a/dev/frontend/hub-flux/12-PHASE-4G-CUSTOMER-PORTAL.md b/dev/frontend/hub-flux/12-PHASE-4G-CUSTOMER-PORTAL.md new file mode 100644 index 0000000..da04652 --- /dev/null +++ b/dev/frontend/hub-flux/12-PHASE-4G-CUSTOMER-PORTAL.md @@ -0,0 +1,78 @@ +# Phase 4G — Customer Portal (Mein Bereich) + +> Sechstes Päckchen aus Phase 4. Folgt auf 4E +> (Profile/Settings). + +**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag · **Risiko**: niedrig–mittel + +--- + +## Scope + +**Liste / Detail / Helper**: + +- `resources/views/livewire/customer/invoices.blade.php` (194 Z.) +- `resources/views/livewire/customer/tokens.blade.php` (212 Z.) +- `resources/views/livewire/customer/bookings.blade.php` (52 Z.) +- `resources/views/livewire/customer/company-switcher.blade.php` + (91 Z., sitzt in der Sidebar) +- `resources/views/livewire/customer/press-kits/index.blade.php` + (119 Z.) +- `resources/views/livewire/customer/press-kits/show.blade.php` + (734 Z., großes Detail-Cockpit) + +NICHT in diesem Päckchen: + +- `customer/press-releases/*` — schon in 4A/4B/4C. +- `customer/dashboard.blade.php` — schon in Phase 2. +- `customer/profile.blade.php`, `customer/security.blade.php` — + schon in 4E. +- Admin-Bereich (Päckchen 4F). + +## Ziel + +Alle Customer-Pages im Hub-Vokabular: + +- **Page-Header** „User Backend"-Pille + Eyebrow + „Mein Bereich · …" + H1 + Subtitle. +- **KPI/Summary-Reihe** wo Stats existieren + (``). +- **Tabellen, Listen, Forms** in `.panel` mit `.panel-head`. +- **Flash-Boxen** (success/info/warn/error) auf Hub-Token. +- **Hub-Badges** statt `flux:badge` (außer dort wo speziell + begründet). +- **Empty-States** als Hub-Icon-Box. +- **Company-Switcher**: bleibt funktional, optisch Hub-Akzent. + +## Was explizit NICHT angefasst wird + +- Volt-Logik in allen Dateien. +- ``, `` usw. +- Konfirm-/Edit-Modals in `press-kits/show.blade.php` (falls + vorhanden). +- Bestimmte Strings, die Tests assertieren: + - **tokens**: „API-Tokens" (Heading), + „API-Tokens werden erst freigeschaltet" (Hinweis). + - **invoices**: „Hinweis zu Rechnungen", + „Rechnungsadresse im Profil pflegen", „Öffnen". + - **company-switcher**: „Firma öffnen", + `route('me.press-kits.show', …)`. + - **press-kits.show**: „Abrechnung", „Statistik" (Tab-Labels + bzw. Section-Headings). + +## Akzeptanzkriterien + +- [x] Plan +- [x] `customer/invoices` +- [x] `customer/tokens` +- [x] `customer/bookings` (Coming-Soon-Stub) +- [x] `customer/company-switcher` (Sidebar-Komponente) +- [x] `customer/press-kits/index` +- [x] `customer/press-kits/show` (Stammdaten/Kontakte/PMs/ + Abrechnung/Statistik im Hub-Stil; Forms inline behalten) +- [x] `CustomerPortalTest`, `CustomerCompanyContextTest`, + `PanelConsolidationTest` grün (29 Tests, 131 Assertions). +- [x] Volle Suite: 230 passed, 3 skipped, 1 pre-existing fail + (`ApiDocumentationTest`, fehlende `docs/api/v1.yml`). +- [x] Build (portal: 418 kB CSS, 44 kB JS) + Pint clean + + PROGRESS. diff --git a/dev/frontend/hub-flux/13-PHASE-4F-ADMIN-REST.md b/dev/frontend/hub-flux/13-PHASE-4F-ADMIN-REST.md new file mode 100644 index 0000000..3d60cc7 --- /dev/null +++ b/dev/frontend/hub-flux/13-PHASE-4F-ADMIN-REST.md @@ -0,0 +1,84 @@ +# Phase 4F — Restliche Admin-Bereiche + +> Siebtes Päckchen aus Phase 4. Folgt auf 4G +> (Customer Portal). + +**Status**: ✅ abgeschlossen · **Aufwand**: ~1,5–2 Tage · **Risiko**: niedrig + +--- + +## Scope + +Insgesamt ~7.500 Z. Blade. Aufgeteilt in 4 Sub-Päckchen: + +### 4F-1 — Stammdaten & Switcher (~1.250 Z.) + +- `admin/presets/{index,create,edit}.blade.php` (361 Z.) +- `admin/presets/partials/form-fields.blade.php` +- `admin/categories/{index,create,edit}.blade.php` (813 Z.) +- `admin/portal-switcher.blade.php` (68 Z., Sidebar-Komponente) + +### 4F-2 — Pressekontakte (~1.360 Z.) + +- `admin/contacts/index.blade.php` (729 Z.) +- `admin/contacts/create.blade.php` (275 Z.) +- `admin/contacts/edit.blade.php` (352 Z.) + +### 4F-3 — Operations & Finance (~1.870 Z.) + +- `admin/footer-codes/{index,create,edit}.blade.php` (673 Z.) +- `admin/reports/slow-requests.blade.php` + table (288 Z.) +- `admin/invoices/index.blade.php` (314 Z.) +- `admin/coupons/index.blade.php` (43 Z., Stub) +- `admin/payments/index.blade.php` (53 Z., Stub) + +### 4F-4 — User-Verwaltung (~3.020 Z.) + +- `admin/users.blade.php` (939 Z.) + + `admin/users/{create,edit,show,table}.blade.php` +- `admin/roles/{index,create,edit}.blade.php` (393 Z.) +- `admin/newsletter/sync.blade.php` (171 Z.) + +## Ziel + +Alle Admin-Pages im Hub-Vokabular: + +- **Page-Header** „Admin Backend"-Pille + Eyebrow + „Administration · …" + H1 + Subtitle. +- **KPI/Summary-Reihe** wo Stats existieren + (``). +- **Tabellen, Listen, Forms** in `.panel` mit `.panel-head`. +- **Flash-Boxen** (success/info/warn/error) auf Hub-Token. +- **Hub-Badges** statt `flux:badge` (außer in begründeten + Fällen). +- **Empty-States** als Hub-Icon-Box. +- **Danger-Zones** mit linkem roten Strip. + +## Was explizit NICHT angefasst wird + +- Volt-Logik in allen Dateien. +- ``, ``, ``, + ``, ``, ``, + ``, ``, `` etc. +- Modals und ihre Bestätigungs-Flows. +- Test-relevante Strings — vor jedem Sub-Päckchen werden die + betreffenden Test-Assertions geprüft. + +## Tests pro Sub-Päckchen + +| Sub | Tests | +|---|---| +| 4F-1 | `CategoryIndexPerformanceTest`, `AdminCategoryManagementTest`, `AdminPresetManagementTest` | +| 4F-2 | (keine spezifischen Contact-Tests gefunden, evtl. via `AdminAssetManifestTest` indirekt) | +| 4F-3 | `AdminFooterCodeManagementTest`, `AdminSlowRequestReportTest`, `AdminSlowRequestLoggingTest`, `AdminLegacyInvoiceArchiveTest` | +| 4F-4 | `UserManagementTest`, `UserImpersonationTest`, `RoleManagementTest` | + +## Akzeptanzkriterien + +- [x] Plan +- [x] 4F-1 Stammdaten & Switcher +- [x] 4F-2 Pressekontakte +- [x] 4F-3 Operations & Finance +- [x] 4F-4 User-Verwaltung +- [x] Tests pro Sub-Päckchen grün +- [x] Build + Pint + PROGRESS. diff --git a/dev/frontend/hub-flux/14-PHASE-4H-PRESS-RELEASES-MOCKUP.md b/dev/frontend/hub-flux/14-PHASE-4H-PRESS-RELEASES-MOCKUP.md new file mode 100644 index 0000000..cebcaf5 --- /dev/null +++ b/dev/frontend/hub-flux/14-PHASE-4H-PRESS-RELEASES-MOCKUP.md @@ -0,0 +1,171 @@ +# Phase 4H — Customer „Meine Pressemitteilungen" auf Mockup-Stil + +> Nachgelagertes Päckchen aus Phase 4. Hebelt das wichtigste +> Customer-Arbeitstool auf das volle Mockup-Vokabular. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~1 Tag · **Risiko**: niedrig + +--- + +## Anlass + +`customer/press-releases/index.blade.php` ist heute auf +~50 % Mockup-Match: Page-Header, Filter-Panel, Tabelle und +Empty-State sind Hub-styled, aber alle hochwirksamen Patterns +aus dem Mockup fehlen. Diese Seite ist die meistbesuchte des +Customer-Bereichs (primäres Arbeitstool). + +## Vorlage + +`dev/frontend/tailwind_v3/User Pressemitteilungen presseportale.html` + +## Match-Ziel + +≥ 90 % zum Mockup, ohne Backend-API-Erweiterungen. + +--- + +## Scope — was umgesetzt wird + +### 1. Counter-Strip im Header + +Statt langer Subzeile: Inline-Counter pro Status direkt +unter H1. + +`24 Mitteilungen · 18 veröffentlicht · 1 in Prüfung · 4 Entwürfe · 1 abgelehnt` + +Zahlen kommen aus aggregiertem `withCount()` über die Status-Enum. + +### 2. Saved-Views-Tabs + +Tab-Leiste statt Status-Dropdown: + +`Alle (24) · Veröffentlicht (18) · Entwürfe (4) · In Prüfung (1) · Abgelehnt (1) · Archiv (0)` + +Aktive Tab unterstrichen mit Hub-Blau. Klick → `statusFilter`-Volt-Property. + +### 3. Filter-Chips mit Caret + +Status/Portal/Firma/Zeitraum als Chips mit Dropdown-Caret. +Aktive Chip in Hub-Blau, inaktive auf weißem Background. + +**Hinweis**: Status-Chip ist im UI redundant mit Saved-Views-Tabs; +wir lassen ihn weg. Bleiben: Portal, Firma, Zeitraum (`erstellt` ab Datum X). + +### 4. Active-Chips (entfernbare Filter) + +Unter den Filter-Chips: Sichtbarmachung aktiver Filter mit +`×`-Button zum Entfernen. + +### 5. Bulk-Selection (nur UI-Vorbereitung) + +Checkbox in Header und pro Zeile. Header-Checkbox kann +indeterminate-State haben. **Keine Bulk-Aktionen** im Scope — +das wird erst später ein eigenes Päckchen (Bulk-Approve etc.). + +### 6. Portal-Pills mit farbigem Dot + +Pro Zeile in Spalte „Portal": je nach `portal`-Enum: +- `presseecho` → grüner Dot +- `businessportal24` → orangener Dot +- `both` → beide Pills nebeneinander + +### 7. Inline-Actions neben Status + +Statusspalte bekommt **zusätzlich** zur Badge eine kleine +Inline-Action je nach Status: + +| Status | Inline-Action | +|---|---| +| Draft | `Zur Prüfung →` | +| Review | `Zurückziehen →` (nur wenn `withdrawFromReview` existiert, sonst weglassen) | +| Published | — (keine Inline-Action, nur Hauptaktion „Vorschau") | +| Rejected | `Grund ansehen →` (Modal/Tooltip mit `rejection_reason`) | +| Archived | — | + +### 8. Row-Tinting + +Zeilen mit Status `review` bekommen `is-row-warn` (sehr +dezent gelb beim Hover), `rejected` bekommen `is-row-err` +(rot beim Hover). + +### 9. Reichere Zeilen-Sub + +Sub-Zeile unter Titel: `PM-Nummer · Datum · Hinweis` +Wir nutzen vorhandene Felder: `id` (als „PM-{id}"), `published_at`, +`rejection_reason`-Existenz. + +### 10. Datum mit Sub + +Datumsspalte zweizeilig: Datum (Mono-Font, tabular-nums) + +Sub (Status-Kontext z.B. „veröffentlicht · 09:12"). + +### 11. 3-fach Empty-State + +Drei Varianten je nach Kontext: + +- **`empty-filter`** — wenn Filter aktiv: „Keine Mitteilungen mit diesen Filtern" + Reset-Button +- **`empty-search`** — wenn `search` gesetzt: „Keine Treffer für `…`" + Suche-Reset +- **`empty-none`** — wenn gar keine PMs überhaupt: „Noch keine Pressemitteilungen" + 3-Schritt-Onboarding + +### 12. Status-Aktionen-Legende + +`panel-warm` unter der Tabelle: 5-Spalten-Grid mit allen +Aktionen pro Status. Reduziert Support-Anfragen. + +### 13. Spalten-/Export-Buttons (rechts im Header) + +„Spalten" (jetzt non-functional als `bald`-Badge) und „Export" +(`bald`-Badge) als sekundäre Buttons. Optional — können auch +weggelassen werden, da wir keine Spalten-Konfiguration haben. + +→ **Entscheidung**: weglassen. Kein UX-Mehrwert ohne Backend. + +--- + +## Was NICHT angefasst wird + +- Volt-Logik (`submitForReview`, `sort`, `with`) — nur erweitert + um Aggregate-Counts. +- Backend-Endpoints / API. +- Detail-/Show-Seite und Create/Edit-Forms. +- Routen. + +## Neue / erweiterte CSS-Klassen in `hub-components.css` + +- `.counter-strip`, `.counter-strip .seg`, `.counter-strip .sep` +- `.view-tab` (mit `.is-active`, `.cnt`) +- `.filter-chip` (mit `.is-active`, `.caret`) +- `.active-chip` (mit `.x`) +- `.portal-pill` (mit `.pe`, `.bp`, `.pdot`) +- `.inline-action` (mit `.warn`, `.err`) +- `.is-row-warn`, `.is-row-err` (Row-Tinting) +- `.empty-stage`, `.empty-ico`, `.empty-title`, `.empty-sub` +- `.badge.muted` (für Draft / Archiv) +- Optional: `.checkbox.indeterminate` (für Bulk-Header) + +## Volt-Erweiterungen + +- `statusCounts` (assoc-Array Status-Value → int) — aggregiert + über `withoutGlobalScopes()->where('user_id', …)->groupBy('status')` +- `totalCount` (int) — Gesamt-Counter unabhängig vom Filter +- Saved-View-Klick mappt auf `statusFilter` (kein eigener Property nötig) + +## Tests + +Keine bestehenden Tests für `customer/press-releases/index` +gefunden. Akzeptanz: + +- `php artisan test --compact` läuft sauber (modulo + pre-existing `ApiDocumentationTest`) +- Build (`npm run build:portal`) clean +- Pint clean + +## Akzeptanzkriterien + +- [x] Plan +- [x] CSS-Klassen ergänzt +- [x] Volt-Counts ergänzt +- [x] Markup auf Mockup-Stil +- [x] Build + Pint + Tests grün +- [x] PROGRESS.md + 03-WEITERE-PHASEN.md aktualisiert diff --git a/dev/frontend/hub-flux/15-PHASE-4I-ADMIN-PRESS-RELEASES.md b/dev/frontend/hub-flux/15-PHASE-4I-ADMIN-PRESS-RELEASES.md new file mode 100644 index 0000000..d3e4439 --- /dev/null +++ b/dev/frontend/hub-flux/15-PHASE-4I-ADMIN-PRESS-RELEASES.md @@ -0,0 +1,136 @@ +# Phase 4I — Admin „Pressemitteilungen" Mockup-Patterns + +> Folgepäckchen zu 4H. Überträgt die in der Customer-PM-Liste +> entwickelten Mockup-Patterns auf die Admin-Seite. Die +> CSS-Komponenten existieren bereits. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag · **Risiko**: niedrig + +--- + +## Anlass + +Nach 4H matched `customer/press-releases/index.blade.php` das +Mockup zu ~90 %. Die gleichen Patterns gehören in die +Admin-Liste — das ist der zentrale Editorial-Workflow. + +## Aktueller Stand + +`admin/press-releases/index.blade.php` ist bei ~60 % Match: + +- ✅ Page-Header (Hub-Stil) +- ✅ 4-KPI-Reihe (``) +- ✅ Filter-Panel (search/status/portal/language/category + + 3 entity-comboboxes) +- ✅ Tabellen-Panel + Empty-State (Hub-styled) +- ✅ Modals (publish/reject/archive) — test-kritisch +- ❌ Saved-Views-Tabs +- ❌ Active-Chips für aktive Filter +- ❌ Portal-Pills (statt Text) +- ❌ Row-Tinting (review/rejected) +- ❌ Inline-Actions („Veröffentlichen →", „Ablehnen →" neben Status) +- ❌ Reichere Sub-Zeilen (PM-{id} + Datum + Status-Kontext) + +## Scope + +### 1. Saved-Views-Tabs + +Tab-Leiste zwischen KPI-Reihe und Filter: + +`Alle · Veröffentlicht · In Prüfung · Entwürfe · Abgelehnt · Archiv` + +Counter-Pille pro Tab basierend auf erweiterten `stats`. + +### 2. Active-Chips + +Sichtbarkeit aller aktiven Filter (Status, Portal, Sprache, +Kategorie, User, Firma, Kontakt, Suche), jeweils mit `×`. + +### 3. Portal-Pills + +Statt „Presseecho"/„Businessportal24"/„Beide" als Text: +Portal-Pills mit farbigem Dot. Bei `Portal::Both` zwei +Pills nebeneinander. + +### 4. Row-Tinting + +`is-row-warn` für review, `is-row-err` für rejected. + +### 5. Inline-Actions + +**Zusätzlich** zu den bestehenden Action-Buttons + Modals: + +| Status | Inline-Action | +|---|---| +| Review | `Freigeben →` + `Ablehnen →` (öffnet die Modals) | +| Published | `Archivieren →` (öffnet Modal) | + +Die Inline-Actions sind **nur** Trigger für die bestehenden +Modals (keine direkte Wire-Methode), damit die existierenden +Test-Modal-Strings („Pressemitteilung veröffentlichen?") +weiter angezeigt werden. Action-Buttons in der `Aktionen`- +Spalte bleiben als Backup für Power-User. + +### 6. Reichere Sub-Zeilen + +In Titel-Zelle: `PM-{id}` als Sub. In Datum-Zelle: Hauptdatum ++ Status-Kontext (`erstellt · 11:02`, `veröffentlicht · 14:30`, …). + +### 7. Counter-Strip ausgelassen + +KPI-Reihe ist bereits 4-spaltig (Gesamt, Veröffentlicht, In +Prüfung, Entwürfe) und voll funktional. Counter-Strip wäre +redundant. Bleibt bei KPI-Cards. + +## Was bleibt unangetastet + +- **Volt-Methoden** (`publish`, `reject`, `archive`, `sort`, + `with`, `clearUserFilter`, …) +- **Bestehende Modals** mit Strings „Pressemitteilung + veröffentlichen?", „Pressemitteilung ablehnen?", + „Pressemitteilung archivieren?" (Test-kritisch) +- **Filter-Panel-Struktur** (Entity-Comboboxes erhalten, + kein Reduktionsexperiment) +- **`stats`-Cache-Methode** (`AdminPerformanceCache`) + +## Erweiterung + +- `pressReleaseStats()` erweitert um `rejected` und `archived` + Counter, damit alle 6 Saved-Views-Tabs ihre Counter haben + +## Tests + +- `AdminPressReleaseActionsTest` (3 Tests, prüft auf Modal-Strings) +- `PressReleaseWorkflowTest` (mehrere Tests, prüft auf + `publish`/`reject`-Methoden + Audit-Logs) +- Volle Suite muss weiter sauber laufen (modulo + pre-existing `ApiDocumentationTest`) + +## Akzeptanzkriterien + +- [x] Plan +- [x] Volt: `stats` um `rejected` + `archived` erweitert +- [x] Volt: `setView()` + `resetFilters()` ergänzt +- [x] Saved-Views-Tabs eingebaut (6 Stück inkl. Counter) +- [x] Active-Chips eingebaut (8 Filter-Typen) +- [x] Portal-Pills statt Text (incl. Both → 2 Pills) +- [x] Row-Tinting (review → warn, rejected → err) +- [x] Inline-Actions als Modal-Trigger + (Freigeben/Ablehnen/Archivieren) zusätzlich neben Badge +- [x] Sub-Zeilen: PM-ID + Firma + Sprache, Datum + Status-Kontext +- [x] Empty-State 2-stufig (mit/ohne Filter) +- [x] Build + Pint + Tests grün (16/16 PR + 230/231 voll) +- [x] PROGRESS.md + 03-WEITERE-PHASEN.md aktualisiert + +## Lessons Learned + +- `@php(...)` Inline-Form führte beim Compile zu einem + Syntax-Fehler im kompilierten View (führte zu + ` Mini-Folgepäckchen: Die in 4H/4I entwickelten +> Mockup-Patterns (Portal-Pills, Status-Sub-Zeilen, +> Inline-Actions) werden auf die kompakten PM-Listen +> in den Dashboards übertragen. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~30 min · **Risiko**: niedrig + +--- + +## Anlass + +Nach 4H/4I sehen die Voll-Listen exakt wie das Mockup aus — +die Dashboard-Listen ("Meine letzten Pressemitteilungen", +"Letzte Pressemitteilungen", "Zur Prüfung") sind aber noch +auf dem alten Stand (Badge rechts, Sub-Zeile ohne Portal). +Das wirkt inkonsistent. + +## Scope + +### Customer-Dashboard (Volt `customer/dashboard.blade.php`) + +- **Volt-Component**: `recent` lädt aktuell + `['id', 'title', 'status', 'company_id', 'created_at']`. + → `portal` ergänzen. +- **Markup `recent`-Liste**: + - Portal-Pills (presseecho/businessportal24) neben dem Badge + - Sub-Zeile mit PM-ID + Firma + Datum (statt nur Firma + Datum) + +### Admin-Dashboard (Controller-View `admin/dashboard.blade.php`) + +- **`recentPRs`-Liste**: + - Portal-Pills neben dem Badge + - Sub-Zeile mit PM-ID + Firma + User + Datum +- **`pendingReviews`-Liste**: + - Portal-Pills neben Titel + - Inline-Action „Prüfen →" als Link zur Show-Page + (im Dashboard keine direkte `publish`/`reject`-Methode + möglich, da Controller+Blade statt Volt) + +## Was bleibt unangetastet + +- Backend-Logik (Controller, Volt-`with()`) +- Customer-Tests (`DashboardTest`) — die geprüften + Strings („Phase 2 Demo Release", „Alle anzeigen", + „Meine letzten Pressemitteilungen", …) bleiben +- Quick-Actions, Newsletter, Brand-Bridge — bereits gut + +## Akzeptanzkriterien + +- [x] Plan +- [x] Customer-Volt: `portal` + `published_at` in + Recent-Select-Liste +- [x] Customer-Dashboard: Portal-Pills + PM-ID-Sub + + published_at als Primärdatum bei Published +- [x] Admin-Dashboard recentPRs: Portal-Pills + PM-ID-Sub, + `badgeClass` mit `muted`-Variante (statt `hub` für + archived/draft) +- [x] Admin-Dashboard pendingReviews: Portal-Pills + + Inline-Action „Prüfen →" + `is-row-warn` Tinting +- [x] Build + Pint + Tests grün (5/5 Dashboard, 230/231 voll) +- [x] PROGRESS.md + 03-WEITERE-PHASEN.md aktualisiert diff --git a/dev/frontend/hub-flux/17-PHASE-5-DARK-MODE.md b/dev/frontend/hub-flux/17-PHASE-5-DARK-MODE.md new file mode 100644 index 0000000..d4a00a1 --- /dev/null +++ b/dev/frontend/hub-flux/17-PHASE-5-DARK-MODE.md @@ -0,0 +1,152 @@ +# Phase 5 — Dark Mode + +> Dark Mode für das Portal (Customer + Admin), gesteuert +> über den FluxUI Appearance-Switcher. Hub-Frontend bleibt +> Light-Only. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag +(meiste Arbeit war Vorbereitung in Phase 0–4) · **Risiko**: niedrig + +--- + +## Befund + +Beim Start in Phase 5 war faktisch ~95 % der Arbeit schon +in den vorherigen Phasen erledigt worden. Konkret: + +### Was bereits da war + +1. **`shared/design-tokens.css`** hat einen kompletten + `.dark { … }`-Block (Z. 182–248) mit: + - Surfaces (bg, bg-elev, bg-rule, bg-card, bg-card-warm) + - Hub-Blau (heller im Dark Mode: `#5a78c2`) + - Bernstein (heller: `#d9a560`), `--color-accent-warm` + bewusst konstant + - Ink-Skala (invertiert) + - Status-Farben (ok/warn/err in helleren Varianten) + - Bridge-Dots (heller) + - Schatten (neutral schwarz statt warm-blau) + - `color-scheme: dark` für native Controls + +2. **`portal.css`** hat: + - `@custom-variant dark (&:where(.dark, .dark *))` für + Tailwind-`dark:`-Variants + - Dark-Mode Shadow-Overrides für FluxUI-Primary-Buttons + - Klare Erläuterung, warum kein Notfall-`.dark { … }`-Hack + mehr nötig ist + +3. **`shared/hub-components.css`** ist **zu 100 % + token-basiert** (panels, badges, view-tabs, filter-chips, + active-chips, portal-pills, inline-actions, empty-stage, + counter-strip). Sobald die Tokens umschalten, schalten + alle Komponenten automatisch um. + +4. **`panel-dark`** nutzt `--color-panel-dark-2` / + `--color-panel-dark` — die sind in beiden Modi + identisch. Die Brand-Bridge-Card bleibt damit immer + dunkel. + +5. **`@fluxAppearance`** ist in beiden Head-Partials + eingebunden (`partials/head.blade.php` + + `partials/admin-head.blade.php`). + +6. **Switcher** ist an drei Stellen verfügbar: + - Sidebar Desktop User-Menü + (`components/layouts/app/sidebar.blade.php`) + - Sidebar Mobile User-Menü (gleiche Datei) + - `settings/appearance.blade.php` (volle Card mit + Light/Dark/System) + Alle drei nutzen `x-model="$flux.appearance"` — + FluxUI's Magic-Object, das LocalStorage-persistent ist + und automatisch `class="dark"` auf `` setzt. + +### Was zu fixen war + +Bei der Inventur fielen nur zwei Stellen auf, die im +Dark Mode brechen würden: + +1. **`customer/tokens.blade.php` Z. 137**: Token-Anzeige + nach Generierung nutzte ein nicht existentes + `--color-ink-deep`-Token. Damit war der Hintergrund + bisher schlicht transparent (Light: kaum sichtbar, + Dark: ebenso). Außerdem würde `--color-ink` im Dark + Mode hell werden — weißer Text auf hellem Bg wäre + unlesbar. Fix: auf `--color-panel-dark-2` (konstant + dunkel) umstellen. + +2. **`customer/security.blade.php` Z. 270**: 2FA-QR-Code + in `bg-white`-Block. Das ist **bewusst** so — QR-Codes + brauchen schwarz-auf-weiß, sonst werden sie nicht + eingescannt. Kein Fix, nur Kommentar zur Klarstellung. + +### Was unkritisch ist + +- `customer/dashboard.blade.php`: 8 Treffer für + `bg-white` / `text-white` — alle im `panel-dark` + Brand-Bridge Block (konstant dunkel, weiße Texte + korrekt) und im Empty-State Counter-Badge auf + `--color-accent` (Bernstein-Bg, beides Modi). +- `admin/dashboard.blade.php` Z. 235: Quick-Action + Hover-State `group-hover:bg-hub group-hover:text-white` + — Hub-Bg ist sowohl Light (dunkles Hub-Blau) als auch + Dark (helleres Hub-Blau) okay für weißen Text. +- Sidebar-`dark:bg-zinc-…` Klassen aus dem Starter-Kit: + Die Zinc-Skala ist in `portal.css` auf warmes + Buchpapier gemapped, das funktioniert weiter — die + Avatar-Bg's sind sowieso nur 8×8-Pixel-Spots. +- `customer/press-kits/show.blade.php` Z. 440: Logo-Bg + `bg-white` — bewusst, weil Firmen-Logos einen weißen + Hintergrund für korrekte Darstellung brauchen. + +### Was außerhalb von Phase 5 ist + +- **`shared-styles.css`** hat `.dark .card`, `.dark + .slider-*`, `.dark .highlight-*`, `.dark .section-*` + Regeln. Diese sind für den **Web-Bereich** + (Hub-Frontend, presseecho, businessportal24), nicht + fürs Portal. `portal.css` importiert + `shared-styles.css` **nicht** — die Regeln landen also + nicht im Portal-Bundle. +- **Web-Frontend** bleibt Light-Only — wie in der + Roadmap definiert. + +## Akzeptanzkriterien + +- [x] Plan +- [x] Recherche aller hardcoded Farbklassen +- [x] `--color-ink-deep` → `--color-panel-dark-2` in + `customer/tokens.blade.php` +- [x] `bg-white` für 2FA-QR-Code in `security.blade.php` + mit erklärendem Kommentar versehen +- [x] Build + Pint + Tests grün +- [x] PROGRESS.md + 03-WEITERE-PHASEN.md auf ✅ + +## Lessons Learned + +- Konsequente Token-Disziplin (kein Hex außer in + `design-tokens.css`) zahlt sich beim Dark Mode massiv + aus: Statt 15 Pages × dutzende Klassen anzufassen, + schaltet das gesamte Portal mit einem `.dark {…}` Block + um. +- Die wenigen Ausnahmen (panel-dark, QR-Code-Bg, + Logo-Bg) sind dokumentierte Bewusst-Entscheidungen, + keine Schuld. +- FluxUI's `$flux.appearance` Magic-Object spart eine + eigene Alpine-Component und persistiert über + LocalStorage. + +## Manueller Smoke-Test (Empfehlung) + +Da Pest keine echte Browser-Rendering-Pipeline hat: +- Im Browser: User-Menü → Erscheinung → „Dunkel" +- Folgende Seiten besuchen + visuell prüfen: + - `/dashboard` (Admin) + `/me/dashboard` (Customer) + - `/me/press-releases` (Customer-Liste mit + Saved-Views-Tabs, Filter-Chips, Portal-Pills, + Row-Tints) + - `/admin/press-releases` (Admin-Liste mit Inline-Actions) + - `/me/security` (2FA-QR mit `bg-white`) + - `/me/tokens` (Token-Anzeige nach Generierung) + - `/admin/companies/{id}` (Detail-View mit allen Panels) +- Erwartung: Lesbar, konsistent, keine grellen + Kontraste, keine „weißen Inseln" auf dunklem Bg. diff --git a/dev/frontend/hub-flux/18-PHASE-6-AUTH-CLEANUP.md b/dev/frontend/hub-flux/18-PHASE-6-AUTH-CLEANUP.md new file mode 100644 index 0000000..3f20c48 --- /dev/null +++ b/dev/frontend/hub-flux/18-PHASE-6-AUTH-CLEANUP.md @@ -0,0 +1,54 @@ +# Phase 6 — Auth-Cleanup + +> Ungenutzte Starter-Kit-Layouts und Debug-Views entfernen, +> die seit der Hub-Auth-Umstellung (Phase 0) keine Verwendung +> mehr haben. + +**Status**: ✅ abgeschlossen · **Aufwand**: ~30 min · **Risiko**: niedrig + +--- + +## Inventur + +### Aktiv genutzt (BEHALTEN) + +| Datei | Genutzt von | +|---|---| +| `components/layouts/app.blade.php` | Wrapper → `app.sidebar` | +| `components/layouts/app/sidebar.blade.php` | primäres Portal-Layout (alle Volt-Pages) | +| `components/layouts/auth/pressekonto.blade.php` | login, register, forgot-password, verify-email, confirm-password, reset-password | + +### Ungenutzt (ENTFERNT) + +| Datei | Grund | +|---|---| +| `components/layouts/auth.blade.php` | dünner Wrapper auf `auth.simple` — nirgends als Layout referenziert (außer `login-simple` + `test-simple` Debug, die ebenfalls weg sind) | +| `components/layouts/auth/simple.blade.php` | Starter-Kit-Rest, hardcoded `class="dark"` | +| `components/layouts/auth/split.blade.php` | Starter-Kit-Rest, hardcoded `class="dark"` | +| `components/layouts/auth/card.blade.php` | Starter-Kit-Rest, hardcoded `class="dark"` | +| `components/layouts/app/header.blade.php` | alternatives App-Layout (Top-Bar statt Sidebar), wird vom Wrapper nie aufgerufen, hardcoded `class="dark"` | +| `livewire/auth/login-simple.blade.php` | Debug-Volt-Login („Log in to your account"-Englisch) ohne Route, nutzte `` | +| `test-simple.blade.php` | Debug-Page „Diese Seite funktioniert ohne Volt/Livewire" ohne Route | + +### Aktualisiert + +- `_docs/FORTIFY-SANCTUM-SETUP.md`: Code-Beispiel von + `components.layouts.auth` auf `components.layouts.auth.pressekonto` + umgestellt (alter Wert verwies auf die soeben gelöschte + Wrapper-Datei). + +## Verifikation + +- `rg "auth\.(simple|split|card)"` und + `rg "app\.header"` → 0 Treffer in `resources/` und `routes/` +- Build, Pint, alle relevanten Tests grün + +## Lessons Learned + +- Mit der Anti-Flash-Bridge aus Phase 5 wären die hardcoded + `class="dark"`-Layouts sowieso zur Stolperfalle für + Light-Mode-User geworden, falls sie je reaktiviert werden. + Lösung: weg damit. +- Hub-Auth-Pages laufen seit Phase 0 ausschließlich über + `auth/pressekonto.blade.php`. Die Starter-Kit-Layouts waren + schon damals tote Last. diff --git a/dev/frontend/hub-flux/PROGRESS.md b/dev/frontend/hub-flux/PROGRESS.md index 570761e..bbea9aa 100644 --- a/dev/frontend/hub-flux/PROGRESS.md +++ b/dev/frontend/hub-flux/PROGRESS.md @@ -5,6 +5,920 @@ --- +## 2026-05-20 · Phase 6 · Auth-Cleanup ✅ + +Mit Phase 6 ist die hub-flux-Roadmap (Phase 0–6) **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**: ``-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 0–4 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. 182–248) 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 4A–4J 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, + ``, ``, + `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 `` zu `
` 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 ` 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 + `` (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 (``), + 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 + `` (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`, …). +- ``, ``, ``, + ``, ``, ``, + ``, ``, ``. +- 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`. ``, `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 `
` 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 + ``-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). + - `` 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 `` (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). + - `` (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 diff --git a/dev/frontend/tailwind_v3/User Neue Mitteilung presseportale.html b/dev/frontend/tailwind_v3/User Neue Mitteilung presseportale.html new file mode 100644 index 0000000..49dd07f --- /dev/null +++ b/dev/frontend/tailwind_v3/User Neue Mitteilung presseportale.html @@ -0,0 +1,976 @@ + + + + + +presseportale.com — Neue Pressemitteilung + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ + +
+
+
+ Hub + / + User Backend + / + Pressemitteilungen + / + Neue Mitteilung +
+ + + + + presseecho + · + businessportal24 + + + + + + + Zuletzt gespeichert vor 8 Sek. + · + PM-DRAFT-2026-0026 + + + + + + +
+
+ + +
+ + +
+
+
+ User Backend + Mein Bereich · A · 02 · Neu + Entwurf +
+

Neue Pressemitteilung

+

+ Schreibfläche links, Steuerung rechts. Speichert automatisch alle paar Sekunden. Beim Klick auf + „Zur Prüfung senden" läuft eine kurze Qualitäts-Checkliste. +

+
+ +
+ + + Zur Liste + + +
+
+ + +
+ + + + +
+ + +
+
+
Für Firma
+ + + Boilerplate und Pressekontakt werden vorbefüllt. + + + + + Neue Firma anlegen + +
+
+ + +
+
+
+ Titel / Headline * +
+
+ + + 62 / 100 + + KI-Titel · bald +
+
+ +
+ 40–90 Zeichen empfohlen. Konkret, ohne Marketing-Floskeln. Wer? Was? Wo? +
+
+ + +
+
+
+ Untertitel — optional +
+ + + 118 / 200 + +
+ +
+ + +
+
+
+ Fließtext * +
+
+ + + 1.420 / 3.500 Z. + + KI-Lektorat · bald +
+
+ + +
+ + + + + + + + + + + + + + + + + + Reduzierter Editor — bewusst eingeschränkt für konsistentes Format. +
+ + +
+

+ Tegernsee, 11.05.2026. Die Tegernseer Brauerei AG eröffnet am 12. Juni 2026 ihre neue + Craft-Beer-Manufaktur direkt am Tegernseer Hafen. Auf rund 1.200 m² entsteht eine + Schau-Brauerei mit angeschlossenem Verkostungsraum und ganzjährigen Besucherführungen. +

+ +

+ Der Neubau ergänzt den 1675 gegründeten Stammsitz und setzt einen Fokus auf + experimentelle Sude in kleinen Chargen. „Wir wollen Bier-Handwerk wieder + erlebbar machen — direkt am Wasser, mit offenen Kesseln und + unseren Brauern als Gastgebern", erklärt Vorstandsvorsitzender Dr. Markus Weishaupt. +

+ +

Verkostung, Manufaktur-Touren, regionale Wertschöpfung

+

+ Die Manufaktur kombiniert drei Erlebnisformate unter einem Dach: +

+ +
    +
  • Schau-Brauerei mit gläsernem Sudhaus und 30-minütigen Kurzführungen.
  • +
  • Verkostungsraum für bis zu 60 Personen, mit wechselnden Sorten aus der Pilot-Anlage.
  • +
  • Direktverkauf ab Werk — ausschließlich aus Tegernseer Roh
  • +
+ +

+ Hier weiterschreiben … +

+
+ + +
+
+ + + + KI-Lektorat liest Korrektur, schlägt Kürzungen vor und prüft auf werbliche Sprache. Erscheint hier inline — bald verfügbar. + bald +
+
+
+ + +
+
+
+ Medien / Bilder + — mindestens 1 Bild empfohlen +
+
+ 2 Bilder hochgeladen · 1 Vorschau + KI-Bildgenerierung · bald +
+
+ +
+ + +
+
+ Titelbild + + + + + + + + + + + + + + + + + + + + + + +
+
+
Außenansicht der neuen Manufaktur am Tegernseer Hafen.
+
Alt: Holzgebäude mit Glasfront direkt am See, Abendlicht.
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
Drei neue Sorten aus der Pilot-Anlage — Spezialeditionen.
+
Alt: Drei Bierflaschen mit unterschiedlichen Etiketten auf Holztisch.
+
+
+ + + + +
+ +
+ Bildunterschrift und Alt-Text sind pro Bild Pflicht für die Veröffentlichung. Das Titelbild erscheint in der Liste auf presseecho & businessportal24. +
+
+ + +
+
+
+ Anhänge / Downloads + — optional +
+ +
+ +
+
+ PDF +
+
Pressemappe_Manufaktur.pdf
+
2,4 MB · 12 Seiten
+
+ +
+ +
+
+ + +
+
+
+ Über das Unternehmen + — Boilerplate aus Firma +
+
+ aus Firmenprofil + +
+
+ +
+

+ Über die Tegernseer Brauerei AG. + Die Tegernseer Brauerei wurde 1675 als Klosterbrauerei der Benediktinerabtei Tegernsee gegründet und + ist heute eine der ältesten kontinuierlich brauenden Brauereien Bayerns. Im Familienbesitz der Herzöge + von Bayern werden jährlich rund 280.000 Hektoliter gebraut. Schwerpunkt: helle Lagerbiere und + Spezialitäten nach dem bayerischen Reinheitsgebot. +

+

+ Sitz: Tegernsee · Mitarbeiter: 142 · Web: tegernseer-brauerei.de +

+
+ +
+ Wird automatisch unter jeder Pressemitteilung dieser Firma angefügt. Pro PM editierbar — Änderungen wirken sich nicht auf andere Mitteilungen aus. +
+
+ +
+ + + + + + + +
+ + + + +
+
+
+
+ + + diff --git a/dev/frontend/tailwind_v3/User Pressemitteilungen presseportale.html b/dev/frontend/tailwind_v3/User Pressemitteilungen presseportale.html new file mode 100644 index 0000000..0fe5fcf --- /dev/null +++ b/dev/frontend/tailwind_v3/User Pressemitteilungen presseportale.html @@ -0,0 +1,1058 @@ + + + + + +presseportale.com — Meine Pressemitteilungen + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ + +
+
+
+ Hub + / + User Backend + / + Meine Pressemitteilungen +
+ + + + + presseecho + · + businessportal24 + + + + +
+ + + + + + ⌘K +
+ + + + + + + + Neue Mitteilung + +
+
+ + +
+ + +
+
+
+ User Backend + Mein Bereich · A · 02 +
+

Meine Pressemitteilungen

+ + +
+ 24 Mitteilungen + + 18 veröffentlicht + + 1 in Prüfung + + 4 Entwürfe + + 1 abgelehnt +
+
+ +
+ + +
+
+ + + + + +
+ +
+ + + + + + + +
+ + + + + + / +
+
+ + +
+ Aktiv + + Zeitraum: Dieser Monat + + + +
+
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusTitelPortalFirma + Datum + + +
Veröffentlicht + Tegernseer Brauerei eröffnet erste Craft-Beer-Manufaktur im Allgäu +
PM-2026-0418 · 4 Bilder · Auto-Twitter aktiv
+
+ presseecho + businessportal24 + Tegernseer Brauerei AG +
14.05.2026
+
veröffentlicht · 09:12
+
+ +
Veröffentlicht + Q1-Ergebnisse: Umsatzwachstum von 18 % im Mittelstand sichtbar +
PM-2026-0411 · 12.483 Aufrufe · ↑ trendet auf businessportal24
+
+ presseecho + businessportal24 + Mittelstandsverband Süd +
12.05.2026
+
veröffentlicht · 14:30
+
+ +
+ In Prüfung + + Neue Niederlassung in Wien — Eröffnung Juli 2026 +
PM-2026-0511 · eingereicht vor 3 h · Prüfer: Redaktion BP24
+
+ presseecho + businessportal24 + Tegernseer Brauerei AG +
11.05.2026
+
eingereicht · 17:48
+
+ +
+ Entwurf + Zur Prüfung → + + Personalmeldung: Dr. Anna Berger übernimmt Vertriebsleitung +
Entwurf · zuletzt bearbeitet vor 12 min · 1 Bild · Sperrfrist 20.05.
+
+ presseecho + Tegernseer Brauerei AG +
10.05.2026
+
erstellt · 11:02
+
+ +
Veröffentlicht + Kooperation mit BMW Group für klimaneutrale Logistik 2030 +
PM-2026-0407 · 8.241 Aufrufe · 6 Backlinks
+
+ presseecho + businessportal24 + Mittelstandsverband Süd +
08.05.2026
+
veröffentlicht · 08:15
+
+ +
+ Abgelehnt + Grund ansehen → + + Großaktion: Nur diese Woche 50 % auf alle Produkte +
Grund: werblich, kein redaktioneller Mehrwert · Redaktion BP24, 07.05.
+
+ businessportal24 + Tegernseer Brauerei AG +
07.05.2026
+
abgelehnt · 16:21
+
+ +
Veröffentlicht + Studie: 7 von 10 Mittelständlern investieren 2026 in KI-Tools +
PM-2026-0402 · 21.107 Aufrufe · meistgelesen der Woche
+
+ presseecho + businessportal24 + Mittelstandsverband Süd +
05.05.2026
+
veröffentlicht · 10:00
+
+ +
+ Entwurf + Zur Prüfung → + + Jahresbericht 2025 — Vorstellung auf Pressekonferenz in München +
Entwurf · 2 Mitautoren · noch keine Bilder hochgeladen
+
— keines —Mittelstandsverband Süd +
03.05.2026
+
erstellt · 09:44
+
+ +
Veröffentlicht + Auszeichnung „Bayerns Unternehmen des Jahres" für Tegernseer Brauerei +
PM-2026-0328 · 3.882 Aufrufe · Auto-Twitter, LinkedIn
+
+ presseecho + businessportal24 + Tegernseer Brauerei AG +
30.04.2026
+
veröffentlicht · 12:00
+
+ +
Veröffentlicht + Eröffnung Innovation Lab in Garching — Forschung trifft Mittelstand +
PM-2026-0326 · 5.214 Aufrufe
+
+ presseecho + Mittelstandsverband Süd +
28.04.2026
+
veröffentlicht · 15:30
+
+ +
Archiviert + Sommerfest 2025 — Rückblick und Bildergalerie +
archiviert 02.05.2026 · 14.892 Lifetime-Aufrufe
+
+ presseecho + Tegernseer Brauerei AG +
22.04.2026
+
veröffentlicht · 09:00
+
+ +
+ Entwurf + + Pressekonferenz zur Brauerei-Expansion (Termin offen) +
Entwurf · seit 27 Tagen nicht bearbeitet
+
— keines —Tegernseer Brauerei AG +
20.04.2026
+
erstellt · 16:55
+
+ +
+ + +
+
+ 1–12 von 24 + · + +
+ +
+ + + + + +
+
+
+ + +
+
+
+ +
+

Keine Mitteilungen mit diesen Filtern

+

Aktive Filter passen auf keine Einträge. Setzen Sie einen Filter zurück oder probieren Sie eine breitere Auswahl.

+
+ + +
+ +
+ Aktiv + Status: Abgelehnt + Portal: presseecho + Zeitraum: Diese Woche +
+
+
+ + +
+
+
+ +
+

Keine Treffer für „brauerei wien expansion 2027"

+

Wir konnten zu Ihrer Suche nichts finden. Prüfen Sie die Schreibweise oder schränken Sie den Suchbegriff ein.

+
+ + +
+
+
+ + +
+
+
+ + + + + +
+

Noch keine Pressemitteilungen

+

Starten Sie mit Ihrer ersten Mitteilung. Nach redaktioneller Prüfung erscheint sie i. d. R. binnen 4 Stunden werktags auf beiden Portalen.

+ +
+
+
01
+
Firma zuordnen
+
+
+
02
+
Mitteilung verfassen
+
+
+
03
+
Zur Prüfung senden
+
+
+
+
+ +
+ + +
+
+
+
Aktionen je Status
+

+ Welche Aktionen das ⋯-Menü und die Inline-Buttons jeweils anbieten. +

+
+ +
+
+ Entwurf +
    +
  • Bearbeiten
  • +
  • Duplizieren
  • +
  • Löschen
  • +
  • → Zur Prüfung senden
  • +
+
+
+ In Prüfung +
    +
  • Vorschau
  • +
  • Duplizieren
  • +
  • → Zurückziehen
  • +
+
+
+ Veröffentlicht +
    +
  • Vorschau
  • +
  • Statistik
  • +
  • Duplizieren
  • +
  • Archivieren
  • +
  • → Korrektur einreichen
  • +
+
+
+ Abgelehnt +
    +
  • Bearbeiten
  • +
  • Duplizieren
  • +
  • Löschen
  • +
  • → Ablehnungsgrund
  • +
+
+
+ Archiviert +
    +
  • Vorschau
  • +
  • → Reaktivieren
  • +
+
+
+
+
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + diff --git a/public/fonts/inter-tight/font.css b/public/fonts/inter-tight/font.css new file mode 100644 index 0000000..4925ef7 --- /dev/null +++ b/public/fonts/inter-tight/font.css @@ -0,0 +1,144 @@ +/* inter-tight-100 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 100; + src: url('../fonts/inter-tight-v9-latin-100.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-100italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 100; + src: url('../fonts/inter-tight-v9-latin-100italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-200 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 200; + src: url('../fonts/inter-tight-v9-latin-200.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-200italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 200; + src: url('../fonts/inter-tight-v9-latin-200italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-300 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 300; + src: url('../fonts/inter-tight-v9-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-300italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 300; + src: url('../fonts/inter-tight-v9-latin-300italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-regular - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 400; + src: url('../fonts/inter-tight-v9-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 400; + src: url('../fonts/inter-tight-v9-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-500 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 500; + src: url('../fonts/inter-tight-v9-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-500italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 500; + src: url('../fonts/inter-tight-v9-latin-500italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-600 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 600; + src: url('../fonts/inter-tight-v9-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-600italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 600; + src: url('../fonts/inter-tight-v9-latin-600italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-700 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 700; + src: url('../fonts/inter-tight-v9-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-700italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 700; + src: url('../fonts/inter-tight-v9-latin-700italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-800 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 800; + src: url('../fonts/inter-tight-v9-latin-800.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-800italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 800; + src: url('../fonts/inter-tight-v9-latin-800italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-900 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: normal; + font-weight: 900; + src: url('../fonts/inter-tight-v9-latin-900.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* inter-tight-900italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Inter Tight'; + font-style: italic; + font-weight: 900; + src: url('../fonts/inter-tight-v9-latin-900italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} \ No newline at end of file diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-100.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-100.woff2 new file mode 100644 index 0000000..826722a Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-100.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-100italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-100italic.woff2 new file mode 100644 index 0000000..af76d1c Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-100italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-200.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-200.woff2 new file mode 100644 index 0000000..55e4f63 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-200.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-200italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-200italic.woff2 new file mode 100644 index 0000000..ca55b45 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-200italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-300.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-300.woff2 new file mode 100644 index 0000000..28b3389 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-300.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-300italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-300italic.woff2 new file mode 100644 index 0000000..9f85a25 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-300italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-500.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-500.woff2 new file mode 100644 index 0000000..5b2ef98 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-500.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-500italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-500italic.woff2 new file mode 100644 index 0000000..0134fb8 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-500italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-600.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-600.woff2 new file mode 100644 index 0000000..0dc47e8 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-600.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-600italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-600italic.woff2 new file mode 100644 index 0000000..b9fae20 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-600italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-700.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-700.woff2 new file mode 100644 index 0000000..46b043d Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-700.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-700italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-700italic.woff2 new file mode 100644 index 0000000..120a0bd Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-700italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-800.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-800.woff2 new file mode 100644 index 0000000..8ff0a25 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-800.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-800italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-800italic.woff2 new file mode 100644 index 0000000..20eadbd Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-800italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-900.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-900.woff2 new file mode 100644 index 0000000..e9a67f5 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-900.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-900italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-900italic.woff2 new file mode 100644 index 0000000..429cbd5 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-900italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-italic.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-italic.woff2 new file mode 100644 index 0000000..8796d32 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-italic.woff2 differ diff --git a/public/fonts/inter-tight/inter-tight-v9-latin-regular.woff2 b/public/fonts/inter-tight/inter-tight-v9-latin-regular.woff2 new file mode 100644 index 0000000..3004d28 Binary files /dev/null and b/public/fonts/inter-tight/inter-tight-v9-latin-regular.woff2 differ diff --git a/public/fonts/jetbrains-mono/font.css b/public/fonts/jetbrains-mono/font.css new file mode 100644 index 0000000..183e1c5 --- /dev/null +++ b/public/fonts/jetbrains-mono/font.css @@ -0,0 +1,128 @@ +/* jetbrains-mono-100 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 100; + src: url('../fonts/jetbrains-mono-v24-latin-100.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-100italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 100; + src: url('../fonts/jetbrains-mono-v24-latin-100italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-200 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 200; + src: url('../fonts/jetbrains-mono-v24-latin-200.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-200italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 200; + src: url('../fonts/jetbrains-mono-v24-latin-200italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-300 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 300; + src: url('../fonts/jetbrains-mono-v24-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-300italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 300; + src: url('../fonts/jetbrains-mono-v24-latin-300italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-regular - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 400; + src: url('../fonts/jetbrains-mono-v24-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 400; + src: url('../fonts/jetbrains-mono-v24-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-500 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 500; + src: url('../fonts/jetbrains-mono-v24-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-500italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 500; + src: url('../fonts/jetbrains-mono-v24-latin-500italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-600 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 600; + src: url('../fonts/jetbrains-mono-v24-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-600italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 600; + src: url('../fonts/jetbrains-mono-v24-latin-600italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-700 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 700; + src: url('../fonts/jetbrains-mono-v24-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-700italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 700; + src: url('../fonts/jetbrains-mono-v24-latin-700italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-800 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 800; + src: url('../fonts/jetbrains-mono-v24-latin-800.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* jetbrains-mono-800italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'JetBrains Mono'; + font-style: italic; + font-weight: 800; + src: url('../fonts/jetbrains-mono-v24-latin-800italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} \ No newline at end of file diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100.woff2 new file mode 100644 index 0000000..1293bd5 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100italic.woff2 new file mode 100644 index 0000000..ccbcd35 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-100italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200.woff2 new file mode 100644 index 0000000..4e5a312 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200italic.woff2 new file mode 100644 index 0000000..a717e92 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-200italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300.woff2 new file mode 100644 index 0000000..3213b19 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300italic.woff2 new file mode 100644 index 0000000..bf5ffc2 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-300italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500.woff2 new file mode 100644 index 0000000..be878e6 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500italic.woff2 new file mode 100644 index 0000000..3149aac Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-500italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600.woff2 new file mode 100644 index 0000000..59c24e7 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600italic.woff2 new file mode 100644 index 0000000..a51274d Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-600italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700.woff2 new file mode 100644 index 0000000..3a4e333 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700italic.woff2 new file mode 100644 index 0000000..69e029c Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-700italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800.woff2 new file mode 100644 index 0000000..6ae3c7f Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800italic.woff2 new file mode 100644 index 0000000..b974034 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-800italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-italic.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-italic.woff2 new file mode 100644 index 0000000..3d3c5d7 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-italic.woff2 differ diff --git a/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-regular.woff2 b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-regular.woff2 new file mode 100644 index 0000000..5858873 Binary files /dev/null and b/public/fonts/jetbrains-mono/jetbrains-mono-v24-latin-regular.woff2 differ diff --git a/public/fonts/source-serif-4/font.css b/public/fonts/source-serif-4/font.css new file mode 100644 index 0000000..3e6f17f --- /dev/null +++ b/public/fonts/source-serif-4/font.css @@ -0,0 +1,128 @@ +/* source-serif-4-200 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 200; + src: url('../fonts/source-serif-4-v14-latin-200.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-200italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 200; + src: url('../fonts/source-serif-4-v14-latin-200italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-300 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 300; + src: url('../fonts/source-serif-4-v14-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-300italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 300; + src: url('../fonts/source-serif-4-v14-latin-300italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-regular - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 400; + src: url('../fonts/source-serif-4-v14-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 400; + src: url('../fonts/source-serif-4-v14-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-500 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 500; + src: url('../fonts/source-serif-4-v14-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-500italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 500; + src: url('../fonts/source-serif-4-v14-latin-500italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-600 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 600; + src: url('../fonts/source-serif-4-v14-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-600italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 600; + src: url('../fonts/source-serif-4-v14-latin-600italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-700 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 700; + src: url('../fonts/source-serif-4-v14-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-700italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 700; + src: url('../fonts/source-serif-4-v14-latin-700italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-800 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 800; + src: url('../fonts/source-serif-4-v14-latin-800.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-800italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 800; + src: url('../fonts/source-serif-4-v14-latin-800italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-900 - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: normal; + font-weight: 900; + src: url('../fonts/source-serif-4-v14-latin-900.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} +/* source-serif-4-900italic - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Source Serif 4'; + font-style: italic; + font-weight: 900; + src: url('../fonts/source-serif-4-v14-latin-900italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ +} \ No newline at end of file diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-200.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-200.woff2 new file mode 100644 index 0000000..58b821a Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-200.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-200italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-200italic.woff2 new file mode 100644 index 0000000..788389f Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-200italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-300.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-300.woff2 new file mode 100644 index 0000000..c6ada36 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-300.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-300italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-300italic.woff2 new file mode 100644 index 0000000..239737e Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-300italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-500.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-500.woff2 new file mode 100644 index 0000000..56bb5e8 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-500.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-500italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-500italic.woff2 new file mode 100644 index 0000000..14ea091 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-500italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-600.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-600.woff2 new file mode 100644 index 0000000..fcbd11d Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-600.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-600italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-600italic.woff2 new file mode 100644 index 0000000..6a700b8 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-600italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-700.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-700.woff2 new file mode 100644 index 0000000..34a307f Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-700.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-700italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-700italic.woff2 new file mode 100644 index 0000000..3388efe Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-700italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-800.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-800.woff2 new file mode 100644 index 0000000..87420b2 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-800.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-800italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-800italic.woff2 new file mode 100644 index 0000000..50cbcd2 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-800italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-900.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-900.woff2 new file mode 100644 index 0000000..fad2a15 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-900.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-900italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-900italic.woff2 new file mode 100644 index 0000000..bbefc10 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-900italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-italic.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-italic.woff2 new file mode 100644 index 0000000..3595a72 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-italic.woff2 differ diff --git a/public/fonts/source-serif-4/source-serif-4-v14-latin-regular.woff2 b/public/fonts/source-serif-4/source-serif-4-v14-latin-regular.woff2 new file mode 100644 index 0000000..e8c6f71 Binary files /dev/null and b/public/fonts/source-serif-4/source-serif-4-v14-latin-regular.woff2 differ diff --git a/resources/css/portal.css b/resources/css/portal.css index f7fdcc2..1c01986 100644 --- a/resources/css/portal.css +++ b/resources/css/portal.css @@ -141,6 +141,32 @@ color: var(--color-hub); } +/* Dark Mode: --color-bg ist DUNKLER als die Sidebar (--color-bg-elev), + ein Hover damit würde das Item „eindrücken" statt hervorheben. Im Dark + Mode nutzen wir deshalb das dezente Hub-Soft (`#1f2a47`) — selbe + Farbfamilie wie der Active-State, nur ohne Active-Strip. */ +.dark [data-flux-navlist-item]:hover { + background: var(--color-hub-soft); + color: var(--color-hub); +} + +/* Klick/Focus/Tap-Highlight: konsistent mit Hub-Soft (statt browser- + default weißem Tap-Flash oder Flux's `bg-zinc-800/5`). Verhindert das + weiße Aufblitzen beim wire:navigate-Klick im Dark Mode. */ +[data-flux-navlist-item]:active, +[data-flux-navlist-item]:focus { + background: var(--color-hub-soft); + color: var(--color-hub); + outline: none; +} +[data-flux-navlist-item] { + -webkit-tap-highlight-color: transparent; +} +[data-flux-navlist-item]:focus-visible { + outline: 2px solid var(--color-hub); + outline-offset: -2px; +} + [data-flux-navlist-item][data-current="true"], [data-flux-navlist-item][aria-current="page"], [data-flux-navlist-item].active { diff --git a/resources/css/shared/design-tokens.css b/resources/css/shared/design-tokens.css index 0464942..6d72091 100644 --- a/resources/css/shared/design-tokens.css +++ b/resources/css/shared/design-tokens.css @@ -245,4 +245,9 @@ /* color-scheme-Hint für native Form-Controls (Scrollbars, Inputs) */ color-scheme: dark; + + /* Brand-Mark Wortmarke (z.B. „presse" bei pressekonto) im Portal-Dark + auf weiß. Wird nur von `` ausgelesen; + Hub-Frontend ist Light-Only, dort bleibt der Inline-Fallback aktiv. */ + --brand-mark-name-color: #ffffff; } diff --git a/resources/css/shared/hub-components.css b/resources/css/shared/hub-components.css index 0b40fad..66925e8 100644 --- a/resources/css/shared/hub-components.css +++ b/resources/css/shared/hub-components.css @@ -244,6 +244,10 @@ background: var(--color-err-soft); color: var(--color-loss); } + .badge.muted { + background: var(--color-bg-rule-2); + color: var(--color-ink-3); + } .badge.dot::before { content: ""; width: 6px; @@ -337,4 +341,359 @@ .eyebrow.on-dark { color: var(--color-hub-line); } + + /* ============================================================ + * Counter-Strip (Inline-Zähler unter H1) + * ============================================================ + * Beispiel: + * 24 Mitteilungen · 18 veröffentlicht · 1 in Prüfung · … + */ + .counter-strip { + display: inline-flex; + align-items: center; + gap: 14px; + padding: 6px 0; + flex-wrap: wrap; + } + .counter-strip .seg { + display: inline-flex; + align-items: baseline; + gap: 6px; + font-size: 12.5px; + color: var(--color-ink-2); + } + .counter-strip .seg b { + font-family: var(--font-mono); + font-variant-numeric: tabular-nums; + font-size: 13.5px; + font-weight: 600; + color: var(--color-ink); + letter-spacing: -0.2px; + } + .counter-strip .seg.is-ok b { + color: var(--color-gain-deep); + } + .counter-strip .seg.is-warn b { + color: var(--color-accent-deep); + } + .counter-strip .seg.is-err b { + color: var(--color-loss); + } + .counter-strip .seg.is-muted b { + color: var(--color-ink-3); + } + .counter-strip .sep { + width: 1px; + height: 11px; + background: var(--color-bg-rule); + } + + /* ============================================================ + * View-Tabs (Saved-Views — Tab-Leiste über Filter) + * ============================================================ */ + .view-tabs { + display: flex; + align-items: center; + gap: 4px; + border-bottom: 1px solid var(--color-bg-rule); + } + .view-tab { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 7px 12px 9px; + font-size: 12.5px; + font-weight: 500; + color: var(--color-ink-3); + border-bottom: 2px solid transparent; + margin-bottom: -1px; + transition: + color 0.12s, + border-color 0.12s; + cursor: pointer; + background: transparent; + border-top: 0; + border-left: 0; + border-right: 0; + } + .view-tab:hover { + color: var(--color-hub); + } + .view-tab.is-active { + color: var(--color-hub); + font-weight: 600; + border-bottom-color: var(--color-hub); + } + .view-tab .cnt { + font-family: var(--font-mono); + font-size: 10.5px; + color: var(--color-ink-3); + background: var(--color-bg-rule-2); + padding: 1px 6px; + border-radius: 999px; + font-weight: 600; + letter-spacing: 0.04em; + } + .view-tab.is-active .cnt { + background: var(--color-hub); + color: var(--color-ink-on-dark); + } + + /* ============================================================ + * Filter-Chips (Dropdown-Buttons mit Caret) + * ============================================================ */ + .filter-chip { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px 6px 14px; + background: var(--color-bg-card); + border: 1px solid var(--color-hub-soft-2); + border-radius: 4px; + font-size: 12.5px; + color: var(--color-hub); + font-weight: 500; + transition: + border-color 0.15s, + background 0.15s; + white-space: nowrap; + cursor: pointer; + } + .filter-chip:hover { + border-color: var(--color-hub); + background: var(--color-bg-elev); + } + .filter-chip.is-active { + background: var(--color-hub); + color: var(--color-ink-on-dark); + border-color: var(--color-hub); + } + .filter-chip.is-active:hover { + background: var(--color-hub-2); + } + .filter-chip .caret { + opacity: 0.55; + } + + /* ============================================================ + * Active-Chips (entfernbare Filter-Anzeige) + * ============================================================ */ + .active-chip { + display: inline-flex; + align-items: center; + gap: 7px; + padding: 4px 6px 4px 11px; + background: var(--color-bg-elev); + border: 1px solid var(--color-bg-rule); + border-radius: 999px; + font-size: 11.5px; + color: var(--color-ink-2); + font-weight: 500; + } + .active-chip strong { + color: var(--color-hub); + font-weight: 600; + } + .active-chip .x { + width: 16px; + height: 16px; + border-radius: 999px; + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--color-ink-3); + background: var(--color-bg-rule-2); + transition: + background 0.12s, + color 0.12s; + border: 0; + cursor: pointer; + } + .active-chip .x:hover { + background: var(--color-hub); + color: var(--color-ink-on-dark); + } + + /* ============================================================ + * Portal-Pills (presseecho / businessportal24 Indikator) + * ============================================================ */ + .portal-pill { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 3px 8px; + border-radius: 999px; + font-size: 10.5px; + font-weight: 600; + letter-spacing: 0.06em; + background: var(--color-bg-elev); + border: 1px solid var(--color-bg-rule); + color: var(--color-ink-2); + white-space: nowrap; + } + .portal-pill .pdot { + width: 6px; + height: 6px; + border-radius: 999px; + } + .portal-pill.pe .pdot { + background: var(--color-bridge-presseecho); + } + .portal-pill.bp .pdot { + background: var(--color-bridge-businessportal); + } + + /* ============================================================ + * Inline-Action (kleine Aktion direkt neben Status-Badge) + * ============================================================ */ + .inline-action { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 11px; + font-weight: 600; + color: var(--color-hub); + background: transparent; + padding: 3px 6px; + margin-left: 4px; + border-radius: 3px; + border: 1px dashed transparent; + transition: + border-color 0.12s, + background 0.12s; + cursor: pointer; + } + .inline-action:hover { + background: var(--color-hub-soft); + border-color: var(--color-hub-soft-2); + } + .inline-action.warn { + color: var(--color-accent-deep); + } + .inline-action.warn:hover { + background: var(--color-warn-soft); + border-color: color-mix( + in oklab, + var(--color-warn), + transparent 60% + ); + } + .inline-action.err { + color: var(--color-loss); + } + .inline-action.err:hover { + background: var(--color-err-soft); + border-color: color-mix( + in oklab, + var(--color-err), + transparent 60% + ); + } + + /* ============================================================ + * Row-Tinting (für Status-Hover-Hervorhebung in Listen) + * ============================================================ */ + .is-row-warn:hover, + tr.is-row-warn:hover td { + background: color-mix( + in oklab, + var(--color-warn-soft), + var(--color-bg-card) 50% + ) !important; + } + .is-row-err:hover, + tr.is-row-err:hover td { + background: color-mix( + in oklab, + var(--color-err-soft), + var(--color-bg-card) 50% + ) !important; + } + + /* ============================================================ + * Empty-Stage (große Empty-States in Panels/Tabellen) + * ============================================================ */ + .empty-stage { + padding: 64px 24px; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + .empty-stage .empty-ico { + width: 64px; + height: 64px; + border-radius: 6px; + background: var(--color-hub-soft); + border: 1px solid var(--color-hub-soft-2); + color: var(--color-hub); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 20px; + } + .empty-stage .empty-ico.warm { + background: var(--color-accent-soft); + border-color: color-mix( + in oklab, + var(--color-accent-warm), + transparent 50% + ); + color: var(--color-accent-deep); + } + .empty-stage .empty-ico.err { + background: var(--color-err-soft); + border-color: color-mix( + in oklab, + var(--color-err), + transparent 50% + ); + color: var(--color-loss); + } + .empty-stage .empty-title { + font-size: 17px; + font-weight: 600; + color: var(--color-ink); + margin: 0; + letter-spacing: -0.2px; + } + .empty-stage .empty-sub { + font-size: 13px; + color: var(--color-ink-3); + line-height: 1.55; + margin: 8px 0 0; + max-width: 440px; + } + +} + +/* ============================================================ + * FluxUI-Tabellen im Hub-Panel-Kontext + * ============================================================ + * FluxUI setzt per Default `first:ps-0 last:pe-0` auf alle + * Tabellen-Zellen/-Spalten — die Tabelle „klebt" am Rand des + * Containers. Im Hub-Stil wollen wir konsistente 18px + * Edge-Padding (wie im Mockup `table.list`). + * + * MUSS in `@layer utilities` stehen (gleicher Layer wie + * FluxUI's `first:ps-0`-Utility), sonst gewinnt FluxUI durch + * CSS-Cascade-Layer-Ordering, unabhängig von Spezifität. + * + * Greift überall, wo eine FluxUI-Tabelle innerhalb eines + * `.panel` oder `.panel-warm` sitzt. Tabellen in Modals, + * Dropdowns oder anderen Kontexten bleiben unangetastet. + */ +@layer utilities { + .panel [data-flux-table] [data-flux-column]:first-child, + .panel [data-flux-table] [data-flux-cell]:first-child, + .panel-warm [data-flux-table] [data-flux-column]:first-child, + .panel-warm [data-flux-table] [data-flux-cell]:first-child { + padding-inline-start: 18px; + } + .panel [data-flux-table] [data-flux-column]:last-child, + .panel [data-flux-table] [data-flux-cell]:last-child, + .panel-warm [data-flux-table] [data-flux-column]:last-child, + .panel-warm [data-flux-table] [data-flux-cell]:last-child { + padding-inline-end: 18px; + } } diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php index fb950de..ec6e08d 100644 --- a/resources/views/admin/dashboard.blade.php +++ b/resources/views/admin/dashboard.blade.php @@ -79,11 +79,25 @@
@forelse ($recentPRs as $pr) + @php + $badgeClass = match ($pr->status->value) { + 'published' => 'ok', + 'review' => 'warn', + 'rejected' => 'err', + 'archived', 'draft' => 'muted', + default => 'hub', + }; + $portal = $pr->portal?->value ?? 'both'; + $showPe = in_array($portal, ['presseecho', 'both'], true); + $showBp = in_array($portal, ['businessportal24', 'both'], true); + @endphp + class="flex items-center justify-between gap-4 px-5 py-3 border-b border-[color:var(--color-bg-rule)] last:border-b-0 hover:bg-[color:var(--color-bg)] transition-colors">

{{ $pr->title }}

+ PM-{{ $pr->id }} + · {{ $pr->company?->name ?? '–' }} · {{ $pr->user?->name ?? '–' }} @@ -91,15 +105,15 @@ {{ $pr->created_at->format('d.m.Y') }}

- $pr->status->value === 'published', - 'warn' => $pr->status->value === 'review', - 'err' => $pr->status->value === 'rejected', - 'hub' => in_array($pr->status->value, ['archived', 'draft'], true), - ])> - {{ $pr->status->label() }} - +
+ @if ($showPe) + presseecho + @endif + @if ($showBp) + businessportal24 + @endif + {{ $pr->status->label() }} +
@empty

@@ -122,17 +136,44 @@ @forelse ($pendingReviews as $pr) - -

{{ $pr->title }}

-

- {{ $pr->company?->name ?? '–' }} - · - {{ $pr->portal->label() }} - · - {{ $pr->created_at->format('d.m.Y') }} -

-
+ @php + $portal = $pr->portal?->value ?? 'both'; + $showPe = in_array($portal, ['presseecho', 'both'], true); + $showBp = in_array($portal, ['businessportal24', 'both'], true); + @endphp +
+ +
+

+ PM-{{ $pr->id }} + · + {{ $pr->company?->name ?? '–' }} + · + {{ $pr->created_at->format('d.m.Y') }} +

+
+ @if ($showPe) + presseecho + @endif + @if ($showBp) + businessportal24 + @endif +
+
+
@empty

{{ __('Keine PMs in der Prüfwarteschlange.') }} diff --git a/resources/views/components/layouts/app/header.blade.php b/resources/views/components/layouts/app/header.blade.php deleted file mode 100644 index ee19e9a..0000000 --- a/resources/views/components/layouts/app/header.blade.php +++ /dev/null @@ -1,124 +0,0 @@ - - - - @include('partials.head') - - - - - - - - - - - - {{ __('Dashboard') }} - - - - - - - - - - - - - - - - - - - - - - - -

-
- - - {{ auth()->user()->initials() }} - - - -
- {{ auth()->user()->name }} - {{ auth()->user()->email }} -
-
-
- - - - - - {{ __('Settings') }} - - - - -
- @csrf - - {{ __('Log Out') }} - -
- - - - - - - - - - - - - - - - {{ __('Dashboard') }} - - - - - - - - - {{ __('Repository') }} - - - - {{ __('Documentation') }} - - - - - {{ $slot }} - - @fluxScripts - - diff --git a/resources/views/components/layouts/app/sidebar.blade.php b/resources/views/components/layouts/app/sidebar.blade.php index c891da7..679a17d 100644 --- a/resources/views/components/layouts/app/sidebar.blade.php +++ b/resources/views/components/layouts/app/sidebar.blade.php @@ -1,10 +1,15 @@ {{-- - Hub × FluxUI Phase 1 — Portal-Shell im Hub-Design. - class="dark" wurde entfernt; Light Mode ist Default, Dark kommt mit - FluxUI Appearance-Switcher in Phase 5. + Hub × FluxUI Phase 5 — Portal-Shell im Hub-Design. + Erscheinung (Light/Dark) wird über FluxUI Appearance-Switcher + gesteuert. Server liest das `flux_appearance`-Cookie (gesetzt vom + JS-Bridge in partials/head.blade.php) und rendert class="dark" + direkt im , damit es bei wire:navigate kein Theme-Flash gibt. + Bei fehlendem Cookie (Erstbesuch) wird Light gerendert und das JS + schaltet bei dunkler Präferenz nach Page-Load nach — der einmalige + Flash beim allerersten Aufruf ist akzeptiert. --}} - + request()->cookie('flux_appearance') === 'dark'])> @include('partials.head') diff --git a/resources/views/components/layouts/auth.blade.php b/resources/views/components/layouts/auth.blade.php deleted file mode 100644 index 56d6cb6..0000000 --- a/resources/views/components/layouts/auth.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - {{ $slot }} - diff --git a/resources/views/components/layouts/auth/card.blade.php b/resources/views/components/layouts/auth/card.blade.php deleted file mode 100644 index db94716..0000000 --- a/resources/views/components/layouts/auth/card.blade.php +++ /dev/null @@ -1,26 +0,0 @@ - - - - @include('partials.head') - - - - @fluxScripts - - diff --git a/resources/views/components/layouts/auth/simple.blade.php b/resources/views/components/layouts/auth/simple.blade.php deleted file mode 100644 index dd25d11..0000000 --- a/resources/views/components/layouts/auth/simple.blade.php +++ /dev/null @@ -1,35 +0,0 @@ - - - - @include('partials.head') - - - - @livewireScripts - @fluxScripts - - - - - - diff --git a/resources/views/components/layouts/auth/split.blade.php b/resources/views/components/layouts/auth/split.blade.php deleted file mode 100644 index 4e9788b..0000000 --- a/resources/views/components/layouts/auth/split.blade.php +++ /dev/null @@ -1,43 +0,0 @@ - - - - @include('partials.head') - - -
- - -
- @fluxScripts - - diff --git a/resources/views/components/settings/layout.blade.php b/resources/views/components/settings/layout.blade.php index 05c0637..e6ddaa5 100644 --- a/resources/views/components/settings/layout.blade.php +++ b/resources/views/components/settings/layout.blade.php @@ -1,20 +1,40 @@ -
-
- - {{ __('Profile') }} - {{ __('Password') }} - {{ __('Appearance') }} - -
- - - -
- {{ $heading ?? '' }} - {{ $subheading ?? '' }} - -
- {{ $slot }} +{{-- Hub-style settings layout: sidebar nav + content panel --}} +
+ + +
+
+
+ {{ $heading ?? '' }} +
+
+ @if (! empty($subheading)) +

+ {{ $subheading }} +

+ @endif + +
+ {{ $slot }} +
+
+
diff --git a/resources/views/components/web/brand-mark.blade.php b/resources/views/components/web/brand-mark.blade.php index ab8db8c..81a2618 100644 --- a/resources/views/components/web/brand-mark.blade.php +++ b/resources/views/components/web/brand-mark.blade.php @@ -79,8 +79,20 @@ $fontClass = $serif ? 'font-serif' : 'font-sans'; $baseAttributes = $attributes->merge(['class' => $fontClass]); + + /** + * Variant=auto: Inline-Color über CSS-Custom-Property mit Light-Fallback. + * Damit kann das Portal im Dark Mode `--brand-mark-name-color` global auf + * weiß setzen, ohne dass das Hub-Frontend (Light-Only) tangiert wird — + * dort ist die Variable nie definiert und der Fallback (Marken-Standardfarbe) + * greift. Bei `on-dark` und `mono` bleibt der Inline-Style hart, weil der + * Aufrufer dort explizit eine Farb-Intention setzt. + */ + $nameStyle = $variant === 'auto' + ? "color: var(--brand-mark-name-color, {$nameColor});" + : "color: {$nameColor};"; @endphp {{ $mark['name'] }}{{ $mark['name'] }}{{ $mark['accent'] }} diff --git a/resources/views/layouts/admin-master.blade.php b/resources/views/layouts/admin-master.blade.php index dd33160..4b1a29c 100644 --- a/resources/views/layouts/admin-master.blade.php +++ b/resources/views/layouts/admin-master.blade.php @@ -1,5 +1,8 @@ - +{{-- Phase 5: Anti-Flash. class="dark" nicht mehr hardcoded — Server liest + das `flux_appearance`-Cookie (vom JS-Bridge in partials/admin-head.blade.php + gesetzt) und rendert es direkt im . --}} + request()->cookie('flux_appearance') === 'dark'])> diff --git a/resources/views/livewire/admin/categories/create.blade.php b/resources/views/livewire/admin/categories/create.blade.php index 2c2c097..b5a240c 100644 --- a/resources/views/livewire/admin/categories/create.blade.php +++ b/resources/views/livewire/admin/categories/create.blade.php @@ -106,27 +106,45 @@ new #[Layout('components.layouts.app'), Title('Kategorie anlegen')] class extend } }; ?> -
- @if(session('success')) - {{ session('success') }} - @endif +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Kategorien') }} +
+

+ {{ __('Kategorie anlegen') }} +

+

+ {{ __('Neue Themen-Kategorie mit deutscher und englischer Übersetzung.') }} +

+
- -
- {{ __('Kategorie anlegen') }} +
{{ __('Zurück') }}
- +
+ + @if (session('success')) +
+ + {{ session('success') }} +
+ @endif
- - {{ __('Deutsche Übersetzung') }} - -
+
+
+ {{ __('Deutsche Übersetzung') }} +
+
- +
- - {{ __('English translation') }} - -
+
+
+ {{ __('English translation') }} +
+
- +
-
- - {{ __('Einstellungen') }} - -
+
+
+
+ {{ __('Einstellungen') }} +
+
{{ __('Portal') }} - @foreach($portalOptions as $option) + @foreach ($portalOptions as $option) @endforeach @@ -197,7 +217,7 @@ new #[Layout('components.layouts.app'), Title('Kategorie anlegen')] class extend {{ __('Übergeordnete Kategorie') }} - @foreach($parentOptions as $parent) + @foreach ($parentOptions as $parent) @@ -208,7 +228,7 @@ new #[Layout('components.layouts.app'), Title('Kategorie anlegen')] class extend
- +
{{ __('Speichern') }} diff --git a/resources/views/livewire/admin/categories/edit.blade.php b/resources/views/livewire/admin/categories/edit.blade.php index 9ab23f5..0fb6b12 100644 --- a/resources/views/livewire/admin/categories/edit.blade.php +++ b/resources/views/livewire/admin/categories/edit.blade.php @@ -172,33 +172,54 @@ new #[Layout('components.layouts.app'), Title('Kategorie bearbeiten')] class ext } }; ?> -
- @if(session('success')) - {{ session('success') }} - @endif - @if(session('error')) - {{ session('error') }} - @endif - - -
-
- {{ __('Kategorie bearbeiten') }} - ID: {{ $id }} · {{ $releaseCount }} {{ __('PMs') }} · {{ $childrenCount }} {{ __('Unterkategorien') }} +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Kategorien') }} + ID #{{ $id }} + {{ $releaseCount }} {{ __('PMs') }} + @if ($childrenCount > 0) + {{ $childrenCount }} {{ __('Unterkategorien') }} + @endif
+

+ {{ __('Kategorie bearbeiten') }} +

+
+ +
{{ __('Zurück') }}
- +
+ + @if (session('success')) +
+ + {{ session('success') }} +
+ @endif + @if (session('error')) +
+ +
{{ session('error') }}
+
+ @endif
- - {{ __('Deutsche Übersetzung') }} - -
+
+
+ {{ __('Deutsche Übersetzung') }} +
+
@@ -208,12 +229,13 @@ new #[Layout('components.layouts.app'), Title('Kategorie bearbeiten')] class ext
- +
- - {{ __('English translation') }} - -
+
+
+ {{ __('English translation') }} +
+
@@ -223,18 +245,19 @@ new #[Layout('components.layouts.app'), Title('Kategorie bearbeiten')] class ext
- +
-
- - {{ __('Einstellungen') }} - -
+
+
+
+ {{ __('Einstellungen') }} +
+
{{ __('Portal') }} - @foreach($portalOptions as $option) + @foreach ($portalOptions as $option) @endforeach @@ -245,7 +268,7 @@ new #[Layout('components.layouts.app'), Title('Kategorie bearbeiten')] class ext {{ __('Übergeordnete Kategorie') }} - @foreach($parentOptions as $parent) + @foreach ($parentOptions as $parent) @@ -256,17 +279,27 @@ new #[Layout('components.layouts.app'), Title('Kategorie bearbeiten')] class ext
- +
{{ __('Änderungen speichern') }} - - - {{ __('Kategorie löschen') }} - - +
+
+ {{ __('Danger Zone') }} +
+
+

+ {{ __('Kategorie unwiderruflich entfernen, sofern keine PMs/Unterkategorien hängen.') }} +

+ + + {{ __('Kategorie löschen') }} + + +
+
diff --git a/resources/views/livewire/admin/categories/index.blade.php b/resources/views/livewire/admin/categories/index.blade.php index 9e85e63..7ec4193 100644 --- a/resources/views/livewire/admin/categories/index.blade.php +++ b/resources/views/livewire/admin/categories/index.blade.php @@ -141,108 +141,107 @@ new #[Layout('components.layouts.app'), Title('Kategorien')] class extends Compo } }; ?> -
- {{-- Statistiken --}} -
- -
-
- {{ __('Kategorien') }} - {{ $stats['total'] }} -
- +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Stammdaten') }}
- +

+ {{ __('Kategorien') }} +

+

+ {{ __('Themen-Taxonomie für Pressemitteilungen über alle Portale hinweg.') }} +

+
- -
-
- {{ __('Mit PMs') }} - {{ $stats['with_releases'] }} -
- -
-
- - -
-
- {{ __('PMs gesamt') }} - {{ $stats['total_releases'] }} -
- -
-
- - - {{ __('Portale') }} -
-
- {{ __('Presseecho') }} - {{ number_format($stats['presseecho_releases']) }} -
-
- {{ __('Businessportal24') }} - {{ number_format($stats['businessportal24_releases']) }} -
-
-
-
- - {{-- Filter + Aktion --}} - -
-
- -
- +
+ {{ __('Kategorie anlegen') }}
- + - {{-- Karten --}} - {{-- Sortier-Buttons --}} - -
- {{ __('Sortierung:') }} - - {{ __('Standard') }} @if($sortBy==='id') {{ $sortDir === 'asc' ? '↑' : '↓' }} @endif - - - {{ __('PMs') }} @if($sortBy==='press_releases_count') {{ $sortDir === 'asc' ? '↑' : '↓' }} @endif - + {{-- ============== KPI-Reihe ============== --}} +
+ + {{ __('gesamt') }} + {{ __('Themen-Taxonomie') }} + + + {{ __('aktiv genutzt') }} + {{ __('mind. eine PM') }} + + + {{ __('alle Portale') }} + {{ __('Content-Output') }} + + +
+
+ {{ __('Portale') }} +
+
+
+
{{ __('Presseecho') }}
+
{{ number_format($stats['presseecho_releases']) }}
+
+
+
{{ __('Businessportal24') }}
+
{{ number_format($stats['businessportal24_releases']) }}
+
+
+
+
+ + {{-- ============== FILTER + SORT ============== --}} +
+
+ {{ __('Filter & Sortierung') }}
- +
+ +
+ + {{ __('Sortierung') }} + + + {{ __('Standard') }} @if ($sortBy === 'id') {{ $sortDir === 'asc' ? '↑' : '↓' }} @endif + + + {{ __('PMs') }} @if ($sortBy === 'press_releases_count') {{ $sortDir === 'asc' ? '↑' : '↓' }} @endif + +
+
+
-
- @forelse($categories as $category) + {{-- ============== KATEGORIE-KARTEN ============== --}} +
+ @forelse ($categories as $category) @php $de = $category->translations->firstWhere('locale', 'de'); $en = $category->translations->firstWhere('locale', 'en'); @endphp - +
-
-
-
- {{ $de?->name ?? '–' }} - {{ $en?->name ?? '–' }} +
+
+
+ {{ __('Kategorie') }}
- - {{ $category->is_active ? __('Aktiv') : __('Inaktiv') }} - + @if ($category->is_active) + {{ __('Aktiv') }} + @else + {{ __('Inaktiv') }} + @endif
- @if($de?->description) - - {{ $de->description }} - - @endif - -
-
-
{{ __('Presseecho') }}
-
{{ number_format($category->presseecho_press_releases_count) }}
+
+
+
+ {{ $de?->name ?? '–' }} +
+
+ {{ $en?->name ?? '–' }} +
-
-
{{ __('Businessportal24') }}
-
{{ number_format($category->businessportal24_press_releases_count) }}
+ + @if ($de?->description) +

+ {{ $de->description }} +

+ @endif + +
+
+
{{ __('Presseecho') }}
+
{{ number_format($category->presseecho_press_releases_count) }}
+
+
+
{{ __('Businessportal24') }}
+
{{ number_format($category->businessportal24_press_releases_count) }}
+
-
-
+
+
- {{ $category->press_releases_count }} {{ __('PMs') }} + {{ $category->press_releases_count }} + {{ __('PMs') }}
- /{{ $de?->slug ?? $category->id }} + /{{ $de?->slug ?? $category->id }}
- +
@empty -
- -
- - {{ __('Keine Kategorien gefunden.') }} +
+
+
+
- -
+
+ {{ __('Keine Kategorien gefunden.') }} +
+
+ @endforelse -
+
{{ $categories->links() }}
diff --git a/resources/views/livewire/admin/companies/create.blade.php b/resources/views/livewire/admin/companies/create.blade.php index 9cc4f8d..96c0620 100644 --- a/resources/views/livewire/admin/companies/create.blade.php +++ b/resources/views/livewire/admin/companies/create.blade.php @@ -117,165 +117,194 @@ new #[Layout('components.layouts.app'), Title('Neue Firma')] class extends Compo } }; ?> -
- {{-- Basisinformationen --}} - - {{ __('Basisinformationen') }} - -
-
- - {{ __('Portal') }} - - @foreach($portalOptions as $portalOption) - - @endforeach - - - - - {{ __('Typ') }} - - @foreach($typeOptions as $typeOption) - - @endforeach - - +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Stammdaten · Neue Firma') }}
- - - {{ __('Firmenname') }} * - - - - - - {{ __('Beschreibung') }} - - - - -
- - {{ __('E-Mail') }} * - - - - - - {{ __('Telefon') }} - - - -
- - - {{ __('Website') }} - - - +

+ {{ __('Neue Firma') }} +

+

+ {{ __('Stammdaten, Adresse, Logo und Rechtsangaben einer neuen Firma erfassen.') }} +

- - {{-- Adresse --}} - - {{ __('Adresse') }} - -
- - {{ __('Straße & Hausnummer') }} - - - - -
- - {{ __('PLZ') }} - - - - - - {{ __('Stadt') }} - - - -
- -
- - {{ __('Bundesland / Region') }} - - - - - - {{ __('Land') }} * - - @foreach($countries as $country) - - @endforeach - - - -
-
-
- - {{-- Rechtliche Daten --}} - - {{ __('Rechtliche Daten') }} - -
- - {{ __('Steuernummer / USt-IdNr.') }} - - - - - - {{ __('Handelsregisternummer') }} - - - -
-
- - {{-- Logo & Status --}} - - {{ __('Logo & Status') }} - -
- - {{ __('Firmenlogo') }} - - {{ __('Maximal 1 MB. Empfohlen: quadratisch, min. 400x400px') }} - - - @if ($logo) -
- {{ __('Vorschau:') }} - -
- @endif -
- -
- - -
-
-
- - {{-- Aktionen --}} - -
- - {{ __('Abbrechen') }} - - - {{ __('Firma erstellen') }} +
+ + {{ __('Zurück') }}
- - +
+ +
+
+
+ {{ __('Basisinformationen') }} +
+
+
+ + {{ __('Portal') }} + + @foreach ($portalOptions as $portalOption) + + @endforeach + + + + + {{ __('Typ') }} + + @foreach ($typeOptions as $typeOption) + + @endforeach + + +
+ + + {{ __('Firmenname') }} * + + + + + + {{ __('Beschreibung') }} + + + + +
+ + {{ __('E-Mail') }} * + + + + + + {{ __('Telefon') }} + + + +
+ + + {{ __('Website') }} + + + +
+
+ +
+
+ {{ __('Adresse') }} +
+
+ + {{ __('Straße & Hausnummer') }} + + + + +
+ + {{ __('PLZ') }} + + + + + + {{ __('Stadt') }} + + + +
+ +
+ + {{ __('Bundesland / Region') }} + + + + + + {{ __('Land') }} * + + @foreach ($countries as $country) + + @endforeach + + + +
+
+
+ +
+
+ {{ __('Rechtliche Daten') }} +
+
+ + {{ __('Steuernummer / USt-IdNr.') }} + + + + + + {{ __('Handelsregisternummer') }} + + + +
+
+ +
+
+ {{ __('Logo & Status') }} +
+
+ + {{ __('Firmenlogo') }} + + {{ __('Maximal 1 MB. Empfohlen: quadratisch, min. 400x400px') }} + + + @if ($logo) +
+
+ {{ __('Vorschau:') }} +
+ +
+ @endif +
+ +
+ + +
+
+
+ +
+
+ {{ __('Aktionen') }} +
+
+ + {{ __('Abbrechen') }} + + + {{ __('Firma erstellen') }} + +
+
+
+
diff --git a/resources/views/livewire/admin/companies/edit.blade.php b/resources/views/livewire/admin/companies/edit.blade.php index 834ffbe..f85945e 100644 --- a/resources/views/livewire/admin/companies/edit.blade.php +++ b/resources/views/livewire/admin/companies/edit.blade.php @@ -195,198 +195,233 @@ new #[Layout('components.layouts.app'), Title('Firma bearbeiten')] class extends } }; ?> -
+
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Stammdaten · Firma bearbeiten') }} + ID {{ $companyId }} +
+

+ {{ __('Firma bearbeiten') }} +

+

+ {{ __('Stammdaten, Adresse, Logo und Rechtsangaben der Firma aktualisieren.') }} +

+
+ +
+ + {{ __('Zurück') }} + +
+
+
- {{-- Basisinformationen --}} - - {{ __('Basisinformationen') }} +
+
+ {{ __('Basisinformationen') }} +
+
+
+ + {{ __('Portal') }} + + @foreach ($portalOptions as $portalOption) + + @endforeach + + + + + {{ __('Typ') }} + + @foreach ($typeOptions as $typeOption) + + @endforeach + + +
-
-
- {{ __('Portal') }} - - @foreach($portalOptions as $portalOption) - - @endforeach - + {{ __('Firmenname') }} * + + - {{ __('Typ') }} - - @foreach($typeOptions as $typeOption) - - @endforeach - + {{ __('Beschreibung') }} + + + + +
+ + {{ __('E-Mail') }} * + + + + + + {{ __('Telefon') }} + + + +
+ + + {{ __('Website') }} + +
+
- - {{ __('Firmenname') }} * - - - - - - {{ __('Beschreibung') }} - - - - -
+
+
+ {{ __('Adresse') }} +
+
- {{ __('E-Mail') }} * - - + {{ __('Straße & Hausnummer') }} + + + + +
+ + {{ __('PLZ') }} + + + + + + {{ __('Stadt') }} + + + +
+ +
+ + {{ __('Bundesland / Region') }} + + + + + + {{ __('Land') }} * + + @foreach ($countries as $country) + + @endforeach + + + +
+
+
+ +
+
+ {{ __('Rechtliche Daten') }} +
+
+ + {{ __('Steuernummer / USt-IdNr.') }} + + - {{ __('Telefon') }} - - + {{ __('Handelsregisternummer') }} + +
+
- - {{ __('Website') }} - - - -
-
- - {{-- Adresse --}} - - {{ __('Adresse') }} - -
- - {{ __('Straße & Hausnummer') }} - - - - -
- - {{ __('PLZ') }} - - - - - - {{ __('Stadt') }} - - - +
+
+ {{ __('Logo & Status') }}
- -
+
- {{ __('Bundesland / Region') }} - - - + {{ __('Firmenlogo') }} + + {{ __('Maximal 4 MB. Varianten (sq/wide) werden automatisch generiert.') }} + - - {{ __('Land') }} * - - @foreach($countries as $country) - - @endforeach - - - -
-
- - - {{-- Rechtliche Daten --}} - - {{ __('Rechtliche Daten') }} - -
- - {{ __('Steuernummer / USt-IdNr.') }} - - - - - - {{ __('Handelsregisternummer') }} - - - -
-
- - {{-- Logo & Status --}} - - {{ __('Logo & Status') }} - -
- - {{ __('Firmenlogo') }} - - {{ __('Maximal 4 MB. Varianten (sq/wide) werden automatisch generiert.') }} - - - @if ($logo) -
- {{ __('Neues Logo (Vorschau):') }} - -
- @elseif($current_logo_url && ! $remove_logo) -
-
- {{ __('Aktuelles Logo:') }} - + @if ($logo) +
+
+ {{ __('Neues Logo (Vorschau):') }} +
+
- - {{ __('Logo entfernen') }} - -
- @elseif($remove_logo) - - {{ __('Logo wird beim Speichern entfernt.') }} - - {{ __('Rückgängig') }} - - - @endif - + @elseif ($current_logo_url && ! $remove_logo) +
+
+
+ {{ __('Aktuelles Logo:') }} +
+ +
+ + {{ __('Logo entfernen') }} + +
+ @elseif ($remove_logo) +
+ +
+ {{ __('Logo wird beim Speichern entfernt.') }} +
+ + {{ __('Rückgängig') }} + +
+ @endif + -
- - +
+ + +
-
- +
- {{-- Aktionen --}} - -
- - - {{ __('Löschen') }} - - -
- - {{ __('Abbrechen') }} - - - {{ __('Änderungen speichern') }} - +
+
+ {{ __('Aktionen') }}
-
- +
+ + + {{ __('Löschen') }} + + +
+ + {{ __('Abbrechen') }} + + + {{ __('Änderungen speichern') }} + +
+
+ diff --git a/resources/views/livewire/admin/companies/index.blade.php b/resources/views/livewire/admin/companies/index.blade.php index dfe6d24..f8b7ce4 100644 --- a/resources/views/livewire/admin/companies/index.blade.php +++ b/resources/views/livewire/admin/companies/index.blade.php @@ -296,43 +296,51 @@ new #[Layout('components.layouts.app'), Title('Firmen')] class extends Component } }; ?> -
- {{-- Statistiken --}} -
- -
-
- {{ __('Gesamt') }} - {{ $stats['total'] }} -
- +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Stammdaten · Firmen') }}
- +

+ {{ __('Firmen') }} +

+

+ {{ __('Übersicht aller Firmen beider Portale, mit Filter, Datenqualität und Schnellaktionen.') }} +

+
- -
-
- {{ __('Aktiv') }} - {{ $stats['active'] }} -
- -
-
+
+ + {{ __('Neue Firma') }} + +
+
- -
-
- {{ __('Inaktiv') }} - {{ $stats['inactive'] }} -
- -
-
-
+ {{-- ============== KPI-Reihe ============== --}} +
+ + {{ __('alle Portale') }} + {{ __('Stammdaten-Basis') }} + + + {{ __('produktiv') }} + {{ __('für PMs nutzbar') }} + + + {{ __('pausiert') }} + {{ __('archiviert oder geblockt') }} + +
- {{-- Filter & Actions --}} - -
+ {{-- ============== FILTER-PANEL ============== --}} +
+
+ {{ __('Filter & Suche') }} +
+
@@ -436,17 +444,17 @@ new #[Layout('components.layouts.app'), Title('Firmen')] class extends Component />
- -
- - {{ __('Neue Firma') }} - -
-
+ - {{-- Tabelle --}} - + {{-- ============== TABELLE-PANEL ============== --}} +
+
+ {{ __('Alle Firmen') }} + + {{ __(':count Einträge', ['count' => $companies->count()]) }} + +
{{ __('Aktionen') }} @@ -481,40 +489,43 @@ new #[Layout('components.layouts.app'), Title('Firmen')] class extends Component
- @if($logoUrl) - {{ $company->name }} + @if ($logoUrl) + {{ $company->name }} @else -
- +
+
@endif - {{ \Illuminate\Support\Str::limit($company->name, 60) }} - + + {{ \Illuminate\Support\Str::limit($company->name, 60) }} +
-
- {{ $company->email ?: __('Keine E-Mail') }} - {{ $company->phone ?: __('Kein Telefon') }} - +
+
+ {{ $company->email ?: __('Keine E-Mail') }} +
+
+ {{ $company->phone ?: __('Kein Telefon') }} +
@if ($company->is_active) - {{ __('Aktiv') }} - + {{ __('Aktiv') }} @else - {{ __('Inaktiv') }} - + {{ __('Inaktiv') }} @endif - - {{ $company->portal?->label() ?? __('Unbekannt') }} - + {{ $company->portal?->label() ?? __('Unbekannt') }} @@ -528,7 +539,7 @@ new #[Layout('components.layouts.app'), Title('Firmen')] class extends Component {{ $company->press_releases_count }} {{ __('PMs') }} @else - 0 + 0 @endif @@ -543,31 +554,39 @@ new #[Layout('components.layouts.app'), Title('Firmen')] class extends Component {{ $company->contacts_count }} {{ __('Kontakte') }} @else - 0 + 0 @endif - + {{ $company->created_at?->format('d.m.Y H:i') ?? '–' }} - + @empty -
- - {{ __('Keine Firmen gefunden') }} +
+
+ +
+
+ {{ __('Keine Firmen gefunden') }} +
+

+ {{ __('Passen Sie die Filter an oder legen Sie eine neue Firma an.') }} +

@endforelse -
+
{{ $companies->links() }}
- +
diff --git a/resources/views/livewire/admin/companies/show.blade.php b/resources/views/livewire/admin/companies/show.blade.php index 2cdb99e..ebce649 100644 --- a/resources/views/livewire/admin/companies/show.blade.php +++ b/resources/views/livewire/admin/companies/show.blade.php @@ -192,129 +192,198 @@ new #[Layout('components.layouts.app'), Title('Firma anzeigen')] class extends C } }; ?> -
- -
-
- @php($logoUrl = $company->logoUrl()) +
+ @if (session('success')) +
+ {{ session('success') }} +
+ @endif + @if (session('error')) +
+ {{ session('error') }} +
+ @endif + @if (session('info')) +
+ {{ session('info') }} +
+ @endif - @if($logoUrl) - {{ $company->name }} + {{-- ============== PAGE HEADER ============== --}} + @php($logoUrl = $company->logoUrl()) +
+
+
+ {{ __('Admin Backend') }} + {{ __('Stammdaten · Firma') }} + @if ($company->is_active) + {{ __('Aktiv') }} @else -
- + {{ __('Inaktiv') }} + @endif + {{ $company->portal?->label() ?? __('Unbekannt') }} + ID {{ $company->id }} +
+
+ @if ($logoUrl) + {{ $company->name }} + @else +
+
@endif - -
- {{ $company->name }} -
- @if($company->is_active) - {{ __('Aktiv') }} - @else - {{ __('Inaktiv') }} - @endif - {{ $company->portal?->label() ?? __('Unbekannt') }} - ID: {{ $company->id }} -
+
+

+ {{ $company->name }} +

+ @if ($company->website) + + {{ $company->website }} + + @endif
+
-
- - {{ __('Bearbeiten') }} +
+ + {{ __('Zurück') }} + + @if (\Illuminate\Support\Facades\Route::has('admin.companies.contacts.create')) + + {{ __('Kontakt hinzufügen') }} - @if (\Illuminate\Support\Facades\Route::has('admin.companies.contacts.create')) - - {{ __('Kontakt hinzufügen') }} - - @endif -
-
- - -
- - {{ __('Pressemitteilungen') }} - {{ $company->press_releases_count }} - - - {{ __('Kontakte') }} - {{ $company->contacts_count }} - - - {{ __('Verknüpfte Benutzer') }} - {{ $company->users_count }} - -
- - -
- - {{ __('Überblick') }} - - - {{ __('Kontakte') }} + @endif + + {{ __('Bearbeiten') }}
-
+
- @if($activeTab === 'overview') + {{-- ============== KPI-Reihe ============== --}} +
+ + {{ __('insgesamt') }} + {{ __('Content-Output dieser Firma') }} + + + {{ __('Ansprechpartner') }} + {{ __('für PMs verfügbar') }} + + + {{ __('Owner & Co-Editors') }} + {{ __('Backend-Zugriff') }} + +
+ + {{-- ============== TABS ============== --}} + + + @if ($activeTab === 'overview')
- - {{ __('Kontaktinformationen') }} -
- {{ $company->email ?: __('Keine E-Mail hinterlegt') }} - {{ $company->phone ?: __('Kein Telefon hinterlegt') }} - {{ $company->website ?: __('Keine Website hinterlegt') }} +
+
+ {{ __('Kontaktinformationen') }}
- +
+
+
{{ __('E-Mail') }}
+
{{ $company->email ?: __('Keine E-Mail hinterlegt') }}
+
+
+
{{ __('Telefon') }}
+
{{ $company->phone ?: __('Kein Telefon hinterlegt') }}
+
+
+
{{ __('Website') }}
+
{{ $company->website ?: __('Keine Website hinterlegt') }}
+
+
+
- - {{ __('Adresse') }} -
- {{ $company->address ?: __('Keine Adresse hinterlegt') }} - {{ $company->country_code ?: __('Kein Land hinterlegt') }} +
+
+ {{ __('Adresse') }}
- +
+
+
{{ __('Anschrift') }}
+
{{ $company->address ?: __('Keine Adresse hinterlegt') }}
+
+
+
{{ __('Land') }}
+
{{ $company->country_code ?: __('Kein Land hinterlegt') }}
+
+
+
- -
- {{ __('Aktuelle Pressemitteilungen') }} +
+
+ {{ __('Aktuelle Pressemitteilungen') }} {{ __('Alle anzeigen') }}
- -
@endif - @if($activeTab === 'contacts') - -
- {{ __('Ansprechpartner') }} ({{ $filteredContactsTotal }}) -
+ @if ($activeTab === 'contacts') +
+
+ {{ __('Ansprechpartner') }} + + {{ $filteredContactsTotal }} {{ __('Einträge') }} + +
+
+
@if (\Illuminate\Support\Facades\Route::has('admin.companies.contacts.create')) @@ -322,79 +391,86 @@ new #[Layout('components.layouts.app'), Title('Firma anzeigen')] class extends C @endif
-
-
- {{ __('Bestehenden Kontakt zuordnen') }} - - - - - @foreach($contactLookupResults as $lookupContact) - @php($lookupName = trim(($lookupContact->first_name ?? '').' '.($lookupContact->last_name ?? '')) ?: __('Kontakt ohne Name')) - - {{ $lookupName }} - - @if($lookupContact->email) - · {{ $lookupContact->email }} +
+
+ {{ __('Bestehenden Kontakt zuordnen') }} +
+ + + + + @foreach ($contactLookupResults as $lookupContact) + @php($lookupName = trim(($lookupContact->first_name ?? '').' '.($lookupContact->last_name ?? '')) ?: __('Kontakt ohne Name')) + + {{ $lookupName }} + + @if ($lookupContact->email) + · {{ $lookupContact->email }} + @endif + · {{ $lookupContact->company?->name ?? __('Unbekannte Firma') }} + + + @endforeach + + + @if (blank(trim($contactLookup))) + {{ __('Mindestens 1 Zeichen eingeben…') }} + @else + {{ __('Kein Kontakt gefunden.') }} @endif - · {{ $lookupContact->company?->name ?? __('Unbekannte Firma') }} - - - @endforeach - - - @if(blank(trim($contactLookup))) - {{ __('Mindestens 1 Zeichen eingeben…') }} - @else - {{ __('Kein Kontakt gefunden.') }} - @endif - - - -
+ + +
+
-
- @forelse($filteredContacts as $contact) -
-
-
-
- - {{ trim(($contact->first_name ?? '').' '.($contact->last_name ?? '')) ?: __('Kontakt ohne Name') }} - - - {{ $contact->portal?->label() ?? __('Unbekannt') }} - +
+ @forelse ($filteredContacts as $contact) +
+
+
+
+ + {{ trim(($contact->first_name ?? '').' '.($contact->last_name ?? '')) ?: __('Kontakt ohne Name') }} + + {{ $contact->portal?->label() ?? __('Unbekannt') }} +
+
+ {{ $contact->responsibility ?: __('Keine Rolle hinterlegt') }} +
+ @if ($contact->email) + + {{ $contact->email }} + + @endif
- {{ $contact->responsibility ?: __('Keine Rolle hinterlegt') }} - @if($contact->email) - {{ $contact->email }} + @if (\Illuminate\Support\Facades\Route::has('admin.contacts.edit')) + @endif
- @if (\Illuminate\Support\Facades\Route::has('admin.contacts.edit')) - - @endif
-
- @empty - {{ __('Keine Kontakte gefunden') }} - @endforelse -
+ @empty +
+ {{ __('Keine Kontakte gefunden') }} +
+ @endforelse +
- @if($filteredContactsTotal > $filteredContacts->count()) - - {{ __('Es werden die ersten :count Kontakte angezeigt. Bitte Suche eingrenzen, um weitere Treffer zu finden.', ['count' => $filteredContacts->count()]) }} - - @endif - + @if ($filteredContactsTotal > $filteredContacts->count()) +

+ {{ __('Es werden die ersten :count Kontakte angezeigt. Bitte Suche eingrenzen, um weitere Treffer zu finden.', ['count' => $filteredContacts->count()]) }} +

+ @endif +
+
@endif
diff --git a/resources/views/livewire/admin/contacts/create.blade.php b/resources/views/livewire/admin/contacts/create.blade.php index 54dadde..281f980 100644 --- a/resources/views/livewire/admin/contacts/create.blade.php +++ b/resources/views/livewire/admin/contacts/create.blade.php @@ -143,19 +143,37 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends } }; ?> -
- - {{ __('Kontakt anlegen') }} - {{ __('Kontakt einer Firma zuordnen und Stammdaten erfassen.') }} - @if($isCompanyPrefilled && $companyId) - - {{ __('Firma wurde vorausgewählt. Du kannst sie bei Bedarf trotzdem ändern.') }} - - @endif - + + {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Pressekontakte') }} + @if ($isCompanyPrefilled && $companyId) + {{ __('Firma vorausgewählt') }} + @endif +
+

+ {{ __('Kontakt anlegen') }} +

+

+ {{ __('Kontakt einer Firma zuordnen und Stammdaten erfassen.') }} +

+
- -
+
+ + {{ __('Zurück') }} + +
+
+ +
+
+ {{ __('Zuordnung') }} +
+
{{ __('Firma') }} @@ -173,7 +191,7 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends /> - @foreach($companies as $company) + @foreach ($companies as $company) {{ $company->name }} @@ -181,7 +199,7 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends - @if(blank(trim($companySearch))) + @if (blank(trim($companySearch))) {{ __('Mindestens 1 Zeichen eingeben…') }} @else {{ __('Keine Firma gefunden.') }} @@ -196,24 +214,25 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends {{ __('Portal') }} - @foreach($portalOptions as $portalOption) + @foreach ($portalOptions as $portalOption) @endforeach
- +
- - {{ __('Kontaktdaten') }} - -
+
+
+ {{ __('Kontaktdaten') }} +
+
{{ __('Anrede') }} - @foreach($salutations as $key => $labels) + @foreach ($salutations as $key => $labels) @endforeach @@ -260,10 +279,10 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends
- +
- -
+
+
{{ __('Abbrechen') }} @@ -271,5 +290,5 @@ new #[Layout('components.layouts.app'), Title('Kontakt anlegen')] class extends {{ __('Kontakt anlegen') }}
- +
diff --git a/resources/views/livewire/admin/contacts/edit.blade.php b/resources/views/livewire/admin/contacts/edit.blade.php index 6f53f1a..d05a5cd 100644 --- a/resources/views/livewire/admin/contacts/edit.blade.php +++ b/resources/views/livewire/admin/contacts/edit.blade.php @@ -178,22 +178,34 @@ new #[Layout('components.layouts.app'), Title('Kontakt bearbeiten')] class exten } }; ?> -
-
- -
-
- {{ __('Kontakt bearbeiten') }} - ID: {{ $id }} +
+ + {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Pressekontakte') }} + ID #{{ $id }} + {{ $this->currentPortalLabel() }}
- - {{ $this->currentPortalLabel() }} - +

+ {{ __('Kontakt bearbeiten') }} +

- - -
+
+ + {{ __('Zurück') }} + +
+
+ +
+
+ {{ __('Zuordnung') }} +
+
{{ __('Firma') }} @@ -211,7 +223,7 @@ new #[Layout('components.layouts.app'), Title('Kontakt bearbeiten')] class exten /> - @foreach($companies as $company) + @foreach ($companies as $company) {{ $company->name }} @@ -219,7 +231,7 @@ new #[Layout('components.layouts.app'), Title('Kontakt bearbeiten')] class exten - @if(blank(trim($companySearch))) + @if (blank(trim($companySearch))) {{ __('Mindestens 1 Zeichen eingeben…') }} @else {{ __('Keine Firma gefunden.') }} @@ -234,24 +246,25 @@ new #[Layout('components.layouts.app'), Title('Kontakt bearbeiten')] class exten {{ __('Portal') }} - @foreach($portalOptions as $portalOption) + @foreach ($portalOptions as $portalOption) @endforeach
- +
- - {{ __('Kontaktdaten') }} - -
+
+
+ {{ __('Kontaktdaten') }} +
+
{{ __('Anrede') }} - @foreach($salutations as $key => $labels) + @foreach ($salutations as $key => $labels) @endforeach @@ -298,10 +311,13 @@ new #[Layout('components.layouts.app'), Title('Kontakt bearbeiten')] class exten
- +
- -
+
+
+ {{ __('Danger Zone & Aktionen') }} +
+
-
+ diff --git a/resources/views/livewire/admin/contacts/index.blade.php b/resources/views/livewire/admin/contacts/index.blade.php index bdfed10..2e3461b 100644 --- a/resources/views/livewire/admin/contacts/index.blade.php +++ b/resources/views/livewire/admin/contacts/index.blade.php @@ -391,55 +391,73 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone } }; ?> -
+
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Pressekontakte') }} +
+

+ {{ __('Kontakte') }} +

+

+ {{ __('Pressekontakte aller Firmen über alle Portale hinweg.') }} +

+
+ +
+ @if (\Illuminate\Support\Facades\Route::has('admin.contacts.create')) + + {{ __('Neuer Kontakt') }} + + @else + + {{ __('Neuer Kontakt') }} + + @endif +
+
+ @if ($notification)
+ @class([ + 'px-4 py-3 rounded-[5px] border text-[12.5px] flex items-center gap-2', + 'bg-[color:var(--color-err-soft)] border-[color:var(--color-err)]/30 text-[color:var(--color-ink-2)]' => $notificationType === 'error', + 'bg-[color:var(--color-ok-soft)] border-[color:var(--color-ok)]/30 text-[color:var(--color-gain-deep)]' => $notificationType !== 'error', + ])> + @if ($notificationType === 'error') + + @else + + @endif {{ $notification }}
@endif - {{-- Statistiken --}} -
- -
-
- {{ __('Gesamt') }} - {{ $stats['total'] }} -
- -
-
+ {{-- ============== KPI-Reihe ============== --}} +
+ + {{ __('Pressekontakte') }} + {{ __('alle Portale') }} + + + {{ __('aktiv versorgt') }} + {{ __('mind. ein Kontakt') }} + + + {{ __('Pflegegrad') }} + {{ __('Kontakte / Firma') }} + +
- -
-
- {{ __('Firmen mit Kontakten') }} - - {{ $stats['companies_with_contacts'] }} -
- -
-
- - -
-
- {{ __('Ø pro Firma') }} - {{ number_format($stats['avg_per_company'], 1) }} - -
- -
-
-
- - {{-- Filter & Actions --}} - -
+ {{-- ============== FILTER-PANEL ============== --}} +
+
+ {{ __('Filter & Suche') }} +
+
@@ -527,49 +545,51 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone @endforeach - - @if (\Illuminate\Support\Facades\Route::has('admin.contacts.create')) - - {{ __('Neuer Kontakt') }} - - @else - - {{ __('Neuer Kontakt') }} - - @endif
- +
- -
-
- - - {{ __('Preset speichern') }} - -
- -
- - - @foreach ($presets as $preset) - - @endforeach - - {{ __('Anwenden') }} - {{ __('Als Standard') }} - {{ __('Löschen') }} -
+ {{-- ============== PRESET-PANEL ============== --}} +
+
+ {{ __('Filter-Presets') }}
- - +
+
+
+ + + {{ __('Preset speichern') }} + +
- {{-- Tabelle --}} - +
+ + + @foreach ($presets as $preset) + + @endforeach + + {{ __('Anwenden') }} + {{ __('Als Standard') }} + {{ __('Löschen') }} +
+
+ +
+
+ + {{-- ============== TABELLE ============== --}} +
+
+ {{ __('Alle Kontakte') }} + + {{ __(':count Einträge', ['count' => $contacts->count()]) }} + +
{{ __('Aktionen') }} @@ -614,43 +634,40 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone
-
- - {{ $contactDisplayName }} - +
+ {{ $contactDisplayName }}
-
- + @if ($contact->company && \Illuminate\Support\Facades\Route::has('admin.companies.show')) + class="text-[12.5px] text-[color:var(--color-hub)] underline underline-offset-2 decoration-[color:var(--color-hub)]/40 hover:decoration-[color:var(--color-hub)]"> {{ \Illuminate\Support\Str::limit($contact->company->name, 60) }} @else - + {{ \Illuminate\Support\Str::limit($contact->company?->name ?? __('Unbekannte Firma'), 80) }} - + @endif - - {{ $contact->portal?->label() ?? __('Unbekannt') }} - + {{ $contact->portal?->label() ?? __('Unbekannt') }} @@ -664,14 +681,14 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone {{ $contact->press_releases_count }} {{ __('PMs') }} @else - 0 + 0 @endif - + {{ $contact->created_at?->format('d.m.Y H:i') ?? '-' }} - + @@ -712,9 +729,14 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone @empty -
- - {{ __('Keine Kontakte gefunden') }} +
+
+ +
+
+ {{ __('Keine Kontakte gefunden') }} +
@@ -722,8 +744,8 @@ new #[Layout('components.layouts.app'), Title('Kontakte')] class extends Compone -
+
{{ $contacts->links() }}
- +
diff --git a/resources/views/livewire/admin/coupons/index.blade.php b/resources/views/livewire/admin/coupons/index.blade.php index f4aa422..fe10c38 100644 --- a/resources/views/livewire/admin/coupons/index.blade.php +++ b/resources/views/livewire/admin/coupons/index.blade.php @@ -12,32 +12,37 @@ new #[Layout('components.layouts.app'), Title('Gutscheine')] class extends Compo } }; ?> -
- -
-
- {{ __('Gutscheine') }} - - {{ __('Coupons sind in der Initialmigration vertagt (Entscheidung D-16). Eine Wiedereinführung wird später separat evaluiert – ggf. direkt über Stripe-Coupons.') }} - +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Finanzen') }} + {{ __('Vertagt') }}
- - {{ __('Vertagt') }} - +

+ {{ __('Gutscheine') }} +

+

+ {{ __('Coupons sind in der Initialmigration vertagt (Entscheidung D-16). Eine Wiedereinführung wird später separat evaluiert – ggf. direkt über Stripe-Coupons.') }} +

- +
- - {{ __('Hinweise') }} -
    +
    +
    + {{ __('Hinweise') }} +
    +
    • - + {{ __('Im neuen Stack sind keine eigenen Coupon-Tabellen vorgesehen. Sobald wieder benötigt, werden Coupons als Stripe-Coupons abgebildet.') }}
    • - + {{ __('Bestehende Legacy-Gutscheine werden nicht migriert – Bestandskunden behalten ihre Konditionen über das Grandfathering-Modell (P8.8).') }}
    - +
diff --git a/resources/views/livewire/admin/footer-codes/create.blade.php b/resources/views/livewire/admin/footer-codes/create.blade.php index 89b0f25..770aee2 100644 --- a/resources/views/livewire/admin/footer-codes/create.blade.php +++ b/resources/views/livewire/admin/footer-codes/create.blade.php @@ -75,31 +75,35 @@ new #[Layout('components.layouts.app'), Title('Footer-Code anlegen')] class exte } }; ?> -
- -
-
- {{ __('Footer-Code anlegen') }} - - {{ __('Snippet, das unter Pressemitteilungen ausgespielt wird.') }} - +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Footer-Codes') }}
- +

+ {{ __('Footer-Code anlegen') }} +

+

+ {{ __('Snippet, das unter Pressemitteilungen ausgespielt wird.') }} +

+
+ +
+ {{ __('Zurück') }}
- +
- - {{ __('Stammdaten') }} - -
+
+
+ {{ __('Stammdaten') }} +
+
- @foreach($portalOptions as $option) + @foreach ($portalOptions as $option) @endforeach @@ -136,12 +140,13 @@ new #[Layout('components.layouts.app'), Title('Footer-Code anlegen')] class exte />
-
+ - - {{ __('Sichtbarkeit') }} - -
+
+
+ {{ __('Sichtbarkeit') }} +
+
- +
- @if(! $isGlobal) - - {{ __('Kategorie-Zuordnung') }} - - {{ __('Nur Pressemitteilungen in diesen Kategorien zeigen den Footer-Code.') }} - - -
- @forelse($categoryOptions as $option) - - @empty - - {{ __('Keine Kategorien vorhanden.') }} - - @endforelse + @if (! $isGlobal) +
+
+ {{ __('Kategorie-Zuordnung') }}
- +
+

+ {{ __('Nur Pressemitteilungen in diesen Kategorien zeigen den Footer-Code.') }} +

+ +
+ @forelse ($categoryOptions as $option) + + @empty +

+ {{ __('Keine Kategorien vorhanden.') }} +

+ @endforelse +
+
+
@endif - -
- +
+
+ {{ __('Abbrechen') }} {{ __('Speichern') }}
- +
diff --git a/resources/views/livewire/admin/footer-codes/edit.blade.php b/resources/views/livewire/admin/footer-codes/edit.blade.php index 1b0b4fc..3502e22 100644 --- a/resources/views/livewire/admin/footer-codes/edit.blade.php +++ b/resources/views/livewire/admin/footer-codes/edit.blade.php @@ -106,29 +106,42 @@ new #[Layout('components.layouts.app'), Title('Footer-Code bearbeiten')] class e } }; ?> -
- -
-
- {{ __('Footer-Code bearbeiten') }} - #{{ $id }} – {{ $title }} +
+ {{-- ============== PAGE HEADER ============== --}} +
+
+
+ {{ __('Admin Backend') }} + {{ __('Administration · Footer-Codes') }} + ID #{{ $id }} + @if ($isGlobal) + {{ __('Global') }} + @endif + @if ($isActive) + {{ __('Aktiv') }} + @else + {{ __('Inaktiv') }} + @endif
- +

+ {{ __('Footer-Code bearbeiten') }} +

+

{{ $title }}

+
+ +
+ {{ __('Zurück') }}
- +
- - {{ __('Stammdaten') }} - -
+
+
+ {{ __('Stammdaten') }} +
+
- @foreach($portalOptions as $option) + @foreach ($portalOptions as $option) @endforeach @@ -159,12 +172,13 @@ new #[Layout('components.layouts.app'), Title('Footer-Code bearbeiten')] class e />
-
+ - - {{ __('Sichtbarkeit') }} - -
+
+
+ {{ __('Sichtbarkeit') }} +
+
- +
- @if(! $isGlobal) - - {{ __('Kategorie-Zuordnung') }} - -
- @forelse($categoryOptions as $option) -