@extends('layouts.dashboard')
@section('content')
@php
/**
* Vendor → TV Screens: every saved board as a live preview card (studio-grid),
* plus where to point a TV to connect it.
* @var iterable $screens rows: id, name, config, media_path
* @var array $devicesByScreen [screen_id => [device rows]]
* @var bool $canManage
* @var array $restaurant the vendor's restaurant (merged in by render())
*/
$screens = $screens ?? [];
$devicesByScreen = $devicesByScreen ?? [];
$playlistMeta = $playlistMeta ?? []; // [screen_id => ['count' =>, 'first' =>]] for slideshow rows
$scheduleNames = $scheduleNames ?? []; // [schedule_id => name] for the dayparted boards
$canManage = $canManage ?? false;
$slug = (string) ($restaurant['slug'] ?? '');
/** Build the live-preview URL for a screen from its saved column config. */
$previewUrl = static function (\App\Models\TvScreen|array $screen) use ($slug, $__env): string {
$c = \App\Models\TvScreen::config($screen);
return url('/tv/preview?' . http_build_query([
'slug' => $slug,
'orientation' => $c['orientation'],
'theme' => $c['theme'],
'accent' => $c['accent'],
'bgColor' => $c['bgColor'],
'header' => $c['header'] ? 1 : 0,
'headerText' => $c['headerText'],
'showCuisine' => $c['showCuisine'] ? 1 : 0,
'footer' => $c['footer'] ? 1 : 0,
'footerText' => $c['footerText'],
'poweredBy' => $c['poweredBy'] ? 1 : 0,
'spacing' => $c['spacing'],
'columns' => json_encode($c['columns'], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
]));
};
$playUrl = rtrim((string) route('tv.play'), '/');
@endphp
@php /* .qm-d2: the dashboard density standard (app.css §35) */
@endphp
@php // Page primary action → top-bar subheader slot (leaves the table card header for the title).
@endphp
@php ob_start();
@endphp
@if ($canManage)
@if (count($screens) - count($playlistMeta) >= 2)
{{ t_raw('vendor.screens.show_add') }}
@endif
{{ t_raw('vendor.screens.btn_add') }}
@endif
@php \App\Support\View::slot('subhead', ob_get_clean());
@endphp
{{ t_raw('vendor.screens.list_heading') }}
{{ t_raw('vendor.screens.subtitle') }}
{{ t_raw('vendor.screens.connect_hint') }}
{{ $playUrl }}
@if (count($screens) === 0)
{{ t_raw('vendor.screens.empty_title') }}
{{ t_raw('vendor.screens.empty_body') }}
@if ($canManage)
{{ t_raw('vendor.screens.btn_add') }}
@endif
@else
@php
$cards = [];
@endphp
@foreach ($screens as $s)
@php
$sid = (int) $s['id'];
$paired = count($devicesByScreen[$sid] ?? []);
ob_start();
@endphp
@if ($paired)
{{ t_raw('vendor.screens.on_tvs', [':n' => $paired]) }}
@else{{ t_raw('vendor.screens.not_paired') }}@endif
@php $sch = $scheduleNames[(int) ($s['schedule_id'] ?? 0)] ?? '';
@endphp
@if ($sch !== '') ·
{{ $sch }}@endif
@php $status = trim(ob_get_clean());
ob_start();
@endphp
@if ($canManage)
@endif
{{ t_raw('common.edit') }}
@php
$actions = ob_get_clean();
// A slideshow card plays its own rotation shell (/vendor/screens/{id}/play — the same
// chrome-free player its Preview opens), so the card transitions exactly as the TV
// will, saved pace and transition included. It froze on the first member's board
// before, which read as a broken slideshow. Everything else (edit/duplicate/delete/
// pairing) is unchanged because a slideshow IS a screen row.
$plMeta = $playlistMeta[$sid] ?? null;
if ($plMeta !== null) {
$chip = '
'
. e(t('vendor.screens.show_count', [':n' => (int) $plMeta['count']])) . '';
$media = ($plMeta['first']
? '
'
: '
')
. $chip;
$status = t('vendor.screens.show_badge') . ' · ' . $status;
} else {
$media = '
';
}
$cards[] = [
'media' => $media,
'href' => url('/vendor/screens/' . $sid),
'name' => $s['name'],
'status' => $status,
'actions' => $actions,
];
@endphp
@endforeach
@php
echo partial('studio-grid', ['cards' => $cards, 'mode' => 'frame', 'cols' => 4, 'ratio' => '16 / 9', 'tone' => 'dark', 'flush' => true]);
@endphp
@endif
@php /* /.qm-d2 */
@endphp
@endsection