diff --git a/app/Http/Controllers/JudgingController.php b/app/Http/Controllers/JudgingController.php index 8857ab2..bd17aaa 100644 --- a/app/Http/Controllers/JudgingController.php +++ b/app/Http/Controllers/JudgingController.php @@ -4,12 +4,13 @@ namespace App\Http\Controllers; use App\Models\Audition; use App\Models\Entry; +use App\Models\JudgeAdvancementVote; use App\Models\ScoreSheet; -use App\Models\SubscoreDefinition; use App\Models\User; -use Illuminate\Support\Facades\Gate; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; + use function compact; use function redirect; use function url; @@ -19,77 +20,107 @@ 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')->with('audition')->get(); + $entries = Entry::where('audition_id', '=', $audition->id)->orderBy('draw_number')->with('audition')->get(); $subscores = $audition->scoringGuide->subscores()->orderBy('display_order')->get(); - return view('judging.audition_entry_list', compact('audition','entries','subscores')); + + return view('judging.audition_entry_list', compact('audition', 'entries', 'subscores')); } public function entryScoreSheet(Entry $entry) { // TODO verify user is assigned to judge this audition - $oldSheet = ScoreSheet::where('user_id',Auth::id())->where('entry_id',$entry->id)->value('subscores') ?? null; - return view('judging.entry_score_sheet',compact('entry','oldSheet')); + $oldSheet = ScoreSheet::where('user_id', Auth::id())->where('entry_id', $entry->id)->value('subscores') ?? null; + $oldVote = JudgeAdvancementVote::where('user_id', Auth::id())->where('entry_id', $entry->id)->first(); + $oldVote = $oldVote ? $oldVote->vote : 'novote'; + + return view('judging.entry_score_sheet', compact('entry', 'oldSheet', 'oldVote')); } public function saveScoreSheet(Request $request, Entry $entry) { - Gate::authorize('create',[ScoreSheet::class,$entry]); + Gate::authorize('create', [ScoreSheet::class, $entry]); // TODO verify user is assigned to judge this audition $scoringGuide = $entry->audition->scoringGuide()->with('subscores')->first(); $scoreValidation = $scoringGuide->validateScores($request->input('score')); if ($scoreValidation != 'success') { - return redirect(url()->previous())->with('error', $scoreValidation)->with('oldScores',$request->all()); + return redirect(url()->previous())->with('error', $scoreValidation)->with('oldScores', $request->all()); } $scoreSheetArray = []; - foreach($scoringGuide->subscores as $subscore) { + foreach ($scoringGuide->subscores as $subscore) { $scoreSheetArray[$subscore->id] = [ 'score' => $request->input('score')[$subscore->id], 'subscore_id' => $subscore->id, - 'subscore_name' => $subscore->name + 'subscore_name' => $subscore->name, ]; } ScoreSheet::create([ 'user_id' => Auth::user()->id, 'entry_id' => $entry->id, - 'subscores' => $scoreSheetArray + 'subscores' => $scoreSheetArray, ]); - return redirect('/judging/audition/' . $entry->audition_id)->with('success','Entered scores for ' . $entry->audition->name . ' ' . $entry->draw_number); + $this->advancementVote($request, $entry); + + return redirect('/judging/audition/'.$entry->audition_id)->with('success', 'Entered scores for '.$entry->audition->name.' '.$entry->draw_number); } public function updateScoreSheet(Request $request, Entry $entry) { - $scoreSheet = ScoreSheet::where('user_id',Auth::id())->where('entry_id',$entry->id)->first(); - if (!$scoreSheet) return redirect()->back()->with('error','Attempt to edit non existent entry'); - Gate::authorize('update',$scoreSheet); + $scoreSheet = ScoreSheet::where('user_id', Auth::id())->where('entry_id', $entry->id)->first(); + if (! $scoreSheet) { + return redirect()->back()->with('error', 'Attempt to edit non existent entry'); + } + Gate::authorize('update', $scoreSheet); $scoringGuide = $entry->audition->scoringGuide()->with('subscores')->first(); $scoreValidation = $scoringGuide->validateScores($request->input('score')); if ($scoreValidation != 'success') { - return redirect(url()->previous())->with('error', $scoreValidation)->with('oldScores',$request->all()); + return redirect(url()->previous())->with('error', $scoreValidation)->with('oldScores', $request->all()); } $scoreSheetArray = []; - foreach($scoringGuide->subscores as $subscore) { + foreach ($scoringGuide->subscores as $subscore) { $scoreSheetArray[$subscore->id] = [ 'score' => $request->input('score')[$subscore->id], 'subscore_id' => $subscore->id, - 'subscore_name' => $subscore->name + 'subscore_name' => $subscore->name, ]; } $scoreSheet->update([ - 'subscores' => $scoreSheetArray + 'subscores' => $scoreSheetArray, ]); - return redirect('/judging/audition/' . $entry->audition_id)->with('success','Updated scores for ' . $entry->audition->name . ' ' . $entry->draw_number); + + $this->advancementVote($request, $entry); + + return redirect('/judging/audition/'.$entry->audition_id)->with('success', 'Updated scores for '.$entry->audition->name.' '.$entry->draw_number); } + protected function advancementVote(Request $request, Entry $entry) + { + if ($entry->for_advancement) { + $request->validate([ + 'advancement-vote' => ['required', 'in:yes,no,dq'], + ]); + try { + JudgeAdvancementVote::where('user_id', Auth::id())->where('entry_id', $entry->id)->delete(); + JudgeAdvancementVote::create([ + 'user_id' => Auth::user()->id, + 'entry_id' => $entry->id, + 'vote' => $request->input('advancement-vote'), + ]); + } catch (\Exception $e) { + return redirect(url()->previous())->with('error', 'Error saving advancement vote'); + } + } + } } diff --git a/app/Models/Entry.php b/app/Models/Entry.php index d63a7c2..db37e65 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -51,6 +51,11 @@ class Entry extends Model } + public function advancementVotes(): HasMany + { + return $this->hasMany(JudgeAdvancementVote::class); + } + public function flags(): HasMany { return $this->hasMany(EntryFlag::class); diff --git a/app/Models/JudgeAdvancementVote.php b/app/Models/JudgeAdvancementVote.php new file mode 100644 index 0000000..e02f95d --- /dev/null +++ b/app/Models/JudgeAdvancementVote.php @@ -0,0 +1,25 @@ +belongsTo(Entry::class); + } + + public function judge(): BelongsTo + { + return $this->belongsTo(User::class); + } + +} diff --git a/app/Models/User.php b/app/Models/User.php index ccfa667..eb96143 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,7 +2,6 @@ namespace App\Models; - use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -11,7 +10,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; 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 { @@ -30,7 +28,7 @@ class User extends Authenticatable implements MustVerifyEmail 'email', 'password', 'profile_image_url', - 'school_id' + 'school_id', ]; /** @@ -56,16 +54,19 @@ class User extends Authenticatable implements MustVerifyEmail ]; } - public function full_name(Bool $last_name_first = false): String + public function full_name(bool $last_name_first = false): string { - if ($last_name_first) return $this->last_name . ', ' . $this->first_name; - return $this->first_name . ' ' . $this->last_name; + if ($last_name_first) { + return $this->last_name.', '.$this->first_name; + } + + return $this->first_name.' '.$this->last_name; } - public function short_name(): String + public function short_name(): string { // return the first letter of $this->first_name and the full $this->last_name - return $this->first_name[0] . '. ' . $this->last_name; + return $this->first_name[0].'. '.$this->last_name; } public function has_school(): bool @@ -76,7 +77,8 @@ class User extends Authenticatable implements MustVerifyEmail public function emailDomain(): string { $pos = strpos($this->email, '@'); - return substr($this->email, $pos+1); + + return substr($this->email, $pos + 1); } public function school(): BelongsTo @@ -87,7 +89,7 @@ class User extends Authenticatable implements MustVerifyEmail public function students(): HasManyThrough { return $this - ->hasManyThrough(Student::class, School::class, 'id','school_id','school_id','id') + ->hasManyThrough(Student::class, School::class, 'id', 'school_id', 'school_id', 'id') ->orderBy('last_name') ->orderBy('first_name'); } @@ -106,7 +108,7 @@ class User extends Authenticatable implements MustVerifyEmail public function rooms(): BelongsToMany { - return $this->belongsToMany(Room::class,'room_user'); + return $this->belongsToMany(Room::class, 'room_user'); } public function judgingAssignments(): BelongsToMany @@ -114,26 +116,38 @@ class User extends Authenticatable implements MustVerifyEmail return $this->rooms(); } - public function isJudge(): Bool + public function advancementVotes(): HasMany + { + return $this->hasMany(JudgeAdvancementVote::class); + } + + public function isJudge(): bool { return $this->judgingAssignments->count() > 0; } /** * Return an array of schools using the users email domain + * * @return SchoolEmailDomain[] */ public function possibleSchools() { if ($this->school_id) { $return[] = $this->school; + return $return; } - return SchoolEmailDomain::with('school')->where('domain','=',$this->emailDomain())->get(); + + return SchoolEmailDomain::with('school')->where('domain', '=', $this->emailDomain())->get(); } - public function canTab() { - if ($this->is_admin) return true; + public function canTab() + { + if ($this->is_admin) { + return true; + } + return $this->is_tab; } @@ -145,12 +159,12 @@ class User extends Authenticatable implements MustVerifyEmail public function scoresForEntry($entry) { // TODO Again, why is this here? Needs to go somewhere else. Maybe a Judging service - return $this->scoreSheets->where('entry_id','=',$entry)->first()?->subscores; + return $this->scoreSheets->where('entry_id', '=', $entry)->first()?->subscores; } public function timeForEntryScores($entry) { // TODO Why is this in the User mode? Move it somewhere else - return $this->scoreSheets->where('entry_id','=',$entry)->first()?->created_at; + return $this->scoreSheets->where('entry_id', '=', $entry)->first()?->created_at; } } diff --git a/database/migrations/2024_06_27_030228_create_judge_advancement_votes_table.php b/database/migrations/2024_06_27_030228_create_judge_advancement_votes_table.php new file mode 100644 index 0000000..c983e7a --- /dev/null +++ b/database/migrations/2024_06_27_030228_create_judge_advancement_votes_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignIdFor(Entry::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate(); + $table->string('vote'); + $table->unique(['user_id', 'entry_id']); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('judge_advancement_votes'); + } +}; diff --git a/resources/views/judging/advancement-vote-form.blade.php b/resources/views/judging/advancement-vote-form.blade.php new file mode 100644 index 0000000..b98569f --- /dev/null +++ b/resources/views/judging/advancement-vote-form.blade.php @@ -0,0 +1,37 @@ +
diff --git a/resources/views/judging/entry_score_sheet.blade.php b/resources/views/judging/entry_score_sheet.blade.php index 36054ba..36806ad 100644 --- a/resources/views/judging/entry_score_sheet.blade.php +++ b/resources/views/judging/entry_score_sheet.blade.php @@ -1,6 +1,9 @@