$game->id, 'title' => $game->title, 'slug' => $game->slug, 'cover_url' => $game->cover_url, 'release_year' => $game->release_year, 'release_date' => $game->release_date?->toDateString(), 'rating_avg' => $game->rating_avg ? (float) $game->rating_avg : null, 'rating_count' => $game->rating_count, 'library_count' => $game->library_count, 'genres' => $game->genres->pluck('name'), 'platforms' => $game->platforms->pluck('name'), ]; } public function index(Request $request): JsonResponse { $query = Game::with(['genres', 'platforms'])->published(); if ($request->filled('genre')) { $query->whereHas('genres', fn ($q) => $q->where('genres.id', $request->genre)); } if ($request->filled('platform')) { $query->whereHas('platforms', fn ($q) => $q->where('platforms.id', $request->platform)); } if ($request->filled('year')) { $query->where('release_year', $request->year); } match ($request->get('sort', 'popular')) { 'rating' => $query->orderByDesc('rating_avg'), 'release' => $query->orderByDesc('release_date'), 'title' => $query->orderBy('title'), default => $query->orderByDesc('library_count'), }; $paginator = $query->paginate(20); return response()->json([ 'data' => $paginator->map(fn ($game) => $this->formatGame($game))->values(), 'meta' => [ 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), 'per_page' => $paginator->perPage(), 'total' => $paginator->total(), ], ]); } public function show(Game $game): JsonResponse { $game->load(['genres', 'platforms', 'companies', 'screenshots', 'reviews.user']); return response()->json([ 'data' => array_merge($this->formatGame($game), [ 'description' => $game->summary, 'companies' => $game->companies->map(fn ($c) => [ 'name' => $c->name, 'role' => $c->pivot->role, ]), 'screenshots' => $game->screenshots->pluck('url'), 'reviews' => $game->reviews->take(5)->map(fn ($r) => [ 'user' => $r->user->slug, 'body' => $r->body, 'rating' => $r->rating, 'created_at' => $r->created_at->toIso8601String(), ]), ]), ]); } public function search(Request $request): JsonResponse { $q = trim((string) $request->get('q', '')); if (mb_strlen($q) < 2) { return response()->json(['error' => 'Query must be at least 2 characters.'], 422); } $games = Game::with(['genres', 'platforms']) ->where('title', 'like', '%' . $q . '%') ->published() ->orderBy('title') ->limit(20) ->get(); return response()->json([ 'data' => $games->map(fn ($game) => $this->formatGame($game))->values(), 'meta' => ['total' => $games->count()], ]); } public function topRated(Request $request): JsonResponse { $paginator = Game::with(['genres', 'platforms']) ->published() ->where('rating_count', '>=', 1) ->orderByDesc('rating_avg') ->orderByDesc('rating_count') ->paginate(20); return response()->json([ 'data' => $paginator->map(fn ($game) => $this->formatGame($game))->values(), 'meta' => [ 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), 'per_page' => $paginator->perPage(), 'total' => $paginator->total(), ], ]); } public function newReleases(Request $request): JsonResponse { $paginator = Game::with(['genres', 'platforms']) ->published() ->where('release_date', '<=', now()) ->orderByDesc('release_date') ->paginate(20); return response()->json([ 'data' => $paginator->map(fn ($game) => $this->formatGame($game))->values(), 'meta' => [ 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), 'per_page' => $paginator->perPage(), 'total' => $paginator->total(), ], ]); } }