Auditionadmin 20 - Bonus scores are fully functional #25
|
|
@ -75,7 +75,8 @@ class AllowForOlympicScoring implements CalculateEntryScore
|
|||
}
|
||||
}
|
||||
// add the bonus points for a seating mode
|
||||
if ($mode === 'seating') {
|
||||
if ($mode === 'seating' && $sums) {
|
||||
|
||||
$sums[0] += $this->getBonusPoints($entry);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use App\Models\BonusScore;
|
|||
use App\Models\Entry;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class EnterBonusScore
|
||||
{
|
||||
|
|
@ -18,9 +19,10 @@ class EnterBonusScore
|
|||
|
||||
public function __invoke(User $judge, Entry $entry, int $score): void
|
||||
{
|
||||
$getRelatedEntries = App::make(GetBonusScoreRelatedEntries::class);
|
||||
$this->basicValidations($judge, $entry);
|
||||
$this->validateJudgeValidity($judge, $entry, $score);
|
||||
$entries = $this->getRelatedEntries($entry);
|
||||
$entries = $getRelatedEntries($entry);
|
||||
|
||||
// Create the score for each related entry
|
||||
foreach ($entries as $relatedEntry) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Actions\Tabulation;
|
||||
|
||||
use App\Models\Entry;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class GetBonusScoreRelatedEntries
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(Entry $entry): Collection
|
||||
{
|
||||
return $this->getRelatedEntries($entry);
|
||||
}
|
||||
|
||||
public function getRelatedEntries(Entry $entry): Collection
|
||||
{
|
||||
$bonusScore = $entry->audition->bonusScore->first();
|
||||
$relatedAuditions = $bonusScore->auditions;
|
||||
|
||||
// Get all entries that have a student_id equal to that of entry and an audition_id in the related auditions
|
||||
return Entry::where('student_id', $entry->student_id)
|
||||
->whereIn('audition_id', $relatedAuditions->pluck('id'))
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Tabulation;
|
||||
|
||||
use App\Actions\Tabulation\GetBonusScoreRelatedEntries;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\BonusScore;
|
||||
use App\Models\Entry;
|
||||
|
||||
use function request;
|
||||
|
||||
class BonusScoreController extends Controller
|
||||
{
|
||||
public function chooseEntry()
|
||||
{
|
||||
$method = 'GET';
|
||||
$formRoute = 'bonus-scores.entryBonusScoreSheet';
|
||||
$title = 'Enter Bonus Scores';
|
||||
|
||||
return view('tabulation.choose_entry', compact('method', 'formRoute', 'title'));
|
||||
}
|
||||
|
||||
public function entryBonusScoreSheet(GetBonusScoreRelatedEntries $getRelatedEntries)
|
||||
{
|
||||
$validData = request()->validate([
|
||||
'entry_id' => 'required|exists:entries,id',
|
||||
]);
|
||||
$entry = Entry::find($validData['entry_id']);
|
||||
$bonusScoreDefinition = $entry->audition->bonusScore->first();
|
||||
$assignedJudges = $bonusScoreDefinition->judges;
|
||||
$relatedEntries = $getRelatedEntries($entry);
|
||||
$existingScores = [];
|
||||
foreach ($relatedEntries as $related) {
|
||||
$existingScores[$related->id] = BonusScore::where('entry_id', $related->id)
|
||||
->with('judge')
|
||||
->with('entry')
|
||||
->with('originallyScoredEntry')
|
||||
->get();
|
||||
}
|
||||
|
||||
return view('tabulation.bonus-score-sheet',
|
||||
compact('entry', 'bonusScoreDefinition', 'assignedJudges', 'existingScores', 'relatedEntries'));
|
||||
}
|
||||
|
||||
public function saveEntryBonusScoreSheet()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function destroyBonusScore()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,9 @@ class EntryFlagController extends Controller
|
|||
{
|
||||
$method = 'GET';
|
||||
$formRoute = 'entry-flags.confirmNoShow';
|
||||
$title = 'No Show';
|
||||
|
||||
return view('tabulation.choose_entry', compact('method', 'formRoute'));
|
||||
return view('tabulation.choose_entry', compact('method', 'formRoute', 'title'));
|
||||
}
|
||||
|
||||
public function noShowConfirm(Request $request)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ class ScoreController extends Controller
|
|||
{
|
||||
$method = 'GET';
|
||||
$formRoute = 'scores.entryScoreSheet';
|
||||
$title = 'Enter Scores';
|
||||
|
||||
return view('tabulation.choose_entry', compact('method', 'formRoute'));
|
||||
return view('tabulation.choose_entry', compact('method', 'formRoute', 'title'));
|
||||
}
|
||||
|
||||
public function destroyScore(ScoreSheet $score)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use Illuminate\Database\Eloquent\Builder;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
|
|
@ -55,6 +55,11 @@ class Entry extends Model
|
|||
|
||||
}
|
||||
|
||||
public function bonusScores(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(BonusScore::class);
|
||||
}
|
||||
|
||||
public function advancementVotes(): HasMany
|
||||
{
|
||||
return $this->hasMany(JudgeAdvancementVote::class);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<div class="absolute left-1/2 z-10 mt-5 flex w-screen max-w-min -translate-x-1/2 px-4" x-show="open" x-cloak>
|
||||
<div class="w-56 shrink rounded-xl bg-white p-4 text-sm font-semibold leading-6 text-gray-900 shadow-lg ring-1 ring-gray-900/5">
|
||||
<a href="{{ route('scores.chooseEntry') }}" class="block p-2 hover:text-indigo-600">Enter Scores</a>
|
||||
<a href="{{ route('bonus-scores.chooseEntry') }}" class="block p-2 hover:text-indigo-600">Enter Bonus Scores</a>
|
||||
<a href="{{ route('entry-flags.noShowSelect') }}" class="block p-2 hover:text-indigo-600">Enter No-Shows</a>
|
||||
<a href="{{ route('seating.status') }}" class="block p-2 hover:text-indigo-600">Audition Status</a>
|
||||
<a href="{{ route('advancement.status') }}" class="block p-2 hover:text-indigo-600">{{ auditionSetting('advanceTo') }} Status</a>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<div>
|
||||
@if($with_title_area)
|
||||
<div class="mb-4 mt-4 sm:px 4 sm:flex sm:items-center">
|
||||
<div class="mb-2 mt-4 sm:px 4 sm:flex sm:items-center">
|
||||
<div class="sm:flex-auto sm:items-center">
|
||||
@if($title)<h1 {{ $title->attributes->merge(['class' => 'text-base font-semibold leading-6 text-gray-900']) }}>{{ $title }}</h1>@endif
|
||||
@if($subtitle)<p {{ $subtitle->attributes->merge(['class' => 'mt-2 text-sm text-gray-700']) }}>{{ $subtitle }}</p>@endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
@php use Illuminate\Support\Carbon; @endphp
|
||||
<x-layout.app>
|
||||
<x-slot:page_title>Enter {{ $bonusScoreDefinition->name }} Score</x-slot:page_title>
|
||||
<x-card.card>
|
||||
<x-card.heading>
|
||||
{{ $entry->student->full_name() }}
|
||||
<x-slot:subheading>{{ $entry->student->school->name }}</x-slot:subheading>
|
||||
</x-card.heading>
|
||||
</x-card.card>
|
||||
<div class="grid grid-cols-3 gap-3 w-full mt-5">
|
||||
|
||||
<x-card.card class="col-span-2">
|
||||
<x-card.heading>Existing Scores</x-card.heading>
|
||||
<div class="px-6">
|
||||
@foreach($relatedEntries as $related)
|
||||
<x-table.table class="mb-8 ">
|
||||
<x-slot:title class="border rounded-md pl-3 bg-gray-100">
|
||||
{{ $related->audition->name }} #{{ $related->draw_number }}
|
||||
</x-slot:title>
|
||||
<x-slot:subtitle>
|
||||
Entry ID: {{ $related->id }}
|
||||
</x-slot:subtitle>
|
||||
<thead>
|
||||
<tr>
|
||||
<x-table.th>Judge</x-table.th>
|
||||
<x-table.th>Audition Scored</x-table.th>
|
||||
<x-table.th>Score</x-table.th>
|
||||
<x-table.th>Timestamp</x-table.th>
|
||||
</tr>
|
||||
</thead>
|
||||
<x-table.body>
|
||||
@foreach($existingScores[$related->id] as $score)
|
||||
<tr>
|
||||
<td>{{ $score->judge->full_name() }}</td>
|
||||
<td>{{ $score->originallyScoredEntry->audition->name }}</td>
|
||||
<td>{{ $score->score }}</td>
|
||||
<td>{{ Carbon::create($score->created_at)->setTimezone('America/Chicago')->format('m/d/y H:i') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table.body>
|
||||
</x-table.table>
|
||||
@endforeach
|
||||
</div>
|
||||
</x-card.card>
|
||||
|
||||
<x-card.card >
|
||||
<x-card.heading>Enter Score</x-card.heading>
|
||||
<div class="mx-5 border-b text-sm">
|
||||
NOTE: Entering score will delete any existing scores for that entry by that judge
|
||||
</div>
|
||||
<x-form.form class="mt-3" method="POST" action="{{route('bonus-scores.saveEntryBonusScoreSheet', $entry)}}">
|
||||
<x-form.select name="judge_id" class="mb-5">
|
||||
<x-slot:label>Judge</x-slot:label>
|
||||
@foreach($assignedJudges as $judge)
|
||||
<option value="{{ $judge->id }}">{{ $judge->full_name() }}</option>
|
||||
@endforeach
|
||||
</x-form.select>
|
||||
<x-form.select name="entry_id" class="mb-5">
|
||||
<x-slot:label>Scored Audition</x-slot:label>
|
||||
@foreach($relatedEntries as $related)
|
||||
<option value="{{$related->id}}" {{$related->id == $entry->id ? 'selected':' '}}>{{ $related->audition->name }}</option>
|
||||
@endforeach
|
||||
</x-form.select>
|
||||
<x-form.field label_text="Score" name="score" type="number" max="{{ $bonusScoreDefinition->max_score }}" />
|
||||
<x-form.button class="mt-5">Enter Score</x-form.button>
|
||||
</x-form.form>
|
||||
</x-card.card>
|
||||
</div>
|
||||
</x-layout.app>
|
||||
|
|
@ -2,13 +2,14 @@
|
|||
/**
|
||||
* @var string $method Method for the select form
|
||||
* @var string $formRoute Route for the form action. Should be a route name
|
||||
* @var string $title Title of the page
|
||||
*/
|
||||
@endphp
|
||||
|
||||
<x-layout.app>
|
||||
<x-slot:page_title>Choose Entry</x-slot:page_title>
|
||||
<x-slot:page_title>{{ $title }}</x-slot:page_title>
|
||||
<x-card.card class="mx-auto max-w-sm">
|
||||
<x-card.heading>Choose Entry</x-card.heading>
|
||||
<x-card.heading>{{ $title }} - Choose Entry</x-card.heading>
|
||||
<div class="">
|
||||
<x-form.form method="{{ $method }}" action="{{ route($formRoute) }}" class="mb-4 mt-3" id="entry-select-form">
|
||||
<x-form.field name="entry_id" label_text="Entry ID"></x-form.field>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
// Tabulation Routes
|
||||
use App\Http\Controllers\Tabulation\AdvancementController;
|
||||
use App\Http\Controllers\Tabulation\BonusScoreController;
|
||||
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\Controllers\Tabulation\TabulationController;
|
||||
use App\Http\Middleware\CheckIfCanTab;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
|
@ -22,6 +22,14 @@ Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function ()
|
|||
Route::delete('/{score}', 'destroyScore')->name('scores.destroy');
|
||||
});
|
||||
|
||||
// Bonus Score Management
|
||||
Route::prefix('bonus-scores/')->controller(BonusScoreController::class)->group(function () {
|
||||
Route::get('/choose_entry', 'chooseEntry')->name('bonus-scores.chooseEntry');
|
||||
Route::get('/entry', 'entryBonusScoreSheet')->name('bonus-scores.entryBonusScoreSheet');
|
||||
Route::post('/entry/{entry}', 'saveEntryBonusScoreSheet')->name('bonus-scores.saveEntryBonusScoreSheet');
|
||||
Route::delete('/{bonusScore}', 'destroyBonusScore')->name('bonus-scores.destroy');
|
||||
});
|
||||
|
||||
// Entry Flagging
|
||||
Route::prefix('entry-flags/')->controller(EntryFlagController::class)->group(function () {
|
||||
Route::get('/choose_no_show', 'noShowSelect')->name('entry-flags.noShowSelect');
|
||||
|
|
|
|||
Loading…
Reference in New Issue