From 98378c6182aecf7cec13bcc7541a98c51ed82683 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Thu, 26 Jun 2025 03:44:34 -0500 Subject: [PATCH] Seating Publication Working --- .../Tabulation/SeatAuditionFormController.php | 108 +++++++++++++++++- .../tabulation/auditionSeating.blade.php | 104 ++++++++++++++--- routes/tabulation.php | 7 +- 3 files changed, 200 insertions(+), 19 deletions(-) diff --git a/app/Http/Controllers/Tabulation/SeatAuditionFormController.php b/app/Http/Controllers/Tabulation/SeatAuditionFormController.php index f0bb00c..8ed4d1a 100644 --- a/app/Http/Controllers/Tabulation/SeatAuditionFormController.php +++ b/app/Http/Controllers/Tabulation/SeatAuditionFormController.php @@ -8,16 +8,33 @@ use App\Exceptions\AuditionAdminException; use App\Http\Controllers\Controller; use App\Models\Audition; use App\Models\Doubler; +use App\Models\Ensemble; use App\Models\Entry; +use App\Models\Seat; +use Debugbar; use Illuminate\Http\Request; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Cache; -use function PHPUnit\Framework\isNull; +use function redirect; class SeatAuditionFormController extends Controller { public function showForm(Request $request, Audition $audition) { + $seatingProposal = (session('proposedSeatingArray-'.$audition->id)); + if ($audition->hasFlag('seats_published')) { + $publishedSeats = Seat::where('audition_id', $audition->id) + ->join('ensembles', 'seats.ensemble_id', '=', 'ensembles.id') + ->orderBy('ensembles.rank') + ->orderBy('seats.seat') + ->select('seats.*') + ->with(['ensemble', 'entry.student.school']) + ->get(); + } else { + $publishedSeats = false; + } + $ranker = app(RankAuditionEntries::class); // Get scored entries in order $scored_entries = $ranker($audition, 'seating'); @@ -63,7 +80,7 @@ class SeatAuditionFormController extends Controller $auditionHasUnresolvedDoublers = false; foreach ($doublerData as $doubler) { - if (! isNull($doubler->accepted_entry)) { + if (! is_null($doubler->accepted_entry)) { continue; } foreach ($doubler->entries() as $entry) { @@ -75,6 +92,7 @@ class SeatAuditionFormController extends Controller } $canSeat = ! $auditionHasUnresolvedDoublers && $unscored_entries->count() === 0; + Debugbar::info($seatingProposal); return view('tabulation.auditionSeating', compact('audition', @@ -85,6 +103,8 @@ class SeatAuditionFormController extends Controller 'doublerData', 'auditionHasUnresolvedDoublers', 'canSeat', + 'seatingProposal', + 'publishedSeats', ) ); } @@ -130,6 +150,90 @@ class SeatAuditionFormController extends Controller return redirect()->route('seating.audition', [$audition])->with('success', $msg); } + public function draftSeats(Audition $audition, Request $request) + { + $ranker = app(RankAuditionEntries::class); + $validated = $request->validate([ + 'ensemble' => ['required', 'array'], + 'ensemble.*' => ['required', 'integer', 'min:0'], + ]); + $proposedSeatingArray = []; + $rankedEntries = $ranker($audition, 'seating'); + $rankedEntries = $rankedEntries->reject(function ($entry) { + return $entry->hasFlag('declined'); + }); + + $rankedEntries->load(['student.school']); + $rankedEnembles = Ensemble::orderBy('rank')->where('event_id', $audition->event_id)->get(); + $ensembleRankOn = 1; + foreach ($rankedEnembles as $ensemble) { + if (! Arr::has($validated['ensemble'], $ensemble->id)) { + continue; + } + $proposedSeatingArray[$ensembleRankOn]['ensemble_id'] = $ensemble->id; + $proposedSeatingArray[$ensembleRankOn]['ensemble_name'] = $ensemble->name; + $proposedSeatingArray[$ensembleRankOn]['accept_count'] = $validated['ensemble'][$ensemble->id]; + for ($n = 1; $n <= $validated['ensemble'][$ensemble->id]; $n++) { + // Escape the loop if we're out of entries + if ($rankedEntries->isEmpty()) { + break; + } + + $thisEntry = $rankedEntries->shift(); + $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['seat'] = $n; + $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_id'] = $thisEntry->id; + $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_name'] = $thisEntry->student->full_name(); + $proposedSeatingArray[$ensembleRankOn]['seats'][$n]['entry_school'] = $thisEntry->student->school->name; + } + + $ensembleRankOn++; + } + $sessionKeyName = 'proposedSeatingArray-'.$audition->id; + $request->session()->put($sessionKeyName, $proposedSeatingArray, 10); + + return redirect()->route('seating.audition', ['audition' => $audition->id]); + } + + public function clearDraft(Audition $audition) + { + session()->forget('proposedSeatingArray-'.$audition->id); + + return redirect()->route('seating.audition', ['audition' => $audition->id]); + } + + public function publishSeats(Audition $audition) + { + $publisher = app('App\Actions\Tabulation\PublishSeats'); + $seatingProposal = (session('proposedSeatingArray-'.$audition->id)); + $proposal = []; + foreach ($seatingProposal as $ensemble) { + $ensembleId = $ensemble['ensemble_id']; + if (isset($ensemble['seats'])) { + foreach ($ensemble['seats'] as $seat) { + $proposal[] = [ + 'ensemble_id' => $ensembleId, + 'audition_id' => $audition->id, + 'seat' => $seat['seat'], + 'entry_id' => $seat['entry_id'], + ]; + } + } + } + $publisher($audition, $proposal); + session()->forget('proposedSeatingArray-'.$audition->id); + + return redirect()->route('seating.audition', [$audition]); + } + + public function unpublishSeats(Audition $audition) + { + $unpublisher = app('App\Actions\Tabulation\UnpublishSeats'); + $unpublisher($audition); + session()->forget('proposedSeatingArray-'.$audition->id); + + return redirect()->route('seating.audition', [$audition]); + } + protected function pickRightPanel(Audition $audition, array $seatable) { if ($audition->hasFlag('seats_published')) { diff --git a/resources/views/tabulation/auditionSeating.blade.php b/resources/views/tabulation/auditionSeating.blade.php index a5fd3cd..1a66854 100644 --- a/resources/views/tabulation/auditionSeating.blade.php +++ b/resources/views/tabulation/auditionSeating.blade.php @@ -1,7 +1,6 @@ Audition Seating - {{ $audition->name }} -
-
+
{{-- Entry Ranking Table --}} {{-- Scored Entries --}} @@ -94,7 +93,8 @@ {{ $entry->student->school->name }} - + Record No Show @@ -157,21 +157,97 @@
- -
- {{-- TODO: Add in bulk delince doubler option --}} - @if($unscored_entries->count() > 0) - - Cannot seat the audition while entries are unscored. +
{{-- Right Column Wrapper --}} + @if($audition->hasFlag('seats_published')) + + Published Results + + @php($previousEnsemble = '') + @foreach($publishedSeats as $seat) + @if($previousEnsemble !== $seat->ensemble->name) + @php($previousEnsemble = $seat->ensemble->name) + {{ $seat->ensemble->name }} + @endif + +
+

{{ $seat->seat }}. {{ $seat->student->full_name() }}

+

{{ $seat->student->school->name }}

+
+
+ @endforeach +
- @endif - @if($auditionHasUnresolvedDoublers) - - Cannot seat the audition while there are unresolved doublers. - + + Unpublish Results + + @else + @if($canSeat) + @if($seatingProposal) + + + Seating Proposal + Results are not yet published + + @foreach($seatingProposal as $proposedEnsemble) +

{{ $proposedEnsemble['ensemble_name'] }}

+ + @if(isset($proposedEnsemble['seats'])) + @foreach($proposedEnsemble['seats'] as $seat) + {{ $seat['seat'] }} + . {{ $seat['entry_name'] }} + @endforeach + @endif + + @endforeach + + Clear Draft + + + Publish + +
+ @else + + + Seat Audition + Choose how many entries to seat in each ensemble + + + @foreach($audition->SeatingLimits()->where('maximum_accepted','>',0)->get() as $limit) + + {{$limit->ensemble->name}} + @for($n = 0; $n< $limit->maximum_accepted; $n++) + + @endfor + + + @endforeach + Draft Seats + + + @endif + @else +
+ {{-- TODO: Add in bulk decline doubler option --}} + @if($unscored_entries->count() > 0) + + Cannot seat the audition while entries are unscored. + + @endif + + @if($auditionHasUnresolvedDoublers) + + Cannot seat the audition while there are unresolved doublers. + + @endif +
+ @endif @endif
+ +
diff --git a/routes/tabulation.php b/routes/tabulation.php index ca24ea2..0accdec 100644 --- a/routes/tabulation.php +++ b/routes/tabulation.php @@ -7,7 +7,6 @@ use App\Http\Controllers\Tabulation\DoublerDecisionController; use App\Http\Controllers\Tabulation\EntryFlagController; use App\Http\Controllers\Tabulation\ScoreController; use App\Http\Controllers\Tabulation\SeatAuditionFormController; -use App\Http\Controllers\Tabulation\SeatingPublicationController; use App\Http\Controllers\Tabulation\SeatingStatusController; use App\Http\Middleware\CheckIfCanTab; use Illuminate\Support\Facades\Route; @@ -43,13 +42,15 @@ Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function () Route::prefix('seating/')->group(function () { Route::get('/', SeatingStatusController::class)->name('seating.status'); Route::get('/{audition}', [SeatAuditionFormController::class, 'showForm'])->name('seating.audition'); + Route::post('/{audition}/draftSeats', [SeatAuditionFormController::class, 'draftSeats'])->name('seating.audition.draftSeats'); + Route::post('/{audition}/clearDraft', [SeatAuditionFormController::class, 'clearDraft'])->name('seating.audition.clearDraft'); Route::post('/{audition}/{entry}/decline', [SeatAuditionFormController::class, 'declineSeat'])->name('seating.audition.decline'); Route::post('/{audition}/{entry}/accept', [SeatAuditionFormController::class, 'acceptSeat'])->name('seating.audition.accept'); Route::post('/{audition}/{entry}/noshow', [SeatAuditionFormController::class, 'noshow'])->name('seating.audition.noshow'); Route::post('/{audition}/publish', - [SeatingPublicationController::class, 'publishSeats'])->name('seating.audition.publish'); + [SeatAuditionFormController::class, 'publishSeats'])->name('seating.audition.publishSeats'); Route::post('/{audition}/unpublish', - [SeatingPublicationController::class, 'unpublishSeats'])->name('seating.audition.unpublish'); + [SeatAuditionFormController::class, 'unpublishSeats'])->name('seating.audition.unpublishSeats'); }); // Advancement Routes