trip-planner/backend/app/Infrastructure/Http/Controllers/API/PlannedItem/PlannedItemController.php
myrmidex 6d738ac66a 7-display-daily-timeline (#34)
Reviewed-on: https://codeberg.org/lvl0/trip-planner/pulls/34
Co-authored-by: myrmidex <myrmidex@myrmidex.net>
Co-committed-by: myrmidex <myrmidex@myrmidex.net>
2025-10-07 22:55:00 +02:00

92 lines
No EOL
3.4 KiB
PHP

<?php
namespace App\Infrastructure\Http\Controllers\API\PlannedItem;
use App\Domain\PlannedItem\Actions\CreatePlannedItemAction;
use App\Domain\PlannedItem\Actions\UpdatePlannedItemAction;
use App\Domain\PlannedItem\Actions\DeletePlannedItemAction;
use App\Domain\PlannedItem\Policies\PlannedItemPolicy;
use App\Infrastructure\Http\Controllers\Controller;
use App\Models\PlannedItem;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Gate;
class PlannedItemController extends Controller
{
public function __construct(
private CreatePlannedItemAction $createAction,
private UpdatePlannedItemAction $updateAction,
private DeletePlannedItemAction $deleteAction,
private PlannedItemPolicy $policy
) {}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'plannable_item_id' => 'required|exists:plannable_items,id',
'trip_id' => 'required|exists:trips,id',
'start_datetime' => 'required|date',
'end_datetime' => 'required|date|after:start_datetime',
'calendar_slot_id' => 'sometimes|exists:calendar_slots,id',
'sort_order' => 'nullable|integer',
]);
// Check authorization using Policy
if (!$this->policy->create(auth()->user(), $validated['trip_id'])) {
return response()->json(['message' => 'Forbidden'], 403);
}
// If calendar_slot_id is provided, use existing flow (backward compatibility)
if (isset($validated['calendar_slot_id'])) {
$plannedItem = $this->createAction->executeFromSlot($validated);
return response()->json($plannedItem, 201);
}
// New flow: Create CalendarSlot from datetime using Action
try {
$calendarSlot = $this->createAction->execute($validated);
return response()->json($calendarSlot, 201);
} catch (\Exception $e) {
return response()->json(['message' => $e->getMessage()], 422);
}
}
public function update(Request $request, PlannedItem $plannedItem): JsonResponse
{
// Check authorization using Policy
if (!$this->policy->update(auth()->user(), $plannedItem)) {
return response()->json(['message' => 'Forbidden'], 403);
}
$validated = $request->validate([
'calendar_slot_id' => 'sometimes|required|exists:calendar_slots,id',
'sort_order' => 'nullable|integer',
]);
// If changing calendar slot, verify user owns the new slot's trip
if (isset($validated['calendar_slot_id'])) {
if (!$this->policy->moveToSlot(auth()->user(), $validated['calendar_slot_id'])) {
return response()->json(['message' => 'Forbidden'], 403);
}
}
// Execute update using Action
$updatedItem = $this->updateAction->execute($plannedItem, $validated);
return response()->json($updatedItem);
}
public function destroy(PlannedItem $plannedItem): JsonResponse
{
// Check authorization using Policy
if (!$this->policy->delete(auth()->user(), $plannedItem)) {
return response()->json(['message' => 'Forbidden'], 403);
}
// Execute delete using Action
$this->deleteAction->execute($plannedItem);
return response()->json(null, 204);
}
}