verifyEventBelongsToOrganisation($organisation, $event); Gate::authorize('viewAny', [TimeSlot::class, $event]); $timeSlots = $event->timeSlots() ->withCount('shifts') ->with(['shifts' => fn ($q) => $q->withCount([ 'shiftAssignments as assignments_count' => fn ($q) => $q->where('status', 'approved'), ])]) ->orderBy('date') ->orderBy('start_time') ->get(); // For sub-events: include parent festival time slots if ($event->isSubEvent() && request()->boolean('include_parent') && $event->parent_event_id) { $parentTimeSlots = TimeSlot::where('event_id', $event->parent_event_id) ->withCount('shifts') ->with([ 'event', 'shifts' => fn ($q) => $q->withCount([ 'shiftAssignments as assignments_count' => fn ($q) => $q->where('status', 'approved'), ]), ]) ->orderBy('date') ->orderBy('start_time') ->get(); $timeSlots->load('event'); $timeSlots->each(fn (TimeSlot $ts) => $ts->setAttribute('source', 'sub_event')); $parentTimeSlots->each(fn (TimeSlot $ts) => $ts->setAttribute('source', 'festival')); $timeSlots = $timeSlots->merge($parentTimeSlots) ->sortBy([['date', 'asc'], ['start_time', 'asc']]) ->values(); } // For festivals: include all sub-event time slots (for cross_event section shift dialogs) if (!$event->isSubEvent() && request()->boolean('include_children')) { $childEventIds = Event::where('parent_event_id', $event->id)->pluck('id'); if ($childEventIds->isNotEmpty()) { $childTimeSlots = TimeSlot::whereIn('event_id', $childEventIds) ->withCount('shifts') ->with([ 'event', 'shifts' => fn ($q) => $q->withCount([ 'shiftAssignments as assignments_count' => fn ($q) => $q->where('status', 'approved'), ]), ]) ->orderBy('date') ->orderBy('start_time') ->get(); $timeSlots->load('event'); $timeSlots->each(fn (TimeSlot $ts) => $ts->setAttribute('source', 'own')); $childTimeSlots->each(function (TimeSlot $ts) use ($event) { $ts->setAttribute('source', $ts->event_id); }); $timeSlots = $timeSlots->merge($childTimeSlots) ->sortBy([['date', 'asc'], ['start_time', 'asc']]) ->values(); } } return TimeSlotResource::collection($timeSlots); } public function store(StoreTimeSlotRequest $request, Organisation $organisation, Event $event): JsonResponse { $this->verifyEventBelongsToOrganisation($organisation, $event); Gate::authorize('create', [TimeSlot::class, $event]); $timeSlot = $event->timeSlots()->create($request->validated()); return $this->created(new TimeSlotResource($timeSlot)); } public function update(UpdateTimeSlotRequest $request, Organisation $organisation, Event $event, TimeSlot $timeSlot): JsonResponse { $this->verifyEventBelongsToOrganisation($organisation, $event); Gate::authorize('update', [$timeSlot, $event]); $timeSlot->update($request->validated()); return $this->success(new TimeSlotResource($timeSlot->fresh())); } public function destroy(Organisation $organisation, Event $event, TimeSlot $timeSlot): JsonResponse { $this->verifyEventBelongsToOrganisation($organisation, $event); Gate::authorize('delete', [$timeSlot, $event]); $timeSlot->delete(); return response()->json(null, 204); } }