@extends('admin.layout') @section('title', 'Admin Dashboard') @section('page_title', 'Dashboard') @section('extra_styles') @endsection @section('content') {{-- ── Alert Banner ── --}} @if($failedCount > 0)
{{ $failedCount }} video{{ $failedCount > 1 ? 's' : '' }} failed processing — these uploads need attention. Review now →
@endif @if($processingCount > 0 || $pendingCount > 0)
{{ $processingCount + $pendingCount }} video{{ ($processingCount + $pendingCount) > 1 ? 's' : '' }} in queue — {{ $processingCount }} processing, {{ $pendingCount }} pending.
@endif {{-- ── Stat Cards ── --}}
{{-- Users --}}
{{ number_format($stats['totalUsers']) }}
Total Users
{{ $stats['growthUsers']['pct'] }}%
+{{ $stats['usersThisWeek'] }} this week
{{-- Videos --}}
{{ number_format($stats['totalVideos']) }}
Total Videos
{{ $stats['growthVideos']['pct'] }}%
+{{ $stats['videosThisWeek'] }} this week
{{-- Views --}}
{{ number_format($stats['totalViews']) }}
Total Views
{{ $stats['growthViews']['pct'] }}%
+{{ number_format($stats['viewsThisWeek']) }} this week
{{-- Likes --}}
{{ number_format($stats['totalLikes']) }}
Total Likes
{{ $stats['growthLikes']['pct'] }}%
+{{ $stats['likesThisWeek'] }} this week
{{-- Comments --}}
{{ number_format($stats['totalComments']) }}
Total Comments
+{{ $stats['commentsThisWeek'] }} this week
{{-- Ready Videos --}}
{{ number_format($videosByStatus->get('ready', 0)) }}
Live Videos
@php $failPct = $stats['totalVideos'] > 0 ? round(($failedCount/$stats['totalVideos'])*100,1) : 0; @endphp
{{ $failedCount }} failed
{{ $processingCount + $pendingCount }} in queue
{{-- ── Activity Chart ── --}}
Activity — Last 30 Days
Content by Type
Generic  {{ $videosByType->get('generic', 0) }}
Music  {{ $videosByType->get('music', 0) }}
Match  {{ $videosByType->get('match', 0) }}
{{-- ── Top Content & Uploaders ── --}}
Top Videos by Views
View All
@forelse($topVideos as $i => $v) @empty @endforelse
# Video Views Likes
{{ $i + 1 }} @if($v->thumbnail) @else
@endif
{{ $v->title }} {{ $v->username }} {{ number_format($v->view_count) }} {{ number_format($v->like_count) }}
No videos yet
Top Uploaders
View All
@forelse($topUploaders as $i => $u) @empty @endforelse
#UserVideosViews
{{ $i + 1 }}
{{ $u->name }}
{{ $u->video_count }} {{ number_format($u->total_views ?? 0) }}
No users yet
{{-- ── Status / Visibility / Engagement ── --}}
Processing Status
@php $totalV = max($stats['totalVideos'], 1); @endphp @foreach([['ready','#22c55e'],['processing','#6366f1'],['pending','#f59e0b'],['failed','#ef4444']] as [$s,$color]) @php $cnt = $videosByStatus->get($s, 0); @endphp
{{ ucfirst($s) }}
{{ $cnt }}
@endforeach
Visibility
@foreach([['public','#22c55e'],['unlisted','#f59e0b'],['private','#6b7280']] as [$v,$color]) @php $cnt = $videosByVisibility->get($v, 0); @endphp
{{ ucfirst($v) }}
{{ $cnt }}
@endforeach
Engagement Metrics
Avg views / video
{{ number_format($avgViewsPerVideo, 1) }}
Like-to-view ratio
{{ $likeToViewRatio }}%
Avg uploads / user
{{ number_format($avgVideosPerUser, 1) }}
{{-- ── Viewers by Country ── --}}
Viewers by Country
@if($viewsByCountry->isEmpty())
No geo data yet — new views will be tracked automatically.
@else @php $maxViews = $viewsByCountry->first()->total; @endphp @foreach($viewsByCountry as $i => $row)
{{ $i + 1 }}
{{ $row->country ? countryCodeToFlag($row->country) : '🌍' }}
{{ $row->country_name ?? 'Unknown' }}
{{ number_format($row->total) }}
@endforeach @endif
Top Countries — View Distribution
@if($viewsByCountry->isEmpty())
Chart will appear once geo data is collected.
@else
@endif
{{-- ── Recent Users & Videos ── --}}
Recent Users
View All
@forelse($recentUsers as $user) @empty @endforelse
UserRoleJoined
{{ $user->name }}
{{ Str::limit($user->email, 22) }}
@if($user->role === 'super_admin') Super Admin @elseif($user->role === 'admin') Admin @else User @endif {{ $user->created_at->diffForHumans() }}
No users
Recent Uploads
View All
@forelse($recentVideos as $video) @empty @endforelse
VideoStatusWhen
@if($video->thumbnail) @else
@endif
{{ $video->title }}
{{ $video->user->name }}
@switch($video->status) @case('ready') Ready @break @case('processing') Processing @break @case('pending') Pending @break @case('failed') Failed @break @endswitch {{ $video->created_at->diffForHumans() }}
No videos
{{-- ── Storage & Quick Actions ── --}}
Storage Breakdown
@php $storageItems = [ ['Videos', $storage['videos'], '#e61e1e'], ['Thumbnails', $storage['thumbnails'], '#f59e0b'], ['Avatars', $storage['avatars'], '#6366f1'], ['Images', $storage['images'], '#22c55e'], ]; $totalSt = max($storage['total'], 0.01); @endphp @foreach($storageItems as [$name, $mb, $color])
{{ $name }}
{{ $mb }} MB
@endforeach
Total used {{ $storage['total'] }} MB
@if(\App\Models\Setting::get('nas_sync_enabled', 'false') === 'true')
@endif
{{-- ── Dash Modal ── --}}
Loading…

Loading…

@endsection @php function countryCodeToFlag(string $code): string { $code = strtoupper(trim($code)); if (strlen($code) !== 2) return '🌍'; $chars = ''; foreach (str_split($code) as $c) { $chars .= mb_chr(0x1F1E6 + ord($c) - ord('A')); } return $chars; } @endphp @section('scripts') @endsection