ghassan 5253f89b63 Add video platform features: authentication, video management, user profiles, likes/views tracking
- Added authentication controllers (Login, Register)
- Added UserController for user profile management
- Added VideoController with full CRUD operations
- Added Video model with relationships (user, likes, views)
- Added User model enhancements (avatar, video relationships)
- Added database migrations for video_likes, video_views, user_avatar, video_visibility
- Added CompressVideoJob for video processing
- Added VideoUploaded mail notification
- Added authentication routes
- Updated web routes with video and user routes
- Added layout templates (app, plain, partials)
- Added user views (profile, settings, channel, history, liked)
- Added video views (create, edit, index, show)
- Added email templates
2026-02-25 00:03:02 +00:00

191 lines
5.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Video;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth')->except(['channel']);
}
// Profile page - view own profile
public function profile()
{
$user = Auth::user();
return view('user.profile', compact('user'));
}
// Update profile
public function updateProfile(Request $request)
{
$user = Auth::user();
$request->validate([
'name' => 'required|string|max:255',
'avatar' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:5120',
]);
$data = ['name' => $request->name];
if ($request->hasFile('avatar')) {
// Delete old avatar
if ($user->avatar) {
Storage::delete('public/avatars/' . $user->avatar);
}
$filename = Str::uuid() . '.' . $request->file('avatar')->getClientOriginalExtension();
$request->file('avatar')->storeAs('public/avatars', $filename);
$data['avatar'] = $filename;
}
$user->update($data);
return redirect()->route('profile')->with('success', 'Profile updated successfully!');
}
// Settings page
public function settings()
{
$user = Auth::user();
return view('user.settings', compact('user'));
}
// Update settings (password)
public function updateSettings(Request $request)
{
$user = Auth::user();
$request->validate([
'current_password' => 'required',
'new_password' => 'required|min:8|confirmed',
]);
if (!Hash::check($request->current_password, $user->password)) {
return back()->withErrors(['current_password' => 'Current password is incorrect']);
}
$user->update([
'password' => Hash::make($request->new_password)
]);
return redirect()->route('settings')->with('success', 'Password updated successfully!');
}
// User's channel page - view videos
public function channel($userId = null)
{
if ($userId) {
$user = User::findOrFail($userId);
} else {
$user = Auth::user();
}
// If viewing own channel, show all videos including private
// If viewing someone else's channel, show only public videos
if (Auth::check() && Auth::user()->id === $user->id) {
$videos = Video::where('user_id', $user->id)
->latest()
->paginate(12);
} else {
$videos = Video::public()
->where('user_id', $user->id)
->latest()
->paginate(12);
}
return view('user.channel', compact('user', 'videos'));
}
// Watch history
public function history()
{
$user = Auth::user();
// Get videos the user has watched, ordered by most recently watched
// Include private videos since they are the user's own
$videoIds = \DB::table('video_views')
->where('user_id', $user->id)
->orderBy('watched_at', 'desc')
->pluck('video_id')
->unique();
$videos = Video::whereIn('id', $videoIds)
->where(function($q) use ($user) {
$q->where('visibility', '!=', 'private')
->orWhere('user_id', $user->id);
})
->get()
->sortByDesc(function ($video) use ($videoIds) {
return $videoIds->search($video->id);
});
return view('user.history', compact('videos'));
}
// Liked videos
public function liked()
{
$user = Auth::user();
// Include private videos in liked (user's own private videos)
$videos = $user->likes()
->where(function($q) use ($user) {
$q->where('visibility', '!=', 'private')
->orWhere('videos.user_id', $user->id);
})
->latest()
->paginate(12);
return view('user.liked', compact('videos'));
}
// Like a video
public function like(Video $video)
{
$user = Auth::user();
if (!$video->isLikedBy($user)) {
$video->likes()->attach($user->id);
}
return back();
}
// Unlike a video
public function unlike(Video $video)
{
$user = Auth::user();
$video->likes()->detach($user->id);
return back();
}
// Toggle like (API)
public function toggleLike(Video $video)
{
$user = Auth::user();
if ($video->isLikedBy($user)) {
$video->likes()->detach($user->id);
$liked = false;
} else {
$video->likes()->attach($user->id);
$liked = true;
}
return response()->json([
'liked' => $liked,
'like_count' => $video->like_count
]);
}
}