qrCodes() ->where('type', QrCode::TYPE_EVENT) ->get(); $eventIds = $events->pluck('id'); $upcomingCount = $events->filter(function (QrCode $event) { $startsAt = $event->content()['starts_at'] ?? null; if (! $startsAt) { return true; } return strtotime((string) $startsAt) >= now()->startOfDay()->timestamp; })->count(); $registrationsQuery = QrEventRegistration::query() ->whereIn('qr_code_id', $eventIds) ->where('status', QrEventRegistration::STATUS_CONFIRMED); $ticketsSold = (clone $registrationsQuery)->count(); $revenueMinor = (int) (clone $registrationsQuery)->sum('amount_minor'); $checkedIn = QrEventRegistration::query() ->whereIn('qr_code_id', $eventIds) ->whereNotNull('checked_in_at') ->count(); $checkInRate = $ticketsSold > 0 ? round(($checkedIn / $ticketsSold) * 100) : 0; $recentEvents = $account->qrCodes() ->where('type', QrCode::TYPE_EVENT) ->latest() ->limit(5) ->get() ->map(function (QrCode $event) { $event->confirmed_count = $event->eventRegistrations() ->where('status', QrEventRegistration::STATUS_CONFIRMED) ->count(); return $event; }); $programmeCount = $account->qrCodes() ->whereIn('type', QrTypeCatalog::programmeTypes()) ->count(); $balanceMinor = 0; try { $balanceMinor = $this->billing->balanceMinor($account->public_id); } catch (Throwable $e) { Log::warning('Events dashboard could not load wallet balance', [ 'user' => $account->public_id, 'error' => $e->getMessage(), ]); } return view('events.dashboard', [ 'upcomingCount' => $upcomingCount, 'ticketsSold' => $ticketsSold, 'revenueMinor' => $revenueMinor, 'checkInRate' => $checkInRate, 'recentEvents' => $recentEvents, 'programmeCount' => $programmeCount, 'balanceMinor' => $balanceMinor, ]); } }