CMS: Standorte an der Marke, Seitenbaum mit Vorschau, Referenzen-Modul

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>
This commit is contained in:
Kevin Adametz 2026-09-15 14:58:45 +00:00
parent 7953a8c9a1
commit 90aa079cf7
50 changed files with 2580 additions and 324 deletions

View file

@ -3,14 +3,16 @@
namespace App\Livewire\Web\Components\Sections;
use App\Models\CmsBrand;
use App\Models\CmsReference;
use Livewire\Component;
/**
* Realisierte Projekte aus den Markengalerien, über alle Marken hinweg gesammelt.
* Realisierte Projekte auf /referenzen.
*
* Keine zweite Pflegestelle: Marcel pflegt die Bilder weiterhin je Marke im Kernmarken-Modul.
* Hier erscheinen ausschließlich Einträge der Rubrik „Realisiertes Projekt" – Visualisierungen
* und Entwürfe bleiben bewusst draußen, damit „Referenzen" hält, was das Wort verspricht.
* Seit Nachtrag 13 pflegt Marcel Referenzen als eigene Einträge im Portal (Titelbild, weitere
* Bilder, beteiligte Marken). Solange dort nichts veröffentlicht ist, greift der Stand aus AP5:
* die als „Realisiertes Projekt“ markierten Bilder aus den Markengalerien, über alle Marken
* hinweg gesammelt. Visualisierungen und Entwürfe bleiben in beiden Fällen draußen.
*/
class ReferenceProjects extends Component
{
@ -30,13 +32,56 @@ class ReferenceProjects extends Component
$this->content = is_array($section) ? $section : [];
$this->bg = $bg;
$this->limit = $limit;
$this->projects = $this->collectProjects();
$projects = $this->fromReferences();
if ($projects === []) {
$projects = $this->fromBrandGalleries();
}
$this->projects = $this->limit > 0 ? array_slice($projects, 0, $this->limit) : $projects;
}
/**
* @return array<int, array<string, mixed>>
*/
private function collectProjects(): array
private function fromReferences(): array
{
$references = CmsReference::query()->published()->ordered()->get();
if ($references->isEmpty()) {
return [];
}
$brands = CmsBrand::forFrontend();
$projects = [];
foreach ($references as $reference) {
$gallery = CmsReference::normalizeGallery($reference->gallery);
$image = (string) ($reference->image ?: ($gallery[0]['image'] ?? ''));
if ($image === '') {
continue;
}
$projects[] = [
'key' => 'ref-'.$reference->id,
'image' => $image,
'caption' => (string) $reference->title,
'meta' => implode(' · ', array_filter([$reference->location, $reference->year])),
'description' => (string) $reference->description,
'gallery' => array_values(array_filter($gallery, fn (array $item) => $item['image'] !== $image)),
'brands' => $reference->resolveBrands($brands),
];
}
return $projects;
}
/**
* @return array<int, array<string, mixed>>
*/
private function fromBrandGalleries(): array
{
$projects = [];
@ -46,14 +91,19 @@ class ReferenceProjects extends Component
'key' => $slug.'-'.$index,
'image' => $item['image'],
'caption' => $item['caption'],
'brand' => (string) ($brand['name'] ?? ''),
'brand_slug' => $slug,
'has_detail_page' => (bool) ($brand['has_detail_page'] ?? false),
'meta' => '',
'description' => '',
'gallery' => [],
'brands' => [[
'slug' => $slug,
'name' => (string) ($brand['name'] ?? ''),
'link' => ! empty($brand['has_detail_page']) ? '/marken/'.$slug : null,
]],
];
}
}
return $this->limit > 0 ? array_slice($projects, 0, $this->limit) : $projects;
return $projects;
}
public function render()