diff --git a/app/Http/Controllers/StudioController.php b/app/Http/Controllers/StudioController.php new file mode 100644 index 0000000..702629d --- /dev/null +++ b/app/Http/Controllers/StudioController.php @@ -0,0 +1,98 @@ +middleware('auth'); + } + + /** + * The studio dashboard — defaults to the content tab. + */ + public function index(Request $request) + { + $user = Auth::user(); + $filter = $request->get('filter', 'all'); + + $query = Video::where('user_id', $user->id)->latest(); + + switch ($filter) { + case 'public': $query->where('visibility', 'public'); break; + case 'unlisted': $query->where('visibility', 'unlisted'); break; + case 'private': $query->where('visibility', 'private'); break; + case 'shorts': $query->where('is_shorts', true); break; + case 'draft': $query->whereIn('status', ['pending', 'processing', 'failed']); break; + } + + $videos = $query->paginate(24)->withQueryString(); + + // Headline numbers for the top bar. + $totals = [ + 'total' => Video::where('user_id', $user->id)->count(), + 'public' => Video::where('user_id', $user->id)->where('visibility', 'public')->count(), + 'unlisted' => Video::where('user_id', $user->id)->where('visibility', 'unlisted')->count(), + 'private' => Video::where('user_id', $user->id)->where('visibility', 'private')->count(), + 'processing' => Video::where('user_id', $user->id)->whereIn('status', ['pending', 'processing'])->count(), + 'failed' => Video::where('user_id', $user->id)->where('status', 'failed')->count(), + 'total_views' => \DB::table('video_views') + ->whereIn('video_id', Video::where('user_id', $user->id)->pluck('id')) + ->count(), + ]; + + return view('studio.index', [ + 'videos' => $videos, + 'filter' => $filter, + 'totals' => $totals, + ]); + } + + /** + * Bulk visibility change. POSTs { video_ids: [...], visibility: '...' }. + * Guards against setting visibility on videos the user doesn't own, so a + * crafted request can't flip anyone else's content. + */ + public function bulkVisibility(Request $request) + { + $request->validate([ + 'video_ids' => ['required', 'array', 'min:1'], + 'video_ids.*' => ['integer'], + 'visibility' => ['required', 'in:public,unlisted,private'], + ]); + + $updated = Video::whereIn('id', $request->video_ids) + ->where('user_id', Auth::id()) + ->update(['visibility' => $request->visibility]); + + return response()->json(['updated' => $updated]); + } + + /** + * Bulk delete. Same owner-only guard as above. + */ + public function bulkDelete(Request $request) + { + $request->validate([ + 'video_ids' => ['required', 'array', 'min:1'], + 'video_ids.*' => ['integer'], + ]); + + $deleted = Video::whereIn('id', $request->video_ids) + ->where('user_id', Auth::id()) + ->delete(); + + return response()->json(['deleted' => $deleted]); + } +} diff --git a/resources/views/layouts/partials/sidebar.blade.php b/resources/views/layouts/partials/sidebar.blade.php index 872bdf4..05dd89b 100644 --- a/resources/views/layouts/partials/sidebar.blade.php +++ b/resources/views/layouts/partials/sidebar.blade.php @@ -57,6 +57,10 @@ Liked Videos + + + Studio + @endauth diff --git a/resources/views/studio/index.blade.php b/resources/views/studio/index.blade.php new file mode 100644 index 0000000..3bf4314 --- /dev/null +++ b/resources/views/studio/index.blade.php @@ -0,0 +1,238 @@ +@extends('layouts.app') + +@section('title', 'Studio | ' . config('app.name')) + +@section('content') + + +
Manage every video you've uploaded. Select rows for bulk visibility changes.
+ +Switch filters above or upload a new video from the sidebar.
+| + + | +Video | +Visibility | +Views | +Likes | +Comments | +Uploaded | +
|---|---|---|---|---|---|---|
| + |
+
+ @if ($v->thumbnail)
+
+
+
+
+ {{ $v->title }}
+
+ @if ($v->description)
+ @php $plain = trim(preg_replace('/\s+/', ' ', strip_tags((string) $v->description))); @endphp
+ {{ Str::limit($plain, 70) }}
+ @endif
+ |
+
+ @switch($v->visibility)
+ @case('public') Public @break
+ @case('unlisted') Unlisted @break
+ @case('private') Private @break
+ @endswitch
+ @if ($v->status !== 'ready')
+ {{ ucfirst($v->status) }}
+ @endif
+ |
+ {{ number_format($v->view_count) }} | +{{ number_format($v->likes()->count()) }} | +{{ number_format($v->comments()->count()) }} | +{{ $v->created_at->format('M j, Y') }} | +