From a323489a6f879c790ef9cd96fa0465bcf5445a90 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 19 Dec 2025 12:31:24 +0100 Subject: [PATCH] feat: hunt steps --- app/Http/Controllers/HuntStepsController.php | 54 +++++++++++++++++++ app/Models/HuntSteps.php | 30 +++++++++++ app/Models/Hunts.php | 4 ++ ...5_12_19_111936_create_hunt_steps_table.php | 37 +++++++++++++ routes/api.php | 1 + 5 files changed, 126 insertions(+) create mode 100644 app/Http/Controllers/HuntStepsController.php create mode 100644 app/Models/HuntSteps.php create mode 100644 database/migrations/2025_12_19_111936_create_hunt_steps_table.php diff --git a/app/Http/Controllers/HuntStepsController.php b/app/Http/Controllers/HuntStepsController.php new file mode 100644 index 0000000..550e70e --- /dev/null +++ b/app/Http/Controllers/HuntStepsController.php @@ -0,0 +1,54 @@ +creator_id !== auth()->id()) { + return response()->json(['message' => 'Unauthorized'], 403); + } + + $validated = $request->validate([ + 'step_number' => 'required|integer', + 'title' => 'required|string|max:255', + 'description' => 'nullable|string', + 'hint_text' => 'required|string', + 'hint_media_url' => 'nullable|string', + 'latitude' => 'required|numeric', + 'longitude' => 'required|numeric', + 'radius_m' => 'integer|min:1', + 'xp' => 'integer|min:0', + ]); + + $step = $hunt->steps()->create($validated); + + return response()->json($step, 201); + } +} diff --git a/app/Models/HuntSteps.php b/app/Models/HuntSteps.php new file mode 100644 index 0000000..488bdd7 --- /dev/null +++ b/app/Models/HuntSteps.php @@ -0,0 +1,30 @@ + 'float', + 'longitude' => 'float', + ]; + + public function hunt() + { + return $this->belongsTo(Hunts::class, 'hunt_id'); + } +} diff --git a/app/Models/Hunts.php b/app/Models/Hunts.php index 6b9c38e..63c8734 100644 --- a/app/Models/Hunts.php +++ b/app/Models/Hunts.php @@ -39,4 +39,8 @@ class Hunts extends Model 'status' => HuntStatus::class, 'difficulty' => HuntDifficulty::class, ]; + public function steps() + { + return $this->hasMany(HuntSteps::class, 'hunt_id'); + } } diff --git a/database/migrations/2025_12_19_111936_create_hunt_steps_table.php b/database/migrations/2025_12_19_111936_create_hunt_steps_table.php new file mode 100644 index 0000000..6796a8f --- /dev/null +++ b/database/migrations/2025_12_19_111936_create_hunt_steps_table.php @@ -0,0 +1,37 @@ +id(); + $table->foreignId('hunt_id')->constrained('hunts')->cascadeOnDelete(); + $table->unsignedSmallInteger('step_number'); + $table->string('title'); + $table->text('description')->nullable(); + $table->string('hint_text'); + $table->string('hint_media_url')->nullable(); + $table->decimal('latitude', 9, 6); + $table->decimal('longitude', 9, 6); + $table->unsignedSmallInteger('radius_m')->default(10); + $table->unsignedBigInteger('xp')->default(0); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('hunt_steps'); + } +}; diff --git a/routes/api.php b/routes/api.php index 310c661..c2d0a74 100644 --- a/routes/api.php +++ b/routes/api.php @@ -23,6 +23,7 @@ Route::get('hunts/{hunt}', [HuntsController::class, 'show']); Route::middleware(['auth:sanctum', EnsureUserIsOrga::class])->group(function () { Route::post('hunts', [HuntsController::class, 'store']); + Route::post('hunts/{hunt}/steps', [\App\Http\Controllers\HuntStepsController::class, 'store']); Route::match(['put', 'patch'], 'hunts/{hunt}', [HuntsController::class, 'update']); Route::delete('hunts/{hunt}', [HuntsController::class, 'destroy']); });