diff --git a/app/Http/Controllers/HuntsController.php b/app/Http/Controllers/HuntsController.php new file mode 100644 index 0000000..563f9f5 --- /dev/null +++ b/app/Http/Controllers/HuntsController.php @@ -0,0 +1,110 @@ +json($hunts); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $validated = $request->validate([ + 'partner_id' => 'required|string', + 'title' => 'required|string', + 'slug' => 'required|string|unique:hunts,slug', + 'description' => 'nullable|string', + 'status' => 'required|string', + 'difficulty' => 'required|string', + 'city' => 'required|string', + 'latitude' => 'nullable|numeric', + 'longitude' => 'nullable|numeric', + 'is_public' => 'boolean', + 'estimated_duration_min' => 'nullable|integer', + 'start_at' => 'nullable|date', + 'end_at' => 'nullable|date', + 'image' => 'nullable|string', + 'creator_id' => 'nullable|exists:users,id', + ]); + + $hunt = Hunts::create($validated); + + return response()->json($hunt, 201); + } + + /** + * Display the specified resource. + */ + public function show($id) + { + $hunt = Hunts::find($id); + + if (!$hunt) { + return response()->json(['message' => 'Hunt not found'], 404); + } + + return response()->json($hunt); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, $id) + { + $hunt = Hunts::find($id); + + if (!$hunt) { + return response()->json(['message' => 'Hunt not found'], 404); + } + + $validated = $request->validate([ + 'partner_id' => 'sometimes|string', + 'title' => 'sometimes|string', + 'slug' => 'sometimes|string|unique:hunts,slug,' . $id, + 'description' => 'nullable|string', + 'status' => 'sometimes|string', + 'difficulty' => 'sometimes|string', + 'city' => 'sometimes|string', + 'latitude' => 'nullable|numeric', + 'longitude' => 'nullable|numeric', + 'is_public' => 'boolean', + 'estimated_duration_min' => 'nullable|integer', + 'start_at' => 'nullable|date', + 'end_at' => 'nullable|date', + 'image' => 'nullable|string', + 'creator_id' => 'nullable|exists:users,id', + ]); + + $hunt->update($validated); + + return response()->json($hunt); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy($id) + { + $hunt = Hunts::find($id); + + if (!$hunt) { + return response()->json(['message' => 'Hunt not found'], 404); + } + + $hunt->delete(); + + return response()->json(['message' => 'Hunt deleted successfully']); + } +} diff --git a/app/Http/Middleware/EnsureUserIsOrga.php b/app/Http/Middleware/EnsureUserIsOrga.php new file mode 100644 index 0000000..61fcf52 --- /dev/null +++ b/app/Http/Middleware/EnsureUserIsOrga.php @@ -0,0 +1,30 @@ +user(); + + if ( + !$user || + ($user->role !== \App\Enums\UserRole::ORGA && $user->role !== \App\Enums\UserRole::ADMIN) + ) { + abort(403, 'Unauthorized action.'); + } + + return $next($request); + } +} diff --git a/app/Models/Hunts.php b/app/Models/Hunts.php new file mode 100644 index 0000000..98d62f3 --- /dev/null +++ b/app/Models/Hunts.php @@ -0,0 +1,40 @@ + 'boolean', + 'start_at' => 'datetime', + 'end_at' => 'datetime', + 'latitude' => 'float', + 'longitude' => 'float', + 'estimated_duration_min' => 'integer', + ]; +} diff --git a/database/migrations/2025_12_18_092945_create_hunts_table.php b/database/migrations/2025_12_18_092945_create_hunts_table.php new file mode 100644 index 0000000..3bfbc3c --- /dev/null +++ b/database/migrations/2025_12_18_092945_create_hunts_table.php @@ -0,0 +1,50 @@ +string('partner_id')->index(); + + $table->string('title'); + $table->string('slug')->unique(); + $table->text('description')->nullable(); + + $table->string('status')->index(); + $table->string('difficulty')->index(); + + $table->string('city')->index(); + $table->decimal('latitude', 10, 7)->nullable(); + $table->decimal('longitude', 10, 7)->nullable(); + + $table->boolean('is_public')->default(false); + + $table->unsignedSmallInteger('estimated_duration_min')->nullable(); + + $table->timestamp('start_at')->nullable(); + $table->timestamp('end_at')->nullable(); + + $table->string('image')->nullable(); + + $table->foreignId('creator_id')->nullable()->constrained('users')->nullOnDelete(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('hunts'); + } +}; diff --git a/routes/api.php b/routes/api.php index e95719d..310c661 100644 --- a/routes/api.php +++ b/routes/api.php @@ -6,6 +6,9 @@ use Illuminate\Support\Facades\Route; +use App\Http\Controllers\HuntsController; +use App\Http\Middleware\EnsureUserIsOrga; + Route::prefix('auth')->group(function (): void { Route::post('register', [AuthController::class, 'register']); Route::post('login', [AuthController::class, 'login']); @@ -15,7 +18,14 @@ Route::prefix('auth')->group(function (): void { }); +Route::get('hunts', [HuntsController::class, 'index']); +Route::get('hunts/{hunt}', [HuntsController::class, 'show']); +Route::middleware(['auth:sanctum', EnsureUserIsOrga::class])->group(function () { + Route::post('hunts', [HuntsController::class, 'store']); + Route::match(['put', 'patch'], 'hunts/{hunt}', [HuntsController::class, 'update']); + Route::delete('hunts/{hunt}', [HuntsController::class, 'destroy']); +}); Route::middleware('auth:sanctum')->group(function (): void { // Route::get('/user', function (Request $request) {