diff --git a/app/Livewire/Forms/FilterForm.php b/app/Livewire/Forms/FilterForm.php new file mode 100644 index 0000000..5a1ab3d --- /dev/null +++ b/app/Livewire/Forms/FilterForm.php @@ -0,0 +1,11 @@ +name = $list->name; + $this->listId = $list->id; + $this->isPublic = $list->is_public; + } + + public function save(): void + { + if ($this->listId) { + $list = MovieList::find($this->listId); + $list->name = $this->name; + $list->is_public = $this->isPublic; + $list->save(); + } + } +} diff --git a/app/Livewire/MovieDetailsPanel.php b/app/Livewire/MovieDetailsPanel.php new file mode 100644 index 0000000..49789bc --- /dev/null +++ b/app/Livewire/MovieDetailsPanel.php @@ -0,0 +1,31 @@ + 'openPanel']; + + public function openPanel(int $movieId): void + { + $this->selectedMovie = Movie::find($movieId); + $this->showDetails = true; + } + + public function closePanel(): void + { + $this->showDetails = false; + $this->selectedMovie = null; + } + + public function render() + { + return view('livewire.movie-details-panel'); + } +} diff --git a/app/Livewire/MovieList.php b/app/Livewire/MovieList.php index b9a678b..a2c6730 100644 --- a/app/Livewire/MovieList.php +++ b/app/Livewire/MovieList.php @@ -3,18 +3,25 @@ namespace App\Livewire; use App\Livewire\Forms\MovieListForm; -use App\Models\Interfaces\MovieDbInterface; +use App\Livewire\Forms\SettingsForm; use App\Models\MovieList as MovieListModel; use Livewire\Component; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class MovieList extends Component { public int $id; - public string $query; public MovieListModel $list; public $movies = []; + public string $filterText = ""; + public $filteredMovies = []; public MovieListForm $form; + public SettingsForm $settingsForm; + public bool $showSettings = false; + + protected $listeners = [ + 'movie-added' => 'getList', + 'list-updated' => 'getList' + ]; public function mount($id): void { @@ -30,25 +37,33 @@ class MovieList extends Component if ($list) { $this->list = $list; $this->movies = $list->movies; + $this->filteredMovies = $list->movies; + $this->settingsForm->setList($list); } else { abort(404); } } - public function addMovie(MovieDbInterface $movie_db) + public function filterMovies(): void { - $this->resetErrorBag(); + $this->filteredMovies = collect($this->movies) + ->filter(fn($movie) => stripos($movie->title, $this->filterText) !== false); + } - try { - $movie = $movie_db->search($this->query); - } catch (NotFoundHttpException $e) { - $this->addError('query', 'Movie not found'); - return; - } + public function toggleSettings(): void + { + $this->showSettings = !$this->showSettings; + } - $this->list->movies()->syncWithoutDetaching($movie->id); + public function saveSettings(): void + { + $this->settingsForm->save(); $this->getList(); - $this->form->reset(); + } + + public function updatedSettingsForm(): void + { + $this->settingsForm->save(); } public function render() diff --git a/app/Livewire/SearchPanel.php b/app/Livewire/SearchPanel.php new file mode 100644 index 0000000..cd42b8e --- /dev/null +++ b/app/Livewire/SearchPanel.php @@ -0,0 +1,54 @@ + 'openSearchPanel']; + + public function openSearchPanel(): void + { + $this->showSearch = true; + } + + public function findMovies(MovieDbInterface $movie_db): void + { + try { + //$movie = $movie_db->search($this->query, ["type" => "imdb"]); + $this->results = $movie_db->search($this->query, ["type" => "title"]); + } catch (NotFoundHttpException $e) { + $this->addError('query', 'Movie not found'); + } + } + + public function addMovie(MovieDbInterface $movieDb, string $imdbId): void + { + $this->resetErrorBag(); + $movie = $movieDb->searchByImdbId($imdbId); + + $list = MovieListModel::find($this->listId); + $list->movies()->syncWithoutDetaching($movie->id); + + $this->dispatch('movie-added'); + $this->showSearch = false; + $this->query = ''; + $this->results = []; + } + + public function render() + { + return view('livewire.search-panel'); + } +} diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index d42ec0c..0dc5d38 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; use Laravel\Fortify\Fortify; +use Laravel\Fortify\Contracts\LoginResponse; class FortifyServiceProvider extends ServiceProvider { diff --git a/app/Services/OmdbService.php b/app/Services/OmdbService.php index 96b95f7..9dcc871 100644 --- a/app/Services/OmdbService.php +++ b/app/Services/OmdbService.php @@ -8,6 +8,7 @@ use App\Models\User; use Exception; use Illuminate\Support\Facades\Http; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use function Symfony\Component\Translation\t; class OmdbService implements MovieDbInterface { @@ -20,14 +21,26 @@ class OmdbService implements MovieDbInterface $this->user = auth()->user(); } - public function search(string $query, array $options = []) + public function search(string $query, array $options = []): array|Movie { - $movie = Http::get($this->url . "&t=" . $query)->json(); + $searchType = $options["type"] ?? "title"; + + $result = match ($searchType) { + 'imdb' => $this->searchByImdbId($query), + 'title' => $this->searchByTitle($query), + default => $this->searchByTitle($query), + }; + + return $result; + } + + public function searchByImdbId(string $imdbId) + { + $movie = Http::get($this->url . "&i=" . $imdbId)->json(); if ($movie['Response'] !== 'True') { throw new NotFoundHttpException("Movie not found"); } - logger()->debug("Movie from OMDB: " . json_encode($movie)); try { $existing_movie = $this->movie->where('imdb_id', $movie['imdbID'])->firstOrFail(); return $existing_movie; @@ -38,4 +51,25 @@ class OmdbService implements MovieDbInterface ); } } + + public function searchByTitle(string $title) + { + $search_results = Http::get($this->url . "&s=" . $title . "&type=movie")->json(); + if ($search_results['Response'] !== 'True') { + throw new NotFoundHttpException("Movie not found"); + } + + $movies = []; + foreach ($search_results['Search'] as $result) { + $movies[] = [ + 'title' => $result['Title'] ?? "", + 'year' => $result['Year'] ?? "", + 'imdb_id' => $result['imdbID'] ?? "", + 'type' => $result['Type'] ?? "", + 'poster' => $result['Poster'] ?? "" + ]; + } + + return $movies; + } } diff --git a/config/fortify.php b/config/fortify.php index 2fce0cc..a0d6f4f 100644 --- a/config/fortify.php +++ b/config/fortify.php @@ -73,7 +73,7 @@ return [ | */ - 'home' => '/dashboard', + 'home' => '/lists', /* |-------------------------------------------------------------------------- diff --git a/package-lock.json b/package-lock.json index 47584d1..197486d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "@fortawesome/fontawesome-free": "^7.1.0", "@tailwindcss/vite": "^4.1.11", "autoprefixer": "^10.4.20", "axios": "^1.7.4", @@ -448,6 +449,15 @@ "node": ">=18" } }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.1.0.tgz", + "integrity": "sha512-+WxNld5ZCJHvPQCr/GnzCTVREyStrAJjisUPtUxG5ngDA8TMlPnKp6dddlTpai4+1GNmltAeuk1hJEkBohwZYA==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", diff --git a/package.json b/package.json index 6a891b6..31cc403 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev": "vite" }, "dependencies": { + "@fortawesome/fontawesome-free": "^7.1.0", "@tailwindcss/vite": "^4.1.11", "autoprefixer": "^10.4.20", "axios": "^1.7.4", diff --git a/resources/css/app.css b/resources/css/app.css index 2f9e968..29a1edc 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,4 +1,5 @@ @import 'tailwindcss'; +@import '@fortawesome/fontawesome-free/css/all.css'; @source '../views'; @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; diff --git a/resources/views/components/header.blade.php b/resources/views/components/header.blade.php index 6fee84d..6627bae 100644 --- a/resources/views/components/header.blade.php +++ b/resources/views/components/header.blade.php @@ -1,9 +1,9 @@ -
- +
+ @auth
  • Lists
  • -
  • Schedule
  • +
  • @csrf diff --git a/resources/views/components/layouts/app/header.blade.php b/resources/views/components/layouts/app/header.blade.php deleted file mode 100644 index bdc354e..0000000 --- a/resources/views/components/layouts/app/header.blade.php +++ /dev/null @@ -1,124 +0,0 @@ - - - - @include('partials.head') - - - - - - - - - - - - {{ __('Dashboard') }} - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - {{ auth()->user()->initials() }} - - - -
    - {{ auth()->user()->name }} - {{ auth()->user()->email }} -
    -
    -
    -
    - - - - - {{ __('Settings') }} - - - - - - @csrf - - {{ __('Log Out') }} - - -
    -
    -
    - - - - - - - - - - - - - {{ __('Dashboard') }} - - - - - - - - - {{ __('Repository') }} - - - - {{ __('Documentation') }} - - - - - {{ $slot }} - - @fluxScripts - - diff --git a/resources/views/components/movie.blade.php b/resources/views/components/movie.blade.php index 7e1b265..be4d5e1 100644 --- a/resources/views/components/movie.blade.php +++ b/resources/views/components/movie.blade.php @@ -1,5 +1,5 @@ @props(['movie']) -
    - {{$movie->title}} - +
    + {{$movie->title}}
    diff --git a/resources/views/components/settings/layout.blade.php b/resources/views/components/settings/layout.blade.php deleted file mode 100644 index dca245b..0000000 --- a/resources/views/components/settings/layout.blade.php +++ /dev/null @@ -1,23 +0,0 @@ -
    -
    - - {{ __('Profile') }} - {{ __('Password') }} - @if (Laravel\Fortify\Features::canManageTwoFactorAuthentication()) - {{ __('Two-Factor Auth') }} - @endif - {{ __('Appearance') }} - -
    - - - -
    - {{ $heading ?? '' }} - {{ $subheading ?? '' }} - -
    - {{ $slot }} -
    -
    -
    diff --git a/resources/views/components/slide-over.blade.php b/resources/views/components/slide-over.blade.php new file mode 100644 index 0000000..b9c4472 --- /dev/null +++ b/resources/views/components/slide-over.blade.php @@ -0,0 +1,44 @@ +@props(['wire:model']) + +
    + +
    + + +
    + +
    + +
    + +
    + + +
    + {{ $slot }} +
    +
    +
    +
    diff --git a/resources/views/components/ui/card.blade.php b/resources/views/components/ui/card.blade.php new file mode 100644 index 0000000..17b66f3 --- /dev/null +++ b/resources/views/components/ui/card.blade.php @@ -0,0 +1,3 @@ +
    merge(['class' => 'bg-gray-800 p-5 flex flex-col gap-5 items-center rounded']) }}> + {{ $slot }} +
    diff --git a/resources/views/components/site-logo.blade.php b/resources/views/components/ui/site-logo.blade.php similarity index 89% rename from resources/views/components/site-logo.blade.php rename to resources/views/components/ui/site-logo.blade.php index 1337659..bf5996d 100644 --- a/resources/views/components/site-logo.blade.php +++ b/resources/views/components/ui/site-logo.blade.php @@ -1,9 +1,9 @@ -
    +
    merge(['class' => "relative -rotate-6 max-w-72 sm:max-w-96"])}}>
    -

    Cinema Corona

    +

    Movie Night

    diff --git a/resources/views/components/ui/slide-over.blade.php b/resources/views/components/ui/slide-over.blade.php new file mode 100644 index 0000000..b584967 --- /dev/null +++ b/resources/views/components/ui/slide-over.blade.php @@ -0,0 +1,44 @@ +@props(['model']) + +
    + +
    + + +
    + +
    + +
    + +
    + + +
    + {{ $slot }} +
    +
    +
    +
    diff --git a/resources/views/livewire/lists.blade.php b/resources/views/livewire/lists.blade.php index 579bca5..651f33d 100644 --- a/resources/views/livewire/lists.blade.php +++ b/resources/views/livewire/lists.blade.php @@ -1,8 +1,7 @@ -
    -

    Lists

    -
    +
    +

    Lists

    +
    -

    Add List

    @if ($errors->any())
      @@ -13,27 +12,25 @@
    @endif -
    - + +
    -
    -
    +
    diff --git a/resources/views/livewire/movie-details-panel.blade.php b/resources/views/livewire/movie-details-panel.blade.php new file mode 100644 index 0000000..b0f224c --- /dev/null +++ b/resources/views/livewire/movie-details-panel.blade.php @@ -0,0 +1,57 @@ + + @if($selectedMovie) +
    + +
    +

    {{ $selectedMovie->title }}

    +

    {{ $selectedMovie->year }}

    +
    + + + @if($selectedMovie->poster && $selectedMovie->poster !== 'N/A') + {{ $selectedMovie->title }} + @endif + + + @if($selectedMovie->plot && $selectedMovie->plot !== 'N/A') +
    +

    Plot

    +

    {{ $selectedMovie->plot }}

    +
    + @endif + + +
    + @if($selectedMovie->director && $selectedMovie->director !== 'N/A') +
    + Director: + {{ $selectedMovie->director }} +
    + @endif + + @if($selectedMovie->actors && $selectedMovie->actors !== 'N/A') +
    + Actors: + {{ $selectedMovie->actors }} +
    + @endif + + @if($selectedMovie->genre && $selectedMovie->genre !== 'N/A') +
    + Genre: + {{ $selectedMovie->genre }} +
    + @endif + + @if($selectedMovie->mpaa_rating && $selectedMovie->mpaa_rating !== 'N/A') +
    + Rating: + {{ $selectedMovie->mpaa_rating }} +
    + @endif +
    +
    + @endif +
    diff --git a/resources/views/livewire/movie-list.blade.php b/resources/views/livewire/movie-list.blade.php index de06bc9..8284abb 100644 --- a/resources/views/livewire/movie-list.blade.php +++ b/resources/views/livewire/movie-list.blade.php @@ -1,22 +1,70 @@ -
    -

    {{$list->name}}

    +
    +
    +

    {{$list->name}}

    + +
    -
    -
    - - - @error('query') {{ $message }} @enderror + +
    + +
    - - +
    +
    + +
    +
    + + + +
    +
      + @foreach ($filteredMovies as $movie) +
    • + +
    • + @endforeach +
    +
    + + +
    +
    + +

    Settings

    +
    + +
    + +
    + + +
    +
    +
    + + +
    +
    +
    +
    +
    -
      - @foreach ($movies as $movie) -
    • - -
    • - @endforeach -
    diff --git a/resources/views/livewire/search-panel.blade.php b/resources/views/livewire/search-panel.blade.php new file mode 100644 index 0000000..83daf97 --- /dev/null +++ b/resources/views/livewire/search-panel.blade.php @@ -0,0 +1,30 @@ + +
    +
    + +
    + + +
    + @error('query') {{ $message }} @enderror +
    + +
    +
      + @foreach ($results as $result) +
    • +
      +
      + {{ $result['title'] }} + ({{$result['year']}}) +
      + +
      + poster +
    • + @endforeach +
    +
    diff --git a/resources/views/pages/auth/login.blade.php b/resources/views/pages/auth/login.blade.php index 663ba6b..ece4e3b 100644 --- a/resources/views/pages/auth/login.blade.php +++ b/resources/views/pages/auth/login.blade.php @@ -1,27 +1,29 @@ -
    -

    Log in

    +
    + -
    - @csrf - @if($errors->any()) -
    - @foreach($errors->all() as $error) -

    {{$error}}

    - @endforeach + + + @csrf + @if($errors->any()) +
    + @foreach($errors->all() as $error) +

    {{$error}}

    + @endforeach +
    + @endif + +
    + + +
    +
    + +
    - @endif -
    - - -
    -
    - - -
    - - - + + +
    diff --git a/resources/views/pages/lists.blade.php b/resources/views/pages/lists.blade.php index 9e5b4c1..b19265a 100644 --- a/resources/views/pages/lists.blade.php +++ b/resources/views/pages/lists.blade.php @@ -1,5 +1,4 @@ -

    Lists

    diff --git a/routes/web.php b/routes/web.php index 4f813ad..77cc9d0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -11,13 +11,10 @@ Route::get('/register', RegisterUser::class)->name('register'); Route::get('/reset-password/{token}', PasswordReset::class)->name('reset-password'); -/* AUTH */ -Route::view('dashboard', 'pages.home') - ->middleware(['auth', 'verified']) - ->name('home'); +Route::view('/', 'pages.auth.login')->name('login'); +/* AUTH */ Route::middleware(['auth'])->group(function () { - Route::view('/', 'pages.home')->name('home'); Route::get('/lists', MovieLists::class)->name('lists'); Route::get('/lists/{id}', MovieList::class)->name('list'); });