From df6246e3c90887f1435665da67a6f5b6a205e7d7 Mon Sep 17 00:00:00 2001 From: w33b Date: Sun, 9 Aug 2026 10:36:03 +0200 Subject: [PATCH] feat(playlist): enhance public playlist index with hero stats and loading optimizations Add a redesigned hero section to the public playlist page displaying community-generated totals for playlists and episodes, plus new string translations (English, German, French). Eager-load user, limited episode previews, and first gallery image to reduce N+1 queries. Cache aggregate statistics for 10 minutes to improve performance on high-traffic pages. --- app/Livewire/Playlists.php | 20 ++ lang/de/playlist.php | 4 + lang/en/playlist.php | 4 + lang/fr/playlist.php | 4 + resources/views/livewire/playlists.blade.php | 259 ++++++++++++++----- resources/views/playlist/index.blade.php | 8 +- 6 files changed, 226 insertions(+), 73 deletions(-) diff --git a/app/Livewire/Playlists.php b/app/Livewire/Playlists.php index e676cd5..fc1f2cd 100644 --- a/app/Livewire/Playlists.php +++ b/app/Livewire/Playlists.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Models\Playlist; +use Illuminate\Support\Facades\Cache; use Livewire\Attributes\Url; use Livewire\Component; use Livewire\WithPagination; @@ -54,11 +55,30 @@ class Playlists extends Component ->withCount('episodes') ->having('episodes_count', '>', 1) ->when($this->search != '', fn ($query) => $query->where('name', 'like', '%'.$this->search.'%')) + ->with([ + 'user', + 'episodes' => fn ($query) => $query->orderBy('position')->limit(4), + 'episodes.episode.gallery' => fn ($query) => $query->limit(1), + ]) ->orderBy($orderby, $orderdirection) ->paginate($this->pagination); + $stats = Cache::remember('publicPlaylistStats', 600, function () { + $playlists = Playlist::where('is_private', 0) + ->withCount('episodes') + ->having('episodes_count', '>', 1) + ->get(); + + return [ + 'playlists' => $playlists->count(), + 'episodes' => $playlists->sum('episodes_count'), + ]; + }); + return view('livewire.playlists', [ 'playlists' => $playlists, + 'totalPlaylists' => $stats['playlists'], + 'totalEpisodes' => $stats['episodes'], ]); } } diff --git a/lang/de/playlist.php b/lang/de/playlist.php index ceda92a..a652d51 100644 --- a/lang/de/playlist.php +++ b/lang/de/playlist.php @@ -2,6 +2,10 @@ return [ 'no-playlist-found' => 'Keine Playlisten gefunden!', + 'hero-subtitle' => 'Kuratierte Episodensammlungen von der Community erstellt.', + 'by' => 'von', + 'playlists-count' => 'Playlisten', + 'clear-search' => 'Suche löschen', 'personal-playlists' => 'Persönliche Playlisten', 'create-on-personal-page' => 'Du kannst einen in deiner persönlichen Playlisten Seite erstellen.', 'play' => 'Abspielen', diff --git a/lang/en/playlist.php b/lang/en/playlist.php index 2c2de46..8bff12f 100644 --- a/lang/en/playlist.php +++ b/lang/en/playlist.php @@ -2,6 +2,10 @@ return [ 'no-playlist-found' => 'No Playlist found!', + 'hero-subtitle' => 'Curated episode collections made by the community.', + 'by' => 'by', + 'playlists-count' => 'Playlists', + 'clear-search' => 'Clear search', 'personal-playlists' => 'Personal Playlists', 'create-on-personal-page' => 'You can create one in your personal playlists page.', 'play' => 'Play', diff --git a/lang/fr/playlist.php b/lang/fr/playlist.php index 1c24270..43691aa 100644 --- a/lang/fr/playlist.php +++ b/lang/fr/playlist.php @@ -2,6 +2,10 @@ return [ 'no-playlist-found' => 'Aucune playlist n\'a été trouvée!', + 'hero-subtitle' => 'Collections d\'épisodes organisées par la communauté.', + 'by' => 'par', + 'playlists-count' => 'Playlists', + 'clear-search' => 'Effacer la recherche', 'personal-playlists' => 'Playlists personnelles', 'create-on-personal-page' => 'Vous pouvez en créer une dans votre page de playlists personnelles.', 'play' => 'Lire', diff --git a/resources/views/livewire/playlists.blade.php b/resources/views/livewire/playlists.blade.php index f8e6a5c..1353328 100644 --- a/resources/views/livewire/playlists.blade.php +++ b/resources/views/livewire/playlists.blade.php @@ -1,27 +1,42 @@
- -
-
-
- -
-
- + +
+
+
+ +
+

+ {{ __('nav.public-playlists') }} +

+

+ {{ __('playlist.hero-subtitle') }} +

+ +
+ + + {{ number_format($totalPlaylists) }} {{ __('playlist.playlists-count') }} + + + + {{ number_format($totalEpisodes) }} {{ __('home.episodes') }} + +
+ +
+
+ +
+
- - - -
-
+
-
- -
-
- + +
+
+ +
+ +
+ +
-
+
+ + +
+
+ @for ($i = 0; $i < 8; $i++) +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @endfor +
+ +
+ @if ($playlists->isEmpty()) +
+
+ +
+

+ {{ __('playlist.no-playlist-found') }} +

+ @if ($search !== '') + + @endif +
+ @else +
+ @foreach ($playlists as $playlist) + @php + $covers = $playlist->episodes + ->take(4) + ->map(fn ($pe) => $pe->episode?->gallery->first()?->thumbnail_url) + ->filter() + ->values(); + @endphp + + + @endforeach +
+ @endif +
-
- - @foreach ($playlists as $playlist) - - @endforeach -
-
- {{ $playlists->links('pagination::tailwind') }} -
+ @if ($playlists->hasPages()) +
+ {{ $playlists->links('pagination::tailwind') }} +
+ @endif
diff --git a/resources/views/playlist/index.blade.php b/resources/views/playlist/index.blade.php index a717882..a708c77 100644 --- a/resources/views/playlist/index.blade.php +++ b/resources/views/playlist/index.blade.php @@ -1,11 +1,5 @@ - -

- {{ __('nav.public-playlists') }} -

-
- -
+
@include('partials.background') @livewire('playlists')