shifts() ->with(['timeSlot', 'location']) ->withCount(['shiftAssignments as filled_slots' => fn ($q) => $q->where('status', ShiftAssignmentStatus::APPROVED)]) ->get(); return ShiftResource::collection($shifts); } public function store(StoreShiftRequest $request, Event $event, FestivalSection $section): JsonResponse { Gate::authorize('create', [Shift::class, $event]); $shift = $section->shifts()->create($request->validated()); $shift->load(['timeSlot', 'location']); return $this->created(new ShiftResource($shift)); } public function update(UpdateShiftRequest $request, Event $event, FestivalSection $section, Shift $shift): JsonResponse { Gate::authorize('update', [$shift, $event, $section]); $shift->update($request->validated()); $shift->load(['timeSlot', 'location']); return $this->success(new ShiftResource($shift->fresh()->load(['timeSlot', 'location']))); } public function destroy(Event $event, FestivalSection $section, Shift $shift): JsonResponse { Gate::authorize('delete', [$shift, $event, $section]); $shift->delete(); return response()->json(null, 204); } public function assign(AssignShiftRequest $request, Event $event, FestivalSection $section, Shift $shift): JsonResponse { Gate::authorize('assign', [$shift, $event, $section]); $festivalEventId = $event->parent_event_id ?? $event->id; $person = Person::where('event_id', $festivalEventId)->findOrFail($request->validated('person_id')); $assignment = $this->shiftAssignmentService->assign($shift, $person, $request->user()); return $this->created(new ShiftAssignmentResource($assignment)); } public function claim(AssignShiftRequest $request, Event $event, FestivalSection $section, Shift $shift): JsonResponse { Gate::authorize('claim', [$shift, $event, $section]); $festivalEventId = $event->parent_event_id ?? $event->id; $person = Person::where('event_id', $festivalEventId)->findOrFail($request->validated('person_id')); $assignment = $this->shiftAssignmentService->claim($shift, $person); return $this->created(new ShiftAssignmentResource($assignment)); } }