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); } }