feat: join hunt
This commit is contained in:
parent
a323489a6f
commit
66cf5e1de8
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum ParticipateStatus: string
|
||||||
|
{
|
||||||
|
case Started = 'started';
|
||||||
|
case Completed = 'completed';
|
||||||
|
}
|
||||||
|
|
@ -57,17 +57,72 @@ class HuntsController extends Controller
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(Request $request, $id)
|
||||||
{
|
{
|
||||||
$hunt = Hunts::find($id);
|
$hunt = Hunts::with('steps')->find($id);
|
||||||
|
|
||||||
if (!$hunt) {
|
if (!$hunt) {
|
||||||
return response()->json(['message' => 'Hunt not found'], 404);
|
return response()->json(['message' => 'Hunt not found'], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user = $request->user('sanctum');
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$participation = $user->participations()->where('hunt_id', $hunt->id)->first();
|
||||||
|
|
||||||
|
if ($participation) {
|
||||||
|
// User is a participant
|
||||||
|
$currentStepNumber = $participation->pivot->current_step_number;
|
||||||
|
|
||||||
|
// Filter steps
|
||||||
|
$hunt->setRelation('steps', $hunt->steps->filter(function ($step) use ($currentStepNumber) {
|
||||||
|
if ($step->step_number < $currentStepNumber) {
|
||||||
|
return true; // Show past steps fully
|
||||||
|
}
|
||||||
|
if ($step->step_number == $currentStepNumber) {
|
||||||
|
// Hide hints for current step
|
||||||
|
$step->makeHidden(['hint_text', 'hint_media_url']);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false; // Hide future steps
|
||||||
|
})->values());
|
||||||
|
|
||||||
|
$hunt->participation_status = $participation->pivot;
|
||||||
|
} elseif ($hunt->creator_id !== $user->id) {
|
||||||
|
// User is logged in but not participant and not creator
|
||||||
|
// Show only first step or nothing specific (keep as is for now, maybe hide all steps or just show basic info)
|
||||||
|
// For now, let's just hide hints of all steps if not participating?
|
||||||
|
// Or maybe just show nothing of steps if not participating?
|
||||||
|
// Requirement: "fetch the hunt in question it retrieves me the hunt steps already passed and the next one" implying context of participation.
|
||||||
|
// If not participating, maybe just return basic hunt info without steps?
|
||||||
|
$hunt->unsetRelation('steps');
|
||||||
|
}
|
||||||
|
// If creator, show everything (default)
|
||||||
|
} else {
|
||||||
|
// Guest
|
||||||
|
$hunt->unsetRelation('steps');
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json($hunt);
|
return response()->json($hunt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function participate(Request $request, $id)
|
||||||
|
{
|
||||||
|
$hunt = Hunts::findOrFail($id);
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
if ($user->participations()->where('hunt_id', $hunt->id)->exists()) {
|
||||||
|
return response()->json(['message' => 'Already participating'], 409);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hunt->participants()->attach($user->id, ['current_step_number' => 1, 'status' => 'started']);
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Participation started'], 201);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,11 @@ class Hunts extends Model
|
||||||
{
|
{
|
||||||
return $this->hasMany(HuntSteps::class, 'hunt_id');
|
return $this->hasMany(HuntSteps::class, 'hunt_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function participants()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class, 'hunt_participants', 'hunt_id', 'user_id')
|
||||||
|
->withPivot(['current_step_number', 'status'])
|
||||||
|
->withTimestamps();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,4 +54,11 @@ class User extends Authenticatable
|
||||||
'role'=> UserRole::class
|
'role'=> UserRole::class
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function participations()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Hunts::class, 'hunt_participants', 'user_id', 'hunt_id')
|
||||||
|
->withPivot(['current_step_number', 'status'])
|
||||||
|
->withTimestamps();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\ParticipateStatus;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('hunt_participants', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('hunt_id')->constrained('hunts')->cascadeOnDelete();
|
||||||
|
$table->unsignedSmallInteger('current_step_number')->default(1);
|
||||||
|
$table->string('status')->default(ParticipateStatus::Started->value);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('hunt_participants');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -7,6 +7,7 @@ use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
||||||
use App\Http\Controllers\HuntsController;
|
use App\Http\Controllers\HuntsController;
|
||||||
|
use App\Http\Controllers\HuntStepsController;
|
||||||
use App\Http\Middleware\EnsureUserIsOrga;
|
use App\Http\Middleware\EnsureUserIsOrga;
|
||||||
|
|
||||||
Route::prefix('auth')->group(function (): void {
|
Route::prefix('auth')->group(function (): void {
|
||||||
|
|
@ -17,36 +18,22 @@ Route::prefix('auth')->group(function (): void {
|
||||||
// Route::get('{provider}/callback', [ProviderCallbackController::class, 'callback']);
|
// Route::get('{provider}/callback', [ProviderCallbackController::class, 'callback']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// List hunts
|
||||||
Route::get('hunts', [HuntsController::class, 'index']);
|
Route::get('hunts', [HuntsController::class, 'index']);
|
||||||
Route::get('hunts/{hunt}', [HuntsController::class, 'show']);
|
Route::get('hunts/{hunt}', [HuntsController::class, 'show']);
|
||||||
|
|
||||||
|
// Ensure is Orga
|
||||||
Route::middleware(['auth:sanctum', EnsureUserIsOrga::class])->group(function () {
|
Route::middleware(['auth:sanctum', EnsureUserIsOrga::class])->group(function () {
|
||||||
Route::post('hunts', [HuntsController::class, 'store']);
|
Route::post('hunts', [HuntsController::class, 'store']);
|
||||||
Route::post('hunts/{hunt}/steps', [\App\Http\Controllers\HuntStepsController::class, 'store']);
|
Route::post('hunts/{hunt}/steps', [HuntStepsController::class, 'store']);
|
||||||
Route::match(['put', 'patch'], 'hunts/{hunt}', [HuntsController::class, 'update']);
|
Route::match(['put', 'patch'], 'hunts/{hunt}', [HuntsController::class, 'update']);
|
||||||
Route::delete('hunts/{hunt}', [HuntsController::class, 'destroy']);
|
Route::delete('hunts/{hunt}', [HuntsController::class, 'destroy']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Auth middleware
|
||||||
Route::middleware('auth:sanctum')->group(function (): void {
|
Route::middleware('auth:sanctum')->group(function (): void {
|
||||||
// Route::get('/user', function (Request $request) {
|
|
||||||
// return $request->user();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// User
|
// User
|
||||||
|
Route::post('hunts/{hunt}/participate', [HuntsController::class, 'participate']);
|
||||||
Route::get('auth/me', [AuthController::class, 'me']);
|
Route::get('auth/me', [AuthController::class, 'me']);
|
||||||
Route::post('auth/logout', [AuthController::class, 'logout']);
|
Route::post('auth/logout', [AuthController::class, 'logout']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Route::middleware([EnsureAdmin::class])->group(function (): void {
|
|
||||||
// Route::apiResource('users', UserController::class);
|
|
||||||
// Route::apiResource('main-categories', MainCategoryController::class)->except(['index', 'show']);
|
|
||||||
// Route::apiResource('categories', CategoryController::class)->except(['index', 'show']);
|
|
||||||
// Route::apiResource('products', ProductsController::class)->except(['index', 'show']);
|
|
||||||
// Route::apiResource('product-variants', ProductVariantController::class);
|
|
||||||
// Route::apiResource('product-variant-images', ProductVariantImagesController::class);
|
|
||||||
// Route::apiResource('pickup-points', PickupPointsController::class)->only(['destroy']);
|
|
||||||
// Route::apiResource('pickup-point-schedules', PickupPointsSchedulesController::class)->except(['index', 'show']);
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
Loading…
Reference in New Issue