where('access_token', $token) ->where('is_active', true) ->first(); } public function touch(DisplayScreen $screen): void { $screen->update(['last_seen_at' => now()]); } /** * @return array */ public function payload(DisplayScreen $screen): array { $queueIds = $screen->service_queue_ids ?? []; $queues = ServiceQueue::query() ->whereIn('id', $queueIds) ->where('is_active', true) ->get(); $nowServing = Ticket::query() ->whereIn('service_queue_id', $queueIds) ->whereIn('status', ['called', 'serving']) ->with(['counter', 'serviceQueue']) ->orderByDesc('called_at') ->limit(5) ->get() ->map(fn (Ticket $t) => [ 'ticket_number' => $t->ticket_number, 'queue_name' => $t->serviceQueue?->name, 'counter' => $t->counter?->name, ]); $waiting = Ticket::query() ->whereIn('service_queue_id', $queueIds) ->where('status', 'waiting') ->count(); $avgWait = (int) Ticket::query() ->whereIn('service_queue_id', $queueIds) ->where('status', 'completed') ->whereDate('issued_at', today()) ->whereNotNull('called_at') ->selectRaw('AVG(TIMESTAMPDIFF(SECOND, issued_at, called_at)) as avg_wait') ->value('avg_wait'); return [ 'screen' => [ 'name' => $screen->name, 'layout' => $screen->layout, ], 'now_serving' => $nowServing, 'waiting_count' => $waiting, 'estimated_wait_minutes' => $avgWait > 0 ? (int) ceil($avgWait / 60) : null, 'queues' => $queues->map(fn (ServiceQueue $q) => [ 'name' => $q->name, 'prefix' => $q->prefix, 'is_paused' => $q->is_paused, ]), 'announcements' => app(VoiceAnnouncementService::class)->pendingForBranch((int) $screen->branch_id), 'updated_at' => now()->toIso8601String(), ]; } }