speakers->eventsForAccount($account->id) ->map(function (QrCode $event) { $event->speaker_count = count($this->speakers->rosterFor($event)); return $event; }); return view('events.speakers-hub', [ 'events' => $events, ]); } public function index(QrCode $event): View { $this->authorize('view', $event); abort_unless($event->type === QrCode::TYPE_EVENT, 404); $roster = $this->invites->rosterWithInviteState($event); return view('events.speakers', [ 'qrCode' => $event, 'roster' => $roster, 'programmeAssignments' => $this->speakers->programmeAssignments($event), 'programme' => $this->speakers->linkedProgramme($event), 'canManualInvite' => collect($roster)->mapWithKeys(fn ($speaker) => [ $speaker['email'] => $this->invites->canSendManualInvite($event, $speaker), ])->all(), ]); } public function update(Request $request, QrCode $event): RedirectResponse { $this->authorize('update', $event); abort_unless($event->type === QrCode::TYPE_EVENT, 404); $validated = $request->validate([ 'speakers' => ['nullable', 'array'], 'speakers.*.name' => ['nullable', 'string', 'max:120'], 'speakers.*.email' => ['required_with:speakers.*.name', 'email', 'max:190'], 'speakers.*.role' => ['nullable', 'string', 'max:80'], 'speakers.*.bio' => ['nullable', 'string', 'max:500'], ]); try { $this->manager->update($event, [ 'speakers' => $validated['speakers'] ?? [], ]); } catch (\RuntimeException $e) { return back()->withInput()->with('error', $e->getMessage()); } return redirect() ->route('speakers.show', $event) ->with('success', 'Speaker roster saved.'); } public function sendInvite(Request $request, QrCode $event): RedirectResponse { $this->authorize('update', $event); abort_unless($event->type === QrCode::TYPE_EVENT, 404); $validated = $request->validate([ 'email' => ['required', 'email', 'max:190'], ]); $owner = ladill_account() ?? $event->user; abort_unless($owner, 500); $result = $this->invites->sendManualInvite($event, $owner, $validated['email']); if (! $result['ok']) { return back()->with('error', $result['error']); } return back()->with('success', 'Speaker invitation sent.'); } }