Nachtrag 11: Herkunfts-Sektion liest Ort, Entfernung und Rolle aus der Markenverwaltung (drei neue Felder an cms_brands, BrandOriginSeeder), Kartenpositionen im Code, „Marken“ in der Sidebar. Nachtrag 12: Inhalte-Editor zeigt die Seiten der Website mit ihren Sektionen in Reihenfolge (config/cms_pages.php, CmsPageTree), Felder in Klartext, fehlende Sektionen aus der Sprachdatei anlegbar, Vorschau der echten Seite im iframe mit Sprung zur Sektion; Anker an allen lebenden Sektionen nachgezogen. Nachtrag 13: Referenzen als eigenes Modul (CmsReference, Portal-Seite, /referenzen mit Fallback auf die Markengalerien); Immobilien-Projekte aus Sidebar und CMS-Übersicht genommen, Route bleibt. Dazu .gitignore für _b2in_interior_shop/ und docs/. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
83 lines
2.8 KiB
PHP
83 lines
2.8 KiB
PHP
<?php
|
||
|
||
namespace App\Livewire\Web\Components\Sections;
|
||
|
||
use App\Models\CmsBrand;
|
||
use Livewire\Component;
|
||
|
||
/**
|
||
* „Aus der Region gefertigt“: die Standorte der Kernmarken rund um Bielefeld
|
||
* (Arbeitsplan 14.09.2026, Punkt 1.3, Nachtrag 11).
|
||
*
|
||
* Überschrift, Karte, Drehscheibe und Ablauf-Block kommen aus dem CMS (Fallback Lang-Datei).
|
||
* Die Standorte kommen aus den veröffentlichten Marken: Ort, Entfernung und Rolle pflegt
|
||
* Marcel in der Markenverwaltung. Die Positionen in der schematischen Karte gehören zur
|
||
* Zeichnung und bleiben hier im Code.
|
||
*/
|
||
class OriginSection extends Component
|
||
{
|
||
/**
|
||
* Position je Marke in der Karte (viewBox 640×400) und Seite der Beschriftung.
|
||
*
|
||
* Eine Marke ohne Eintrag erscheint in den Kacheln, aber nicht in der Karte.
|
||
*
|
||
* @var array<string, array{x: int, y: int, label: string}>
|
||
*/
|
||
public const MAP_POSITIONS = [
|
||
'rotpunkt' => ['x' => 330, 'y' => 55, 'label' => 'left'],
|
||
'februe' => ['x' => 480, 'y' => 90, 'label' => 'right'],
|
||
'tischlerei' => ['x' => 295, 'y' => 285, 'label' => 'left'],
|
||
'cabinet' => ['x' => 80, 'y' => 345, 'label' => 'right'],
|
||
];
|
||
|
||
/** @var array<string, mixed> */
|
||
public array $content = [];
|
||
|
||
public string $bg = '';
|
||
|
||
public function mount(string $bg = ''): void
|
||
{
|
||
$section = cms_theme_section('origin_section');
|
||
$this->content = is_array($section) ? $section : [];
|
||
$this->bg = $bg;
|
||
}
|
||
|
||
/**
|
||
* Veröffentlichte Marken mit gepflegtem Fertigungsort, in der Reihenfolge der Marken.
|
||
*
|
||
* Eine unveröffentlichte Marke fällt heraus, eine Marke ohne Ort ebenfalls. Der Link zur
|
||
* Markenseite hängt daran, ob die Marke eine Detailseite hat (Lang-Fallback: keine).
|
||
*
|
||
* @return list<array{slug: string, city: string, brand: string, role: string, distance: string, link: ?string, map: ?array{x: int, y: int, label: string}}>
|
||
*/
|
||
public function getLocationsProperty(): array
|
||
{
|
||
$out = [];
|
||
|
||
foreach (CmsBrand::forFrontend() as $slug => $brand) {
|
||
$city = trim((string) ($brand['origin_city'] ?? ''));
|
||
$name = trim((string) ($brand['name'] ?? ''));
|
||
|
||
if ($city === '' || $name === '') {
|
||
continue;
|
||
}
|
||
|
||
$out[] = [
|
||
'slug' => (string) $slug,
|
||
'city' => $city,
|
||
'brand' => $name,
|
||
'role' => trim((string) ($brand['origin_role'] ?? '')),
|
||
'distance' => trim((string) ($brand['origin_distance'] ?? '')),
|
||
'link' => ! empty($brand['has_detail_page']) ? '/marken/'.$slug : null,
|
||
'map' => self::MAP_POSITIONS[$slug] ?? null,
|
||
];
|
||
}
|
||
|
||
return $out;
|
||
}
|
||
|
||
public function render()
|
||
{
|
||
return view('livewire.web.components.sections.origin-section');
|
||
}
|
||
}
|