userStatsService = $userStatsService; $this->systemMetricsService = $systemMetricsService; $this->registrationStatusService = $registrationStatusService; $this->siteStatusService = $siteStatusService; $this->snapshot = $snapshot; } /** * @throws \Exception */ public function index(): mixed { $this->setAdminPrefs(); $payload = $this->snapshot->get(); return view('admin.dashboard', array_merge($this->viewData, [ 'meta_title' => 'Admin Home', 'meta_description' => 'Admin home page', // Lightweight data is rendered server-side; heavy widgets fetch on mount. 'stats' => $payload['stats'], 'registrationStatus' => $payload['registrationStatus'], 'nextRegistrationPeriod' => $payload['nextRegistrationPeriod'], ])); } /** * JSON payload consumed by the dashboard's deferred widgets (User Statistics, * System Resources history, Recent Activity, Site Status) and by the * client-side auto-refresh which also re-renders the headline stat tiles * and the registration status panel from this payload. Reads from the * same snapshot cache the index uses, so the warmer keeps it hot. */ public function getDashboardData(): JsonResponse { $payload = $this->snapshot->get(); $serviceStatuses = collect($payload['serviceStatuses'])->map(static fn ($svc) => [ 'name' => $svc->name, 'slug' => $svc->slug, 'check_type' => $svc->check_type, 'status' => $svc->status->value, 'status_label' => $svc->status->label(), 'uptime_percentage' => (float) $svc->uptime_percentage, ])->values(); $activeIncidents = collect($payload['activeIncidents'])->map(static fn ($incident) => [ 'id' => $incident->id, 'title' => $incident->title, 'impact' => $incident->impact->value, 'impact_label' => $incident->impact->label(), 'started_at' => $incident->started_at?->toIso8601String(), 'started_at_human' => $incident->started_at?->diffForHumans(), 'is_auto' => (bool) $incident->is_auto, 'services' => $incident->services->pluck('name')->all(), ])->values(); $recentActivity = array_map(static fn ($activity): array => [ 'type' => $activity->type, 'message' => $activity->message, 'icon' => $activity->icon, 'icon_bg' => $activity->icon_bg, 'icon_color' => $activity->icon_color, 'created_at' => $activity->created_at?->toIso8601String(), 'created_at_human' => $activity->created_at?->diffForHumans(), 'username' => $activity->username, 'metadata' => $activity->metadata, ], $payload['recent_activity']); $registrationStatus = $payload['registrationStatus']; $serializePeriod = static fn ($period): ?array => $period === null ? null : [ 'id' => $period->id, 'name' => $period->name, 'starts_at' => $period->starts_at?->format('Y-m-d H:i'), 'ends_at' => $period->ends_at?->format('Y-m-d H:i'), ]; $registrationPayload = [ 'manual_status' => $registrationStatus['manual_status'], 'manual_status_label' => $registrationStatus['manual_status_label'], 'effective_status' => $registrationStatus['effective_status'], 'effective_status_label' => $registrationStatus['effective_status_label'], 'scheduled_override_active' => (bool) $registrationStatus['scheduled_override_active'], 'message' => $registrationStatus['message'], 'active_period' => $serializePeriod($registrationStatus['active_period']), ]; $generatedAt = $payload['generated_at'] ?? now()->toIso8601String(); $generatedAtCarbon = Carbon::parse($generatedAt); return response()->json([ 'success' => true, 'generated_at' => $generatedAt, 'generated_at_time' => $generatedAtCarbon->format('H:i:s'), 'stats' => $payload['stats'], 'registrationStatus' => $registrationPayload, 'nextRegistrationPeriod' => $serializePeriod($payload['nextRegistrationPeriod']), 'userStats' => $payload['userStats'], 'systemMetrics' => $payload['systemMetrics'], 'recent_activity' => $recentActivity, 'serviceStatuses' => $serviceStatuses, 'activeIncidents' => $activeIncidents, ]); } public function getRecentActivity(): JsonResponse { $payload = $this->snapshot->get(); $activities = array_map(static fn ($activity): array => [ 'type' => $activity->type, 'message' => $activity->message, 'icon' => $activity->icon, 'icon_bg' => $activity->icon_bg, 'icon_color' => $activity->icon_color, 'created_at' => $activity->created_at?->diffForHumans(), 'username' => $activity->username, 'metadata' => $activity->metadata, ], $payload['recent_activity']); return response()->json([ 'success' => true, 'activities' => $activities, ]); } public function getUserActivityMinutes(): JsonResponse { $downloadsPerMinute = $this->userStatsService->getDownloadsPerMinute(60); $apiHitsPerMinute = $this->userStatsService->getApiHitsPerMinute(60); return response()->json([ 'downloads' => $downloadsPerMinute, 'api_hits' => $apiHitsPerMinute, ]); } public function getCurrentMetrics(): JsonResponse { $cpuUsage = $this->systemMetricsService->getCpuUsage(); $ramUsage = $this->systemMetricsService->getRamUsage(); $cpuInfo = $this->systemMetricsService->getCpuInfo(); $loadAverage = $this->systemMetricsService->getLoadAverage(); return response()->json([ 'success' => true, 'cpu' => [ 'current' => $cpuUsage, 'cores' => $cpuInfo['cores'], 'threads' => $cpuInfo['threads'], 'model' => $cpuInfo['model'], 'load_average' => $loadAverage, ], 'ram' => [ 'used' => $ramUsage['used'], 'total' => $ramUsage['total'], 'percentage' => $ramUsage['percentage'], ], ]); } public function getHistoricalMetrics(): JsonResponse { $timeRange = request('range', '24h'); if ($timeRange === '30d') { $cpuHistory = $this->systemMetricsService->getDailyMetrics('cpu', 30); $ramHistory = $this->systemMetricsService->getDailyMetrics('ram', 30); } else { $cpuHistory = $this->systemMetricsService->getHourlyMetrics('cpu', 24); $ramHistory = $this->systemMetricsService->getHourlyMetrics('ram', 24); } return response()->json([ 'success' => true, 'cpu_history' => $cpuHistory, 'ram_history' => $ramHistory, 'range' => $timeRange, ]); } }