Showing score form for judges working, need to implement inserting scores

This commit is contained in:
Matt Young 2024-06-08 14:47:00 -05:00
parent 2033ac371b
commit 359ad3252c
11 changed files with 218 additions and 11 deletions

View File

@ -0,0 +1,49 @@
<?php
namespace App\Http\Controllers;
use App\Models\Audition;
use App\Models\Entry;
use App\Models\SubscoreDefinition;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use function compact;
use function redirect;
use function url;
class JudgingController extends Controller
{
public function index()
{
$rooms = Auth::user()->judgingAssignments;
return view('judging.index', compact('rooms'));
}
public function auditionEntryList(Audition $audition)
{
// TODO verify user is assigned to judge this audition
$entries = Entry::where('audition_id','=',$audition->id)->orderBy('draw_number')->get();
return view('judging.audition_entry_list', compact('audition','entries'));
}
public function entryScoreSheet(Entry $entry)
{
// TODO verify user is assigned to judge this audition
return view('judging.entry_score_sheet',compact('entry'));
}
public function saveScoreSheet(Request $request, Entry $entry)
{
// TODO verify user is assigned to judge this audition
$scoringGuide = $entry->audition->scoringGuide;
$scoreValidation = $scoringGuide->validateScores($request->input('score'));
if ($scoreValidation != 'success') {
return redirect(url()->previous())->with('error', $scoreValidation)->with('oldScores',$request->all());
}
dd($scoreValidation);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use App\Settings;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
use function redirect;
class CheckIfCanJudge
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if( !Settings::get('judging_enabled')) {
return redirect('/dashboard')->with('error', 'Judging is not currently enabled.');
}
if(! Auth::user()->isJudge()) {
return redirect('/dashboard')->with('error', 'You are not assigned to judge.');
}
return $next($request);
}
}

View File

@ -27,6 +27,11 @@ class ScoringGuide extends Model
return $this->hasMany(SubscoreDefinition::class);
}
/**
* Validate a set of subscores. Expects an array in the form of subscore_id => score
* @param array $prospective_score
* @return string
*/
public function validateScores(Array $prospective_score)
{
foreach ($this->subscores as $subscore) {

View File

@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use phpDocumentor\Reflection\Types\Boolean;
class User extends Authenticatable implements MustVerifyEmail
{
@ -106,6 +107,11 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->rooms();
}
public function isJudge(): Bool
{
return $this->judgingAssignments->count() > 0;
}
/**
* Return an array of schools using the users email domain
* @return SchoolEmailDomain[]

View File

@ -1,4 +1,4 @@
@php use Illuminate\Support\Facades\Auth; @endphp
@php use App\Settings;use Illuminate\Support\Facades\Auth; @endphp
{{--TODO Clean up mobile menu area--}}
<nav class="bg-indigo-600"
x-data="{
@ -15,9 +15,16 @@
</div>
<div class="hidden md:block">
<div class="ml-10 flex items-baseline space-x-4">
<x-layout.navbar.nav-link href="/dashboard" :active="request()->is('dashboard')">Dashboard</x-layout.navbar.nav-link>
<x-layout.navbar.nav-link href="/students" :active="request()->is('students')">Students</x-layout.navbar.nav-link>
<x-layout.navbar.nav-link href="/entries" :active="request()->is('entries')">Entries</x-layout.navbar.nav-link>
<x-layout.navbar.nav-link href="/dashboard" :active="request()->is('dashboard')">Dashboard
</x-layout.navbar.nav-link>
<x-layout.navbar.nav-link href="/students" :active="request()->is('students')">Students
</x-layout.navbar.nav-link>
<x-layout.navbar.nav-link href="/entries" :active="request()->is('entries')">Entries
</x-layout.navbar.nav-link>
@if(Auth::user()->isJudge() AND Settings::get('judging_enabled'))
<x-layout.navbar.nav-link href="/judging" :active="request()->is('judging')">Judging
</x-layout.navbar.nav-link>
@endif
@if(Auth::user()->is_admin)
@include('components.layout.navbar.menus.admin')
@endif

View File

@ -0,0 +1,27 @@
<x-layout.app>
<x-slot:page_title>Judging Dashboard</x-slot:page_title>
<x-card.card>
<x-card.heading>{{ $audition->name }}</x-card.heading>
<x-table.table>
<thead>
<tr>
<x-table.th>Entry</x-table.th>
@foreach($audition->scoringGuide->subscores()->orderBy('display_order')->get(); as $subscore)
<x-table.th>{{ $subscore->name }}</x-table.th>
@endforeach
</tr>
</thead>
<x-table.body>
@foreach($entries as $entry)
<tr>
<x-table.td>
<a href="/judging/entry/{{$entry->id}}">
{{ $audition->name }} {{ $entry->draw_number }}
</a>
</x-table.td>
</tr>
@endforeach
</x-table.body>
</x-table.table>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,42 @@
<x-layout.app>
@php
$oldScores = session()->get('oldScores') ?? null;
@endphp
<x-slot:page_title>Entry Dashboard</x-slot:page_title>
<x-card.card class="mx-auto max-w-md">
<x-card.heading>
{{ $entry->audition->name }} {{ $entry->draw_number }}
<x-slot:subheading>
<ul class="mt-.5 max-w-2xl text-sm leading-6 text-gray-500">
<li>All Scores must be complete</li>
<li>You may enter zero</li>
<li>Whole numbrers only</li>
</ul>
</x-slot:subheading>
</x-card.heading>
<x-form.form metohd="POST" action="/judging/entry/{{$entry->id}}">
<x-card.list.body class="mt-1">
@foreach($entry->audition->scoringGuide->subscores()->orderBy('display_order')->get() as $subscore)
<li class="py-2">
<x-form.field
name="score[{{$subscore->id}}]"
type="number"
placeholder="{{$subscore->name}}"
:value="$oldScores ? $oldScores['score'][$subscore->id] : ''"
max="{{ $subscore->max_score }}"
required
>
<x-slot:label>{{ $subscore->name }} <span class="text-xs text-base text-gray-400 pl-3">max: {{$subscore->max_score}}</span></x-slot:label>
</x-form.field>
</li>
@endforeach
</x-card.list.body>
<x-form.footer><x-form.button class="mb-5">Save Scores</x-form.button></x-form.footer>
</x-form.form>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,20 @@
<x-layout.app>
<x-slot:page_title>Judging Dashboard</x-slot:page_title>
<h2 class="overflow-hidden mx-auto max-w-md py-3 px-1 text-base font-semibold leading-7 text-gray-900">Choose auditon to judge</h2>
@foreach($rooms as $room)
<x-card.card class="mx-auto max-w-md mb-3">
<x-card.heading>{{ $room->name }}</x-card.heading>
<x-card.list.body>
@foreach($room->auditions as $audition)
<a href="/judging/audition/{{$audition->id}}">
<x-card.list.row class="!py-3 ml-3">{{ $audition->name }}</x-card.list.row>
</a>
@endforeach
</x-card.list.body>
</x-card.card>
@endforeach
</x-layout.app>

View File

@ -1,5 +1,5 @@
<x-layout.app>
@php($oldScores = session()->get('oldScores')) {{-- TODO Need to handle if null --}}
@php($oldScores = session()->get('oldScores') ?? null)
<x-slot:page_title>Entry Score Sheet</x-slot:page_title>
<x-card.card class="mx-auto max-w-7xl">
<x-card.heading>

View File

@ -1,9 +1,20 @@
@php use App\Models\Audition;use App\Models\School;use App\Models\SchoolEmailDomain;use App\Models\ScoreSheet;use App\Models\ScoringGuide;use App\Models\User;use App\Settings;use Illuminate\Support\Facades\Auth;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Session; @endphp
@php use App\Models\Audition;
use App\Models\School;
use App\Models\SchoolEmailDomain;
use App\Models\ScoreSheet;
use App\Models\ScoringGuide;
use App\Models\User;
use App\Settings;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
@endphp
<x-layout.app>
<x-slot:page_title>Test Page</x-slot:page_title>
@php($scoreSheet = ScoreSheet::find(11))
@php(dump($scoreSheet->subscores[1]['score']))
@php(dump($scoreSheet->getSubscore(1)))
@php
$user = User::find(1);
dump($user->isJudge());
@endphp
</x-layout.app>

View File

@ -4,20 +4,29 @@ use App\Http\Controllers\Admin\AuditionController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\EntryController;
use App\Http\Controllers\FilterController;
use App\Http\Controllers\JudgingController;
use App\Http\Controllers\SchoolController;
use App\Http\Controllers\StudentController;
use App\Http\Controllers\Tabulation\TabulationController;
use App\Http\Controllers\TestController;
use App\Http\Controllers\UserController;
use App\Http\Middleware\CheckIfAdmin;
use App\Http\Middleware\CheckIfCanJudge;
use App\Http\Middleware\CheckIfCanTab;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
Route::get('/test',[TestController::class,'flashTest'])->middleware('auth','verified');
Route::view('/','welcome')->middleware('guest');
// Judging Routes
Route::middleware(['auth','verified',CheckIfCanJudge::class])->prefix('judging')->controller(JudgingController::class)->group(function() {
Route::get('/','index');
Route::get('/audition/{audition}','auditionEntryList');
Route::get('/entry/{entry}','entryScoreSheet');
Route::post('/entry/{entry}','saveScoreSheet');
});
// Score Tabulation Routes
Route::middleware(['auth','verified',CheckIfCanTab::class])->prefix('tabulation/')->group(function() {
// Generic Tabulation Routes