Draw working

This commit is contained in:
Matt Young 2024-06-06 22:07:59 -05:00
parent f49c10821a
commit 969efd5e54
11 changed files with 220 additions and 13 deletions

View File

@ -9,10 +9,14 @@ 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
{
@ -143,4 +147,31 @@ class AuditionController extends Controller
$audition->delete();
return redirect('/admin/auditions');
}
public function prepareDraw()
{
if(! Auth::user()->is_admin) abort(403);
$allAuditions = Audition::with('entries')->orderBy('score_order')->get();
$nodraw_auditions = $allAuditions->filter(function($audition) {
return $audition->has_no_draw();
});
$drawn_auditions = $allAuditions->filter(function($audition) {
return $audition->has_complete_draw();
});
$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'));
}
public function runDraw(Request $request)
{
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();
}
return redirect('/admin/auditions/run_draw');
}
}

View File

@ -9,6 +9,7 @@ use App\Models\School;
use App\Models\Student;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use function compact;
class EntryController extends Controller
{
@ -108,4 +109,6 @@ class EntryController extends Controller
return redirect('/admin/entries');
}
}

View File

@ -45,9 +45,78 @@ class Audition extends Model
return '$' . number_format($this->entry_fee / 100, 2);
}
public function has_no_draw(): bool
{
// return true if all of my entries have a null draw_number
//return $this->entries->every(fn($entry) => is_null($entry->draw_number));
// return $this->entries()->whereNotNull('draw_number')->doesntExist();
if ($this->entries->count() == 0) {
return false;
}
if ($this->relationLoaded('entries')) {
return $this->entries->every(function ($entry) {
return is_null($entry->draw_number);
});
} else {
return $this->entries()->whereNotNull('draw_number')->doesntExist();
}
}
public function has_complete_draw(): bool
{
// return true if all of my entries have a draw_number
// return $this->entries->every(fn($entry) => !is_null($entry->draw_number));
// return $this->entries()->whereNull('draw_number')->doesntExist();
if ($this->entries->count() == 0) {
return false;
}
if ($this->relationLoaded('entries')) {
return $this->entries->every(function ($entry) {
return !is_null($entry->draw_number);
});
} else {
return $this->entries()->whereNull('draw_number')->doesntExist();
}
}
public function has_partial_draw(): bool
{
if ($this->entries->count() == 0) {
return false;
}
// return true I have at least one entry with a null draw number AND at least one entry with a non-null draw number
//return $this->entries->contains(fn($entry) => is_null($entry->draw_number)) && $this->entries->contains(fn($entry) => !is_null($entry->draw_number));
//$hasNull = $this->entries()->whereNull('draw_number')->exists();
//$hasNotNull = $this->entries()->whereNotNull('draw_number')->exists();
//return $hasNull && $hasNotNull;
if ($this->relationLoaded('entries')) {
$hasNull = $this->entries->contains(function ($entry) {
return is_null($entry->draw_number);
});
$hasNotNull = $this->entries->contains(function ($entry) {
return !is_null($entry->draw_number);
});
return $hasNull && $hasNotNull;
} else {
$hasNull = $this->entries()->whereNull('draw_number')->exists();
$hasNotNull = $this->entries()->whereNotNull('draw_number')->exists();
return $hasNull && $hasNotNull;
}
}
public function runDraw(): null
{
$entries = $this->entries->shuffle();
foreach ($entries as $index => $entry) {
$entry->update(['draw_number' => $index + 1]);
$entry->save();
}
return null;
}
}

View File

@ -0,0 +1,32 @@
<?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->integer('draw_number')->nullable()->default(null);
$table->unique(['audition_id', 'draw_number']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('entries', function (Blueprint $table) {
//drop unique constraint for audition_id and draw_number
$table->dropUnique(['audition_id', 'draw_number']);
// drop column draw_number
$table->dropColumn('draw_number');
});
}
};

View File

@ -0,0 +1,31 @@
<x-layout.app>
<x-slot:page_title>Run Draw</x-slot:page_title>
<form method="post" action="/admin/auditions/run_draw">
@csrf
<div class="mx-auto max-w-lg mb-3">
<x-form.button>Run Draw for Selected Auditions</x-form.button>
</div>
<div class="flex w-full grow flex-wrap">
@if($nodraw_auditions->count() > 0)
<x-draw-page.audition-switches :auditions="$nodraw_auditions">
These auditions have no draw
</x-draw-page.audition-switches>
@endif
@if($partial_draw_auditions->count() > 0)
<x-draw-page.audition-switches :auditions="$partial_draw_auditions">
These auditions have a partial draw
</x-draw-page.audition-switches>
@endif
@if($drawn_auditions->count() > 0)
<x-draw-page.audition-switches :auditions="$drawn_auditions">
These auditions have already been drawn
</x-draw-page.audition-switches>
@endif
</div>
</form>
</x-layout.app>
{{--TODO when an entry is made anywhere in the system, there needs to be a check if a draw needs to be run--}}

View File

@ -0,0 +1,30 @@
@props([
'auditions',
])
<x-card.card {{ $attributes->merge(['class'=>'grow mx-2 my-2']) }}>
<x-card.heading>
{{ $slot }}
</x-card.heading>
<div class="p-3 flex-col" x-data="{ checked: false }">
<div class="pb-2 mb-3 -mt-0.5 border-b">
<button @click="checked = true" class="rounded bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-600 shadow-sm hover:bg-indigo-100 mr-3" type="button">Check All</button>
<button @click="checked = false" class="rounded bg-indigo-50 px-2 py-1 text-xs font-semibold text-indigo-600 shadow-sm hover:bg-indigo-100" type="button">Uncheck All</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2">
@foreach($auditions->chunk($auditions->count() /2) as $chunk)
<div>
@foreach($chunk as $audition)
<div class="relative flex items-start">
<div class="flex h-6 items-center">
<input id="auditions-{{ $audition->id }}" name="auditions[{{$audition->id}}]" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600" x-bind:checked="checked">
</div>
<div class="ml-3 text-sm leading-6">
<label for="comments" class="font-medium text-gray-900">{{ $audition->name }}</label>
</div>
</div>
@endforeach
</div>
@endforeach
</div>
</div>
</x-card.card>

View File

@ -1,7 +1,7 @@
@props(['name', 'checked' => false])
<div x-data="{ toggle: {{ $checked ? 'true':'false'}} }" class="flex items-center">
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" x-model="toggle" name="{{ $name }}" class="sr-only" {{ $checked ? 'checked':''}} value="1">
<label {{ $attributes->merge(['class'=>'relative inline-flex items-center cursor-pointer']) }}>{{ $slot }}
<input type="checkbox" x-model="toggle" name="{{ $name }}" class="sr-only" {{ $checked ? 'checked':''}} value="1" >
<div :class="toggle ? 'bg-blue-600' : 'bg-gray-200'" class="w-11 h-6 rounded-full transition-colors duration-300"></div>
<div :class="toggle ? 'translate-x-6' : 'translate-x-1'" class="absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform duration-300"></div>
</label>

View File

@ -29,6 +29,7 @@
<a href="/admin/scoring" class="block p-2 hover:text-indigo-600">Scoring</a>
<a href="/admin/rooms" class="block p-2 hover:text-indigo-600">Rooms</a>
<a href="/admin/rooms/judging_assignments" class="block p-2 hover:text-indigo-600">Judges</a>
<a href="/admin/auditions/run_draw" class="block p-2 hover:text-indigo-600">Run Draw</a>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@
<x-layout.page-section-container>
<x-layout.page-section>
<x-slot:section_name>Add Entry</x-slot:section_name>
<x-form.form method="POST" action="/entries">
<x-form.form method="POST" action="/entries" class="pt-6 pb-8">
<x-form.body-grid columns="7" class="max-w-full" x-data="studentAuditionFilter()">
@ -29,7 +29,7 @@
</template>
</x-form.select>
<x-form.button class="mt-8">Save</x-form.button>
<x-form.button class="mt-6">Save</x-form.button>
</x-form.body-grid>
</x-form.form>
</x-layout.page-section>
@ -38,7 +38,7 @@
<x-layout.page-section>
<x-slot:section_name>Entry Listing</x-slot:section_name>
<x-slot:section_description>You have {{ $entries->count() }} entries</x-slot:section_description>
<div class="px-4">
<div class="px-6 md:px-8 py-3">
<x-table.table>
<thead>
<tr>

View File

@ -3,15 +3,22 @@
<x-slot:page_title>Test Page</x-slot:page_title>
@php
$scores =[
['subcoreID' => 13, 'score' => 93],
['subcoreID' => 23, 'score' => 91],
['subcoreID' => 42, 'score' => 81],
['subcoreID' => 78, 'score' => 16],
['subcoreID' => 74, 'score' => 23],
];
$auditions = Audition::with('entries')->get();
@endphp
@foreach($auditions as $audition)
{{ $audition->name }} has {{ $audition->entries->count() }} entries.<br>
@if($audition->has_complete_draw())
<strong class="text-green-600">Draw is complete.</strong>
@endif
@if($audition->has_partial_draw())
<strong class="text-yellow-600">Has a partial draw.</strong>
@endif
@if($audition->has_no_draw())
<strong class="text-red-600">Has no draw.</strong>
@endif
<hr><hr>
@endforeach
</x-layout.app>

View File

@ -68,6 +68,8 @@ Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->gr
Route::patch('/{audition}','update');
Route::post('/reorder','reorder');
Route::delete('/{audition}','destroy');
Route::get('/run_draw','prepareDraw');
Route::post('/run_draw','runDraw');
});
// Admin Entries Routes
@ -77,6 +79,7 @@ Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->gr
Route::post('/','store');
Route::get('/{entry}/edit','edit');
Route::patch('/{entry}','update');
});
// Admin Student Routes