Arbeitsplan 14.09.2026, Punkte 1.1 bis 1.4 (Nachträge 6 bis 10 im Entwicklungsplan): - Farbwelt Interior (Tanne, Creme, Sand, Ocker, Clay) als Standard, Immobilien-Welt behält das bisherige Blau über body.world-immobilien; Logo je Welt, Favicons neu, Welten-Wechsler in Kopf- und Fußzeile. - Saubere Trennung der Welten: eigene Navigation, Ankündigungsleiste, Magazinliste, Über-uns-Seite, FAQ, Kontaktseite und Abschluss-CTA für Immobilien; Beiträge tragen eine Welt (Migration + Admin-Feld). Abschluss-CTA Ton in Ton statt Grün-zu-Ocker. - Kontakt: Betreffe in Gruppen Interior / Immobilien / B2in, Marken darin. Terminanfrage-Buttons öffnen das Widget mit vorgewähltem Anliegen; Select-Felder einheitlich gestaltet. - Tischlerei als vierte Kernmarke (Platzhalter), Kachelraster 2×2. - Herkunfts-Sektion „Aus der Region gefertigt“ mit schematischer Standortkarte und Ablauf CABINET (Beratung Bielefeld, Fertigung Köln, Aufbau mit Tischlerei). Deployment: migrate, WorldSplitCmsSeeder, CmsBrandSeeder, OriginSectionCmsSeeder (Abschnitt 8 im Entwicklungsplan). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
122 lines
3.8 KiB
PHP
122 lines
3.8 KiB
PHP
<?php
|
||
|
||
namespace App\Livewire\Web\Components\Ui;
|
||
|
||
use Livewire\Component;
|
||
|
||
class Header extends Component
|
||
{
|
||
public $isMobileMenuOpen = false;
|
||
public $domainName;
|
||
public $domainUrl;
|
||
public $content = [];
|
||
public $currentLocale;
|
||
public $availableLocales = [
|
||
'de' => 'DE',
|
||
'en' => 'EN',
|
||
];
|
||
|
||
/** Farbwelt der Seite (`interior` | `immobilien`), in mount() festgehalten. */
|
||
public string $world = 'interior';
|
||
|
||
/** @var array<string, array{label: string, url: string, active: bool}> */
|
||
public array $worlds = [];
|
||
|
||
public string $logoPath = '';
|
||
|
||
/** Pfad der Seite, in mount() festgehalten – ein Livewire-Request traegt ihn nicht mehr. */
|
||
public string $currentPath = '/';
|
||
|
||
/** Ziel des Kontakt-Buttons: /contact (Interior) bzw. /immobilien/kontakt (Immobilien). */
|
||
public string $contactUrl = '';
|
||
|
||
public function mount(): void
|
||
{
|
||
$this->domainName = \App\Helpers\ThemeHelper::getDomainName();
|
||
$this->domainUrl = \App\Helpers\ThemeHelper::getDomainUrl();
|
||
$this->currentLocale = app()->getLocale();
|
||
$this->world = b2in_world();
|
||
$this->worlds = b2in_worlds($this->world);
|
||
$this->logoPath = \App\Helpers\ThemeHelper::getLogoPath('positive', $this->world);
|
||
$this->currentPath = '/'.ltrim(request()->path(), '/');
|
||
$this->contactUrl = route($this->world === 'immobilien' ? 'immobilien.contact' : 'contact');
|
||
|
||
// Jede Welt hat ihre eigene Navigation (CMS: global.header bzw. global.header_immobilien).
|
||
$this->content = cms_theme_section($this->world === 'immobilien' ? 'header_immobilien' : 'header');
|
||
|
||
// Ensure required keys exist
|
||
if (!isset($this->content['portal_login'])) {
|
||
$this->content['portal_login'] = 'Portal Login';
|
||
}
|
||
if (!isset($this->content['navigation']) || !is_array($this->content['navigation'])) {
|
||
$this->content['navigation'] = [];
|
||
}
|
||
}
|
||
|
||
public function switchLanguage(string $locale): mixed
|
||
{
|
||
if (array_key_exists($locale, $this->availableLocales)) {
|
||
app()->setLocale($locale);
|
||
session(['locale' => $locale]);
|
||
$this->currentLocale = $locale;
|
||
|
||
$referer = request()->header('Referer') ?? '/';
|
||
|
||
return redirect()->to($referer);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public function toggleMobileMenu(): void
|
||
{
|
||
$this->isMobileMenuOpen = ! $this->isMobileMenuOpen;
|
||
}
|
||
|
||
public function closeMobileMenu(): void
|
||
{
|
||
$this->isMobileMenuOpen = false;
|
||
}
|
||
/**
|
||
* Aktiver Navigationspunkt: exakter Treffer, sonst der laengste Eintrag, dessen Pfad ein
|
||
* Praefix der Seite ist. So markiert /immobilien/magazin nur „Magazin“, nicht auch
|
||
* „Immobilien“. Anker (#…) zaehlen nicht zum Pfad.
|
||
*/
|
||
public function isActiveRoute($url): bool
|
||
{
|
||
$path = $this->navPath((string) $url);
|
||
|
||
if ($this->currentPath === $path) {
|
||
return true;
|
||
}
|
||
|
||
if ($path === '/' || ! str_starts_with($this->currentPath, rtrim($path, '/').'/')) {
|
||
return false;
|
||
}
|
||
|
||
foreach ($this->content['navigation'] ?? [] as $navItem) {
|
||
$other = $this->navPath((string) ($navItem['url'] ?? ''));
|
||
|
||
if ($other === $this->currentPath) {
|
||
return false;
|
||
}
|
||
|
||
if (strlen($other) > strlen($path) && str_starts_with($this->currentPath, rtrim($other, '/').'/')) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private function navPath(string $url): string
|
||
{
|
||
$path = (string) (parse_url($url, PHP_URL_PATH) ?? '/');
|
||
|
||
return '/'.ltrim($path, '/');
|
||
}
|
||
public function render()
|
||
{
|
||
return view('livewire.web.components.ui.header');
|
||
}
|
||
}
|