12-05-2026 admin, Panel Displays
This commit is contained in:
parent
0762e3beac
commit
6a65354f4c
43 changed files with 3273 additions and 410 deletions
199
app/Services/DisplayPlaylistConfigBuilder.php
Normal file
199
app/Services/DisplayPlaylistConfigBuilder.php
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\DisplayPlaylist;
|
||||
use App\Models\DisplayVersion;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class DisplayPlaylistConfigBuilder
|
||||
{
|
||||
/**
|
||||
* @return array{playlist: array<int, array<string, mixed>>, updated_at: string|null}
|
||||
*/
|
||||
public function fromPlaylist(DisplayPlaylist $playlist): array
|
||||
{
|
||||
$playlist->loadMissing('modules.items');
|
||||
|
||||
return $this->fromModules($playlist->modules, $playlist->updated_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, DisplayVersion> $modules
|
||||
* @return array{playlist: array<int, array<string, mixed>>, updated_at: string|null}
|
||||
*/
|
||||
public function fromModules(Collection $modules, mixed $fallbackUpdatedAt = null): array
|
||||
{
|
||||
$playlist = $modules
|
||||
->loadMissing('items')
|
||||
->map(fn (DisplayVersion $module) => $this->moduleData($module))
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'playlist' => $playlist,
|
||||
'updated_at' => $this->updatedAt($modules, $fallbackUpdatedAt),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function moduleData(DisplayVersion $module): ?array
|
||||
{
|
||||
$items = $module->items
|
||||
->where('is_active', true)
|
||||
->sortBy('sort_order')
|
||||
->values();
|
||||
|
||||
return match ($module->type->value) {
|
||||
'video-display' => $this->videoDisplayData($module, $items),
|
||||
'b2in' => $this->b2inData($module, $items),
|
||||
'offers' => $this->offersData($module, $items),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, DisplayVersion> $modules
|
||||
*/
|
||||
private function updatedAt(Collection $modules, mixed $fallbackUpdatedAt = null): ?string
|
||||
{
|
||||
$timestamps = collect([$fallbackUpdatedAt])
|
||||
->merge($modules->pluck('updated_at'))
|
||||
->merge($modules->flatMap(fn (DisplayVersion $module) => $module->items->pluck('updated_at')))
|
||||
->filter();
|
||||
|
||||
return $timestamps->max()?->toIso8601String();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, \App\Models\DisplayVersionItem> $items
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function videoDisplayData(DisplayVersion $module, Collection $items): array
|
||||
{
|
||||
$videos = $items->where('item_type', 'video')->values()->map(fn ($item) => [
|
||||
'src' => $this->mediaSource($item->content['filename'] ?? ''),
|
||||
'position' => $item->content['position'] ?? 25,
|
||||
]);
|
||||
|
||||
$footerContent = $items->where('item_type', 'footer')->values()->map(function ($item) {
|
||||
$data = [
|
||||
'headline' => $item->content['headline'] ?? '',
|
||||
'subline' => $item->content['subline'] ?? '',
|
||||
];
|
||||
|
||||
if (! empty($item->content['url'])) {
|
||||
$data['url'] = $item->content['url'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
});
|
||||
|
||||
return [
|
||||
'type' => 'video-display',
|
||||
'version_name' => $module->name,
|
||||
'settings' => array_replace([
|
||||
'qr_label' => 'Website',
|
||||
], $module->settings ?? []),
|
||||
'videoPlaylist' => $videos,
|
||||
'footerContent' => $footerContent,
|
||||
];
|
||||
}
|
||||
|
||||
private function mediaSource(string $source): string
|
||||
{
|
||||
if ($source === '' || str_starts_with($source, 'http') || str_starts_with($source, '/') || str_starts_with($source, '../')) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
return 'assets/'.$source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, \App\Models\DisplayVersionItem> $items
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function b2inData(DisplayVersion $module, Collection $items): array
|
||||
{
|
||||
$mediaItems = $items->where('item_type', 'media')->values()->map(fn ($item) => [
|
||||
'id' => $item->id,
|
||||
'category' => $item->content['category'] ?? 'immobilien',
|
||||
'media_type' => $item->content['media_type'] ?? 'image',
|
||||
'media_url' => $item->content['media_url'] ?? '',
|
||||
'headline' => $item->content['headline'] ?? '',
|
||||
'subline' => $item->content['subline'] ?? '',
|
||||
'duration_seconds' => $item->content['duration_seconds'] ?? 10,
|
||||
'sort_order' => $item->sort_order,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
return [
|
||||
'type' => 'b2in',
|
||||
'version_name' => $module->name,
|
||||
'settings' => array_replace_recursive([
|
||||
'theme' => 'dark',
|
||||
'header_logo_url' => '../assets/b2in-logo-positive.svg',
|
||||
'header_claim' => 'Connecting Design & Property',
|
||||
'footer_url' => 'B2in.eu',
|
||||
'footer_name' => '',
|
||||
'footer_prefix' => 'by',
|
||||
'qr_url' => '',
|
||||
'transition' => [
|
||||
'type' => 'crossfade',
|
||||
'duration_ms' => 800,
|
||||
],
|
||||
'default_image_duration' => 10,
|
||||
], $module->settings ?? []),
|
||||
'items' => $mediaItems,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, \App\Models\DisplayVersionItem> $items
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function offersData(DisplayVersion $module, Collection $items): array
|
||||
{
|
||||
$slides = $items->where('item_type', 'slide')->values()->map(fn ($item) => [
|
||||
'type' => $item->content['type'] ?? 'product-hero',
|
||||
'duration' => $item->content['duration'] ?? 8000,
|
||||
'image_url' => $item->content['image_url'] ?? '',
|
||||
'badge_text' => $item->content['badge_text'] ?? '',
|
||||
'eyebrow' => $item->content['eyebrow'] ?? '',
|
||||
'title' => $item->content['title'] ?? '',
|
||||
'subline' => $item->content['subline'] ?? '',
|
||||
'price' => $item->content['price'] ?? '',
|
||||
'original_price' => $item->content['original_price'] ?? '',
|
||||
'tag_text' => $item->content['tag_text'] ?? '',
|
||||
'bullets' => $item->content['bullets'] ?? [],
|
||||
'disclaimer' => $item->content['disclaimer'] ?? '',
|
||||
'qr_url' => $item->content['qr_url'] ?? '',
|
||||
'qr_title' => $item->content['qr_title'] ?? '',
|
||||
'contact' => $item->content['contact'] ?? '',
|
||||
'show_brand_text' => $item->content['show_brand_text'] ?? false,
|
||||
'brand_tagline' => $item->content['brand_tagline'] ?? '',
|
||||
]);
|
||||
|
||||
return [
|
||||
'type' => 'offers',
|
||||
'version_name' => $module->name,
|
||||
'settings' => array_replace_recursive([
|
||||
'loop' => true,
|
||||
'logo_url' => '../logo-cabinet-300.png',
|
||||
'brand_text' => 'Bielefeld',
|
||||
'footer_claim' => '',
|
||||
'footer_url' => '',
|
||||
'qr_default_title' => 'Kontakt',
|
||||
'qr_subtitle' => 'QR scannen',
|
||||
'transition' => [
|
||||
'type' => 'fade',
|
||||
'duration' => 600,
|
||||
],
|
||||
], $module->settings ?? []),
|
||||
'slides' => $slides,
|
||||
];
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue