10-04-2026

This commit is contained in:
Kevin Adametz 2026-04-10 17:18:17 +02:00
parent 4d6b4930b2
commit 4bb89aad8c
836 changed files with 52961 additions and 5950 deletions

View file

@ -0,0 +1,453 @@
<?php
namespace App\Livewire\Admin\Cms;
use App\Enums\DisplayVersionType;
use App\Models\DisplayVersion;
use App\Models\DisplayVersionItem;
use Illuminate\Support\Facades\File;
use Livewire\Attributes\On;
use Livewire\Component;
class DisplayVersionEditor extends Component
{
public DisplayVersion $version;
public string $versionName = '';
// Item Modal
public bool $showItemModal = false;
public ?int $itemId = null;
public string $itemType = '';
// Video-Display: Video fields
public string $videoFilename = '';
public string $videoTitle = '';
public int $videoPosition = 25;
public bool $videoIsActive = true;
// Video-Display: Footer fields
public string $footerHeadline = '';
public string $footerSubline = '';
public string $footerUrl = '';
public bool $footerIsActive = true;
// B2in: Media fields
public string $mediaType = 'image';
public string $mediaCategory = 'immobilien';
public string $mediaUrl = '';
public string $mediaHeadline = '';
public string $mediaSubline = '';
public int $mediaDuration = 10;
public bool $mediaIsActive = true;
// Offers: Slide fields
public string $slideType = 'product-hero';
public int $slideDuration = 8000;
public string $slideImageUrl = '';
public string $slideBadge = '';
public string $slideEyebrow = '';
public string $slideTitle = '';
public string $slideSubline = '';
public string $slidePrice = '';
public string $slideOriginalPrice = '';
public string $slideTagText = '';
/** @var array<string> */
public array $slideBullets = [];
public string $slideDisclaimer = '';
public string $slideQrUrl = '';
public string $slideQrTitle = '';
public string $slideContact = '';
public bool $slideShowBrandText = false;
public string $slideBrandTagline = '';
public bool $slideIsActive = true;
// Settings Modal
public bool $showSettingsModal = false;
public array $settings = [];
/** @var array<string> */
public array $availableVideos = [];
public function mount(DisplayVersion $displayVersion): void
{
$this->version = $displayVersion;
$this->versionName = $displayVersion->name;
$this->settings = $displayVersion->settings ?? [];
if ($this->version->type === DisplayVersionType::VideoDisplay) {
$this->loadAvailableVideos();
}
}
public function loadAvailableVideos(): void
{
$assetsPath = public_path('_cabinet/assets');
if (File::exists($assetsPath)) {
$this->availableVideos = collect(File::files($assetsPath))
->map(fn ($file) => $file->getFilename())
->filter(fn ($filename) => in_array(pathinfo($filename, PATHINFO_EXTENSION), ['mp4', 'webm', 'mov']))
->values()
->toArray();
}
}
public function toggleTheme(): void
{
$settings = $this->version->settings ?? [];
$settings['theme'] = ($settings['theme'] ?? 'dark') === 'dark' ? 'light' : 'dark';
$this->version->update(['settings' => $settings]);
$this->settings = $settings;
}
public function saveName(): void
{
$this->validate([
'versionName' => 'required|string|max:255',
]);
$this->version->update(['name' => $this->versionName]);
session()->flash('success', 'Name aktualisiert!');
}
// ========================================
// SETTINGS
// ========================================
public function openSettingsModal(): void
{
$this->settings = $this->version->settings ?? [];
$this->showSettingsModal = true;
}
public function saveSettings(): void
{
$this->version->update(['settings' => $this->settings]);
$this->showSettingsModal = false;
session()->flash('success', 'Einstellungen gespeichert!');
}
// ========================================
// ITEM CRUD
// ========================================
public function openItemModal(?int $id = null, string $type = ''): void
{
$this->resetItemForm();
if ($id) {
$item = DisplayVersionItem::findOrFail($id);
$this->itemId = $item->id;
$this->itemType = $item->item_type;
$this->loadItemContent($item);
} else {
$this->itemType = $type ?: $this->defaultItemType();
}
$this->showItemModal = true;
}
public function saveItem(): void
{
$content = $this->buildItemContent();
$isActive = $this->getActiveFlag();
if ($this->itemId) {
$item = DisplayVersionItem::findOrFail($this->itemId);
$item->update([
'content' => $content,
'is_active' => $isActive,
]);
session()->flash('success', 'Inhalt aktualisiert!');
} else {
$maxSort = DisplayVersionItem::where('display_version_id', $this->version->id)
->where('item_type', $this->itemType)
->max('sort_order') ?? -1;
DisplayVersionItem::create([
'display_version_id' => $this->version->id,
'item_type' => $this->itemType,
'content' => $content,
'sort_order' => $maxSort + 1,
'is_active' => $isActive,
]);
session()->flash('success', 'Inhalt hinzugefügt!');
}
$this->closeItemModal();
}
public function deleteItem(int $id): void
{
DisplayVersionItem::findOrFail($id)->delete();
session()->flash('success', 'Inhalt gelöscht!');
}
public function toggleItemStatus(int $id): void
{
$item = DisplayVersionItem::findOrFail($id);
$item->update(['is_active' => ! $item->is_active]);
}
public function moveItem(int $id, string $direction): void
{
$item = DisplayVersionItem::findOrFail($id);
$currentOrder = $item->sort_order;
$swapItem = DisplayVersionItem::where('display_version_id', $this->version->id)
->where('item_type', $item->item_type)
->where('sort_order', $direction === 'up' ? $currentOrder - 1 : $currentOrder + 1)
->first();
if ($swapItem) {
$item->update(['sort_order' => $swapItem->sort_order]);
$swapItem->update(['sort_order' => $currentOrder]);
}
}
#[On('display-media-selected')]
public function onDisplayMediaSelected(string $field, ?int $mediaId, ?string $url): void
{
if (! $url) {
return;
}
match ($field) {
'videoFilename' => $this->videoFilename = $url,
'mediaUrl' => $this->mediaUrl = $url,
'slideImageUrl' => $this->slideImageUrl = $url,
default => null,
};
}
public function addBullet(): void
{
$this->slideBullets[] = '';
}
public function removeBullet(int $index): void
{
unset($this->slideBullets[$index]);
$this->slideBullets = array_values($this->slideBullets);
}
public function closeItemModal(): void
{
$this->showItemModal = false;
$this->resetItemForm();
}
// ========================================
// HELPERS
// ========================================
private function loadItemContent(DisplayVersionItem $item): void
{
$content = $item->content;
match ($item->item_type) {
'video' => $this->loadVideoContent($content),
'footer' => $this->loadFooterContent($content),
'media' => $this->loadMediaContent($content),
'slide' => $this->loadSlideContent($content),
default => null,
};
}
private function loadVideoContent(array $content): void
{
$this->videoFilename = $content['filename'] ?? '';
$this->videoTitle = $content['title'] ?? '';
$this->videoPosition = $content['position'] ?? 25;
$this->videoIsActive = true;
}
private function loadFooterContent(array $content): void
{
$this->footerHeadline = $content['headline'] ?? '';
$this->footerSubline = $content['subline'] ?? '';
$this->footerUrl = $content['url'] ?? '';
$this->footerIsActive = true;
}
private function loadMediaContent(array $content): void
{
$this->mediaType = $content['media_type'] ?? 'image';
$this->mediaCategory = $content['category'] ?? 'immobilien';
$this->mediaUrl = $content['media_url'] ?? '';
$this->mediaHeadline = $content['headline'] ?? '';
$this->mediaSubline = $content['subline'] ?? '';
$this->mediaDuration = $content['duration_seconds'] ?? 10;
$this->mediaIsActive = true;
}
private function loadSlideContent(array $content): void
{
$this->slideType = $content['type'] ?? 'product-hero';
$this->slideDuration = $content['duration'] ?? 8000;
$this->slideImageUrl = $content['image_url'] ?? '';
$this->slideBadge = $content['badge_text'] ?? '';
$this->slideEyebrow = $content['eyebrow'] ?? '';
$this->slideTitle = $content['title'] ?? '';
$this->slideSubline = $content['subline'] ?? '';
$this->slidePrice = $content['price'] ?? '';
$this->slideOriginalPrice = $content['original_price'] ?? '';
$this->slideTagText = $content['tag_text'] ?? '';
$this->slideBullets = $content['bullets'] ?? [];
$this->slideDisclaimer = $content['disclaimer'] ?? '';
$this->slideQrUrl = $content['qr_url'] ?? '';
$this->slideQrTitle = $content['qr_title'] ?? '';
$this->slideContact = $content['contact'] ?? '';
$this->slideShowBrandText = $content['show_brand_text'] ?? false;
$this->slideBrandTagline = $content['brand_tagline'] ?? '';
$this->slideIsActive = true;
}
/**
* @return array<string, mixed>
*/
private function buildItemContent(): array
{
return match ($this->itemType) {
'video' => [
'filename' => $this->videoFilename,
'title' => $this->videoTitle,
'position' => $this->videoPosition,
],
'footer' => [
'headline' => $this->footerHeadline,
'subline' => $this->footerSubline,
'url' => $this->footerUrl ?: null,
],
'media' => [
'media_type' => $this->mediaType,
'category' => $this->mediaCategory,
'media_url' => $this->mediaUrl,
'headline' => $this->mediaHeadline,
'subline' => $this->mediaSubline,
'duration_seconds' => $this->mediaDuration,
],
'slide' => [
'type' => $this->slideType,
'duration' => $this->slideDuration,
'image_url' => $this->slideImageUrl,
'badge_text' => $this->slideBadge,
'eyebrow' => $this->slideEyebrow,
'title' => $this->slideTitle,
'subline' => $this->slideSubline,
'price' => $this->slidePrice,
'original_price' => $this->slideOriginalPrice,
'tag_text' => $this->slideTagText,
'bullets' => $this->slideBullets,
'disclaimer' => $this->slideDisclaimer,
'qr_url' => $this->slideQrUrl,
'qr_title' => $this->slideQrTitle,
'contact' => $this->slideContact,
'show_brand_text' => $this->slideShowBrandText,
'brand_tagline' => $this->slideBrandTagline,
],
default => [],
};
}
private function getActiveFlag(): bool
{
return match ($this->itemType) {
'video' => $this->videoIsActive,
'footer' => $this->footerIsActive,
'media' => $this->mediaIsActive,
'slide' => $this->slideIsActive,
default => true,
};
}
private function defaultItemType(): string
{
return match ($this->version->type) {
DisplayVersionType::VideoDisplay => 'video',
DisplayVersionType::B2in => 'media',
DisplayVersionType::Offers => 'slide',
};
}
private function resetItemForm(): void
{
$this->itemId = null;
$this->itemType = '';
$this->videoFilename = '';
$this->videoTitle = '';
$this->videoPosition = 25;
$this->videoIsActive = true;
$this->footerHeadline = '';
$this->footerSubline = '';
$this->footerUrl = '';
$this->footerIsActive = true;
$this->mediaType = 'image';
$this->mediaCategory = 'immobilien';
$this->mediaUrl = '';
$this->mediaHeadline = '';
$this->mediaSubline = '';
$this->mediaDuration = 10;
$this->mediaIsActive = true;
$this->slideType = 'product-hero';
$this->slideDuration = 8000;
$this->slideImageUrl = '';
$this->slideBadge = '';
$this->slideEyebrow = '';
$this->slideTitle = '';
$this->slideSubline = '';
$this->slidePrice = '';
$this->slideOriginalPrice = '';
$this->slideTagText = '';
$this->slideBullets = [];
$this->slideDisclaimer = '';
$this->slideQrUrl = '';
$this->slideQrTitle = '';
$this->slideContact = '';
$this->slideShowBrandText = false;
$this->slideBrandTagline = '';
$this->slideIsActive = true;
}
public function render()
{
$items = $this->version->items()->get()->groupBy('item_type');
return view('livewire.admin.cms.display-version-editor', [
'items' => $items,
]);
}
}