isAgentPortal() ? collect() : User::query()->orderBy('username')->get(['id', 'username']); return view('admin.dashboard.index', [ 'portal' => $this->portal(), 'agents' => $agents, ]); } public function data(Request $request) { $range = (string) $request->query('range', '30d'); [$from, $to] = $this->rangeBounds($range); $channelId = trim((string) $request->query('channel_id', '')); $agentUserId = $this->isAgentPortal() ? (int) ($this->agent()?->id ?? 0) : (int) $request->query('agent_user_id', 0); $base = Device::query(); AgentScope::applyDeviceChannelScope($base, $this->agent()); if (! $this->isAgentPortal() && $agentUserId > 0) { AgentScope::applyAgentUserFilter($base, $agentUserId); } if ($channelId !== '') { $base->where('channel_id', 'like', '%'.$channelId.'%'); } $total = (clone $base)->count(); $newCount = (clone $base)->whereBetween('created_at', [$from, $to])->count(); $activeCount = (clone $base)->whereBetween('updated_at', [$from, $to])->count(); $visits = PageVisit::query(); AgentScope::applyChannelIdScope($visits, $this->agent()); if (! $this->isAgentPortal() && $agentUserId > 0) { AgentScope::applyChannelIdAgentUserFilter($visits, $agentUserId); } if ($channelId !== '') { $visits->where('channel_id', 'like', '%'.$channelId.'%'); } $visits->whereBetween('created_at', [$from, $to]); $pv = (clone $visits)->count(); $uv = (int) (clone $visits)->selectRaw('COUNT(DISTINCT client_uid) as aggregate')->value('aggregate'); $byOs = (clone $visits) ->select('os') ->selectRaw('COUNT(*) as pv') ->selectRaw('COUNT(DISTINCT client_uid) as uv') ->groupBy('os') ->orderByDesc('pv') ->limit(10) ->get() ->map(static fn ($r) => [ 'label' => ((string) ($r->os ?? '')) !== '' ? (string) $r->os : 'Unknown', 'pv' => (int) $r->pv, 'uv' => (int) $r->uv, ]) ->values(); $byBrowser = (clone $visits) ->select('browser') ->selectRaw('COUNT(*) as pv') ->selectRaw('COUNT(DISTINCT client_uid) as uv') ->groupBy('browser') ->orderByDesc('pv') ->limit(10) ->get() ->map(static fn ($r) => [ 'label' => ((string) ($r->browser ?? '')) !== '' ? (string) $r->browser : 'Unknown', 'pv' => (int) $r->pv, 'uv' => (int) $r->uv, ]) ->values(); return response()->json([ 'code' => 0, 'msg' => '', 'data' => [ 'total' => $total, 'new_count' => $newCount, 'active_count' => $activeCount, 'pv' => $pv, 'uv' => $uv, 'by_os' => $byOs, 'by_browser' => $byBrowser, 'range' => $range, 'from' => $from->toDateTimeString(), 'to' => $to->toDateTimeString(), ], ]); } /** * @return array{0: Carbon, 1: Carbon} */ private function rangeBounds(string $range): array { $now = Carbon::now(); return match ($range) { 'today' => [$now->copy()->startOfDay(), $now->copy()->endOfDay()], 'yesterday' => [ $now->copy()->subDay()->startOfDay(), $now->copy()->subDay()->endOfDay(), ], '7d' => [$now->copy()->subDays(6)->startOfDay(), $now->copy()->endOfDay()], default => [$now->copy()->subDays(29)->startOfDay(), $now->copy()->endOfDay()], }; } }