12-05-2026 Frontend dev
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-12 18:32:33 +02:00
parent 405df0a122
commit 5b8bdf4182
779 changed files with 480564 additions and 6241 deletions

View file

@ -0,0 +1,343 @@
# Backend-Status: presseportale.test
**Projekt:** BusinessPortal24 → Laravel 12 Migration
**Domain:** presseportale.test
**Stand:** 23. Januar 2026 nach Server-Neustart
**Status:** 🟡 Admin-UI-Gerüst vorhanden, Routing auf bestehende Volt-Komponenten konsolidiert
---
## ✅ Weitgehend implementiert (Gerüst)
### 📐 Struktur & Navigation
#### 1. Sidebar-Navigation (`components/layouts/app/sidebar.blade.php`)
- ✅ Dashboard
- ✅ Content-Bereich (Pressemitteilungen, Kategorien)
- ✅ CRM-Bereich (Firmen, Kontakte)
- ✅ Billing-Bereich (Rechnungen, Zahlungen, Gutscheine)
- ✅ Administration-Bereich (Benutzer, Rollen & Rechte)
- ✅ System-Bereich (Scheduler, Newsletter, Einstellungen)
#### 2. Routing (`routes/admin.php`)
- ✅ **24 Admin-Routes** definiert (nur bestehende Volt-Ziele)
- ✅ Alle aktiven Bereiche technisch konsistent
- ✅ RESTful Namenskonvention
---
## 📄 Erstellte Views (17 Admin-Views)
```
resources/views/admin/
├── dashboard.blade.php ✅ (bereits vorhanden)
├── README.md ✅
├── FLUX_COMPONENTS.md ✅
├── categories/
│ └── index.blade.php ✅
├── companies/
│ ├── index.blade.php ✅
│ ├── create.blade.php ✅
│ ├── show.blade.php ✅
│ └── edit.blade.php ✅
├── contacts/
│ └── index.blade.php ✅
├── coupons/
│ └── index.blade.php ✅
├── invoices/
│ └── index.blade.php ✅
├── payments/
│ └── index.blade.php ✅
├── press-releases/
│ ├── index.blade.php ✅
│ ├── create.blade.php ✅
│ ├── show.blade.php ✅
│ └── edit.blade.php ✅
└── roles/
├── index.blade.php ✅
├── create.blade.php ✅
└── edit.blade.php ✅
```
---
## 🎨 Livewire-Komponenten (16 Komponenten)
```
resources/views/livewire/admin/
├── users.blade.php ✅ (bereits vorhanden)
├── users/
│ └── table.blade.php ✅ (bereits vorhanden)
├── categories/
│ └── index.blade.php ✅
├── companies/
│ ├── index.blade.php ✅
│ ├── create.blade.php ✅
│ ├── show.blade.php ✅
│ └── edit.blade.php ✅
├── contacts/
│ └── index.blade.php ✅
├── coupons/
│ └── index.blade.php ✅
├── invoices/
│ └── index.blade.php ✅
├── payments/
│ └── index.blade.php ✅
├── press-releases/
│ ├── index.blade.php ✅
│ ├── create.blade.php ✅
│ ├── show.blade.php ✅
│ └── edit.blade.php ✅
└── roles/
├── index.blade.php ✅
├── create.blade.php ✅
└── edit.blade.php ✅
```
---
## 🎯 Features der erstellten Views
### 📰 Pressemitteilungen (komplett)
- ✅ **Index:** Volltext-Suche, Status-/Sprachfilter, Statistiken, Sortierung
- ✅ **Create:** Vollständiges Formular (Titel, Content, Kategorien, SEO, Medien)
- ✅ **Show:** Detailansicht mit Metadaten, verwandten Artikeln
- ✅ **Edit:** Bearbeitungsmaske mit allen Feldern
**Features:**
- Multi-Kategorie-Auswahl (Checkboxen)
- Image-Upload mit Vorschau
- SEO-Felder (Meta Title, Description, Keywords)
- Status-Verwaltung (Draft, Published, Archived)
- Veröffentlichungsdatum
---
### 🏢 Firmen (komplett)
- ✅ **Index:** Suche, Aktiv/Inaktiv-Filter, Statistiken
- ✅ **Create:** Firmendaten, Adresse, rechtliche Infos, Logo-Upload
- ✅ **Show:** Übersicht mit Kontakten, PMs, Rechnungen
- ✅ **Edit:** Vollständige Bearbeitungsmaske
**Features:**
- Logo-Upload mit Vorschau
- Adress-Verwaltung (Straße, PLZ, Stadt, Land)
- Rechtliche Daten (Steuernummer, Handelsregister)
- Status-Management (Verifiziert, Aktiv/Inaktiv)
- Verknüpfung zu Kontakten und PMs
---
### 💳 Rechnungen
- ✅ **Index:** Status-Filter, Finanz-Statistiken, Mahnwesen
**Features:**
- Überfälligkeits-Anzeige (farblich hervorgehoben)
- PDF-Download-Button (vorbereitet)
- Mahnung-Button für überfällige Rechnungen
- Gesamtumsatz, Bezahlt, Offen-Statistiken
---
### 💰 Zahlungen
- ✅ **Index:** Status-/Methoden-Filter, Transaktions-IDs, Statistiken
**Features:**
- Stripe/Rechnung-Unterscheidung
- Status-Badges (Erfolgreich, Ausstehend, Fehlgeschlagen)
- Transaktions-ID-Anzeige
- Retry-Button für fehlgeschlagene Zahlungen
---
### 👥 Kontakte
- ✅ **Index:** Suche, Firmen-Filter, Kontaktdetails
**Features:**
- Zuordnung zu Firmen
- Mailto-Links
- Position/Verantwortlichkeit
- Statistiken (Durchschnitt pro Firma)
---
### 🏷️ Kategorien
- ✅ **Index:** Grid-Ansicht, Mehrsprachigkeit (DE/EN)
**Features:**
- Karten-Layout statt Tabelle
- Zuordnung zu Pressemitteilungen
- Slug-Anzeige
- Dropdown-Menü mit Aktionen
---
### 🎟️ Gutscheine
- ✅ **Index:** Status-Filter, Verwendungsstatistiken
**Features:**
- Verwendungsfortschritt (Balken)
- Prozent- vs. Festbetrag-Rabatte
- Gültigkeitsprüfung
- Copy-Button für Code
---
### 🛡️ Rollen & Rechte (komplett)
- ✅ **Index:** Tab-basiert (Rollen/Berechtigungen)
- ✅ **Create:** Rollen-Erstellung mit Berechtigungsauswahl
- ✅ **Edit:** Bearbeitung mit System-Rollen-Warnung
**Features:**
- Gruppierte Berechtigungen
- Farb-Badges für Rollen
- Benutzer-/Berechtigungszähler
- Multi-Select für Permissions
---
## 🎨 Design-System
### Flux UI v2 (korrekte Syntax)
- ✅ `<flux:table.columns>` / `<flux:table.column>`
- ✅ `<flux:table.rows>` / `<flux:table.row>` / `<flux:table.cell>`
- ✅ Alle Komponenten dokumentiert in `FLUX_COMPONENTS.md`
### Konsistentes Design
- ✅ Statistik-Cards überall
- ✅ Einheitliche Filter-Bars
- ✅ Empty States mit Icons
- ✅ Status-Badges mit Farben
- ✅ Responsive Grid-Layouts
- ✅ Dark Mode Support
---
## 📊 Statistiken
### Dateien erstellt: **33**
- 17 Admin-Views
- 16 Livewire-Komponenten
### Bereiche abgedeckt: **7**
1. ✅ Content Management (Press Releases, Categories)
2. ✅ CRM (Companies, Contacts)
3. ✅ Billing (Invoices, Payments, Coupons)
4. ✅ Administration (Users, Roles)
5. ✅ Dashboard
6. ⏳ System (Scheduler, Newsletter, Settings) - TODO
7. ⏳ User Settings - bereits vorhanden
### Routes definiert: **24**
- Alle aktiven Bereiche konsistent geroutet
---
## ⏳ Noch zu erstellen (optional)
### System-Bereich
- ⏳ Scheduler Jobs Index
- ⏳ Newsletter Management (Index, Subscribers, Campaigns)
- ⏳ System-Einstellungen
### Detail-Views für einige Bereiche
- ⏳ Invoice Show (Detail mit PDF)
- ⏳ Payment Show (Transaktionsdetails)
- ⏳ Contact Create/Edit (Formular)
- ⏳ Category Create/Edit (Formular)
- ⏳ Coupon Create/Edit (Formular)
### Nicht aktive Bereiche (noch ohne Route)
- ⏳ Kategorien: Create/Edit
- ⏳ Kontakte: Create/Edit
- ⏳ Rechnungen: Show
- ⏳ Zahlungen: Show
- ⏳ Gutscheine: Create/Edit
- ⏳ Benutzer: Create/Edit
- ⏳ System: Scheduler, Newsletter, Einstellungen
---
## 🔄 Nächste Schritte
### Option 1: Migrations-Projekt starten 🔴 (Empfohlen)
Beginne mit der eigentlichen Migration gemäß:
- `/var/www/html/_businessportal24.com/dev/migration/CHECKLIST.md`
- Phase 1: Laravel-Setup, Packages, DB-Verbindung
- Phase 2: Domain Models erstellen
- Phase 3: Services implementieren
### Option 2: Fehlende System-Views erstellen 🟡
- Scheduler Jobs Management
- Newsletter Management
- System-Einstellungen
### Option 3: Backend testen 🟢
- Dev-Server starten (`npm run dev`)
- Backend öffnen (`http://presseportale.test/admin/press-releases`)
- UI und Navigation prüfen
### Option 4: Dummy-Daten verfeinern 🟢
- Mehr realistische Test-Daten
- Pagination implementieren
- Filter-Logik verbessern
---
## 🧪 Testen des Backends
```bash
# Dev-Server starten (Terminal 1)
npm run dev:portal
# Laravel-Server starten (Terminal 2)
php artisan serve
# Backend öffnen
http://presseportale.test/admin/press-releases
http://presseportale.test/admin/companies
http://presseportale.test/admin/invoices
http://presseportale.test/admin/contacts
http://presseportale.test/admin/payments
http://presseportale.test/admin/categories
http://presseportale.test/admin/coupons
http://presseportale.test/admin/roles
```
---
## 📚 Dokumentation
### Erstellt
- ✅ `resources/views/admin/README.md` - Ordnerübersicht
- ✅ `resources/views/admin/FLUX_COMPONENTS.md` - Flux v2 Referenz
- ✅ `routes/ADMIN_ROUTES.md` - Route-Dokumentation
- ✅ `resources/views/admin/BACKEND_STATUS.md` - Dieser Status
### Migrations-Dokumentation
- `/var/www/html/_businessportal24.com/dev/migration/`
- `CHECKLIST.md` - 127 Migrations-Aufgaben
- `PROGRESS.md` - Verlaufsprotokoll
- `IMPLEMENTATION.md` - Schritt-für-Schritt
- `API-MIGRATION.md` - API-Details
- `DATA-MIGRATION.md` - Datenbank-Migration
- `TESTING.md` - Test-Strategie
---
## 🎉 Meilenstein erreicht!
**Backend-Struktur für presseportale.test ist als Gerüst weitgehend vorbereitet.**
- ✅ 7 Hauptbereiche mit Navigation
- ✅ 24 Routes definiert (konsistent gemappt)
- ✅ 33 Views/Komponenten erstellt
- ✅ Flux UI v2 korrekte Syntax
- ✅ Responsive & Dark Mode
- ✅ Vorbereitet für echte Daten
**Bereit für die nächste Phase: Migration der Symfony-Daten und Model-Implementation!**
---
**Letztes Update:** 23. Januar 2026 (nach Server-Neustart)

View file

@ -0,0 +1,516 @@
# Flux UI v2 - Komponenten-Referenz
**Projekt:** presseportale.test Backend
**Flux Version:** 2.x
**Stand:** 23. Januar 2026
---
## ⚠️ Korrekte Flux v2 Syntax
### ✅ Offizielle Syntax (v2.x)
**Quelle:** [Flux UI Table Documentation](https://fluxui.dev/components/table)
```blade
<flux:table>
<flux:table.columns>
<flux:table.column>Name</flux:table.column>
</flux:table.columns>
<flux:table.rows>
<flux:table.row>
<flux:table.cell>Value</flux:table.cell>
</flux:table.row>
</flux:table.rows>
</flux:table>
```
**Wichtig:** Flux nutzt **Punktnotation** (`.`) für verschachtelte Komponenten!
---
## 📋 Tabellen (Tables)
### Einfache Tabelle
```blade
<flux:table>
<flux:table.columns>
<flux:table.column>Name</flux:table.column>
<flux:table.column>Email</flux:table.column>
<flux:table.column>Status</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@foreach($users as $user)
<flux:table.row :key="$user->id">
<flux:table.cell>{{ $user->name }}</flux:table.cell>
<flux:table.cell>{{ $user->email }}</flux:table.cell>
<flux:table.cell>
<flux:badge color="green">Active</flux:badge>
</flux:table.cell>
</flux:table.row>
@endforeach
</flux:table.rows>
</flux:table>
```
### Tabelle mit Empty State
```blade
<flux:table>
<flux:table.columns>
<flux:table.column>Spalte 1</flux:table.column>
<flux:table.column>Spalte 2</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@forelse($items as $item)
<flux:table.row :key="$item->id">
<flux:table.cell>{{ $item->value }}</flux:table.cell>
</flux:table.row>
@empty
<flux:table.row>
<flux:table.cell colspan="2">
<div class="flex flex-col items-center justify-center py-12">
<flux:icon.inbox class="size-12 text-zinc-400" />
<flux:text class="mt-4 text-zinc-500">Keine Daten gefunden</flux:text>
</div>
</flux:table.cell>
</flux:table.row>
@endforelse
</flux:table.rows>
</flux:table>
```
---
## 🎨 Cards
### Einfache Card
```blade
<flux:card>
<flux:heading>Überschrift</flux:heading>
<flux:text>Inhalt der Card</flux:text>
</flux:card>
```
### Card mit statistiken
```blade
<flux:card>
<div class="flex items-center justify-between">
<div>
<flux:text class="text-sm text-zinc-500">Label</flux:text>
<flux:text size="xl" weight="bold">1,234</flux:text>
</div>
<flux:icon.chart-bar class="size-8 text-blue-500" />
</div>
</flux:card>
```
---
## 🔘 Buttons
### Standard Button
```blade
<flux:button>Klick mich</flux:button>
```
### Button mit Icon
```blade
<flux:button icon="plus">Neu erstellen</flux:button>
<flux:button icon-trailing="arrow-right">Weiter</flux:button>
```
### Button-Varianten
```blade
<flux:button variant="primary">Primary</flux:button>
<flux:button variant="ghost">Ghost</flux:button>
<flux:button variant="danger">Danger</flux:button>
```
### Button-Größen
```blade
<flux:button size="sm">Klein</flux:button>
<flux:button size="md">Mittel</flux:button>
<flux:button size="lg">Groß</flux:button>
```
### Link-Button (Livewire Navigate)
```blade
<flux:button href="{{ route('admin.users') }}" wire:navigate>
Benutzer
</flux:button>
```
---
## 🏷️ Badges
### Standard Badge
```blade
<flux:badge>Standard</flux:badge>
```
### Badge mit Farben
```blade
<flux:badge color="green">Erfolg</flux:badge>
<flux:badge color="red">Fehler</flux:badge>
<flux:badge color="yellow">Warnung</flux:badge>
<flux:badge color="blue">Info</flux:badge>
<flux:badge color="gray">Neutral</flux:badge>
<flux:badge color="zinc">Default</flux:badge>
```
### Badge mit Icon
```blade
<flux:badge color="green" icon="check">Aktiv</flux:badge>
<flux:badge color="red" icon="x-mark">Inaktiv</flux:badge>
```
### Badge-Größen
```blade
<flux:badge size="sm">Klein</flux:badge>
<flux:badge size="md">Mittel</flux:badge>
<flux:badge size="lg">Groß</flux:badge>
```
---
## 📝 Formulare
### Input
```blade
<flux:input
wire:model="name"
label="Name"
placeholder="Geben Sie Ihren Namen ein"
icon="user"
/>
```
### Input mit Fehler
```blade
<flux:input
wire:model="email"
label="E-Mail"
:error="$errors->first('email')"
/>
```
### Select
```blade
<flux:select wire:model="status" label="Status">
<option value="">Bitte wählen...</option>
<option value="active">Aktiv</option>
<option value="inactive">Inaktiv</option>
</flux:select>
```
### Textarea
```blade
<flux:textarea
wire:model="description"
label="Beschreibung"
rows="5"
/>
```
### Checkbox
```blade
<flux:checkbox wire:model="terms">
Ich akzeptiere die AGB
</flux:checkbox>
```
### Radio
```blade
<flux:radio wire:model="type" value="option1">Option 1</flux:radio>
<flux:radio wire:model="type" value="option2">Option 2</flux:radio>
```
---
## 🔍 Suche & Filter
### Suchfeld
```blade
<flux:input
wire:model.live.debounce.300ms="search"
placeholder="Suchen..."
icon="magnifying-glass"
/>
```
### Filter-Kombination
```blade
<div class="flex gap-4">
<flux:input
wire:model.live.debounce.300ms="search"
placeholder="Suchen..."
icon="magnifying-glass"
class="flex-1"
/>
<flux:select wire:model.live="status" class="w-40">
<option value="all">Alle Status</option>
<option value="active">Aktiv</option>
<option value="inactive">Inaktiv</option>
</flux:select>
</div>
```
---
## 🎭 Icons (Hero Icons)
### Icon-Verwendung
```blade
<flux:icon.user class="size-6" />
<flux:icon.check-circle class="size-8 text-green-500" />
<flux:icon.x-mark class="size-4" />
```
### Häufig verwendete Icons
```blade
{{-- Allgemein --}}
<flux:icon.home />
<flux:icon.cog />
<flux:icon.bell />
{{-- Benutzer --}}
<flux:icon.user />
<flux:icon.user-group />
<flux:icon.users />
{{-- Content --}}
<flux:icon.newspaper />
<flux:icon.document-text />
<flux:icon.folder />
{{-- Business --}}
<flux:icon.building-office />
<flux:icon.credit-card />
<flux:icon.chart-bar />
{{-- Actions --}}
<flux:icon.pencil />
<flux:icon.trash />
<flux:icon.eye />
<flux:icon.plus />
{{-- Status --}}
<flux:icon.check-circle />
<flux:icon.x-circle />
<flux:icon.exclamation-triangle />
{{-- Navigation --}}
<flux:icon.arrow-right />
<flux:icon.chevron-down />
<flux:icon.bars-3 />
```
Vollständige Liste: https://heroicons.com
---
## 📦 Modal / Dialogs
### Einfaches Modal
```blade
<flux:modal name="confirm-delete" variant="danger">
<flux:modal.content>
<flux:heading>Bestätigung</flux:heading>
<flux:text>Möchten Sie diesen Eintrag wirklich löschen?</flux:text>
</flux:modal.content>
<flux:modal.footer>
<flux:button variant="ghost" wire:click="$set('showModal', false)">
Abbrechen
</flux:button>
<flux:button variant="danger" wire:click="delete">
Löschen
</flux:button>
</flux:modal.footer>
</flux:modal>
```
---
## 🎨 Layout-Komponenten
### Main Container
```blade
<flux:main>
<flux:heading size="xl">Seitentitel</flux:heading>
{{-- Inhalt --}}
</flux:main>
```
### Grid Layout
```blade
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<flux:card>...</flux:card>
<flux:card>...</flux:card>
<flux:card>...</flux:card>
<flux:card>...</flux:card>
</div>
```
### Spacer
```blade
<flux:spacer />
```
---
## 📊 Statistik-Cards (Beispiel)
```blade
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<flux:card>
<div class="flex items-center justify-between">
<div>
<flux:text class="text-sm text-zinc-500 dark:text-zinc-400">
{{ __('Gesamt') }}
</flux:text>
<flux:text size="xl" weight="bold">1,234</flux:text>
</div>
<flux:icon.users class="size-8 text-blue-500" />
</div>
</flux:card>
<flux:card>
<div class="flex items-center justify-between">
<div>
<flux:text class="text-sm text-zinc-500 dark:text-zinc-400">
{{ __('Aktiv') }}
</flux:text>
<flux:text size="xl" weight="bold">890</flux:text>
</div>
<flux:icon.check-circle class="size-8 text-green-500" />
</div>
</flux:card>
</div>
```
---
## 🎯 Best Practices
### 1. Immer mit Card-Wrapper
```blade
<flux:card class="overflow-hidden">
<flux:table>
{{-- Tabellen-Inhalt --}}
</flux:table>
</flux:card>
```
### 2. Empty States mit Icons
```blade
@empty
<flux:tr>
<flux:td colspan="7">
<div class="flex flex-col items-center justify-center py-12">
<flux:icon.inbox class="size-12 text-zinc-400 dark:text-zinc-600" />
<flux:text class="mt-4 text-zinc-500">
{{ __('Keine Einträge gefunden') }}
</flux:text>
</div>
</flux:td>
</flux:tr>
@endforelse
```
### 3. Responsive Actions
```blade
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="flex flex-1 gap-4">
{{-- Filter --}}
</div>
<flux:button icon="plus">Neu</flux:button>
</div>
```
### 4. Livewire Wire:navigate
```blade
<flux:button href="{{ route('admin.users') }}" wire:navigate>
Benutzer
</flux:button>
```
### 5. Dark Mode Support
Flux unterstützt automatisch Dark Mode mit `dark:` Klassen:
```blade
<div class="bg-white dark:bg-zinc-800">
<flux:text class="text-zinc-900 dark:text-zinc-100">Text</flux:text>
</div>
```
---
## 🔗 Ressourcen
- **Flux UI Docs:** https://fluxui.dev/docs
- **Hero Icons:** https://heroicons.com
- **Tailwind CSS:** https://tailwindcss.com/docs
- **Livewire:** https://livewire.laravel.com
---
## ✅ Korrektur-Checkliste
Beim Erstellen neuer Views prüfen:
- [ ] `<flux:table>` als Wrapper
- [ ] `<flux:table.columns>` für Header
- [ ] `<flux:table.column>` für einzelne Spalten
- [ ] `<flux:table.rows>` für Body
- [ ] `<flux:table.row :key="...">` für Zeilen (mit key!)
- [ ] `<flux:table.cell>` für Zellen
- [ ] Icons mit `flux:icon.{name}` Syntax
- [ ] Dark Mode Klassen wo nötig
- [ ] Responsive Klassen (`sm:`, `lg:`)
- [ ] `wire:navigate` bei internen Links
---
**Letztes Update:** 23. Januar 2026
**Version:** Flux UI v2.x
**Status:** ✅ Alle Views korrigiert

View file

@ -0,0 +1,193 @@
# Admin Backend - Strukturübersicht
## 📁 Ordnerstruktur
```
resources/views/admin/
├── README.md (diese Datei)
├── dashboard.blade.php (✅ vorhanden)
├── press-releases/
│ └── index.blade.php (✅ erstellt)
├── companies/
│ └── index.blade.php (✅ erstellt)
├── contacts/
│ └── index.blade.php (⏳ TODO)
├── invoices/
│ └── index.blade.php (✅ erstellt)
├── payments/
│ └── index.blade.php (⏳ TODO)
├── coupons/
│ └── index.blade.php (⏳ TODO)
├── users/
│ └── index.blade.php (⏳ TODO)
├── roles/
│ └── index.blade.php (⏳ TODO)
├── categories/
│ └── index.blade.php (⏳ TODO)
├── scheduler/
│ └── index.blade.php (⏳ TODO)
└── newsletter/
└── index.blade.php (⏳ TODO)
```
## 🎯 Migrations-Projekt Kontext
Diese Backend-Struktur ist Teil der **BusinessPortal24 → Laravel 12 Migration**.
**Migrations-Dokumentation:** `/var/www/html/_businessportal24.com/dev/migration/`
### Wichtige Dokumente:
- `CHECKLIST.md` - Alle Aufgaben
- `PROGRESS.md` - Verlaufsprotokoll
- `IMPLEMENTATION.md` - Schritt-für-Schritt Anleitung
- `API-MIGRATION.md` - API-Details
- `DATA-MIGRATION.md` - Daten-Migration
## 📋 Aktueller Stand
### ✅ Erstellt (23.01.2026)
1. **Navigation (Sidebar)**
- Datei: `resources/views/components/layouts/app/sidebar.blade.php`
- Gruppen: Content, CRM, Billing, Administration, System
- Icons: Hero Icons
2. **Admin-Views**
- Press Releases Index
- Companies Index
- Invoices Index
3. **Livewire-Komponenten**
- `livewire/admin/press-releases/index.blade.php`
- `livewire/admin/companies/index.blade.php`
- `livewire/admin/invoices/index.blade.php`
### ⏳ Nächste Schritte
1. **Routes erstellen** (routes/web.php)
```php
Route::prefix('admin')->middleware('auth')->group(function () {
Route::get('/press-releases', ...)->name('admin.press-releases.index');
Route::get('/companies', ...)->name('admin.companies.index');
Route::get('/invoices', ...)->name('admin.invoices.index');
// ... weitere Routes
});
```
2. **Weitere Index-Views erstellen**
- Contacts
- Payments
- Coupons
- Categories
- Users (erweitern)
- Roles & Permissions
3. **CRUD-Views erstellen**
- create.blade.php
- edit.blade.php
- show.blade.php
4. **Models & Services implementieren**
- Nach DATA-MIGRATION.md
- Domain-Struktur: `app/Domain/{PressRelease,Company,Billing,...}/Models/`
## 🎨 Design-System
### FluxUI Komponenten
Alle Views nutzen **FluxUI** Komponenten:
- `<flux:card>` - Container
- `<flux:table>` - Tabellen
- `<flux:button>` - Buttons
- `<flux:badge>` - Status-Badges
- `<flux:input>` - Eingabefelder
- `<flux:select>` - Dropdowns
### Icons (Hero Icons)
Verwendete Icons:
- `newspaper` - Pressemitteilungen
- `building-office` - Firmen
- `document-text` - Rechnungen
- `user-group` - Kontakte/Users
- `credit-card` - Zahlungen
- `folder` - Kategorien
## 💾 Dummy-Daten
**Wichtig:** Alle aktuellen Komponenten verwenden Dummy-Daten (`collect([...])`).
Nach der Migration werden diese ersetzt durch:
```php
use App\Domain\PressRelease\Models\PressRelease;
$pressReleases = PressRelease::query()
->with(['company', 'category', 'images'])
->when($this->search, fn($q) => $q->where('title', 'like', "%{$this->search}%"))
->paginate(20);
```
## 🔄 Migration-Workflow
1. **Phase 1:** Backend-Struktur anlegen ✅ **(AKTUELL)**
2. Phase 2: Laravel Models erstellen
3. Phase 3: Services implementieren
4. Phase 4: Dummy-Daten durch echte Models ersetzen
5. Phase 5: API-Integration
6. Phase 6: Daten-Migration durchführen
7. Phase 7: Testing
## 📝 Namenskonventionen
### Routes
```
admin.{resource}.index - Liste
admin.{resource}.create - Formular (neu)
admin.{resource}.store - Speichern (POST)
admin.{resource}.show - Details
admin.{resource}.edit - Formular (bearbeiten)
admin.{resource}.update - Aktualisieren (PUT)
admin.{resource}.destroy - Löschen (DELETE)
```
### Livewire-Komponenten
```
livewire/admin/{resource}/index.blade.php
livewire/admin/{resource}/create.blade.php
livewire/admin/{resource}/edit.blade.php
```
### Admin-Views
```
admin/{resource}/index.blade.php
admin/{resource}/create.blade.php
admin/{resource}/edit.blade.php
admin/{resource}/show.blade.php
```
## 🚀 Development-Server starten
```bash
# In Terminal 1: Laravel
php artisan serve
# In Terminal 2: Vite
npm run dev
# Backend öffnen:
http://presseportale.test/admin/press-releases
```
## 📚 Weitere Ressourcen
- **FluxUI Docs:** https://fluxui.dev/docs
- **Livewire Volt:** https://livewire.laravel.com/docs/volt
- **Laravel 12:** https://laravel.com/docs/12.x
- **Hero Icons:** https://heroicons.com
---
**Stand:** 23. Januar 2026
**Status:** Backend-Struktur Initial Setup ✅
**Nächster Schritt:** Routes erstellen und weitere Index-Views implementieren

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Kategorien') }}</flux:heading>
@livewire('admin.categories.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.companies.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Neue Firma') }}</flux:heading>
@livewire('admin.companies.create')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.companies.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Firma bearbeiten') }}</flux:heading>
@livewire('admin.companies.edit', ['companyId' => request()->route('company')])
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Firmen') }}</flux:heading>
@livewire('admin.companies.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,11 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.companies.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
@livewire('admin.companies.show', ['companyId' => request()->route('company')])
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Kontakte') }}</flux:heading>
@livewire('admin.contacts.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Gutscheine') }}</flux:heading>
@livewire('admin.coupons.index')
</flux:main>
</x-layouts.app>

View file

@ -1,18 +1,110 @@
<x-layouts.app title="Dashboard">
<div class="flex h-full w-full flex-1 flex-col gap-4 rounded-xl">
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700 p-4">
<livewire:notifications />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
<div class="space-y-6">
{{-- Statistik-Karten --}}
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-5">
<a href="{{ route('admin.press-releases.index') }}" wire:navigate class="block">
<div class="rounded-xl border border-zinc-200 bg-white p-4 transition hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900">
<p class="text-xs text-zinc-500">{{ __('PMs gesamt') }}</p>
<p class="mt-1 text-2xl font-bold">{{ number_format($stats['press_releases']['total']) }}</p>
<div class="mt-2 flex gap-2 text-xs text-zinc-400">
<span class="text-green-600">{{ $stats['press_releases']['published'] }} pub</span>
<span class="text-yellow-600">{{ $stats['press_releases']['review'] }} prüf</span>
<span>{{ $stats['press_releases']['draft'] }} entwurf</span>
</div>
</div>
</a>
<a href="{{ route('admin.companies.index') }}" wire:navigate class="block">
<div class="rounded-xl border border-zinc-200 bg-white p-4 transition hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900">
<p class="text-xs text-zinc-500">{{ __('Firmen') }}</p>
<p class="mt-1 text-2xl font-bold">{{ number_format($stats['companies']) }}</p>
</div>
</a>
<a href="{{ route('admin.contacts.index') }}" wire:navigate class="block">
<div class="rounded-xl border border-zinc-200 bg-white p-4 transition hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900">
<p class="text-xs text-zinc-500">{{ __('Kontakte') }}</p>
<p class="mt-1 text-2xl font-bold">{{ number_format($stats['contacts']) }}</p>
</div>
</a>
<a href="{{ route('admin.users.index') }}" wire:navigate class="block">
<div class="rounded-xl border border-zinc-200 bg-white p-4 transition hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900">
<p class="text-xs text-zinc-500">{{ __('Benutzer') }}</p>
<p class="mt-1 text-2xl font-bold">{{ number_format($stats['users']) }}</p>
</div>
</a>
<div class="rounded-xl border border-zinc-200 bg-white p-4 dark:border-zinc-700 dark:bg-zinc-900">
<p class="text-xs text-zinc-500">{{ __('Newsletter') }}</p>
<p class="mt-1 text-2xl font-bold">{{ number_format($stats['newsletter']) }}</p>
<p class="mt-2 text-xs text-zinc-400">{{ __('bestätigt') }}</p>
</div>
</div>
<div class="relative h-full flex-1 overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
<div class="grid gap-6 lg:grid-cols-[1fr,360px]">
{{-- Letzte Pressemitteilungen --}}
<div class="overflow-hidden rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900">
<div class="flex items-center justify-between border-b border-zinc-200 px-4 py-3 dark:border-zinc-700">
<h2 class="font-semibold">{{ __('Letzte Pressemitteilungen') }}</h2>
<a href="{{ route('admin.press-releases.index') }}" wire:navigate class="text-sm text-blue-600 hover:underline dark:text-blue-400">{{ __('Alle anzeigen') }}</a>
</div>
<div class="divide-y divide-zinc-100 dark:divide-zinc-800">
@forelse($recentPRs as $pr)
<a href="{{ route('admin.press-releases.show', $pr->id) }}" wire:navigate
class="flex items-center justify-between gap-3 px-4 py-3 transition hover:bg-zinc-50 dark:hover:bg-zinc-800">
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium">{{ $pr->title }}</p>
<p class="text-xs text-zinc-500">{{ $pr->company?->name ?? '' }} · {{ $pr->created_at->format('d.m.Y') }}</p>
</div>
<span class="shrink-0 rounded-full px-2 py-0.5 text-xs font-medium {{ match($pr->status->value) {
'published' => 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',
'review' => 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400',
'rejected' => 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',
'archived' => 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
default => 'bg-zinc-100 text-zinc-600 dark:bg-zinc-700 dark:text-zinc-300',
} }}">
{{ $pr->status->label() }}
</span>
</a>
@empty
<p class="px-4 py-6 text-center text-sm text-zinc-500">{{ __('Noch keine Pressemitteilungen.') }}</p>
@endforelse
</div>
</div>
{{-- Warteschlange Prüfung --}}
<div class="overflow-hidden rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900">
<div class="flex items-center justify-between border-b border-zinc-200 px-4 py-3 dark:border-zinc-700">
<h2 class="font-semibold">{{ __('Zur Prüfung') }}</h2>
@if($stats['press_releases']['review'] > 0)
<span class="rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400">
{{ $stats['press_releases']['review'] }}
</span>
@endif
</div>
<div class="divide-y divide-zinc-100 dark:divide-zinc-800">
@forelse($pendingReviews as $pr)
<a href="{{ route('admin.press-releases.show', $pr->id) }}" wire:navigate
class="block px-4 py-3 transition hover:bg-zinc-50 dark:hover:bg-zinc-800">
<p class="truncate text-sm font-medium">{{ $pr->title }}</p>
<p class="text-xs text-zinc-500">
{{ $pr->company?->name ?? '' }} · {{ $pr->portal->label() }} · {{ $pr->created_at->format('d.m.Y') }}
</p>
</a>
@empty
<p class="px-4 py-6 text-center text-sm text-zinc-500">{{ __('Keine PMs in der Prüfwarteschlange.') }}</p>
@endforelse
</div>
@if($stats['press_releases']['review'] > count($pendingReviews))
<div class="border-t border-zinc-100 px-4 py-2 dark:border-zinc-800">
<a href="{{ route('admin.press-releases.index', ['statusFilter' => 'review']) }}" wire:navigate
class="text-xs text-blue-600 hover:underline dark:text-blue-400">
+ {{ $stats['press_releases']['review'] - count($pendingReviews) }} {{ __('weitere') }}
</a>
</div>
@endif
</div>
</div>
</div>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Rechnungen') }}</flux:heading>
@livewire('admin.invoices.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Zahlungen') }}</flux:heading>
@livewire('admin.payments.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.press-releases.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Neue Pressemitteilung') }}</flux:heading>
@livewire('admin.press-releases.create')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.press-releases.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Pressemitteilung bearbeiten') }}</flux:heading>
@livewire('admin.press-releases.edit', ['pressReleaseId' => request()->route('pressRelease')])
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Pressemitteilungen') }}</flux:heading>
@livewire('admin.press-releases.index')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,11 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.press-releases.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
@livewire('admin.press-releases.show', ['pressReleaseId' => request()->route('pressRelease')])
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.roles.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Neue Rolle erstellen') }}</flux:heading>
@livewire('admin.roles.create')
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,13 @@
<x-layouts.app>
<flux:main>
<div class="mb-6">
<flux:button variant="ghost" icon="arrow-left" href="{{ route('admin.roles.index') }}" wire:navigate>
{{ __('Zurück zur Übersicht') }}
</flux:button>
</div>
<flux:heading size="xl" class="mb-6">{{ __('Rolle bearbeiten') }}</flux:heading>
@livewire('admin.roles.edit', ['roleId' => request()->route('role')])
</flux:main>
</x-layouts.app>

View file

@ -0,0 +1,7 @@
<x-layouts.app>
<flux:main>
<flux:heading size="xl" class="mb-6">{{ __('Rollen & Rechte') }}</flux:heading>
@livewire('admin.roles.index')
</flux:main>
</x-layouts.app>