171 lines
5.2 KiB
Markdown
171 lines
5.2 KiB
Markdown
# 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
|