This commit is contained in:
2025-10-09 00:22:54 +03:00
parent 7e0e330ef6
commit b8b39c945d
28 changed files with 2186 additions and 452 deletions
@@ -69,6 +69,7 @@ class FetchItemDataCommand extends Command
$bar = $this->output->createProgressBar(count($items));
foreach ($items as $item) {
echo "Processing ".$item->tmdb_id."\n";
$this->processItem($item, $job, $type);
$bar->advance();
}
@@ -0,0 +1,128 @@
<?php
namespace App\Console\Commands\TmdbFetch;
use App\Models\ItemToFetch;
use App\Models\ItemToFetchJobs;
use App\Service\TMDBApi\MoviesApi;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class DiscoverMoviesCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tmdb:discover-movies {--page=1} {--limit=5}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Discover movies from TMDB API and add them to the fetch queue';
private MoviesApi $moviesApi;
public function __construct(MoviesApi $moviesApi)
{
$this->moviesApi = $moviesApi;
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$page = $this->option('page');
$limit = $this->option('limit');
$this->info("Discovering movies from TMDB API (page: {$page}, limit: {$limit})");
$totalPages = 0;
$processedCount = 0;
try {
for ($currentPage = $page; $currentPage < $page + $limit; $currentPage++) {
$this->info("Processing page {$currentPage}");
$discoverResult = $this->moviesApi->discover([
'page' => $currentPage,
'sort_by' => 'popularity.desc',
'include_adult' => false,
'include_video' => false,
]);
if (empty($discoverResult) || empty($discoverResult['results'])) {
$this->error("No results found on page {$currentPage}");
break;
}
$totalPages = $discoverResult['total_pages'];
if ($currentPage > $totalPages) {
$this->info("Reached the end of results (total pages: {$totalPages})");
break;
}
DB::beginTransaction();
foreach ($discoverResult['results'] as $movie) {
$this->processMovie($movie);
$processedCount++;
}
DB::commit();
// Sleep to avoid rate limiting
sleep(1);
}
$this->info("Successfully processed {$processedCount} movies");
} catch (\Throwable $e) {
DB::rollBack();
$this->error("Error processing movies: " . $e->getMessage());
$this->error($e->getTraceAsString());
}
}
private function processMovie(array $movie)
{
$tmdbId = $movie['id'];
// Check if this movie is already in the queue
$existingJob = ItemToFetchJobs::where('tmdb_id', $tmdbId)
->where('type', 'movie')
->first();
if ($existingJob) {
$this->line("Movie ID {$tmdbId} already in queue, skipping");
return;
}
// Create ItemToFetch record if it doesn't exist
$itemToFetch = ItemToFetch::firstOrCreate(
[
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_MOVIE,
]
);
// Prepare jobs list
$jobs = ItemToFetchJobs::MOVIE_JOBS;
$jobs[] = ItemToFetchJobs::JOB_DETAILS;
// Create ItemToFetchJobs record
ItemToFetchJobs::create([
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_MOVIE,
'jobs' => implode(',', $jobs),
]);
$this->line("Added movie ID {$tmdbId} to fetch queue");
}
}
@@ -0,0 +1,127 @@
<?php
namespace App\Console\Commands\TmdbFetch;
use App\Models\ItemToFetch;
use App\Models\ItemToFetchJobs;
use App\Service\TMDBApi\ShowsApi;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class DiscoverTvSeriesCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tmdb:discover-tv-series {--page=1} {--limit=5}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Discover TV series from TMDB API and add them to the fetch queue';
private ShowsApi $showsApi;
public function __construct(ShowsApi $showsApi)
{
$this->showsApi = $showsApi;
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$page = $this->option('page');
$limit = $this->option('limit');
$this->info("Discovering TV series from TMDB API (page: {$page}, limit: {$limit})");
$totalPages = 0;
$processedCount = 0;
try {
for ($currentPage = $page; $currentPage < $page + $limit; $currentPage++) {
$this->info("Processing page {$currentPage}");
$discoverResult = $this->showsApi->discover([
'page' => $currentPage,
'sort_by' => 'popularity.desc',
'include_adult' => false,
]);
if (empty($discoverResult) || empty($discoverResult['results'])) {
$this->error("No results found on page {$currentPage}");
break;
}
$totalPages = $discoverResult['total_pages'];
if ($currentPage > $totalPages) {
$this->info("Reached the end of results (total pages: {$totalPages})");
break;
}
DB::beginTransaction();
foreach ($discoverResult['results'] as $show) {
$this->processShow($show);
$processedCount++;
}
DB::commit();
// Sleep to avoid rate limiting
sleep(1);
}
$this->info("Successfully processed {$processedCount} TV series");
} catch (\Throwable $e) {
DB::rollBack();
$this->error("Error processing TV series: " . $e->getMessage());
$this->error($e->getTraceAsString());
}
}
private function processShow(array $show)
{
$tmdbId = $show['id'];
// Check if this show is already in the queue
$existingJob = ItemToFetchJobs::where('tmdb_id', $tmdbId)
->where('type', ItemToFetch::TYPE_TV_SERIES)
->first();
if ($existingJob) {
$this->line("TV series ID {$tmdbId} already in queue, skipping");
return;
}
// Create ItemToFetch record if it doesn't exist
$itemToFetch = ItemToFetch::firstOrCreate(
[
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_TV_SERIES,
]
);
// Prepare jobs list
$jobs = ItemToFetchJobs::SHOW_JOBS;
$jobs[] = ItemToFetchJobs::JOB_DETAILS;
// Create ItemToFetchJobs record
ItemToFetchJobs::create([
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_TV_SERIES,
'jobs' => implode(',', $jobs),
]);
$this->line("Added TV series ID {$tmdbId} to fetch queue");
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ class MediaListController extends Controller
return view('profile.lists.show', compact('list', 'items', 'user'));
}
public function create()
public function create(string $userSlug)
{
$user = Auth::user();
+10 -1
View File
@@ -4,8 +4,10 @@ namespace App\Http\Controllers;
use App\Http\Requests\Movie\CommentRequest;
use App\Models\Comment;
use App\Models\MediaList;
use App\Models\Movie;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class MovieController extends Controller
{
@@ -26,7 +28,14 @@ class MovieController extends Controller
->where('entity_type', Comment::TYPE_MOVIE)
->paginate(15);
return view('movie.show', compact('movie', 'comments'));
$userLists = [];
if (Auth::check()) {
$userLists = MediaList::whereNotIn('name', MediaList::SPECIAL_LISTS)
->where('user_id', Auth::user()->id)
->get();
}
return view('movie.show', compact('movie', 'comments', 'userLists'));
}
public function storeComment(CommentRequest $request, string $movieSlug)
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers;
use App\Models\Movie;
use App\Models\Person;
use App\Models\Show;
use Illuminate\Http\Request;
class SearchController extends Controller
{
public function index(Request $request)
{
$query = $request->input('query');
$type = $request->input('type', 'all');
$movies = collect([]);
$shows = collect([]);
$people = collect([]);
if ($query) {
// Search for movies if type is 'all' or 'movie'
if ($type === 'all' || $type === 'movie') {
$movies = Movie::where('title', 'like', "%{$query}%")
->orWhere('overview', 'like', "%{$query}%")
->limit(20)
->get();
}
// Search for TV shows if type is 'all' or 'tv'
if ($type === 'all' || $type === 'tv') {
$shows = Show::where('name', 'like', "%{$query}%")
->orWhere('overview', 'like', "%{$query}%")
->limit(20)
->get();
}
// Search for people if type is 'all' or 'person'
if ($type === 'all' || $type === 'person') {
$people = Person::where('name', 'like', "%{$query}%")
->limit(20)
->get();
}
}
return view('search.results', [
'query' => $query,
'type' => $type,
'movies' => $movies,
'shows' => $shows,
'people' => $people,
]);
}
}
+13
View File
@@ -297,4 +297,17 @@ class MoviesApi extends AbstractApiService
sleep(1);
return $this->get('movie/' . $movieId . '/external_ids', $parameters, $headers);
}
/**
* Discover movies based on filters.
*
* @param array $parameters
* @param array $headers
* @return mixed
*/
public function discover(array $parameters = [], array $headers = [])
{
sleep(1);
return $this->get('discover/movie', $parameters, $headers);
}
}
+12
View File
@@ -296,4 +296,16 @@ class ShowsApi extends AbstractApiService
{
return $this->get('tv/' . $seriesTmdbId . '/season/'.$seasonNumber);
}
/**
* Discover TV shows based on filters.
*
* @param array $parameters
* @param array $headers
* @return mixed
*/
public function discover(array $parameters = [], array $headers = [])
{
sleep(1);
return $this->get('discover/tv', $parameters, $headers);
}
}
+1 -1
View File
@@ -16,7 +16,7 @@
"laravel/tinker": "^2.9",
"laravel/ui": "^4.6",
"livewire/livewire": "^3.5",
"multicaret/laravel-acquaintances": "^3.6"
"multicaret/laravel-acquaintances": "^3.7"
},
"require-dev": {
"fakerphp/faker": "^1.23",
Generated
+7 -7
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6d84b8d65adb605b5a8df2d31dee572e",
"content-hash": "9d587736fd8ce83beea4888793faef40",
"packages": [
{
"name": "blade-ui-kit/blade-ui-kit",
@@ -2328,16 +2328,16 @@
},
{
"name": "multicaret/laravel-acquaintances",
"version": "v3.6.1",
"version": "v3.7.3",
"source": {
"type": "git",
"url": "https://github.com/multicaret/laravel-acquaintances.git",
"reference": "ae1c4aebe2137cc5c89072e2124e99e8843cdf64"
"reference": "58022069b29540cc37486cdf2618f30284ef447b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/multicaret/laravel-acquaintances/zipball/ae1c4aebe2137cc5c89072e2124e99e8843cdf64",
"reference": "ae1c4aebe2137cc5c89072e2124e99e8843cdf64",
"url": "https://api.github.com/repos/multicaret/laravel-acquaintances/zipball/58022069b29540cc37486cdf2618f30284ef447b",
"reference": "58022069b29540cc37486cdf2618f30284ef447b",
"shasum": ""
},
"require": {
@@ -2392,9 +2392,9 @@
],
"support": {
"issues": "https://github.com/multicaret/laravel-acquaintances/issues",
"source": "https://github.com/multicaret/laravel-acquaintances/tree/v3.6.1"
"source": "https://github.com/multicaret/laravel-acquaintances/tree/v3.7.3"
},
"time": "2024-06-08T13:48:12+00:00"
"time": "2025-08-06T12:41:26+00:00"
},
{
"name": "nesbot/carbon",
+15
View File
@@ -106,3 +106,18 @@ $('.remove-from-watchlist').on('click', function(e){
});
return false;
});
$('.list-action').on('click', function(e){
e.preventDefault();
let url = '/lists/' + $(this).data('list') + '/' + $(this).data('id') + '/' + $(this).data('type');
var self = this
$.ajax({
url: url,
method: 'GET',
success: function(data){
// Show a success message
alert('Movie ' + (data.added ? 'added to' : 'removed from') + ' list');
}
});
return false;
});
+840 -83
View File
File diff suppressed because it is too large Load Diff
+47 -33
View File
@@ -4,69 +4,83 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="auth-form-container">
<div class="text-center mb-4">
<h1 class="auth-logo mb-2" style="font-family: 'Lobster', cursive;">MovieAddict</h1>
<p class="auth-subtitle">Welcome back! Log in to your account</p>
</div>
<div class="card-body">
<div class="card auth-card shadow">
<div class="card-body p-4">
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
<div class="mb-4">
<label for="email" class="form-label">{{ __('Email Address') }}</label>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:email"></span></span>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus placeholder="Enter your email">
</div>
@error('email')
<span class="invalid-feedback" role="alert">
<span class="invalid-feedback d-block" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-4">
<div class="d-flex justify-content-between align-items-center">
<label for="password" class="form-label">{{ __('Password') }}</label>
@if (Route::has('password.request'))
<a class="small text-decoration-none" href="{{ route('password.request') }}">
{{ __('Forgot Password?') }}
</a>
@endif
</div>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:lock"></span></span>
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password" placeholder="Enter your password">
</div>
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<span class="invalid-feedback d-block" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<div class="col-md-6 offset-md-4">
<div class="mb-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
</label>
</div>
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
<div class="d-grid gap-2 mb-4">
<button type="submit" class="btn btn-primary btn-lg">
<span class="iconify me-2" data-icon="mdi:login"></span>{{ __('Login') }}
</button>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
<div class="text-center">
<p class="mb-0">Don't have an account? <a href="{{ route('register') }}" class="text-decoration-none">Register now</a></p>
</div>
</form>
</div>
</div>
<div class="auth-footer text-center mt-4">
<div class="auth-bg-icons">
<span class="iconify auth-icon" data-icon="mdi:movie"></span>
<span class="iconify auth-icon" data-icon="mdi:television"></span>
<span class="iconify auth-icon" data-icon="mdi:star"></span>
<span class="iconify auth-icon" data-icon="mdi:account-group"></span>
<span class="iconify auth-icon" data-icon="mdi:popcorn"></span>
</div>
<p class="small text-muted mt-3">Track, rate and discover your favorite movies and TV shows</p>
</div>
</div>
</div>
</div>
</div>
+60 -36
View File
@@ -4,73 +4,97 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Register') }}</div>
<div class="auth-form-container">
<div class="text-center mb-4">
<h1 class="auth-logo mb-2" style="font-family: 'Lobster', cursive;">MovieAddict</h1>
<p class="auth-subtitle">Create your account and start tracking movies</p>
</div>
<div class="card-body">
<div class="card auth-card shadow">
<div class="card-body p-4">
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="row mb-3">
<label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
<div class="mb-4">
<label for="name" class="form-label">{{ __('Name') }}</label>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:account"></span></span>
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus placeholder="Enter your name">
</div>
@error('name')
<span class="invalid-feedback" role="alert">
<span class="invalid-feedback d-block" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-4">
<label for="email" class="form-label">{{ __('Email Address') }}</label>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:email"></span></span>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" placeholder="Enter your email">
</div>
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
@error('email')
<span class="invalid-feedback" role="alert">
<span class="invalid-feedback d-block" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="mb-4">
<label for="password" class="form-label">{{ __('Password') }}</label>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:lock"></span></span>
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password" placeholder="Choose a password (min. 8 characters)">
</div>
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<span class="invalid-feedback d-block" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
<div class="mb-4">
<label for="password-confirm" class="form-label">{{ __('Confirm Password') }}</label>
<div class="input-group">
<span class="input-group-text"><span class="iconify" data-icon="mdi:lock-check"></span></span>
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password" placeholder="Confirm your password">
</div>
</div>
<div class="row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Register') }}
<div class="mb-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="terms" id="terms" required>
<label class="form-check-label" for="terms">
I agree to the <a href="#" class="text-decoration-none">Terms of Service</a> and <a href="#" class="text-decoration-none">Privacy Policy</a>
</label>
</div>
</div>
<div class="d-grid gap-2 mb-4">
<button type="submit" class="btn btn-primary btn-lg">
<span class="iconify me-2" data-icon="mdi:account-plus"></span>{{ __('Create Account') }}
</button>
</div>
<div class="text-center">
<p class="mb-0">Already have an account? <a href="{{ route('login') }}" class="text-decoration-none">Log in</a></p>
</div>
</form>
</div>
</div>
<div class="auth-footer text-center mt-4">
<div class="auth-bg-icons">
<span class="iconify auth-icon" data-icon="mdi:movie"></span>
<span class="iconify auth-icon" data-icon="mdi:television"></span>
<span class="iconify auth-icon" data-icon="mdi:star"></span>
<span class="iconify auth-icon" data-icon="mdi:account-group"></span>
<span class="iconify auth-icon" data-icon="mdi:popcorn"></span>
</div>
<p class="small text-muted mt-3">Join thousands of movie lovers in our community</p>
</div>
</div>
</div>
</div>
</div>
+1 -16
View File
@@ -56,22 +56,7 @@
<div class="col-lg-3">
<div class="card">
<div class="card-body">
<div class="user-actions">
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-eye-check-outline"></span> Mark as seen
</a>
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-thumb-up-outline"></span> Like
</a>
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-playlist-check"></span> Add to list
<span class="float-end">
<span class="iconify" data-icon="mdi-chevron-down"></span>
</span>
</a>
<hr>
@include('layouts.rating')
</div>
menu
</div>
</div>
</div>
+4 -2
View File
@@ -12,9 +12,11 @@
{{ $thread->name }}
</div>
<div class="col-md-2">
<a href="{{ route('forums.thread.topics.create', [$category->slug ?? 'unknown', $thread->slug]) }}" class="btn btn-primary">
@if(auth()->check())
<a href="{{ route('forums.thread.topics.create', [$category->slug ?? 'unknown', $thread->slug]) }}" class="btn btn-primary pull-right">
New topic
</a>
@endif
</div>
</div>
</h1>
@@ -50,7 +52,7 @@
</div>
<div class="col-md-8">
<a href="{{ route('forums.thread.topics.show', [$category->slug ?? 'unknown', $thread->slug, $topic->slug]) }}">{{ $topic->name }}</a> <br>
<small>Created by {{ $topic->author->name ?? 'Unknown User' }} {{ $topic->created_at ? $topic->created_at->diffForHumans() : 'N/A' }}</small>
<small>Created by <a href="">{{ $topic->author->name ?? 'Unknown User' }}</a> {{ $topic->created_at ? $topic->created_at->diffForHumans() : 'N/A' }}</small>
</div>
<div class="col-md-1">
<span title="Views"><span class="iconify me-1" data-icon="mdi-eye"></span> {{ $topic->views_no }}</span><br>
@@ -54,6 +54,12 @@
</div>
</div>
{{ $posts->links() }}
<div class="card">
<div class="card-header">
Reply
</div>
<div class="card-body">
@if(auth()->check())
<hr>
<form action="{{ route('forums.thread.topics.post.store', [$thread->category->slug ?? 'unknown', $thread->slug, $topic->slug]) }}" method="POST">
@csrf
@@ -66,6 +72,14 @@
</div>
</div>
</form>
@else
<div class="alert alert-info">
<span class="iconify me-1" data-icon="mdi-information"></span>
You must be <a href="{{ route('login') }}" class="alert-link">logged in</a> to write a review.
</div>
@endif
</div>
</div>
</div>
<div class="col-md-2">
<div class="card">
+8 -2
View File
@@ -9,9 +9,15 @@
</button>
<div class="collapse navbar-collapse" id="navbarContent">
<form class="d-flex mx-auto my-2 my-lg-0" role="search">
<form class="d-flex mx-auto my-2 my-lg-0" role="search" action="{{ route('search') }}" method="GET">
<div class="input-group">
<input type="search" class="form-control" placeholder="Search movies, shows, celebrities..." aria-label="Search">
<select name="type" class="form-select" style="max-width: 140px;">
<option value="all" selected>Movies & TV</option>
<option value="movie">Movies</option>
<option value="tv">TV Shows</option>
<option value="person">People</option>
</select>
<input type="search" name="query" class="form-control" placeholder="Search movies, shows, celebrities..." aria-label="Search">
<button class="btn btn-outline-primary" type="submit">
<span class="iconify" data-icon="mdi-magnify"></span>
</button>
@@ -1,5 +1,6 @@
<div>
<div class="cast-list">
@if(count($peopleByDepartment))
@foreach($peopleByDepartment as $department => $personInfo)
<div class="department">
{{ $department }}
@@ -27,5 +28,8 @@
</div>
</div>
@endforeach
@else
<em>There are no crew members here.</em>
@endif
</div>
</div>
+208 -32
View File
@@ -246,59 +246,235 @@
</div>
<!-- Sidebar -->
<div class="col-lg-3">
<div class="card">
<div class="col-lg-3 right-sidebar">
<!-- User Actions Card -->
<div class="card mb-4 action-card">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:bookmark-outline"></span> Your Actions</h5>
</div>
<div class="card-body">
<div class="user-actions">
@if(auth()->check())
<a href="#" class="d-block mb-3 text-decoration-none mark-as-seen-btn mark-action {{ auth()->check() ? ($movie->wasListedBy('watched', auth()->user()) ? 'seen' : '') : '' }}"
<a href="#" class="d-flex align-items-center justify-content-between mb-3 text-decoration-none mark-as-seen-btn mark-action {{ auth()->check() ? ($movie->wasListedBy('watched', auth()->user()) ? 'seen' : '') : '' }}"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="watched">
<span class="iconify me-1" data-icon="mdi-eye-check-outline"></span>
<span>
<span class="iconify me-2" data-icon="mdi:eye-check-outline" data-width="20"></span>
Mark as seen
</span>
<span class="badge rounded-pill">
<span class="iconify" data-icon="mdi:check-circle" data-width="16"></span>
</span>
</a>
@else
<a href="{{ route('login') }}?msg=login-to-mark-as-seen" class="d-block mb-3 text-decoration-none mark-as-seen-btn"
<a href="{{ route('login') }}?msg=login-to-mark-as-seen" class="d-flex align-items-center justify-content-between mb-3 text-decoration-none mark-as-seen-btn"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="watched">
<span class="iconify me-1" data-icon="mdi-eye-check-outline"></span>
<span>
<span class="iconify me-2" data-icon="mdi:eye-check-outline" data-width="20"></span>
Mark as seen
</a>
@endif
@if(auth()->check())
<a href="#" class="d-block mb-3 text-decoration-none like-btn like-action {{ auth()->check() ? ($movie->wasListedBy('liked', auth()->user()) ? 'liked' : '') : '' }}"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="liked">
<span class="iconify me-1" data-icon="mdi-thumb-up-outline"></span>
Like
</a>
@else
<a href="{{ route('login') }}?msg=login-to-like" class="d-block mb-3 text-decoration-none like-btn"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="liked">
<span class="iconify me-1" data-icon="mdi-thumb-up-outline"></span>
Like
</a>
@endif
@if(auth()->check())
<a href="#" class="d-block mb-3 text-decoration-none add-to-list-btn">
<span class="iconify me-1" data-icon="mdi-playlist-check"></span>
Add to list
<span class="float-end">
<span class="iconify" data-icon="mdi-chevron-down"></span>
</span>
<span class="badge rounded-pill">
<span class="iconify" data-icon="mdi:login" data-width="16"></span>
</span>
</a>
@endif
<hr>
@if(auth()->check())
<a href="#" class="d-flex align-items-center justify-content-between mb-3 text-decoration-none like-btn like-action {{ auth()->check() ? ($movie->wasListedBy('liked', auth()->user()) ? 'liked' : '') : '' }}"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="liked">
<span>
<span class="iconify me-2" data-icon="mdi:thumb-up-outline" data-width="20"></span>
Like
</span>
<span class="badge rounded-pill">
<span class="iconify" data-icon="mdi:heart" data-width="16"></span>
</span>
</a>
@else
<a href="{{ route('login') }}?msg=login-to-like" class="d-flex align-items-center justify-content-between mb-3 text-decoration-none like-btn"
data-id="{{ $movie->id }}"
data-type="movie"
data-list="liked">
<span>
<span class="iconify me-2" data-icon="mdi:thumb-up-outline" data-width="20"></span>
Like
</span>
<span class="badge rounded-pill">
<span class="iconify" data-icon="mdi:login" data-width="16"></span>
</span>
</a>
@endif
@if(auth()->check())
<div class="dropdown mb-3">
<a href="#" class="d-flex align-items-center justify-content-between text-decoration-none add-to-list-btn dropdown-toggle" id="listDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<span>
<span class="iconify me-2" data-icon="mdi:playlist-check" data-width="20"></span>
Add to list
</span>
<span class="badge rounded-pill">
<span class="iconify" data-icon="mdi:chevron-down" data-width="16"></span>
</span>
</a>
<ul class="dropdown-menu" aria-labelledby="listDropdown">
@foreach($userLists as $list)
<li>
<a class="dropdown-item list-action" href="#"
data-list="{{ $list->slug }}"
data-id="{{ $movie->id }}"
data-type="movie">
<span class="iconify me-2" data-icon="mdi:playlist-plus"></span>
{{ $list->name }}
</a>
</li>
@endforeach
@if($userLists->isEmpty())
<li><div class="dropdown-item text-muted">No custom lists found</div></li>
@endif
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item" href="{{ route('profile.list.create', Auth::user()->slug) }}">
<span class="iconify me-2" data-icon="mdi:playlist-plus"></span>
Create new list
</a>
</li>
</ul>
</div>
@endif
<div class="rating-section mt-4">
<h6 class="mb-3">Rate this movie:</h6>
@include('layouts.rating')
</div>
</div>
</div>
</div>
<!-- Movie Info Card -->
<div class="card mb-4 info-card">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:information-outline"></span> Movie Info</h5>
</div>
<div class="card-body p-0">
<ul class="list-group list-group-flush movie-info-list">
@if($movie->release_date)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:calendar"></span> Release Date</span>
<span class="info-value">{{ $movie->release_date->format('M d, Y') }}</span>
</li>
@endif
@if($movie->runtime)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:clock-outline"></span> Runtime</span>
<span class="info-value">{{ $movie->runtime }} min</span>
</li>
@endif
@if($movie->budget)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:cash"></span> Budget</span>
<span class="info-value">${{ number_format($movie->budget) }}</span>
</li>
@endif
@if($movie->revenue)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:cash-multiple"></span> Revenue</span>
<span class="info-value">${{ number_format($movie->revenue) }}</span>
</li>
@endif
@if($movie->vote_average)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:star"></span> Rating</span>
<span class="info-value">{{ number_format($movie->vote_average, 1) }}/10</span>
</li>
@endif
@if($movie->vote_count)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:account-group"></span> Votes</span>
<span class="info-value">{{ number_format($movie->vote_count) }}</span>
</li>
@endif
@if($movie->status)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="info-label"><span class="iconify me-2" data-icon="mdi:information"></span> Status</span>
<span class="info-value">{{ $movie->status }}</span>
</li>
@endif
</ul>
</div>
</div>
<!-- Trending Movies Card -->
<div class="card mb-4 trending-card">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:trending-up"></span> Trending Movies</h5>
</div>
<div class="card-body p-0">
<div class="trending-movies">
@for($i = 0; $i < 5; $i++)
<div class="movie-item p-3">
<div class="d-flex">
<img src="https://picsum.photos/seed/movie{{ $i }}/100/150" class="rounded shadow-sm" alt="Movie poster">
<div class="movie-info ms-3">
<h6 class="mb-1">Popular Movie Title</h6>
<div class="rating mb-2">
<span class="iconify text-warning" data-icon="mdi:star"></span>
<span>{{ number_format(rand(70, 95) / 10, 1) }}</span>
</div>
<a href="#" class="btn btn-sm btn-outline-primary">View</a>
</div>
</div>
</div>
@endfor
</div>
</div>
</div>
<!-- Quick Links Card -->
<div class="card quick-links-card">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:link-variant"></span> Quick Links</h5>
</div>
<div class="card-body p-0">
<div class="quick-links">
<ul>
<li>
<a href="#">
<span class="iconify" data-icon="mdi:movie-open"></span>
Browse All Movies
</a>
</li>
<li>
<a href="#">
<span class="iconify" data-icon="mdi:television-classic"></span>
TV Shows
</a>
</li>
<li>
<a href="#">
<span class="iconify" data-icon="mdi:account-group"></span>
Celebrities
</a>
</li>
<li>
<a href="#">
<span class="iconify" data-icon="mdi:forum"></span>
Discussion Forums
</a>
</li>
<li>
<a href="#">
<span class="iconify" data-icon="mdi:help-circle"></span>
Help & Support
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
+78 -44
View File
@@ -3,100 +3,134 @@
@section('content')
<div class="profile-page pattern{{ rand(1,6) }}">
<div class="container">
<div class="row align-items-center">
<div class="col-md-3 text-center">
<div class="position-relative">
<img src="{{ asset('/img/user_no_avatar.png') }}" alt="{{ $user->name }}'s avatar" class="user-avatar">
@if(auth()->check() && auth()->user()->id === $user->id)
<div class="avatar-edit-overlay">
<a href="#" class="btn btn-sm btn-light rounded-circle">
<span class="iconify" data-icon="mdi:camera"></span>
</a>
</div>
@endif
</div>
</div>
<div class="col-md-6">
<div class="profile-info">
<h1 class="mb-1">{{ $user->name }}</h1>
<div class="user-meta mb-2">
<span class="register-date"><span class="iconify" data-icon="mdi:calendar-clock"></span> Member since {{ $user->created_at->format('F Y') }}</span>
</div>
<div class="user-stats">
<div class="row">
<div class="col-md-2 text-center">
<img src="{{ asset('/img/user_no_avatar.png') }}" alt="" class="user-avatar">
<div class="col-4 text-center">
<div class="stat-value">2</div>
<div class="stat-label">Followers</div>
</div>
<div class="col-md-5">
<h1>{{ $user->name }}</h1><span class="register-date">Member since {{ $user->created_at->format('F Y') }}</span>
<br>
2 Followers 3 Following average movie score average tv series score
<div class="col-4 text-center">
<div class="stat-value">3</div>
<div class="stat-label">Following</div>
</div>
<div class="col-md-5">
<div class="col-4 text-center">
<div class="stat-value">7.5</div>
<div class="stat-label">Avg Rating</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 text-end">
@if(auth()->check() && auth()->user()->id !== $user->id)
<button class="btn btn-primary mb-2"><span class="iconify" data-icon="mdi:account-plus"></span> Follow</button>
@elseif(auth()->check() && auth()->user()->id === $user->id)
<a href="#" class="btn btn-outline-secondary mb-2"><span class="iconify" data-icon="mdi:account-edit"></span> Edit Profile</a>
@endif
</div>
</div>
</div>
</div>
<div class="profile-page-menu">
<div class="row justify-content-center" style="margin-right: 0;">
<div class="col-md-10">
<div class="profile-nav">
<div class="menu-nav">
<ul class="list-inline">
<li class="float-start">
<div class="container">
<div class="row">
<div class="col-12">
<nav class="profile-nav">
<ul class="nav nav-pills">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.show', $user->slug)) ? 'active' : '' }}"
href="{{ route('profile.show', $user->slug) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.show', $user->slug)) ? 'active' : '' }}"
>
Profile
<span class="iconify" data-icon="mdi:account"></span> Profile
</a>
</li>
<li class="float-start">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.list.index', $user->slug)) ? 'active' : '' }}"
href="{{ route('profile.list.index', $user->slug) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.list.index', $user->slug)) ? 'active' : '' }}"
>
Lists
<span class="iconify" data-icon="mdi:format-list-bulleted"></span> Lists
</a>
</li>
<li class="float-start">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'watched'])) ? 'active' : '' }}"
href="{{ route('profile.list.show', [$user->slug, 'watched']) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'watched'])) ? 'active' : '' }}"
>
History
<span class="iconify" data-icon="mdi:history"></span> History
</a>
</li>
<li class="float-start">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'watchlist'])) ? 'active' : '' }}"
href="{{ route('profile.list.show', [$user->slug, 'watchlist']) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'watchlist'])) ? 'active' : '' }}"
>
Watchlist
<span class="iconify" data-icon="mdi:bookmark-outline"></span> Watchlist
</a>
</li>
<li class="float-start">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'collection'])) ? 'active' : '' }}"
href="{{ route('profile.list.show', [$user->slug, 'collection']) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'collection'])) ? 'active' : '' }}"
>
Collection
<span class="iconify" data-icon="mdi:movie-open"></span> Collection
</a>
</li>
<li class="float-start">
<a href="">
Ratings
<li class="nav-item">
<a class="nav-link" href="#">
<span class="iconify" data-icon="mdi:star-outline"></span> Ratings
</a>
</li>
<li class="float-start">
<a href="">
Reviews
<li class="nav-item">
<a class="nav-link" href="#">
<span class="iconify" data-icon="mdi:comment-text-outline"></span> Reviews
</a>
</li>
<li class="float-start">
<li class="nav-item">
<a
class="nav-link {{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'liked'])) ? 'active' : '' }}"
href="{{ route('profile.list.show', [$user->slug, 'liked']) }}"
class="{{ \App\Service\ToolService::isCurrentRoute(route('profile.list.show', [$user->slug, 'liked'])) ? 'active' : '' }}"
>
Likes
<span class="iconify" data-icon="mdi:heart-outline"></span> Likes
</a>
</li>
<li class="float-start">
<a href="">
Network
<li class="nav-item">
<a class="nav-link" href="#">
<span class="iconify" data-icon="mdi:account-group"></span> Network
</a>
</li>
<li class="float-start">
<a href="">
Stats
<li class="nav-item">
<a class="nav-link" href="#">
<span class="iconify" data-icon="mdi:chart-bar"></span> Stats
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
<div class="profile-content py-4">
@yield('page_content')
</div>
@endsection
+253 -45
View File
@@ -1,78 +1,286 @@
@extends('profile.profile')
@section('page_content')
<br>
<div class="container">
<div class="row justify-content-center">
<!-- Top Cards Row -->
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-header">Last watched</div>
<div class="card-body">
<div class="card shadow-sm h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:play-circle-outline"></span> Last Watched</h5>
<a href="#" class="text-decoration-none small">View All</a>
</div>
<div class="card-body text-center">
@if($lastWatched)
<a href="">
<img src="http://image.tmdb.org/t/p/w185/{{ $lastWatched->poster_path }}" alt="">
</a>r
<div class="position-relative mb-3">
<a href="#" class="d-block">
<img src="http://image.tmdb.org/t/p/w342/{{ $lastWatched->poster_path }}" alt="{{ $lastWatched->title ?? $lastWatched->name }}" class="img-fluid rounded shadow-sm">
<div class="overlay-play">
<span class="iconify" data-icon="mdi:play-circle" data-width="48"></span>
</div>
</a>
</div>
<h6 class="mb-1">{{ $lastWatched->title ?? $lastWatched->name }}</h6>
<div class="text-muted small">Watched on {{ now()->subDays(rand(1, 5))->format('M d, Y') }}</div>
@else
<div class="alert alert-success text-center">
Nothing to show here! <br> Go watch something!
<div class="alert alert-light text-center p-4 mb-0">
<span class="iconify mb-3" data-icon="mdi:movie-off" data-width="48"></span>
<h6>Nothing watched yet!</h6>
<p class="mb-0 text-muted small">Start watching to track your viewing history.</p>
</div>
@endif
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">Stats</div>
<div class="card-body">
Last 30 Days/Watched <br>
Shows — 4d 20h 24m (147 eps) <br>
Movies — 0m<br>
<br>
All Time/Watched<br>
Shows — 297d 17h 23m (12,095 eps)<br>
Movies — 44d 15h 23m (568 movies)
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">Featured list</div>
<div class="card-body"></div>
<div class="card shadow-sm h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:chart-timeline-variant"></span> Watching Stats</h5>
<a href="#" class="text-decoration-none small">Details</a>
</div>
<div class="card-body">
<h6 class="text-uppercase text-muted small mb-3">Last 30 Days</h6>
<div class="d-flex justify-content-between mb-2">
<span><span class="iconify" data-icon="mdi:television"></span> Shows</span>
<span class="badge bg-primary rounded-pill">147 eps</span>
</div>
<div class="progress mb-3" style="height: 8px;">
<div class="progress-bar bg-primary" role="progressbar" style="width: 75%;" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<div class="d-flex justify-content-between mb-2">
<span><span class="iconify" data-icon="mdi:movie"></span> Movies</span>
<span class="badge bg-success rounded-pill">12 movies</span>
</div>
<div class="progress mb-4" style="height: 8px;">
<div class="progress-bar bg-success" role="progressbar" style="width: 25%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<h6 class="text-uppercase text-muted small mb-3">All Time</h6>
<div class="row text-center">
<div class="col-6">
<h4 class="mb-0">12,095</h4>
<div class="small text-muted">Episodes</div>
</div>
<div class="col-6">
<h4 class="mb-0">568</h4>
<div class="small text-muted">Movies</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:format-list-bulleted"></span> Featured List</h5>
<a href="{{ route('profile.list.index', $user->slug) }}" class="text-decoration-none small">All Lists</a>
</div>
<div class="card-body">
<div class="featured-list">
<h6 class="mb-3">My Favorite Sci-Fi Movies</h6>
<div class="list-posters d-flex mb-3">
<div class="poster-thumbnail me-2">
<img src="https://image.tmdb.org/t/p/w92/rEm96ib0sPiZBADNKBHKBv5bve9.jpg" class="rounded shadow-sm" alt="Movie poster">
</div>
<div class="poster-thumbnail me-2">
<img src="https://image.tmdb.org/t/p/w92/5KlRFKKSbyCiyYpZSS3A6G5bW0K.jpg" class="rounded shadow-sm" alt="Movie poster">
</div>
<div class="poster-thumbnail me-2">
<img src="https://image.tmdb.org/t/p/w92/wuMc08IPKEatf9rnMNXvIDxqP4W.jpg" class="rounded shadow-sm" alt="Movie poster">
</div>
<div class="poster-thumbnail more-posters d-flex justify-content-center align-items-center rounded">
<span>+12</span>
</div>
</div>
<a href="#" class="btn btn-sm btn-outline-primary w-100">View List</a>
</div>
</div>
</div>
</div>
</div>
<!-- Favorites Section -->
<div class="row mt-4">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:heart"></span> Favorites</h5>
<a href="#" class="text-decoration-none small">View All</a>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">Favourite</div>
<div class="card-body"></div>
@for ($i = 0; $i < 6; $i++)
<div class="col-md-2 col-sm-4 col-6 mb-3">
<div class="favorite-item text-center">
<a href="#" class="d-block mb-2">
<img src="https://picsum.photos/seed/{{ $i }}/185/278" class="img-fluid rounded shadow-sm" alt="Favorite item">
</a>
<h6 class="mb-0 text-truncate">Favorite Title</h6>
<div class="small text-muted">
<span class="iconify" data-icon="mdi:star" data-width="14"></span> 8.5
</div>
</div>
</div>
@endfor
</div>
</div>
</div>
</div>
</div>
<!-- Recent Activity Sections -->
<div class="row mt-4">
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:television"></span> Recent Episodes</h5>
<a href="#" class="text-decoration-none small">View All</a>
</div>
<div class="card-body p-0">
<ul class="list-group list-group-flush">
@for ($i = 0; $i < 5; $i++)
<li class="list-group-item">
<div class="d-flex">
<div class="flex-shrink-0 me-3">
<img src="https://picsum.photos/seed/ep{{ $i }}/120/68" class="rounded shadow-sm" alt="Episode thumbnail">
</div>
<div>
<h6 class="mb-0">Show Title</h6>
<div class="small text-muted mb-1">S{{ rand(1, 5) }}E{{ rand(1, 20) }} • {{ rand(20, 45) }} min</div>
<div class="small">Watched {{ rand(1, 30) }} days ago</div>
</div>
</div>
</li>
@endfor
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:movie"></span> Recent Movies</h5>
<a href="#" class="text-decoration-none small">View All</a>
</div>
<div class="card-body p-0">
<ul class="list-group list-group-flush">
@for ($i = 0; $i < 5; $i++)
<li class="list-group-item">
<div class="d-flex">
<div class="flex-shrink-0 me-3">
<img src="https://picsum.photos/seed/mv{{ $i }}/120/68" class="rounded shadow-sm" alt="Movie thumbnail">
</div>
<div>
<h6 class="mb-0">Movie Title</h6>
<div class="small text-muted mb-1">{{ rand(90, 180) }} min • {{ rand(2010, 2023) }}</div>
<div class="small">
<span class="badge bg-light text-dark me-1">Action</span>
<span class="badge bg-light text-dark">Drama</span>
</div>
</div>
</div>
</li>
@endfor
</ul>
</div>
</div>
</div>
</div>
<!-- Bottom Sections -->
<div class="row mt-4">
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:chart-pie"></span> Most Watched Genres</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
recently watched episodes
@foreach(['Action', 'Drama', 'Comedy', 'Sci-Fi', 'Thriller', 'Horror'] as $index => $genre)
<div class="col-6 mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<span>{{ $genre }}</span>
<span class="small text-muted">{{ rand(10, 150) }}</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-{{ ['primary', 'success', 'info', 'warning', 'danger', 'secondary'][$index] }}"
role="progressbar"
style="width: {{ rand(20, 95) }}%;"
aria-valuenow="{{ rand(20, 95) }}"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
</div>
<div class="row">
<div class="col-md-12">
recently watched movies
@endforeach
</div>
</div>
<div class="row">
<div class="col-md-12">
most watched genres
</div>
</div>
<div class="row">
<div class="col-md-12">
ratings graph
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:star"></span> Ratings Distribution</h5>
</div>
<div class="card-body">
<div class="ratings-chart">
@for ($i = 10; $i >= 1; $i--)
<div class="d-flex align-items-center mb-2">
<div class="rating-label me-2">{{ $i }}</div>
<div class="progress flex-grow-1" style="height: 12px;">
<div class="progress-bar bg-{{ $i >= 8 ? 'success' : ($i >= 5 ? 'warning' : 'danger') }}"
role="progressbar"
style="width: {{ $i == 8 ? 25 : ($i == 7 ? 20 : ($i == 9 ? 15 : rand(5, 10))) }}%;"
aria-valuenow="{{ $i == 8 ? 25 : ($i == 7 ? 20 : ($i == 9 ? 15 : rand(5, 10))) }}"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
<div class="rating-count ms-2 small">{{ $i == 8 ? 25 : ($i == 7 ? 20 : ($i == 9 ? 15 : rand(5, 10))) }}</div>
</div>
@endfor
<div class="text-center mt-3">
<div class="small text-muted">Average rating: <strong>7.5</strong> from <strong>142</strong> ratings</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Comments Section -->
<div class="row mt-4 mb-3">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><span class="iconify" data-icon="mdi:comment-multiple"></span> Recent Comments</h5>
<a href="#" class="text-decoration-none small">View All</a>
</div>
<div class="card-body p-0">
<ul class="list-group list-group-flush">
@for ($i = 0; $i < 3; $i++)
<li class="list-group-item">
<div class="d-flex">
<div class="flex-shrink-0 me-3">
<img src="https://picsum.photos/seed/user{{ $i }}/50/50" class="rounded-circle" alt="User avatar">
</div>
<div>
<div class="d-flex align-items-center mb-1">
<h6 class="mb-0 me-2">User Name</h6>
<small class="text-muted">on <a href="#" class="text-decoration-none">Movie Title</a></small>
</div>
<p class="mb-1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in dui mauris.</p>
<div class="small text-muted">{{ rand(1, 30) }} days ago</div>
</div>
</div>
</li>
@endfor
</ul>
</div>
</div>
<div class="row">
<div class="col-md-12">
comments
</div>
</div>
</div>
+167
View File
@@ -0,0 +1,167 @@
@extends('layouts.app')
@section('content')
<div class="container-fluid py-4">
<div class="row justify-content-center">
<div class="col-md-10">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Search Results for "{{ $query }}"</h5>
</div>
<div class="card-body">
@if(!$query)
<div class="alert alert-info">
Please enter a search term to find movies, TV shows, or people.
</div>
@elseif($movies->isEmpty() && $shows->isEmpty() && $people->isEmpty())
<div class="alert alert-warning">
No results found for "{{ $query }}". Please try a different search term.
</div>
@else
<ul class="nav nav-tabs mb-4" id="searchTabs" role="tablist">
@if($type === 'all')
<li class="nav-item" role="presentation">
<button class="nav-link active" id="movies-tab" data-bs-toggle="tab" data-bs-target="#movies" type="button" role="tab" aria-controls="movies" aria-selected="true">
Movies ({{ $movies->count() }})
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="shows-tab" data-bs-toggle="tab" data-bs-target="#shows" type="button" role="tab" aria-controls="shows" aria-selected="false">
TV Shows ({{ $shows->count() }})
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="people-tab" data-bs-toggle="tab" data-bs-target="#people" type="button" role="tab" aria-controls="people" aria-selected="false">
People ({{ $people->count() }})
</button>
</li>
@elseif($type === 'movie')
<li class="nav-item" role="presentation">
<button class="nav-link active" id="movies-tab" data-bs-toggle="tab" data-bs-target="#movies" type="button" role="tab" aria-controls="movies" aria-selected="true">
Movies ({{ $movies->count() }})
</button>
</li>
@elseif($type === 'tv')
<li class="nav-item" role="presentation">
<button class="nav-link active" id="shows-tab" data-bs-toggle="tab" data-bs-target="#shows" type="button" role="tab" aria-controls="shows" aria-selected="true">
TV Shows ({{ $shows->count() }})
</button>
</li>
@elseif($type === 'person')
<li class="nav-item" role="presentation">
<button class="nav-link active" id="people-tab" data-bs-toggle="tab" data-bs-target="#people" type="button" role="tab" aria-controls="people" aria-selected="true">
People ({{ $people->count() }})
</button>
</li>
@endif
</ul>
<div class="tab-content" id="searchTabsContent">
<!-- Movies Tab -->
<div class="tab-pane fade {{ ($type === 'all' || $type === 'movie') ? 'show active' : '' }}" id="movies" role="tabpanel" aria-labelledby="movies-tab">
@if($movies->isEmpty())
<div class="alert alert-info">No movies found matching "{{ $query }}".</div>
@else
<div class="row">
@foreach($movies as $movie)
<div class="col-md-2 mb-4">
<div class="movie-card">
<a href="{{ route('movie.show', $movie->slug) }}" title="{{ $movie->title }}">
<img
src="@if($movie->poster_path) http://image.tmdb.org/t/p/w185/{{ $movie->poster_path }} @else /img/no_poster.png @endif"
alt="{{ $movie->title }}"
title="{{ $movie->title }} @if($movie->release_date) ({{ $movie->release_date->format('Y') }}) @endif"
class="img img-fluid"
>
</a>
<ul class="quick-actions">
<li>
<a href=""><span class="iconify" data-icon="mdi-check-outline"></span></a>
</li>
<li>
<a href=""><span class="iconify" data-icon="mdi-image-multiple"></span></a>
</li>
<li>
<a href="">
{{ $movie->vote_average }} <span class="iconify" data-icon="mdi-star"></span>
</a>
</li>
</ul>
</div>
</div>
@endforeach
</div>
@endif
</div>
<!-- TV Shows Tab -->
<div class="tab-pane fade {{ $type === 'tv' ? 'show active' : '' }}" id="shows" role="tabpanel" aria-labelledby="shows-tab">
@if($shows->isEmpty())
<div class="alert alert-info">No TV shows found matching "{{ $query }}".</div>
@else
<div class="row">
@foreach($shows as $show)
<div class="col-md-2 mb-4">
<div class="movie-card">
<a href="{{ route('show.show', $show->slug) }}" title="{{ $show->name }}">
<img
src="@if($show->poster_path) http://image.tmdb.org/t/p/w185/{{ $show->poster_path }} @else /img/no_poster.png @endif"
alt="{{ $show->name }}"
title="{{ $show->name }} @if($show->first_air_date) ({{ $show->first_air_date->format('Y') }}) @endif"
class="img img-fluid"
>
</a>
<ul class="quick-actions">
<li>
<a href=""><span class="iconify" data-icon="mdi-check-outline"></span></a>
</li>
<li>
<a href=""><span class="iconify" data-icon="mdi-image-multiple"></span></a>
</li>
<li>
<a href="">
{{ $show->vote_average }} <span class="iconify" data-icon="mdi-star"></span>
</a>
</li>
</ul>
</div>
</div>
@endforeach
</div>
@endif
</div>
<!-- People Tab -->
<div class="tab-pane fade {{ $type === 'person' ? 'show active' : '' }}" id="people" role="tabpanel" aria-labelledby="people-tab">
@if($people->isEmpty())
<div class="alert alert-info">No people found matching "{{ $query }}".</div>
@else
<div class="row">
@foreach($people as $person)
<div class="col-md-2 mb-4">
<div class="movie-card">
<a href="{{ route('celebrity.show', $person->slug) }}" title="{{ $person->name }}">
<img
src="@if($person->profile_path) http://image.tmdb.org/t/p/w185/{{ $person->profile_path }} @else /img/user_no_avatar.png @endif"
alt="{{ $person->name }}"
title="{{ $person->name }}"
class="img img-fluid"
>
</a>
<div class="text-center mt-2">
<small>{{ $person->name }}</small>
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection
+33 -51
View File
@@ -1,71 +1,53 @@
@extends('layouts.app')
@section('content')
<div class="container-fluid show-page py-4">
<div class="row">
<!-- Main Content -->
<div class="col-lg-9">
<div class="card mb-4">
<div class="card-header bg-white">
<h5 class="mb-0">Shows</h5>
</div>
<div class="container-fluid movie-page">
<div class="row justify-content-center">
<div class="col-md-10">
<div class="card">
<div class="card-header">Shows</div>
<div class="card-body">
<div class="row">
@foreach($shows as $show)
<div class="col-md-2 mb-3">
<a href="{{ route('show.show', $show->slug) }}" class="text-decoration-none">
@if($show->poster_path)
<div class="movie-poster">
<div class="col-md-2">
<div class="movie-card">
<a href="{{ route('show.show', $show->slug) }}" title="{{ $show->name }}">
<img
src="http://image.tmdb.org/t/p/w185/{{ $show->poster_path }}"
src="
@if($show->poster_path)
http://image.tmdb.org/t/p/w185/{{ $show->poster_path }}
@else
/img/no_poster.png
@endif"
alt="{{ $show->name }}"
title="{{ $show->name }} @if($show->first_air_date) ({{ $show->first_air_date->format('Y') }}) @endif"
class="img-fluid rounded shadow-sm"
class="img img-fluid"
>
<div class="movie-title text-center mt-2">
<small>{{ $show->name }}</small>
</div>
</div>
@else
<div class="no-poster rounded shadow-sm d-flex align-items-center justify-content-center p-2" style="height: 150px; background-color: #f8f9fa;">
<small class="text-center">
{{ $show->name }} @if($show->first_air_date) ({{ $show->first_air_date->format('Y') }}) @endif
</small>
</div>
@endif
</a>
<ul class="quick-actions">
<li>
<a href=""><span class="iconify" data-icon="mdi-check-outline"></span></a>
</li>
<li>
<a href=""><span class="iconify" data-icon="mdi-image-multiple"></span></a>
</li>
<li>
<a href="">
{{ $show->vote_average }} <span class="iconify" data-icon="mdi-star"></span>
</a>
</li>
</ul>
</div>
</div>
@endforeach
</div>
<div class="mt-4">
</div>
</div>
{{ $shows->links() }}
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-3">
<div class="col-md-2">
<div class="card">
<div class="card-body">
<div class="user-actions">
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-eye-check-outline"></span> Mark as seen
</a>
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-thumb-up-outline"></span> Like
</a>
<a href="#" class="d-block mb-3 text-decoration-none">
<span class="iconify me-1" data-icon="mdi-playlist-check"></span> Add to list
<span class="float-end">
<span class="iconify" data-icon="mdi-chevron-down"></span>
</span>
</a>
<hr>
@include('layouts.rating')
</div>
</div>
menu
</div>
</div>
</div>
+2
View File
@@ -52,6 +52,8 @@ Route::prefix('lists')->group(function () {
Route::get('/rate/{itemType}/{itemId}/{rating}', [\App\Http\Controllers\RatingController::class, 'rate'])->name('rating.process');
Route::get('/search', [\App\Http\Controllers\SearchController::class, 'index'])->name('search');
Route::prefix('profile/{userSlug}')->group(function () {
Route::get('/', [\App\Http\Controllers\ProfileController::class, 'show'])->name('profile.show');
Route::get('/lists', [\App\Http\Controllers\MediaListController::class, 'index'])->name('profile.list.index');