590 lines
12 KiB
Markdown
590 lines
12 KiB
Markdown
# Migration der Presswave Landingpage zu Laravel/Livewire
|
|
|
|
Dokumentation der Konvertierung der React/TypeScript Presswave-Landingpage zu Laravel Blade + Livewire für Business Portal 24.
|
|
|
|
**Datum:** 15. Oktober 2025
|
|
**Ziel-Domain:** businessportal24.test
|
|
**Theme-Farben:** Primary #cf3628 (Rot), Secondary #f0834a (Orange)
|
|
|
|
---
|
|
|
|
## 1. Analyse der Quellstruktur
|
|
|
|
### Ursprüngliche React-Struktur (dev/presswave)
|
|
```
|
|
src/
|
|
├── pages/
|
|
│ └── Index.tsx # Haupt-Landingpage
|
|
├── components/
|
|
│ ├── Header.tsx # Navigation & Suche
|
|
│ ├── FilterBar.tsx # Filter-Komponente
|
|
│ ├── PressReleaseCard.tsx # Karten-Komponente für Pressemitteilungen
|
|
│ └── BurgerMenu.tsx # Mobile Navigation
|
|
└── assets/
|
|
└── *.jpg # Bilder
|
|
```
|
|
|
|
### Hauptkomponenten identifiziert:
|
|
1. **Header** - Sticky Navigation mit Logo, Suchleiste und CTA-Buttons
|
|
2. **FilterBar** - Sticky Filter mit Zeitraum, Branche, Region und Sortierung
|
|
3. **Hero Section** - Gradient-Banner mit Überschrift
|
|
4. **Featured Section** - 3-spaltiges Grid mit hervorgehobenen Releases
|
|
5. **Main Grid** - 3-spaltiges Responsive Grid mit allen Releases
|
|
6. **Footer** - 4-spaltige Link-Struktur mit Social Media
|
|
|
|
---
|
|
|
|
## 2. Laravel Blade Struktur erstellt
|
|
|
|
### Haupt-Blade-Datei
|
|
**Pfad:** `resources/views/web/businessportal24.blade.php`
|
|
|
|
```blade
|
|
@extends('web.layouts.web-master')
|
|
|
|
@section('content')
|
|
<main class="min-h-screen flex flex-col">
|
|
<livewire:web.header />
|
|
<livewire:web.filter-bar />
|
|
<!-- Hero Banner -->
|
|
<!-- Featured Section -->
|
|
<livewire:web.featured-releases />
|
|
<!-- Main Grid -->
|
|
<livewire:web.press-releases-grid />
|
|
<livewire:web.footer />
|
|
</main>
|
|
@endsection
|
|
```
|
|
|
|
**Features:**
|
|
- Verwendet CSS-Variablen für Theme-Farben: `var(--color-primary)` und `var(--color-secondary)`
|
|
- Animationen via CSS Keyframes (`@keyframes fade-in-up`)
|
|
- Responsive Design mit Tailwind CSS
|
|
- Alpine.js für interaktive Elemente
|
|
|
|
---
|
|
|
|
## 3. Livewire-Komponenten erstellt
|
|
|
|
### 3.1 Header-Komponente
|
|
**Pfad:** `resources/views/livewire/web/header.blade.php`
|
|
|
|
**Funktionen:**
|
|
- Sticky Header mit Gradient-Border-Top
|
|
- Responsive Suchleiste (Desktop & Mobile)
|
|
- Burger-Menü für Mobile
|
|
- Logo mit dynamischem Gradient
|
|
- CTA-Buttons: "Anmelden" und "Veröffentlichen"
|
|
|
|
**Livewire Properties:**
|
|
```php
|
|
public $searchQuery = '';
|
|
public $showMobileSearch = false;
|
|
```
|
|
|
|
**Alpine.js Integration:**
|
|
- Mobile Search Toggle
|
|
- Smooth Transitions
|
|
|
|
---
|
|
|
|
### 3.2 FilterBar-Komponente
|
|
**Pfad:** `resources/views/livewire/web/filter-bar.blade.php`
|
|
|
|
**Funktionen:**
|
|
- Sticky Position unterhalb Header (top-16)
|
|
- 4 Filter-Dropdowns: Zeitraum, Branche, Region, Sortierung
|
|
- Active Filters Display mit Remove-Buttons
|
|
- "Alle zurücksetzen" Button
|
|
- Live-Wire: Real-time Filtering
|
|
|
|
**Livewire Properties:**
|
|
```php
|
|
public $timeframe = '7';
|
|
public $industry = 'all';
|
|
public $region = 'all';
|
|
public $sortBy = 'newest';
|
|
public $activeFilters = [];
|
|
```
|
|
|
|
**Events:**
|
|
```php
|
|
$this->dispatch('filters-updated', [...]);
|
|
```
|
|
|
|
---
|
|
|
|
### 3.3 PressReleaseCard-Komponente
|
|
**Pfad:** `resources/views/components/web/press-release-card.blade.php`
|
|
|
|
**Props:**
|
|
- `title`, `teaser`, `company`, `industry`, `region`, `date`
|
|
- `hasImage`, `hasPdf`, `companyLogo`, `slug`, `imageUrl`
|
|
|
|
**Features:**
|
|
- Image Preview mit Lazy Loading
|
|
- Company Logo Overlay
|
|
- Meta-Informationen (Branche, Region, Datum)
|
|
- Badges für Medien (Bild, PDF)
|
|
- Hover-Effekte: Scale & Border-Color
|
|
- Transition-Animationen (300ms)
|
|
|
|
**CSS-Klassen:**
|
|
```css
|
|
.card {
|
|
@apply hover:scale-[1.02] hover:border-primary/20;
|
|
@apply transition-all duration-300;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.4 Featured Releases-Komponente
|
|
**Pfad:** `resources/views/livewire/web/featured-releases.blade.php`
|
|
|
|
**Layout:**
|
|
- 3-spaltiges Grid (lg:grid-cols-3)
|
|
- Linke Seite: 1 große Featured Card (lg:col-span-2)
|
|
- Rechte Seite: 2 gestapelte Cards
|
|
|
|
**Mock-Daten:**
|
|
- 3 Releases mit unterschiedlichen Bildern (Unsplash)
|
|
- Verschiedene Branchen: IT, Energie, Finanzen
|
|
|
|
---
|
|
|
|
### 3.5 Press Releases Grid-Komponente
|
|
**Pfad:** `resources/views/livewire/web/press-releases-grid.blade.php`
|
|
|
|
**Layout:**
|
|
- Responsive Grid: 1 col (mobile), 2 cols (md), 3 cols (lg)
|
|
- 6 Mock-Releases
|
|
|
|
**Features:**
|
|
- Verwendet `x-web.press-release-card` Komponente
|
|
- Loop durch `$releases` Array
|
|
|
|
---
|
|
|
|
### 3.6 Footer-Komponente
|
|
**Pfad:** `resources/views/livewire/web/footer.blade.php`
|
|
|
|
**Layout:**
|
|
- 4-spaltiges Grid (md:grid-cols-4)
|
|
- Spalten: Unternehmen, Services, Rechtliches, Social Media
|
|
- Theme-Toggle Button (Alpine.js)
|
|
|
|
**Links:**
|
|
- Interne Links: `/ueber-uns`, `/kontakt`, `/preise`, etc.
|
|
- Externe Links: LinkedIn, Twitter (target="_blank")
|
|
|
|
---
|
|
|
|
## 4. Theme & Styling
|
|
|
|
### 4.1 CSS-Theme-Datei
|
|
**Pfad:** `resources/css/web/theme-businessportal24.css`
|
|
|
|
**Farb-Variablen (HSL):**
|
|
```css
|
|
--primary: 4 61% 49%; /* #cf3628 */
|
|
--secondary: 22 84% 61%; /* #f0834a */
|
|
```
|
|
|
|
**Dark Mode Support:**
|
|
```css
|
|
.dark {
|
|
--background: 4 20% 10%;
|
|
--primary: 4 61% 49%;
|
|
/* ... */
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4.2 Animationen
|
|
|
|
**Keyframes definiert:**
|
|
```css
|
|
@keyframes fade-in-up {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
@keyframes fade-in-down { /* ... */ }
|
|
@keyframes slide-in-right { /* ... */ }
|
|
@keyframes scale-in { /* ... */ }
|
|
```
|
|
|
|
**Utility-Klassen:**
|
|
```css
|
|
.animate-fade-in-up { animation: fade-in-up 0.6s ease-out forwards; }
|
|
.animation-delay-200 { animation-delay: 0.2s; opacity: 0; }
|
|
```
|
|
|
|
**Verwendung in Blade:**
|
|
```html
|
|
<h1 class="animate-fade-in-up">Titel</h1>
|
|
<p class="animate-fade-in-up animation-delay-200">Text</p>
|
|
```
|
|
|
|
---
|
|
|
|
### 4.3 Component Styles
|
|
|
|
**Buttons:**
|
|
```css
|
|
.btn-primary {
|
|
@apply bg-gradient-to-r from-primary to-secondary;
|
|
@apply shadow-md hover:shadow-lg;
|
|
@apply transition-all duration-300;
|
|
}
|
|
```
|
|
|
|
**Cards:**
|
|
```css
|
|
.card {
|
|
@apply rounded-xl border shadow-sm hover:shadow-lg;
|
|
@apply transition-all duration-300;
|
|
}
|
|
```
|
|
|
|
**Badges:**
|
|
```css
|
|
.badge-primary {
|
|
@apply bg-primary/10 text-primary border border-primary/20;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. React → Blade/Livewire Konvertierung
|
|
|
|
### Mapping-Tabelle
|
|
|
|
| React-Konzept | Laravel-Äquivalent | Beispiel |
|
|
|---------------|-------------------|----------|
|
|
| `useState()` | `public $property` | `public $searchQuery = '';` |
|
|
| `props` | `@props([...])` | `@props(['title', 'teaser'])` |
|
|
| `onClick` | `wire:click` | `wire:click="search"` |
|
|
| `onChange` | `wire:model.live` | `wire:model.live="timeframe"` |
|
|
| `map()` | `@foreach` | `@foreach($releases as $release)` |
|
|
| `x-show` (React) | `x-show` (Alpine) | `x-show="showMobileSearch"` |
|
|
| `dispatch()` | `$this->dispatch()` | `$this->dispatch('event')` |
|
|
| CSS-in-JS | Tailwind Classes | `class="bg-primary text-white"` |
|
|
|
|
---
|
|
|
|
### Spezifische Konvertierungen:
|
|
|
|
#### React Search Component:
|
|
```tsx
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
|
|
<input
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
/>
|
|
```
|
|
|
|
#### Livewire Äquivalent:
|
|
```php
|
|
public $searchQuery = '';
|
|
|
|
<input wire:model="searchQuery" />
|
|
```
|
|
|
|
---
|
|
|
|
#### React Filter Update:
|
|
```tsx
|
|
const [timeframe, setTimeframe] = useState('7');
|
|
|
|
<select
|
|
value={timeframe}
|
|
onChange={(e) => setTimeframe(e.target.value)}
|
|
>
|
|
```
|
|
|
|
#### Livewire Äquivalent:
|
|
```php
|
|
public $timeframe = '7';
|
|
|
|
<select wire:model.live="timeframe">
|
|
```
|
|
|
|
---
|
|
|
|
#### React Conditional Rendering:
|
|
```tsx
|
|
{hasImage && (
|
|
<Badge>Bild</Badge>
|
|
)}
|
|
```
|
|
|
|
#### Blade Äquivalent:
|
|
```blade
|
|
@if($hasImage)
|
|
<span class="badge">Bild</span>
|
|
@endif
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Routing & Integration
|
|
|
|
### Route hinzufügen
|
|
**Pfad:** `routes/web.php` oder `routes/domains.php`
|
|
|
|
```php
|
|
Route::domain('businessportal24.test')->group(function () {
|
|
Route::get('/', function () {
|
|
return view('web.businessportal24');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Domain-Config
|
|
**Pfad:** `config/domains.php`
|
|
|
|
```php
|
|
'businessportal24' => [
|
|
'domain_name' => 'businessportal24.test',
|
|
'theme' => 'businessportal24',
|
|
'view_prefix' => 'web',
|
|
'assets_dir' => 'build/web',
|
|
'color_scheme' => [
|
|
'primary' => '#cf3628',
|
|
'secondary' => '#f0834a',
|
|
],
|
|
'font' => 'Montserrat',
|
|
],
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Verbesserungen & Best Practices
|
|
|
|
### Implementierte Verbesserungen:
|
|
|
|
1. **Performance:**
|
|
- Lazy Loading für Bilder (`loading="lazy"`)
|
|
- CSS-Transitions statt JavaScript-Animationen
|
|
- Livewire Live-Updates nur wo nötig
|
|
|
|
2. **Accessibility:**
|
|
- `aria-label` für Icon-Buttons
|
|
- Semantische HTML-Tags (`<header>`, `<footer>`, `<article>`)
|
|
- Keyboard-Navigation Support
|
|
|
|
3. **SEO:**
|
|
- Semantische Meta-Informationen
|
|
- Alt-Texte für Bilder
|
|
- Strukturierte Daten via `<article>`
|
|
|
|
4. **Responsive Design:**
|
|
- Mobile-First Approach
|
|
- Breakpoints: `sm:`, `md:`, `lg:`
|
|
- Touch-optimierte Buttons
|
|
|
|
---
|
|
|
|
## 8. Testing & Debugging
|
|
|
|
### Lokales Testing:
|
|
|
|
1. **Vite Dev-Server starten:**
|
|
```bash
|
|
npm run dev:web
|
|
```
|
|
|
|
2. **Laravel Dev-Server:**
|
|
```bash
|
|
php artisan serve
|
|
```
|
|
|
|
3. **Domain-Simulation (.env):**
|
|
```env
|
|
DEV_SIMULATE_DOMAIN=true
|
|
DEV_SIMULATED_DOMAIN=businessportal24.test
|
|
```
|
|
|
|
4. **Browser öffnen:**
|
|
```
|
|
http://localhost:8000
|
|
```
|
|
|
|
---
|
|
|
|
### Debug-Tipps:
|
|
|
|
**Livewire-Debugging:**
|
|
```blade
|
|
<div>
|
|
{{ var_dump($searchQuery) }}
|
|
@json($activeFilters)
|
|
</div>
|
|
```
|
|
|
|
**Alpine.js Debugging:**
|
|
```html
|
|
<div x-data="{ debug: true }">
|
|
<template x-if="debug">
|
|
<pre x-text="JSON.stringify($data, null, 2)"></pre>
|
|
</template>
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Nächste Schritte
|
|
|
|
### Zu implementieren:
|
|
|
|
1. **Datenbank-Integration:**
|
|
- Eloquent Model für `PressRelease`
|
|
- Migration erstellen
|
|
- Seeder für Test-Daten
|
|
|
|
2. **Pagination:**
|
|
- Livewire Pagination implementieren
|
|
- Infinite Scroll Option
|
|
|
|
3. **Suche:**
|
|
- Laravel Scout Integration
|
|
- Full-Text Search mit Meilisearch
|
|
|
|
4. **Filter-Persistenz:**
|
|
- Query-Parameter für Filter
|
|
- Browser-History Integration
|
|
|
|
5. **API:**
|
|
- REST API für Releases
|
|
- API-Dokumentation (Swagger)
|
|
|
|
6. **Admin-Panel:**
|
|
- CRUD für Pressemitteilungen
|
|
- Bild-Upload mit Media Library
|
|
|
|
---
|
|
|
|
## 10. Dateistruktur (Zusammenfassung)
|
|
|
|
```
|
|
resources/
|
|
├── views/
|
|
│ ├── web/
|
|
│ │ └── businessportal24.blade.php # Haupt-Blade
|
|
│ ├── livewire/
|
|
│ │ └── web/
|
|
│ │ ├── header.blade.php
|
|
│ │ ├── filter-bar.blade.php
|
|
│ │ ├── featured-releases.blade.php
|
|
│ │ ├── press-releases-grid.blade.php
|
|
│ │ └── footer.blade.php
|
|
│ └── components/
|
|
│ └── web/
|
|
│ └── press-release-card.blade.php
|
|
└── css/
|
|
└── web/
|
|
└── theme-businessportal24.css # Theme-Styles
|
|
|
|
config/
|
|
└── domains.php # Domain-Config
|
|
|
|
routes/
|
|
└── domains.php # Routing
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Lessons Learned
|
|
|
|
### Was gut funktioniert hat:
|
|
|
|
1. **Livewire für State Management:**
|
|
- Einfache Syntax
|
|
- Keine JS-Komplexität
|
|
- Reaktive Updates
|
|
|
|
2. **Tailwind CSS:**
|
|
- Schnelles Styling
|
|
- Konsistentes Design
|
|
- Responsive Utilities
|
|
|
|
3. **Alpine.js für UI-Interaktionen:**
|
|
- Leichtgewichtig
|
|
- Vue-ähnliche Syntax
|
|
- Perfekt für kleine Interaktionen
|
|
|
|
### Herausforderungen:
|
|
|
|
1. **Komplexe React-Hooks → Livewire:**
|
|
- Lösung: Einfachere State-Struktur
|
|
|
|
2. **CSS-in-JS → Tailwind:**
|
|
- Lösung: Utility-Klassen + @layer
|
|
|
|
3. **React Context → Laravel:**
|
|
- Lösung: View::share() & Config
|
|
|
|
---
|
|
|
|
## 12. Performance-Metriken
|
|
|
|
### Ziel-Metriken:
|
|
|
|
- **First Contentful Paint:** < 1.5s
|
|
- **Time to Interactive:** < 3.5s
|
|
- **Lighthouse Score:** > 90
|
|
|
|
### Optimierungen:
|
|
|
|
1. **Asset-Optimierung:**
|
|
- Vite Build: Code-Splitting
|
|
- Image Optimization (WebP)
|
|
- CSS Minification
|
|
|
|
2. **Livewire-Optimierung:**
|
|
- `wire:model.lazy` wo möglich
|
|
- Polling vermeiden
|
|
- Lazy-Loading von Komponenten
|
|
|
|
---
|
|
|
|
## 13. Maintenance & Updates
|
|
|
|
### Regelmäßige Updates:
|
|
|
|
1. **Dependencies:**
|
|
```bash
|
|
composer update
|
|
npm update
|
|
```
|
|
|
|
2. **Laravel Updates:**
|
|
```bash
|
|
php artisan migrate
|
|
php artisan optimize:clear
|
|
```
|
|
|
|
3. **Vite Rebuild:**
|
|
```bash
|
|
npm run build:web
|
|
```
|
|
|
|
---
|
|
|
|
## Kontakt & Support
|
|
|
|
**Entwickler:** Claude Code
|
|
**Datum:** 15. Oktober 2025
|
|
**Version:** 1.0.0
|
|
|
|
Bei Fragen oder Problemen:
|
|
- CLAUDE.md im Root-Verzeichnis konsultieren
|
|
- Laravel Dokumentation: https://laravel.com/docs
|
|
- Livewire Dokumentation: https://livewire.laravel.com
|
|
|
|
---
|
|
|
|
**Ende der Dokumentation**
|