Core implementation: controllers, views, routes, models, import command

This commit is contained in:
Mark
2026-05-29 09:37:07 +03:00
parent 8e1fe4a2f5
commit 5813bc779a
24 changed files with 1361 additions and 37 deletions
+106
View File
@@ -0,0 +1,106 @@
<?php
namespace App\Http\Controllers;
use App\Models\Game;
use App\Models\Genre;
use App\Models\Platform;
use Illuminate\Http\Request;
class GameController extends Controller
{
public function index(Request $request)
{
$query = Game::published()->with(['genres', 'platforms']);
// Filters
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);
}
// Sort
match ($request->get('sort', 'rating')) {
'rating' => $query->orderByDesc('rating_avg')->orderByDesc('rating_count'),
'release' => $query->orderByDesc('release_date'),
'title' => $query->orderBy('title'),
'popular' => $query->orderByDesc('library_count'),
default => $query->orderByDesc('rating_avg'),
};
$games = $query->paginate(24)->withQueryString();
$genres = Genre::orderBy('name')->get();
$platforms = Platform::orderBy('name')->get();
return view('games.index', compact('games', 'genres', 'platforms'));
}
public function show(Game $game)
{
$game->load(['genres', 'platforms', 'companies', 'screenshots', 'reviews.user']);
$userGame = null;
if (auth()->check()) {
$userGame = $game->userGames()->where('user_id', auth()->id())->first();
}
return view('games.show', compact('game', 'userGame'));
}
public function search(Request $request)
{
$q = $request->get('q', '');
$games = collect();
if (strlen($q) >= 2) {
$games = Game::published()
->where('title', 'like', "%{$q}%")
->orderByDesc('rating_count')
->limit(20)
->get();
}
if ($request->expectsJson()) {
return response()->json($games->map(fn($g) => [
'id' => $g->id,
'title' => $g->title,
'slug' => $g->slug,
'cover_thumb' => $g->cover_thumb_url,
'release_year' => $g->release_year,
'rating_avg' => $g->rating_avg,
'url' => route('games.show', $g),
]));
}
return view('games.search', compact('games', 'q'));
}
public function topRated(Request $request)
{
$games = Game::published()
->where('rating_count', '>=', 1)
->orderByDesc('rating_avg')
->orderByDesc('rating_count')
->paginate(24)
->withQueryString();
return view('games.top-rated', compact('games'));
}
public function newReleases(Request $request)
{
$games = Game::published()
->whereNotNull('release_date')
->where('release_date', '<=', now())
->orderByDesc('release_date')
->paginate(24)
->withQueryString();
return view('games.new-releases', compact('games'));
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers;
use App\Models\Game;
class HomeController extends Controller
{
public function index()
{
$topRated = Game::published()
->where('rating_count', '>=', 1)
->orderByDesc('rating_avg')
->orderByDesc('rating_count')
->limit(12)
->get();
$newReleases = Game::published()
->whereNotNull('release_date')
->where('release_date', '<=', now())
->orderByDesc('release_date')
->limit(8)
->get();
return view('home', compact('topRated', 'newReleases'));
}
}
@@ -0,0 +1,73 @@
<?php
namespace App\Http\Controllers;
use App\Models\Game;
use App\Models\UserGame;
use Illuminate\Http\Request;
class LibraryController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request)
{
$request->validate([
'game_id' => 'required|exists:games,id',
'status' => 'required|in:' . implode(',', UserGame::STATUSES),
'rating' => 'nullable|integer|min:1|max:10',
]);
$userGame = UserGame::updateOrCreate(
['user_id' => auth()->id(), 'game_id' => $request->game_id],
['status' => $request->status, 'rating' => $request->rating]
);
// Recalculate rating on the game
$userGame->game->recalculateRating();
if ($request->expectsJson()) {
return response()->json(['status' => 'ok', 'userGame' => $userGame]);
}
return back()->with('success', 'Added to your library.');
}
public function update(Request $request, UserGame $userGame)
{
$this->authorize('update', $userGame);
$request->validate([
'status' => 'sometimes|in:' . implode(',', UserGame::STATUSES),
'rating' => 'nullable|integer|min:1|max:10',
'notes' => 'nullable|string|max:1000',
]);
$userGame->update($request->only(['status', 'rating', 'notes']));
$userGame->game->recalculateRating();
if ($request->expectsJson()) {
return response()->json(['status' => 'ok', 'userGame' => $userGame]);
}
return back()->with('success', 'Library entry updated.');
}
public function destroy(UserGame $userGame)
{
$this->authorize('delete', $userGame);
$game = $userGame->game;
$userGame->delete();
$game->recalculateRating();
if (request()->expectsJson()) {
return response()->json(['status' => 'ok']);
}
return back()->with('success', 'Removed from your library.');
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\UserGame;
class UserController extends Controller
{
public function show(User $user)
{
$stats = [
'played' => $user->library()->where('status', 'played')->count(),
'playing' => $user->library()->where('status', 'playing')->count(),
'want_to_play' => $user->library()->where('status', 'want_to_play')->count(),
'total' => $user->library()->count(),
];
$recentlyPlayed = $user->library()
->with('game')
->where('status', 'played')
->latest('updated_at')
->limit(6)
->get();
return view('users.show', compact('user', 'stats', 'recentlyPlayed'));
}
public function library(User $user)
{
$status = request('status');
$query = $user->library()->with('game');
if ($status && in_array($status, UserGame::STATUSES)) {
$query->where('status', $status);
}
$entries = $query->latest('updated_at')->paginate(24)->withQueryString();
return view('users.library', compact('user', 'entries', 'status'));
}
}