toDateString(); $yesterday = now()->subDay()->toDateString(); // ── Заявки ──────────────────────────────────────────────────────── $leadsToday = Lead::whereDate('created_at', $today)->count(); $leadsYesterday = Lead::whereDate('created_at', $yesterday)->count(); $leadsTotal = Lead::count(); $leadsUnread = Lead::whereNull('read_at')->count(); // График заявок за 14 дней $leadsChart = $this->chartData( Lead::class, 'created_at', 14, 'Заявки' ); // Последние 6 заявок $recentLeads = Lead::latest()->limit(6)->get(); // ── Посетители ──────────────────────────────────────────────────── $visitRow = DB::table('page_visits')->where('date', $today)->first(); $visitYesterday = DB::table('page_visits')->where('date', $yesterday)->first(); $visitsToday = $visitRow?->views ?? 0; $uniqueToday = $visitRow?->unique_ips ?? 0; // График посетителей за 14 дней $visitsChart = $this->visitsChartData(14); // ── Контент ─────────────────────────────────────────────────────── $carsTotal = Car::count(); $servicesTotal = Service::count(); $reviewsTotal = Review::count(); // ── Скорость / система ──────────────────────────────────────────── $systemInfo = $this->systemInfo(); // ── Средняя скорость ответа (самозамер) ─────────────────────────── $responseTime = $this->measureSelfResponseTime(); return view('admin.dashboard', compact( 'leadsToday', 'leadsYesterday', 'leadsTotal', 'leadsUnread', 'leadsChart', 'recentLeads', 'visitsToday', 'uniqueToday', 'visitYesterday', 'visitsChart', 'carsTotal', 'servicesTotal', 'reviewsTotal', 'systemInfo', 'responseTime' )); } // ── Приватные хелперы ───────────────────────────────────────────────── private function chartData(string $model, string $column, int $days, string $label): array { $start = now()->subDays($days - 1)->startOfDay(); $rows = DB::table((new $model)->getTable()) ->selectRaw("DATE($column) as d, COUNT(*) as cnt") ->where($column, '>=', $start) ->groupBy('d') ->pluck('cnt', 'd'); $labels = []; $data = []; for ($i = $days - 1; $i >= 0; $i--) { $date = now()->subDays($i)->toDateString(); $labels[] = now()->subDays($i)->format('d.m'); $data[] = (int) ($rows[$date] ?? 0); } return compact('labels', 'data', 'label'); } private function visitsChartData(int $days): array { $start = now()->subDays($days - 1)->toDateString(); $rows = DB::table('page_visits') ->where('date', '>=', $start) ->orderBy('date') ->pluck('views', 'date'); $labels = []; $data = []; for ($i = $days - 1; $i >= 0; $i--) { $date = now()->subDays($i)->toDateString(); $labels[] = now()->subDays($i)->format('d.m'); $data[] = (int) ($rows[$date] ?? 0); } return ['labels' => $labels, 'data' => $data, 'label' => 'Просмотры']; } private function systemInfo(): array { $cacheDriver = config('cache.default', 'file'); $opcache = function_exists('opcache_get_status') ? opcache_get_status(false) : null; return [ 'php' => PHP_VERSION, 'laravel' => app()->version(), 'cache_driver' => $cacheDriver, 'opcache' => $opcache && ($opcache['opcache_enabled'] ?? false), 'opcache_hits' => $opcache ? ($opcache['opcache_statistics']['hits'] ?? 0) : 0, 'opcache_misses'=> $opcache ? ($opcache['opcache_statistics']['misses'] ?? 0) : 0, 'disk_free' => $this->humanBytes(disk_free_space(base_path())), 'disk_total' => $this->humanBytes(disk_total_space(base_path())), 'disk_pct' => round((1 - disk_free_space(base_path()) / disk_total_space(base_path())) * 100), 'memory_limit' => ini_get('memory_limit'), 'max_upload' => ini_get('upload_max_filesize'), ]; } private function measureSelfResponseTime(): ?int { // Берём время старта текущего запроса как proxy метрики if (defined('LARAVEL_START')) { return (int) ((microtime(true) - LARAVEL_START) * 1000); } return null; } private function humanBytes(float $bytes): string { foreach (['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'] as $unit) { if ($bytes < 1024) { return round($bytes, 1) . ' ' . $unit; } $bytes /= 1024; } return round($bytes, 1) . ' ПБ'; } }