- Mediathek: Video-Vorschaubilder statt Icons (FFmpeg-Thumbnails + Backfill-Command), Kategorie "Sonstiges" - B2in Media-Picker zeigt alle Medientypen, Typ wird automatisch erkannt; Thumbnail-Preview vor allen Medien-URL-Feldern - B2in Marke/Footer: Footer ein/aus, Logo+Claim frei positionierbar (Ecken) mit Constraints, separate Anzeige-Schalter - Angebote-Modul dynamisch: kein Slide-Typ mehr, einheitliches Detail-Layout mit ein-/ausblendbaren Bloecken, Logo/Brand pro Slide, Streichpreis-Option - Player: leere Module stoppen Endlosschleife, dynamische Layout-Anpassung bei verstecktem Footer/Header - Fix: Script-Ladereihenfolge (Livewire vor Flux), entfernte stale public/flux/flux.js, Modal-Crash beim Aktualisieren behoben Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
5.1 KiB
PHP
81 lines
5.1 KiB
PHP
{{-- Offers: Slides --}}
|
||
@php
|
||
$slides = $items->get('slide', collect());
|
||
@endphp
|
||
|
||
<flux:card>
|
||
<div class="flex items-center justify-between mb-6">
|
||
<div>
|
||
<flux:heading size="lg">{{ __('Angebote') }}</flux:heading>
|
||
<flux:subheading>{{ __('Angebote werden im einheitlichen Detail-Layout in der angegebenen Reihenfolge angezeigt') }}</flux:subheading>
|
||
</div>
|
||
<flux:button wire:click="openItemModal(null, 'slide')" icon="plus">
|
||
{{ __('Angebot hinzufügen') }}
|
||
</flux:button>
|
||
</div>
|
||
|
||
@if($slides->isEmpty())
|
||
<div class="text-center py-12 text-zinc-500 dark:text-zinc-400">
|
||
<flux:icon.presentation-chart-bar class="w-16 h-16 mx-auto mb-4 opacity-50" />
|
||
<p>{{ __('Noch keine Angebote vorhanden.') }}</p>
|
||
</div>
|
||
@else
|
||
<div class="space-y-3">
|
||
@foreach($slides as $index => $item)
|
||
<div wire:key="item-{{ $item->id }}"
|
||
class="flex items-center gap-4 p-4 bg-zinc-50 dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 transition">
|
||
|
||
<div class="flex flex-col gap-1">
|
||
@if($index > 0)
|
||
<flux:button wire:click="moveItem({{ $item->id }}, 'up')" size="xs" variant="ghost" icon="chevron-up" class="text-zinc-400 hover:text-zinc-600"></flux:button>
|
||
@endif
|
||
@if($index < count($slides) - 1)
|
||
<flux:button wire:click="moveItem({{ $item->id }}, 'down')" size="xs" variant="ghost" icon="chevron-down" class="text-zinc-400 hover:text-zinc-600"></flux:button>
|
||
@endif
|
||
</div>
|
||
|
||
<div class="flex h-28 w-20 shrink-0 flex-col rounded-lg border border-zinc-200 bg-white p-1.5 dark:border-zinc-700 dark:bg-zinc-900">
|
||
<div class="mb-1.5 h-14 rounded bg-zinc-100 bg-cover bg-center dark:bg-zinc-800"
|
||
@if(!empty($item->content['image_url'])) style="background-image: url('{{ $item->content['image_url'] }}')" @endif></div>
|
||
<div class="line-clamp-2 text-[10px] font-semibold leading-tight text-zinc-700 dark:text-zinc-200">{{ $item->content['title'] ?? 'Slide' }}</div>
|
||
<div class="mt-auto truncate text-[9px] text-zinc-500">{{ $item->content['price'] ?? ($item->content['badge_text'] ?? '') }}</div>
|
||
</div>
|
||
|
||
<div class="flex-1 min-w-0">
|
||
@php
|
||
$c = $item->content;
|
||
$enabledBlocks = collect([
|
||
'Badge' => ($c['show_badge'] ?? ! empty($c['badge_text'])) && ! empty($c['badge_text']),
|
||
'Aufzählung' => ($c['show_bullets'] ?? ! empty($c['bullets'])) && ! empty($c['bullets']),
|
||
'Preis' => ($c['show_price'] ?? ! empty($c['price'])) && ! empty($c['price']),
|
||
'QR' => ($c['show_qr'] ?? ! empty($c['qr_url'])) && ! empty($c['qr_url']),
|
||
'Kontakt' => ($c['show_contact'] ?? ! empty($c['contact'])) && ! empty($c['contact']),
|
||
])->filter()->keys();
|
||
@endphp
|
||
<div class="flex items-center gap-3 mb-1">
|
||
<flux:badge :color="$item->is_active ? 'green' : 'zinc'" size="sm">
|
||
{{ $item->is_active ? __('Aktiv') : __('Inaktiv') }}
|
||
</flux:badge>
|
||
<span class="font-semibold text-sm truncate">{{ $c['title'] ?? '–' }}</span>
|
||
</div>
|
||
<div class="flex flex-wrap items-center gap-2 text-xs text-zinc-600 dark:text-zinc-400">
|
||
<span>{{ number_format(($c['duration'] ?? 8000) / 1000, 1) }}s</span>
|
||
@if(!empty($c['price']) && ($c['show_price'] ?? ! empty($c['price'])))
|
||
<span class="font-medium">{{ $c['price'] }}</span>
|
||
@endif
|
||
@foreach($enabledBlocks as $block)
|
||
<flux:badge color="zinc" size="sm">{{ $block }}</flux:badge>
|
||
@endforeach
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-2">
|
||
<flux:button wire:click="toggleItemStatus({{ $item->id }})" size="sm" variant="ghost" :icon="$item->is_active ? 'eye-slash' : 'eye'"></flux:button>
|
||
<flux:button wire:click="openItemModal({{ $item->id }})" size="sm" variant="ghost" icon="pencil"></flux:button>
|
||
<flux:button wire:click="deleteItem({{ $item->id }})" wire:confirm="Möchten Sie diesen Eintrag wirklich löschen?" size="sm" variant="ghost" icon="trash" class="text-red-600 hover:text-red-700"></flux:button>
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
@endif
|
||
</flux:card>
|