searchService->discoverTrending($perPage); $artworks = $results->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $results, 'page_title' => 'Trending Artworks', 'section' => 'trending', 'description' => 'The most-viewed artworks on Skinbase over the past 7 days.', 'icon' => 'fa-fire', ]); } // ─── /discover/fresh ───────────────────────────────────────────────────── public function fresh(Request $request) { $perPage = 24; $results = $this->searchService->discoverFresh($perPage); $results->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $results, 'page_title' => 'Fresh Uploads', 'section' => 'fresh', 'description' => 'The latest artworks just uploaded to Skinbase.', 'icon' => 'fa-bolt', ]); } // ─── /discover/top-rated ───────────────────────────────────────────────── public function topRated(Request $request) { $perPage = 24; $results = $this->searchService->discoverTopRated($perPage); $results->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $results, 'page_title' => 'Top Rated Artworks', 'section' => 'top-rated', 'description' => 'The most-loved artworks on Skinbase, ranked by community favourites.', 'icon' => 'fa-medal', ]); } // ─── /discover/most-downloaded ─────────────────────────────────────────── public function mostDownloaded(Request $request) { $perPage = 24; $results = $this->searchService->discoverMostDownloaded($perPage); $results->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $results, 'page_title' => 'Most Downloaded', 'section' => 'most-downloaded', 'description' => 'All-time most downloaded artworks on Skinbase.', 'icon' => 'fa-download', ]); } // ─── /discover/on-this-day ─────────────────────────────────────────────── public function onThisDay(Request $request) { $perPage = 24; $today = now(); $artworks = Artwork::query() ->public() ->published() ->with(['user:id,name', 'categories:id,name,slug,content_type_id,parent_id,sort_order']) ->whereRaw('MONTH(published_at) = ?', [$today->month]) ->whereRaw('DAY(published_at) = ?', [$today->day]) ->whereRaw('YEAR(published_at) < ?', [$today->year]) ->orderByDesc('published_at') ->paginate($perPage) ->withQueryString(); $artworks->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $artworks, 'page_title' => 'On This Day', 'section' => 'on-this-day', 'description' => 'Artworks published on ' . $today->format('F j') . ' in previous years.', 'icon' => 'fa-calendar-day', ]); } // ─── /creators/rising ──────────────────────────────────────────────────── public function risingCreators(Request $request) { $perPage = 20; // Creators with artworks published in the last 90 days, ordered by total recent views. $hasStats = false; try { $hasStats = Schema::hasTable('artwork_stats'); } catch (\Throwable) {} if ($hasStats) { $sub = Artwork::query() ->public() ->published() ->join('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id') ->where('artworks.published_at', '>=', now()->subDays(90)) ->selectRaw('artworks.user_id, SUM(artwork_stats.views) as recent_views, MAX(artworks.published_at) as latest_published') ->groupBy('artworks.user_id'); } else { $sub = Artwork::query() ->public() ->published() ->where('published_at', '>=', now()->subDays(90)) ->selectRaw('user_id, COUNT(*) as recent_views, MAX(published_at) as latest_published') ->groupBy('user_id'); } $creators = DB::table(DB::raw('(' . $sub->toSql() . ') as t')) ->mergeBindings($sub->getQuery()) ->join('users as u', 'u.id', '=', 't.user_id') ->select('u.id as user_id', 'u.name as uname', 'u.username', 't.recent_views', 't.latest_published') ->orderByDesc('t.recent_views') ->orderByDesc('t.latest_published') ->paginate($perPage) ->withQueryString(); $creators->getCollection()->transform(function ($row) { return (object) [ 'user_id' => $row->user_id, 'uname' => $row->uname, 'username' => $row->username, 'total' => (int) $row->recent_views, 'metric' => 'views', ]; }); return view('web.creators.rising', [ 'creators' => $creators, 'page_title' => 'Rising Creators — Skinbase', ]); } // ─── /discover/following ───────────────────────────────────────────────── public function following(Request $request) { $user = $request->user(); $perPage = 24; // Subquery: IDs of users this viewer follows $followingIds = DB::table('user_followers') ->where('follower_id', $user->id) ->pluck('user_id'); if ($followingIds->isEmpty()) { // Trending fallback: show popular artworks so the page isn't blank try { $fallbackResults = $this->searchService->discoverTrending(12); $fallbackArtworks = $fallbackResults->getCollection() ->transform(fn ($a) => $this->presentArtwork($a)); } catch (\Throwable) { $fallbackArtworks = collect(); } // Suggested creators: most-followed users the viewer doesn't follow yet $suggestedCreators = DB::table('users') ->join('user_statistics', 'users.id', '=', 'user_statistics.user_id') ->where('users.id', '!=', $user->id) ->whereNotNull('users.email_verified_at') ->where('users.is_active', true) ->orderByDesc('user_statistics.followers_count') ->limit(8) ->select( 'users.id', 'users.name', 'users.username', 'user_statistics.followers_count', ) ->get(); return view('web.discover.index', [ 'artworks' => collect(), 'page_title' => 'Following Feed', 'section' => 'following', 'description' => 'Follow some creators to see their work here.', 'icon' => 'fa-user-group', 'empty' => true, 'fallback_trending' => $fallbackArtworks, 'fallback_creators' => $suggestedCreators, ]); } $page = (int) request()->get('page', 1); $cacheKey = "discover.following.{$user->id}.p{$page}"; $artworks = Cache::remember($cacheKey, 60, function () use ($user, $followingIds, $perPage): \Illuminate\Pagination\LengthAwarePaginator { return Artwork::query() ->public() ->published() ->with(['user:id,name,username', 'categories:id,name,slug,content_type_id,parent_id,sort_order']) ->whereIn('user_id', $followingIds) ->orderByDesc('published_at') ->paginate($perPage) ->withQueryString(); }); $artworks->getCollection()->transform(fn ($a) => $this->presentArtwork($a)); return view('web.discover.index', [ 'artworks' => $artworks, 'page_title' => 'Following Feed', 'section' => 'following', 'description' => 'The latest artworks from creators you follow.', 'icon' => 'fa-user-group', ]); } // ─── Helpers ───────────────────────────────────────────────────────────── private function presentArtwork(Artwork $artwork): object { $primaryCategory = $artwork->categories->sortBy('sort_order')->first(); $present = ThumbnailPresenter::present($artwork, 'md'); return (object) [ 'id' => $artwork->id, 'name' => $artwork->title, 'category_name' => $primaryCategory->name ?? '', 'gid_num' => $primaryCategory ? ((int) $primaryCategory->id % 5) * 5 : 0, 'thumb_url' => $present['url'], 'thumb_srcset' => $present['srcset'] ?? $present['url'], 'uname' => $artwork->user->name ?? 'Skinbase', 'published_at' => $artwork->published_at, ]; } }