# 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**
