diff --git a/app/Http/Controllers/VideoController.php b/app/Http/Controllers/VideoController.php index 461a2b1..0cd7913 100644 --- a/app/Http/Controllers/VideoController.php +++ b/app/Http/Controllers/VideoController.php @@ -58,6 +58,7 @@ class VideoController extends Controller 'video' => 'required|file|mimes:mp4,webm,ogg,mov,avi,wmv,flv,mkv|max:512000', 'thumbnail' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:5120', 'visibility' => 'nullable|in:public,unlisted,private', + 'type' => 'nullable|in:generic,music,match', ]); $videoFile = $request->file('video'); @@ -148,6 +149,7 @@ class VideoController extends Controller 'height' => $height, 'status' => 'processing', 'visibility' => $request->visibility ?? 'public', + 'type' => $request->type ?? 'generic', ]); // Dispatch compression job in the background @@ -221,6 +223,7 @@ class VideoController extends Controller 'thumbnail' => $video->thumbnail, 'thumbnail_url' => $video->thumbnail ? asset('storage/thumbnails/' . $video->thumbnail) : null, 'visibility' => $video->visibility ?? 'public', + 'type' => $video->type ?? 'generic', ] ]); } @@ -237,9 +240,10 @@ class VideoController extends Controller 'description' => 'nullable|string', 'thumbnail' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:5120', 'visibility' => 'nullable|in:public,unlisted,private', + 'type' => 'nullable|in:generic,music,match', ]); - $data = $request->only(['title', 'description', 'visibility']); + $data = $request->only(['title', 'description', 'visibility', 'type']); if ($request->hasFile('thumbnail')) { if ($video->thumbnail) { diff --git a/app/Models/Video.php b/app/Models/Video.php index 0d0ee99..294ff66 100644 --- a/app/Models/Video.php +++ b/app/Models/Video.php @@ -21,6 +21,7 @@ class Video extends Model 'height', 'status', 'visibility', + 'type', ]; protected $casts = [ @@ -137,5 +138,30 @@ class Video extends Model } return $query->where('visibility', '!=', 'private'); } + + // Video type helpers + public function getTypeIconAttribute() + { + return match($this->type) { + 'music' => 'bi-music-note', + 'match' => 'bi-trophy', + default => 'bi-film', + }; + } + + public function isGeneric() + { + return $this->type === 'generic'; + } + + public function isMusic() + { + return $this->type === 'music'; + } + + public function isMatch() + { + return $this->type === 'match'; + } } diff --git a/database/migrations/2026_02_25_000000_add_type_to_videos_table.php b/database/migrations/2026_02_25_000000_add_type_to_videos_table.php new file mode 100644 index 0000000..319fad7 --- /dev/null +++ b/database/migrations/2026_02_25_000000_add_type_to_videos_table.php @@ -0,0 +1,22 @@ +enum('type', ['generic', 'music', 'match'])->default('generic')->after('visibility'); + }); + } + + public function down() + { + Schema::table('videos', function (Blueprint $table) { + $table->dropColumn('type'); + }); + } +}; diff --git a/resources/views/components/video-card.blade.php b/resources/views/components/video-card.blade.php new file mode 100644 index 0000000..1ba8f81 --- /dev/null +++ b/resources/views/components/video-card.blade.php @@ -0,0 +1,817 @@ +@props(['video' => null, 'size' => 'medium']) + +@php +$videoUrl = $video ? asset('storage/videos/' . $video->filename) : null; +$thumbnailUrl = $video && $video->thumbnail + ? asset('storage/thumbnails/' . $video->thumbnail) + : ($video ? 'https://picsum.photos/seed/' . $video->id . '/640/360' : 'https://picsum.photos/seed/random/640/360'); + +$typeIcon = $video ? match($video->type) { + 'music' => 'bi-music-note', + 'match' => 'bi-trophy', + default => 'bi-film', +} : 'bi-film'; + +// Check if current user is the owner of the video +$isOwner = $video && auth()->check() && auth()->id() == $video->user_id; + +// Size classes +$sizeClasses = match($size) { + 'small' => 'yt-video-card-sm', + default => '', +}; +@endphp + +