diff --git a/api/app/Http/Controllers/AuthController.php b/api/app/Http/Controllers/AuthController.php index afd66e9..957ed11 100644 --- a/api/app/Http/Controllers/AuthController.php +++ b/api/app/Http/Controllers/AuthController.php @@ -53,6 +53,10 @@ class AuthController extends Controller if (User::where('email', $request->email)->exists()) { return response()->json(['message' => 'Email already registered'], 409); } + + if (User::where('nickname', $request->nickname)->exists()) { + return response()->json(['message' => 'Nickname already registered'], 409); + } $user = User::create([ 'email' => $request->email, diff --git a/api/app/Http/Controllers/ProfileController.php b/api/app/Http/Controllers/ProfileController.php index eaf8b4c..63ef7d5 100644 --- a/api/app/Http/Controllers/ProfileController.php +++ b/api/app/Http/Controllers/ProfileController.php @@ -3,6 +3,12 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use App\Models\User; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; + class ProfileController extends Controller { @@ -52,7 +58,7 @@ class ProfileController extends Controller $user = $request->user(); - if (!\Hash::check($request->current_password, $user->password)) { + if (!Hash::check($request->current_password, $user->password)) { return response()->json( [ "message" => "Current password is incorrect", @@ -61,7 +67,7 @@ class ProfileController extends Controller ); } - $user->password = \Hash::make($request->new_password); + $user->password = Hash::make($request->new_password); $user->save(); return response()->json([ @@ -69,6 +75,13 @@ class ProfileController extends Controller ]); } + public function getCoins(Request $request) + { + return response()->json([ + 'coins' => $request->user()->coins_balance + ]); + } + public function updateAvatar(Request $request) { $request->validate([ @@ -78,7 +91,7 @@ class ProfileController extends Controller $user = $request->user(); if ($user->photo_avatar_filename) { - \Storage::disk("public")->delete( + Storage::disk("public")->delete( "photos_avatars/" . $user->photo_avatar_filename, ); } @@ -87,7 +100,7 @@ class ProfileController extends Controller $filename = str_pad($user->id, 5, "0", STR_PAD_LEFT) . "_" . - \Str::random(10) . + Str::random(10) . "." . $file->extension(); $file->storeAs("photos_avatars", $filename, "public"); diff --git a/api/app/Http/Controllers/StatisticsController.php b/api/app/Http/Controllers/StatisticsController.php new file mode 100644 index 0000000..faf7d6e --- /dev/null +++ b/api/app/Http/Controllers/StatisticsController.php @@ -0,0 +1,76 @@ +count(); + + $totalGames = Game::where('status', 'Ended')->count(); + $activeGames = Game::where('status', 'Playing')->count(); + + return response()->json([ + 'total_players' => $totalPlayers, + 'total_games' => $totalGames, + 'active_games' => $activeGames, + ]); + } + + public function getLeaderboard(Request $request) + { + $type = $request->query('type'); + + $query = User::where('type', 'P') + ->withCount(['wonGames' => function ($query) use ($type) { + if ($type) { + $query->where('type', $type); + } + }]) + ->orderBy('won_games_count', 'desc') + ->take(10); + + $leaderboard = $query->get(['id', 'nickname', 'photo_avatar_filename']); + + return response()->json($leaderboard); + } + + public function getPersonalStats(Request $request) + { + $user = $request->user(); + + $totalGames = Game::where('status', 'Ended') + ->where(function ($q) use ($user) { + $q->where('player1_user_id', $user->id) + ->orWhere('player2_user_id', $user->id); + }) + ->count(); + + $totalWins = Game::where('status', 'Ended') + ->where('winner_user_id', $user->id) + ->count(); + + $totalLosses = $totalGames - $totalWins; // Simplest math + + $winRate = 0; + if ($totalGames > 0) { + $winRate = round(($totalWins / $totalGames) * 100, 1); + } + + return response()->json([ + 'nickname' => $user->nickname, + 'total_games' => $totalGames, + 'total_wins' => $totalWins, + 'total_losses' => $totalLosses, + 'win_rate' => $winRate . '%', + 'current_balance' => $user->coins_balance, // Extra info + ]); + } +} \ No newline at end of file diff --git a/api/app/Models/User.php b/api/app/Models/User.php index 9209a76..b33dc36 100644 --- a/api/app/Models/User.php +++ b/api/app/Models/User.php @@ -48,4 +48,14 @@ class User extends Authenticatable 'blocked' => 'boolean', 'deleted_at' => 'datetime', ]; + + public function wonGames() + { + return $this->hasMany(Game::class, 'winner_user_id'); + } + + public function games() + { + return $this->hasMany(Game::class, 'player1_user_id')->orWhere('player2_user_id', $this->id); + } } diff --git a/api/routes/api.php b/api/routes/api.php index 0601edb..b4991af 100644 --- a/api/routes/api.php +++ b/api/routes/api.php @@ -5,6 +5,7 @@ use App\Http\Controllers\GameController; use App\Http\Controllers\MatchController; use App\Http\Controllers\ProfileController; use App\Http\Controllers\UserController; +use App\Http\Controllers\StatisticsController; use Illuminate\Support\Facades\Route; Route::prefix('v1')->group(function () { @@ -12,14 +13,18 @@ Route::prefix('v1')->group(function () { Route::post('/login', [AuthController::class, 'login']); Route::post('/register', [AuthController::class, 'register']); + Route::get('/statistics/public', [StatisticsController::class, 'getPublicStats']); + Route::get('/leaderboard', [StatisticsController::class, 'getLeaderboard']); + // Authenticated Routes Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () { Route::post('/logout', [AuthController::class, 'logout']); - + Route::get('/statistics/me', [StatisticsController::class, 'getPersonalStats']); Route::prefix('users/me')->group(function () { Route::get('/', [ProfileController::class, 'show']); Route::put('/', [ProfileController::class, 'update']); Route::delete('/', [ProfileController::class, 'destroy']); + Route::get('/coins', [ProfileController::class, 'getCoins']); Route::put('/password', [ ProfileController::class, 'updatePassword',