Finish last migration

This commit is contained in:
Matt Young 2024-06-25 21:11:49 -05:00
parent e6f6bd6c8c
commit 42b7837541
9 changed files with 232 additions and 77 deletions

View File

@ -2,108 +2,130 @@
namespace App\Http\Controllers\Admin;
use App\Events\AuditionChange;
use App\Events\RoomJudgeChange;
use App\Http\Controllers\Controller;
use App\Models\Audition;
use App\Models\Event;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use function abort;
use function array_keys;
use function compact;
use function dd;
use function redirect;
use function request;
use function response;
use function route;
use function view;
class AuditionController extends Controller
{
public function index()
{
if(! Auth::user()->is_admin) abort(403);
$auditions = Audition::with(['event','entries'])->orderBy('score_order')->orderBy('created_at','desc')->get();
return view('admin.auditions.index', ['auditions' => $auditions] );
if (! Auth::user()->is_admin) {
abort(403);
}
$auditions = Audition::with(['event', 'entries'])->orderBy('score_order')->orderBy('created_at', 'desc')->get();
return view('admin.auditions.index', ['auditions' => $auditions]);
}
public function create()
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$events = Event::orderBy('name')->get();
return view('admin.auditions.create',['events'=> $events]);
return view('admin.auditions.create', ['events' => $events]);
}
public function store(Request $request)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$validData = request()->validate([
'event_id' => ['required', 'exists:events,id'],
'name' => ['required'],
'event_id' => ['required', 'exists:events,id'],
'name' => ['required'],
'entry_deadline' => ['required', 'date'],
'entry_fee' => ['required', 'numeric'],
'minimum_grade' => ['required', 'integer'],
'maximum_grade' => 'required|numeric|gt:minimum_grade',
'entry_fee' => ['required', 'numeric'],
'minimum_grade' => ['required', 'integer'],
'maximum_grade' => 'required|numeric|gte:minimum_grade',
], [
'maximum_grade.gt' => 'The maximum grade must be greater than the minimum grade.',
'maximum_grade.gte' => 'The maximum grade must be greater than the minimum grade.',
]);
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
Audition::create([
'event_id' => $validData['event_id'],
'name' => $validData['name'],
'event_id' => $validData['event_id'],
'name' => $validData['name'],
'entry_deadline' => $validData['entry_deadline'],
'entry_fee' => $validData['entry_fee'] * 100,
'minimum_grade' => $validData['minimum_grade'],
'maximum_grade' => $validData['maximum_grade'],
'entry_fee' => $validData['entry_fee'] * 100,
'minimum_grade' => $validData['minimum_grade'],
'maximum_grade' => $validData['maximum_grade'],
'for_seating' => $validData['for_seating'],
'for_advancement' => $validData['for_advancement'],
]);
return redirect('/admin/auditions');
}
public function edit(Audition $audition)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$events = Event::orderBy('name')->get();
return view('admin.auditions.edit', ['audition' => $audition,'events'=> $events]);
return view('admin.auditions.edit', ['audition' => $audition, 'events' => $events]);
}
public function update(Audition $audition)
public function update(Request $request, Audition $audition)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$validData = request()->validate([
'event_id' => ['required', 'exists:events,id'],
'name' => ['required'],
'event_id' => ['required', 'exists:events,id'],
'name' => ['required'],
'entry_deadline' => ['required', 'date'],
'entry_fee' => ['required', 'numeric'],
'minimum_grade' => ['required', 'integer'],
'entry_fee' => ['required', 'numeric'],
'minimum_grade' => ['required', 'integer'],
'maximum_grade' => 'required|numeric|gt:minimum_grade',
], [
'maximum_grade.gt' => 'The maximum grade must be greater than the minimum grade.',
]);
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
$audition->update([
'event_id' => $validData['event_id'],
'name' => $validData['name'],
'event_id' => $validData['event_id'],
'name' => $validData['name'],
'entry_deadline' => $validData['entry_deadline'],
'entry_fee' => $validData['entry_fee'] * 100,
'minimum_grade' => $validData['minimum_grade'],
'maximum_grade' => $validData['maximum_grade'],
'entry_fee' => $validData['entry_fee'] * 100,
'minimum_grade' => $validData['minimum_grade'],
'maximum_grade' => $validData['maximum_grade'],
'for_seating' => $validData['for_seating'],
'for_advancement' => $validData['for_advancement'],
]);
return redirect('/admin/auditions');
}
public function reorder(Request $request)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$order = $request->order;
foreach ($order as $index => $id) {
$audition = Audition::find($id);
$audition->update(['score_order' => $index]);
}
return response()->json(['status' => 'success']);
}
@ -115,9 +137,10 @@ class AuditionController extends Controller
Audition::where('id', $audition['id'])
->update([
'room_id' => $audition['room_id'],
'order_in_room' => $audition['room_order']
'order_in_room' => $audition['room_order'],
]);
}
return response()->json(['status' => 'success']);
}
@ -128,44 +151,53 @@ class AuditionController extends Controller
if ($audition) {
$audition->update([
'scoring_guide_id' => $request->new_guide_id
'scoring_guide_id' => $request->new_guide_id,
]);
return response()->json(['success' => true]);
}
return response()->json(['success' => false], 404);
}
public function destroy(Audition $audition)
{
if(! Auth::user()->is_admin) abort(403);
// if($audition->entries->count() > 0) abort(403, 'Cannot delete an audition with entries.'
if($audition->entries->count() > 0) {
if (! Auth::user()->is_admin) {
abort(403);
}
// if($audition->entries->count() > 0) abort(403, 'Cannot delete an audition with entries.'
if ($audition->entries->count() > 0) {
return redirect()->route('admin.auditions.index')->with('error', 'Cannot delete an audition with entries.');
}
$audition->delete();
return redirect('/admin/auditions');
}
public function prepareDraw()
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$allAuditions = Audition::with('entries')->orderBy('score_order')->get();
$nodraw_auditions = $allAuditions->filter(function($audition) {
$nodraw_auditions = $allAuditions->filter(function ($audition) {
return $audition->has_no_draw();
});
$drawn_auditions = $allAuditions->filter(function($audition) {
$drawn_auditions = $allAuditions->filter(function ($audition) {
return $audition->has_complete_draw();
});
$partial_draw_auditions = $allAuditions->filter(function($audition) {
$partial_draw_auditions = $allAuditions->filter(function ($audition) {
return $audition->has_partial_draw();
});
return view('admin.entries.prepare_draw',compact('nodraw_auditions','drawn_auditions','partial_draw_auditions'));
return view('admin.entries.prepare_draw', compact('nodraw_auditions', 'drawn_auditions', 'partial_draw_auditions'));
}
public function runDraw(Request $request)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$draw_auditions = Audition::with('entries')->find(array_keys($request->input('auditions')));
foreach ($draw_auditions as $audition) {
$audition->runDraw();

View File

@ -2,15 +2,14 @@
namespace App\Http\Controllers\Admin;
use App\Events\AuditionChange;
use App\Http\Controllers\Controller;
use App\Models\ScoringGuide;
use App\Models\SubscoreDefinition;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use function abort;
use function dd;
use function request;
use function response;
@ -18,72 +17,86 @@ class ScoringGuideController extends Controller
{
public function index()
{
if (! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
DB::table('auditions')
->whereNull('scoring_guide_id')
->update(['scoring_guide_id' => 0]);
$guides = ScoringGuide::with('auditions')->orderBy('name')->get();
return view('admin.scoring.index',['guides'=>$guides]);
return view('admin.scoring.index', ['guides' => $guides]);
}
public function store()
{
if (! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
request()->validate([
'name' => ['required','unique:scoring_guides']
'name' => ['required', 'unique:scoring_guides'],
]);
$guide = ScoringGuide::create([
'name' => request('name')
'name' => request('name'),
]);
return redirect('/admin/scoring');
}
public function edit(Request $request, ScoringGuide $guide)
{
if (! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$tab = $request->query('tab') ?? 'detail';
if ($tab == 'tiebreakOrder') {
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('tiebreak_order')->get();
} else {
$subscores = SubscoreDefinition::where('scoring_guide_id', $guide->id)->orderBy('display_order')->get();
}
return view('admin.scoring.edit',['guide'=>$guide,'subscores'=>$subscores, 'tab'=>$tab]);
return view('admin.scoring.edit', ['guide' => $guide, 'subscores' => $subscores, 'tab' => $tab]);
}
public function update(ScoringGuide $guide)
{
if (! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
request()->validate([
'name' => ['required','unique:scoring_guides']
'name' => ['required', 'unique:scoring_guides'],
]);
$guide->update([
'name' => request('name')
'name' => request('name'),
]);
return redirect('/admin/scoring/guides/' . $guide->id . '/edit' )->with('success','Scoring guide updated');
return redirect('/admin/scoring/guides/'.$guide->id.'/edit')->with('success', 'Scoring guide updated');
}
public function subscore_store(Request $request, ScoringGuide $guide)
{
if (! Auth::user()->is_admin) abort(403);
if (!$guide->exists()) abort(409);
if (! Auth::user()->is_admin) {
abort(403);
}
if (! $guide->exists()) {
abort(409);
}
$validateData = request()->validate([
'name' => ['required'],
'max_score' => ['required','integer'],
'weight'=>['required','integer'],
'for_seating'=>['nullable','boolean'],
'for_advance'=>['nullable','boolean'],
'max_score' => ['required', 'integer'],
'weight' => ['required', 'integer'],
'for_seating' => ['nullable', 'boolean'],
'for_advance' => ['nullable', 'boolean'],
]);
$for_seating = $request->has('for_seating') ? (bool) $request->input('for_seating') : false;
$for_advance = $request->has('for_advance') ? (bool) $request->input('for_advance') : false;
$display_order = SubscoreDefinition::where('scoring_guide_id','=',$guide->id)->max('display_order') + 1;
$tiebreak_order = SubscoreDefinition::where('scoring_guide_id','=',$guide->id)->max('tiebreak_order') + 1;
$display_order = SubscoreDefinition::where('scoring_guide_id', '=', $guide->id)->max('display_order') + 1;
$tiebreak_order = SubscoreDefinition::where('scoring_guide_id', '=', $guide->id)->max('tiebreak_order') + 1;
$subscore = SubscoreDefinition::create([
'scoring_guide_id' => $guide->id,
@ -95,30 +108,37 @@ class ScoringGuideController extends Controller
'for_seating' => $for_seating,
'for_advance' => $for_advance,
]);
return redirect('/admin/scoring/guides/' . $guide->id . '/edit' )->with('success','Subscore added');
return redirect('/admin/scoring/guides/'.$guide->id.'/edit')->with('success', 'Subscore added');
}
public function reorder_display(Request $request)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$order = $request->order;
foreach ($order as $index => $id) {
$subscore = SubscoreDefinition::find($id);
$subscore->update(['display_order' => $index]);
}
return response()->json(['status'=>'success']);
return response()->json(['status' => 'success']);
}
public function reorder_tiebreak(Request $request)
{
if(! Auth::user()->is_admin) abort(403);
if (! Auth::user()->is_admin) {
abort(403);
}
$order = $request->order;
foreach ($order as $index => $id) {
$subscore = SubscoreDefinition::find($id);
$subscore->update(['tiebreak_order' => $index]);
}
return response()->json(['status'=>'success']);
return response()->json(['status' => 'success']);
}
}

View File

@ -12,7 +12,8 @@ return new class extends Migration
public function up(): void
{
Schema::table('auditions', function (Blueprint $table) {
//
$table->boolean('for_seating')->default(1);
$table->boolean('for_advancement')->default(1);
});
}
@ -22,7 +23,8 @@ return new class extends Migration
public function down(): void
{
Schema::table('auditions', function (Blueprint $table) {
//
$table->dropColumn('for_seating');
$table->dropColumn('for_advancement');
});
}
};

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('entries', function (Blueprint $table) {
$table->boolean('for_seating')->default(1);
$table->boolean('for_advancement')->default(1);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('entries', function (Blueprint $table) {
$table->dropColumn('for_seating');
$table->dropColumn('for_advancement');
});
}
};

View File

@ -18,6 +18,16 @@
<x-form.field name="entry_fee" label_text="Entry Fee" type="number" colspan="6" />
<x-form.field name="minimum_grade" label_text="Minimum Grade" type="number" colspan="6" />
<x-form.field name="maximum_grade" label_text="Maximum Grade" type="number" colspan="6" />
@if(auditionSetting('advanceTo'))
<div class="col-span-6 align-top">
<x-form.checkbox name="for_seating" label="For Seats" description="Students will be seated in this audition" checked />
</div>
<div class="col-span-6 align-top">
<x-form.checkbox name="for_advancement" label="For {{ auditionSetting('advanceTo') }}" description="Students compete for advancement" checked/>
</div>
@else
<input type="hidden" name="for_seating" value="on">
@endif
</x-form.body-grid>
<x-form.footer submit-button-text="Create Audition" class="pb-4"/>
</x-form.form>

View File

@ -18,6 +18,25 @@
<x-form.field name="entry_fee" label_text="Entry Fee" type="number" colspan="6" value="{{ $audition->entry_fee / 100 }}" />
<x-form.field name="minimum_grade" label_text="Minimum Grade" type="number" colspan="6" value="{{ $audition->minimum_grade }}" />
<x-form.field name="maximum_grade" label_text="Maximum Grade" type="number" colspan="6" value="{{ $audition->maximum_grade }}" />
@if(auditionSetting('advanceTo'))
<div class="col-span-6 align-top">
<x-form.checkbox name="for_seating"
label="For Seats"
description="Students will be seated in this audition"
:checked="$audition->for_seating"
/>
</div>
<div class="col-span-6 align-top">
<x-form.checkbox name="for_advancement"
label="For {{ auditionSetting('advanceTo') }}"
description="Students compete for advancement"
:checked="$audition->for_advancement"/>
</div>
@else
<input type="hidden" name="for_seating" value="on">
@endif
</x-form.body-grid>
<x-form.footer submit-button-text="Update Audition" class="pb-4 !justify-between">
<div>

View File

@ -15,6 +15,10 @@
<x-table.th>Deadline</x-table.th>
<x-table.th>Entry Fee</x-table.th>
<x-table.th>Grade Range</x-table.th>
@if(auditionSetting('advanceTo'))
<x-table.th>Seats</x-table.th>
<x-table.th>{{ auditionSetting('advanceTo') }}</x-table.th>
@endif
<x-table.th>Entries</x-table.th>
@ -29,6 +33,22 @@
<x-table.td>{{ $audition->entry_deadline }}</x-table.td>
<x-table.td>{{ $audition->dislpay_fee() }}</x-table.td>
<x-table.td>{{ $audition->minimum_grade }} - {{ $audition->maximum_grade }}</x-table.td>
@if(auditionSetting('advanceTo'))
<x-table.td>
@if($audition->for_seating)
<x-icons.checkmark color="green" />
@else
<x-icons.circle-slash-no color="red" />
@endif
</x-table.td>
<x-table.td>
@if($audition->for_advancement)
<x-icons.checkmark color="green" />
@else
<x-icons.circle-slash-no color="red" />
@endif
</x-table.td>
@endif
<x-table.td>{{ $audition->entries->count() }}</x-table.td>
</tr>
@endforeach

View File

@ -0,0 +1,18 @@
@props(['name','label','description' => '', 'checked' => false])
<div class="relative flex items-start">
<div class="flex h-6 items-center">
<input id="{{ $name }}"
aria-describedby="comments-description"
name="{{ $name }}"
type="checkbox"
@if($checked) checked @endif
class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600">
</div>
<div class="ml-3 text-sm leading-6">
<label for="{{ $name }}" class="font-medium text-gray-900">{{ $label }}</label>
<p id="comments-description" class="text-gray-500">{{ $description }}</p>
@error($name)
<p class="text-xs text-red-500 font-semibold mt-1 ml-3">{{ $message }}</p>
@enderror
</div>
</div>

View File

@ -0,0 +1,4 @@
@props(['color' => 'currentColor'])
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="{{ $color }}" stroke-linecap="round" stroke-width="2" d="m6 6 12 12m3-6a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
</svg>