b2in/dev/flux-cms/PLAN.md
2026-04-10 17:18:17 +02:00

524 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Flux CMS Integration Entwicklungsplan
> **Ziel:** Integration des flux-cms Packages für die b2in-Webseite.
> **Scope:** Nur b2in weitere Subseiten (b2a, stileigentum, style2own) folgen später.
> **Stand:** 2026-03-18
---
## Ausgangslage
### Was existiert
- **Package:** `packages/flux-cms/` (core, components, starter-components) liegt im Projekt
- **Composer:** `packages/*/*` Repository-Pfad ist in `composer.json` konfiguriert
- **Frontend:** Vollständige b2in-Webseite mit ~15 Seiten
- **Content-Quelle:** `config/content.php` statische PHP-Arrays pro Theme
- **Content-Zugriff:** Livewire-Sections laden via `config("content.themes.{$theme}.{$section}")`
- **Immobilien/Projekte:** Komplett in `config/content.php` definiert (Slug, Titel, Preise, Galerie, Quick Facts, Investment Case, Location etc.), Route `immobilien/{slug}` liest direkt aus Config
- **Admin-Portal:** `portal.b2in.test` mit eigenem CMS (Cabinets/Displays), User-/Partner-Management
- **Domain-System:** Multi-Domain-Setup in `config/domains.php`
### Was fehlt
- flux-cms/core ist **nicht** als Composer-Dependency installiert
- Keine `app/helpers.php` mit `cms()`/`tcms()`/`cms_media_url()`
- Keine `config/flux-cms.php` publiziert
- Keine `flux_cms_*` Datenbanktabellen
- Keine Admin-Views/Routes für das CMS
- Keine Medienbibliothek
- Kein Immobilien-Model (Projekte leben in Config)
### Scope-Einschränkung Phase 1
**Nur diese Tabellen werden initial benötigt:**
- `flux_cms_contents` Alle Seiteninhalte (Key-Value mit Übersetzungen)
- `flux_cms_media` Medienbibliothek (Bilder, PDFs)
**Nicht benötigt (kommt später bei Bedarf):**
- ~~`flux_cms_news_items`~~ Nachrichteneinträge
- ~~`flux_cms_industries`~~ Branchen
- ~~`flux_cms_faqs`~~ FAQ-Einträge
- ~~`flux_cms_downloads`~~ Downloads
- ~~`flux_cms_linkedin_posts`~~ LinkedIn-Posts
- ~~`flux_cms_search_index`~~ Suchindex
**Zusätzlich benötigt:**
- Neues **Immobilien/Projekte-Model** mit eigenem CRUD im CMS-Backend (ersetzt die statischen Projekte aus `config/content.php`)
---
## Phasen-Übersicht
| Phase | Beschreibung | Abhängig von |
|-------|-------------|--------------|
| **1** | Package-Installation & Infrastruktur | |
| **2** | Immobilien-Model & CRUD | Phase 1 |
| **3** | Content-Migration (config → DB) | Phase 1 |
| **4** | CMS Admin-Backend | Phase 1 |
| **5** | Frontend-Umstellung (config → cms) | Phase 2, 3 |
| **6** | Medienbibliothek & Bilder | Phase 1, 4 |
| **7** | Tests | Phase 26 |
| **8** | Feinschliff & Dokumentation | Phase 57 |
---
## Phase 1 Package-Installation & Infrastruktur
### 1.1 Composer-Dependency installieren
```bash
composer require flux-cms/core:@dev
composer require intervention/image
```
**Prüfen:**
- [ ] `FluxCmsServiceProvider` wird automatisch geladen
- [ ] Keine Konflikte mit bestehenden Dependencies
### 1.2 Konfiguration publizieren
```bash
php artisan vendor:publish --tag=flux-cms-config
```
**Anpassen in `config/flux-cms.php`:**
- `default_locale``'de'`
- `locales``['de' => 'Deutsch', 'en' => 'English']`
- `media.profiles` → an b2in-Bildgrößen anpassen
- `routes.enabled``false` (eigene Admin-Routes im Portal)
### 1.3 Migrations ausführen
**Nur die benötigten Migrations:**
- `create_flux_cms_contents_table`
- `create_flux_cms_media_table`
Die restlichen Migrations (news, industries, faqs, downloads, linkedin, search_index) werden **nicht ausgeführt** sie liegen im Package und können bei Bedarf später migriert werden.
**Optionen:**
- A) Alle Migrations laufen lassen (Tabellen existieren, werden aber nicht genutzt) einfacher
- B) Nur selektiv migrieren sauberer, erfordert ggf. Anpassung am ServiceProvider
**Empfehlung: Option A** leere Tabellen stören nicht und vereinfachen spätere Erweiterung.
```bash
php artisan migrate
```
### 1.4 Helper-Funktionen einrichten
**Erstellen:** `app/helpers.php` mit `cms()`, `tcms()`, `cms_media_url()`, `media_url()`
**Registrieren in `composer.json`:**
```json
"autoload": {
"files": ["app/helpers.php"]
}
```
```bash
composer dump-autoload
```
### 1.5 Storage-Link
```bash
php artisan storage:link
```
**Ergebnis Phase 1:** Package installiert, DB-Tabellen vorhanden, Helper verfügbar.
---
## Phase 2 Immobilien/Projekte-Model & CRUD
### 2.1 Datenstruktur analysieren
Aktuelle Projekt-Daten aus `config/content.php` (am Beispiel Azizi Creek Views 4):
| Feld | Typ | Beispiel |
|------|-----|---------|
| `slug` | string | `azizi-creek-views-4` |
| `title` | string | `Azizi Developments: Creek Views 4` |
| `location` | string | `Al Jaddaf, Dubai` |
| `status` | string | `NEW LAUNCH` |
| `launch_date` | string | `03.03.2026` |
| `price_from` | integer (AED) | `1125000` |
| `image` | string (Pfad) | `expose/a1/image-4.jpeg` |
| `highlights` | array\<string\> | `['Prime Waterfront Views', ...]` |
| `quick_facts` | array\<{icon, label, value}\> | Typen, Größe, Einheiten, Entwickler |
| `investment_case` | object | `{title, text, views[]}` |
| `gallery` | array\<string\> | Bildpfade |
| `location_info` | object | `{title, map_url, points[]}` |
| `contact` | object | `{title, subtitle, options[]}` |
### 2.2 Migration erstellen
Neue Migration `create_cms_projects_table`:
```php
Schema::create('cms_projects', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->json('title'); // translatable
$table->json('location'); // translatable
$table->string('status')->nullable();
$table->date('launch_date')->nullable();
$table->unsignedInteger('price_from_aed')->nullable();
$table->string('currency')->default('AED');
$table->string('image')->nullable(); // CmsMedia Referenz
$table->json('highlights')->nullable(); // translatable array
$table->json('quick_facts')->nullable(); // [{icon, label, value}]
$table->json('investment_case')->nullable(); // {title, text, views[]}
$table->json('gallery')->nullable(); // [filename, ...]
$table->json('location_info')->nullable(); // {title, map_url, points[]}
$table->json('contact')->nullable(); // {title, subtitle, options[]}
$table->boolean('is_published')->default(false);
$table->unsignedInteger('order')->default(0);
$table->timestamps();
});
```
### 2.3 Model erstellen
`App\Models\CmsProject` mit:
- `HasTranslations` (Spatie) für `title`, `location`, `highlights`
- Scopes: `published()`, `ordered()`
- `toFrontendArray()` → kompatibles Array für bestehende Blade-Views
- `getFormattedPrice()` → nutzt `PriceHelper::formatAed()`
- Accessors für `gallery_urls`, `image_url` etc.
### 2.4 Factory & Seeder
- **Factory:** `CmsProjectFactory` für Tests
- **Seeder:** `CmsProjectSeeder` importiert die bestehenden Projekte aus `config/content.php` in die DB
### 2.5 Admin CRUD (Volt-Komponente)
Admin-View `admin.cms.projects-index`:
- Liste aller Projekte (Titel, Status, Preis, Published, Order)
- Erstellen/Bearbeiten Modal oder Inline
- Felder: alle aus 2.2
- Galerie-Management via MediaPicker
- Bild-Upload via MediaLibraryUploader
- Sortierung per Drag & Drop oder Order-Feld
- Publish/Unpublish Toggle
### 2.6 Route für Immobilien-Show anpassen
```php
// Vorher:
Route::get('/immobilien/{slug}', function (string $slug) {
$project = config("content.themes.{$theme}.immobilien_projects.projects.{$slug}");
...
});
// Nachher:
Route::get('/immobilien/{slug}', function (string $slug) {
$project = CmsProject::where('slug', $slug)->published()->firstOrFail();
return view('web.immobilien-show', ['project' => $project->toFrontendArray()]);
});
```
**Ergebnis Phase 2:** Immobilien-Projekte in DB, editierbar im CMS, Frontend nutzt Model.
---
## Phase 3 Content-Migration (config → DB)
### 3.1 Content-Struktur analysieren
Die `config/content.php` enthält das b2in-Theme mit folgenden Sektionen:
| Page | Section | Typ |
|------|---------|-----|
| global | `announcement_bar` | Text + Links |
| global | `header` | Navigation |
| global | `footer` | Text + Links |
| home | `hero` | Text + Bild + Stats |
| home | `founder_bar` | Text + Bild |
| home | `synergie_section` | Text + Bild |
| home | `vision_section` | Text + Bild |
| home | `ecosystem_core` | Text + Items |
| home | `cta_section` | Text + Link |
| home | `brand_worlds` | Text + Items |
| about | `about_hero`, `our_story`, `our_values`, `leadership_team` | Diverse |
| immobilien | `immobilien_hero_v2`, `immobilien_warum_dubai`, `immobilien_kaufprozess`, `immobilien_bruecke`, `immobilien_mindset`, `immobilien_moebel_vorteil` | Diverse |
| faq | FAQ-Kategorien | Q&A |
| netzwerk | Hero, Stats, Sections | Diverse |
| contact | Form-Info | Text |
| impressum/privacy/terms/cookie-policy | Langtext | HTML |
### 3.2 CmsContentSeeder erstellen
**Strategie:** Alle b2in-Inhalte aus `config/content.php` in `flux_cms_contents` überführen.
- **Key-Schema:** `{page}.{section}.{field}` (z.B. `home.hero.title`, `about.our_story.title`)
- **Typen:** `text`, `html`, `image`, `json` (für Arrays wie `pillars`, `stats`, `navigation`)
- **Gruppen:** `home`, `about`, `immobilien`, `netzwerk`, `faq`, `contact`, `impressum`, `privacy`, `terms`, `cookie_policy`, `global` (Header, Footer)
**Datei:** `database/seeders/CmsContentSeeder.php` liest `config/content.php` und schreibt in DB.
### 3.3 Seeders ausführen & verifizieren
```bash
php artisan db:seed --class=CmsContentSeeder
```
**Ergebnis Phase 3:** Alle b2in-Inhalte in der DB, abrufbar über `cms('home.hero.title')`.
---
## Phase 4 CMS Admin-Backend
### 4.1 CMS als eigener Menüpunkt
Das CMS wird im Admin-Portal (`portal.b2in.test`) als **eigener Top-Level-Menüpunkt "CMS"** in der Sidebar integriert.
**Sidebar-Erweiterung** (`resources/views/components/layouts/app/sidebar.blade.php`):
```
CMS
├── Dashboard (Übersicht: Anzahl Contents, Medien, Projekte)
├── Inhalte (Content-Editor für Text/HTML/Image/JSON Keys)
├── Projekte (Immobilien-CRUD aus Phase 2)
├── Medienbibliothek (Upload, Grid, Conversions)
```
### 4.2 CMS-Layout
**Entscheidung:** Die CMS-Views nutzen das bestehende Admin-Portal-Layout (`admin-master.blade.php` / `app.blade.php`), damit Navigation und User-Menü konsistent bleiben.
→ Das Reference-Layout `layout-cms.blade.php` wird **nicht** als separates Layout genutzt, sondern als Vorlage für die Content-Struktur innerhalb des bestehenden Layouts.
### 4.3 Admin-Views erstellen
Aus den Package-Referenz-Views nur die benötigten kopieren und anpassen:
| View | Quelle | Ziel |
|------|--------|------|
| Dashboard | `admin-reference/cms/dashboard.blade.php` | `livewire/admin/cms/dashboard.blade.php` |
| Content-Editor | `admin-reference/cms/content-index.blade.php` | `livewire/admin/cms/content-index.blade.php` |
| Medienbibliothek | `admin-reference/cms/media-index.blade.php` | `livewire/admin/cms/media-index.blade.php` |
| MediaPicker | `admin-reference/cms/media-picker.blade.php` | `livewire/admin/cms/media-picker.blade.php` |
| MediaUploader | `admin-reference/cms/media-library-uploader.blade.php` | `livewire/admin/cms/media-library-uploader.blade.php` |
| **Projekte** | **Neu erstellen** | `livewire/admin/cms/projects-index.blade.php` |
**Nicht benötigt (vorerst):** news-index, industries-index, faqs-index, linkedin-index, downloads-index, team-index, search-index
### 4.4 Livewire-Komponenten einrichten
```bash
mkdir -p app/Livewire/Admin/Cms/
```
Aus Package kopieren + Namespace anpassen:
- `MediaLibraryUploader.php``App\Livewire\Admin\Cms`
- `MediaPicker.php``App\Livewire\Admin\Cms`
- `MediaUploader.php``App\Livewire\Admin\Cms`
### 4.5 Admin-Routes registrieren
In `routes/admin.php` innerhalb der bestehenden `auth`-Middleware-Gruppe:
```php
// Flux CMS Routes
Volt::route('admin/cms', 'admin.cms.dashboard')->name('cms.dashboard');
Volt::route('admin/cms/content', 'admin.cms.content-index')->name('cms.content.index');
Volt::route('admin/cms/media', 'admin.cms.media-index')->name('cms.media.index');
Volt::route('admin/cms/projects', 'admin.cms.projects-index')->name('cms.projects.index');
```
**Ergebnis Phase 4:** Funktionierendes Admin-Backend unter `portal.b2in.test/admin/cms` mit Dashboard, Content-Editor, Medienbibliothek und Projekte-CRUD.
---
## Phase 5 Frontend-Umstellung (config → cms)
### 5.1 Strategie: Dualer Betrieb mit Fallback
Die Umstellung erfolgt inkrementell. Jede Section einzeln umstellen, mit Fallback auf `config()`:
```php
// Vorher (Hero.php):
$this->content = config("content.themes.{$theme}.hero", []);
// Nachher:
$this->content = $this->loadFromCms('home.hero');
// Fallback-Methode in einem Trait oder Base-Class:
protected function loadFromCms(string $group): array
{
$cmsContent = app(CmsContentService::class)->getGroup($group);
if (empty($cmsContent)) {
$theme = config('app.theme', 'b2in');
$section = Str::afterLast($group, '.');
return config("content.themes.{$theme}.{$section}", []);
}
return $cmsContent;
}
```
### 5.2 Sections schrittweise umstellen
**Reihenfolge (nach Priorität / Sichtbarkeit):**
1. **Home-Page Sections:**
- [ ] Hero → `home.hero`
- [ ] FounderBar → `home.founder_bar`
- [ ] ContentSection → `home.{section}` (dynamisch)
- [ ] VisionSection → `home.vision_section`
- [ ] EcosystemCore → `home.ecosystem_core`
- [ ] CTASection → `home.cta_section`
2. **Globale Elemente:**
- [ ] Header (Navigation) → `global.header`
- [ ] Footer → `global.footer`
- [ ] AnnouncementBar → `global.announcement_bar`
3. **Immobilien-Seite (statischer Content):**
- [ ] HeroV2 → `immobilien.hero_v2`
- [ ] WarumDubai → `immobilien.warum_dubai`
- [ ] Kaufprozess → `immobilien.kaufprozess`
- [ ] Brücke → `immobilien.bruecke`
- [ ] Mindset → `immobilien.mindset`
- [ ] MöbelVorteil → `immobilien.moebel_vorteil`
- [ ] Projekte-Liste → **CmsProject::published()->ordered()** (aus Phase 2)
4. **Unterseiten:**
- [ ] About
- [ ] FAQ
- [ ] Contact
- [ ] Impressum / Privacy / Terms / Cookie-Policy
- [ ] Netzwerk
- [ ] Service / Portfolio
### 5.3 Immobilien-Route umstellen
```php
// routes/web.php von config auf Model:
Route::get('/immobilien/{slug}', function (string $slug) {
$project = \App\Models\CmsProject::where('slug', $slug)
->published()
->firstOrFail();
return view('web.immobilien-show', ['project' => $project->toFrontendArray()]);
})->name('immobilien.show');
```
Die `immobilien.blade.php` Projekte-Liste ebenfalls umstellen:
```php
// Vorher: $projects = config("content.themes.{$theme}.immobilien_projects", []);
// Nachher: $projects = CmsProject::published()->ordered()->get();
```
### 5.4 Bilder umstellen
```diff
- asset('img/assets/' . $heroV2['image'])
+ cms_media_url('immobilien.hero_v2.image', 'hero')
```
**Ergebnis Phase 5:** b2in-Frontend liest Inhalte aus DB + CmsProject-Model, editierbar über Admin.
---
## Phase 6 Medienbibliothek & Bilder
### 6.1 Bestehende Bilder importieren
Alle b2in-Bilder (aus `public/img/assets/`) in die CMS-Medienbibliothek importieren:
- `b2in/` allgemeine b2in-Bilder (Hero, Founder, Sections)
- `expose/` Immobilien-Projektbilder
### 6.2 CmsMediaSeeder
Seeder erstellt `CmsMedia`-Einträge für alle bestehenden Bilder und verknüpft sie mit den CmsContent-Keys vom Typ `image`.
### 6.3 Bildprofile definieren
In `config/flux-cms.php`:
- `hero` → 1920×800 (Hero-Banner)
- `card` → 768×512 (Kacheln, Sections)
- `thumbnail` → 400×300 (Listen, Übersichten)
- `avatar` → 400×400 (Team-Fotos, Founder)
- `gallery` → 1200×900 (Projekt-Galerie)
- `og_image` → 1200×630 (Social Sharing)
### 6.4 Conversions generieren
```bash
php artisan flux-cms:clear-cache
```
**Ergebnis Phase 6:** Alle Bilder in Medienbibliothek, Conversions generiert, URLs aufgelöst.
---
## Phase 7 Tests
### 7.1 Referenz-Tests kopieren (selektiv)
```bash
mkdir -p tests/Feature/Cms
cp packages/flux-cms/core/tests-reference/Feature/Cms/CmsMediaTest.php tests/Feature/Cms/
cp packages/flux-cms/core/tests-reference/Feature/Cms/CmsContentServiceTest.php tests/Feature/Cms/
```
### 7.2 Projektspezifische Tests
- **CmsProjectTest** CRUD, published/unpublished, toFrontendArray(), Validierung
- **CmsContentSeederTest** Prüft ob alle Keys aus config in DB existieren
- **CmsAdminAccessTest** Prüft Zugriffskontrolle auf CMS-Admin-Routen
- **ImmobilienRouteTest** Prüft `/immobilien/{slug}` mit DB-Daten
- **FrontendFallbackTest** Prüft dualen Betrieb (CMS → config Fallback)
- **MediaIntegrationTest** Upload, Conversion, URL-Auflösung
### 7.3 Tests ausführen
```bash
php artisan test --compact --filter=Cms
php artisan test --compact --filter=Immobilien
```
**Ergebnis Phase 7:** Alle CMS-Funktionalitäten sind getestet.
---
## Phase 8 Feinschliff & Dokumentation
### 8.1 Cache & Performance
- CMS-Content-Cache aktivieren
- Eager Loading optimieren
- Prüfen: Keine N+1-Queries auf Frontseiten
### 8.2 config/content.php aufräumen
- Nach vollständiger Umstellung: b2in-Theme-Daten als `@deprecated` markieren
- Noch nicht entfernen (Fallback für andere Themes!)
- Immobilien-Projekte aus Config entfernen (leben jetzt in DB)
### 8.3 Sidebar-Berechtigungen
- CMS-Zugang über Spatie-Permission absichern (`permission:manage-cms`)
- CMS-Menüpunkt nur für berechtigte User anzeigen
### 8.4 Dokumentation
- Diesen Plan aktualisieren mit Status
- Notizen für Integration weiterer Subseiten (b2a, stileigentum, style2own)
---
## Offene Fragen / Entscheidungen
| # | Frage | Entscheidung |
|---|-------|-------------|
| 1 | Alle flux-cms Migrations laufen lassen oder nur contents + media? | Empfehlung: Alle (leere Tabellen stören nicht) |
| 2 | CmsProject: Eigene Migration oder flux-cms erweitern? | Eigene Migration im Projekt |
| 3 | FAQ-Daten: Vorerst in config belassen oder direkt in `flux_cms_faqs`? | Vorerst config |
| 4 | Magazin: Eigenes System belassen oder später auf CMS? | Vorerst belassen |
| 5 | Andere Themes (b2a etc.) weiterhin via `config()`? | Ja |
---
## Fortschritt
| Phase | Status | Notizen |
|-------|--------|---------|
| 1 Installation & Infrastruktur | ✅ Fertig | 2026-03-18: Package installiert, Config angepasst, Migrations gelaufen, Helpers eingerichtet, 434 Tests grün |
| 2 Immobilien-Model & CRUD | ✅ Fertig | 2026-03-18: Migration, Model, Factory, Seeder, 9 Tests grün. CRUD Admin-View folgt in Phase 4. |
| 3 Content-Migration | ✅ Fertig | 2026-03-18: 61 Sections in 8 Gruppen migriert, Section-als-JSON-Ansatz, 8 Tests grün |
| 4 CMS Admin-Backend | ✅ Fertig | 2026-03-18: Dashboard, Content-Editor, Projekte-CRUD, Medienbibliothek, Sidebar-Menü, MediaPicker/Uploader, 16 Tests grün |
| 5 Frontend-Umstellung | ⬜ Offen | |
| 6 Medienbibliothek | ⬜ Offen | |
| 7 Tests | ⬜ Offen | |j
| 8 Feinschliff | ⬜ Offen | |