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:
parent
7953a8c9a1
commit
90aa079cf7
50 changed files with 2580 additions and 324 deletions
|
|
@ -45,6 +45,9 @@ class CmsBrand extends Model
|
|||
'gallery',
|
||||
'website_url',
|
||||
'showroom',
|
||||
'origin_city',
|
||||
'origin_distance',
|
||||
'origin_role',
|
||||
'is_published',
|
||||
'order',
|
||||
];
|
||||
|
|
@ -59,6 +62,9 @@ class CmsBrand extends Model
|
|||
'widget_label',
|
||||
'cta_title',
|
||||
'cta_text',
|
||||
'origin_city',
|
||||
'origin_distance',
|
||||
'origin_role',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
|
|
@ -139,6 +145,9 @@ class CmsBrand extends Model
|
|||
'gallery' => [],
|
||||
'website_url' => '',
|
||||
'showroom' => '',
|
||||
'origin_city' => '',
|
||||
'origin_distance' => '',
|
||||
'origin_role' => '',
|
||||
'has_detail_page' => false,
|
||||
], $brand, ['slug' => $slug, 'has_detail_page' => false]);
|
||||
|
||||
|
|
@ -311,6 +320,9 @@ class CmsBrand extends Model
|
|||
'gallery' => self::normalizeGallery($this->gallery),
|
||||
'website_url' => $this->website_url,
|
||||
'showroom' => $this->showroom,
|
||||
'origin_city' => (string) $this->origin_city,
|
||||
'origin_distance' => (string) $this->origin_distance,
|
||||
'origin_role' => (string) $this->origin_role,
|
||||
'has_detail_page' => true,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
115
app/Models/CmsReference.php
Normal file
115
app/Models/CmsReference.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\Translatable\HasTranslations;
|
||||
|
||||
/**
|
||||
* Referenzprojekt der Interior-Welt: ein realisierter Auftrag mit Titelbild, weiteren Bildern
|
||||
* und den beteiligten Kernmarken (Nachtrag 13). Erscheint auf /referenzen.
|
||||
*
|
||||
* Nicht zu verwechseln mit {@see CmsProject} – das sind die Immobilienprojekte.
|
||||
*/
|
||||
class CmsReference extends Model
|
||||
{
|
||||
use HasFactory, HasTranslations;
|
||||
|
||||
protected $table = 'cms_references';
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'location',
|
||||
'year',
|
||||
'description',
|
||||
'image',
|
||||
'gallery',
|
||||
'brand_slugs',
|
||||
'is_published',
|
||||
'order',
|
||||
];
|
||||
|
||||
/** @var array<string> */
|
||||
public array $translatable = ['title', 'description'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'gallery' => 'array',
|
||||
'brand_slugs' => 'array',
|
||||
'is_published' => 'boolean',
|
||||
'order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function scopePublished(Builder $query): Builder
|
||||
{
|
||||
return $query->where('is_published', true);
|
||||
}
|
||||
|
||||
public function scopeOrdered(Builder $query): Builder
|
||||
{
|
||||
return $query->orderBy('order')->orderBy('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Galerie in eine feste Form bringen: nur Einträge mit Bild, Bildunterschrift getrimmt.
|
||||
*
|
||||
* @param mixed $gallery
|
||||
* @return list<array{image: string, caption: string}>
|
||||
*/
|
||||
public static function normalizeGallery($gallery): array
|
||||
{
|
||||
if (! is_array($gallery)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$out = [];
|
||||
|
||||
foreach ($gallery as $item) {
|
||||
$image = trim((string) (is_array($item) ? ($item['image'] ?? '') : $item));
|
||||
|
||||
if ($image === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$out[] = [
|
||||
'image' => $image,
|
||||
'caption' => is_array($item) ? trim((string) ($item['caption'] ?? '')) : '',
|
||||
];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Beteiligte Marken als Liste mit Name und Link, aufgelöst gegen die veröffentlichten Marken.
|
||||
*
|
||||
* Eine unveröffentlichte oder gelöschte Marke fällt heraus.
|
||||
*
|
||||
* @param array<string, array<string, mixed>> $brands Ergebnis von CmsBrand::forFrontend()
|
||||
* @return list<array{slug: string, name: string, link: ?string}>
|
||||
*/
|
||||
public function resolveBrands(array $brands): array
|
||||
{
|
||||
$out = [];
|
||||
|
||||
foreach ($this->brand_slugs ?? [] as $slug) {
|
||||
$slug = (string) $slug;
|
||||
|
||||
if (! isset($brands[$slug])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$out[] = [
|
||||
'slug' => $slug,
|
||||
'name' => (string) ($brands[$slug]['name'] ?? $slug),
|
||||
'link' => ! empty($brands[$slug]['has_detail_page']) ? '/marken/'.$slug : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue