diff --git a/app/Http/Controllers/Admin/DrawController.php b/app/Http/Controllers/Admin/DrawController.php new file mode 100644 index 0000000..e874b90 --- /dev/null +++ b/app/Http/Controllers/Admin/DrawController.php @@ -0,0 +1,16 @@ +get(); + + return view('admin.draw.index', compact('events')); + } +} diff --git a/app/Models/Event.php b/app/Models/Event.php index 2df0d6a..b8b9726 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -13,7 +13,7 @@ class Event extends Model public function auditions(): HasMany { - return $this->hasMany(Audition::class); + return $this->hasMany(Audition::class)->orderBy('score_order'); } public function ensembles(): HasMany diff --git a/resources/views/admin/draw/index.blade.php b/resources/views/admin/draw/index.blade.php new file mode 100644 index 0000000..ac658ee --- /dev/null +++ b/resources/views/admin/draw/index.blade.php @@ -0,0 +1,36 @@ +@php + /** + * @var \App\Models\Event[] $events A collection of all events with auditions + */ +@endphp + + + + @foreach($events as $event) + @continue($event->auditions->isEmpty()) + + + {{ $event->name }} + + + + + +
+ @foreach($event->auditions as $audition) +
+ + {{$audition->name}} +
+ @endforeach +
+
+
+
+ Run Draw +
+
+
+ @endforeach +
+
diff --git a/resources/views/components/form/checkbox.blade.php b/resources/views/components/form/checkbox.blade.php index ea0af3a..fbba523 100644 --- a/resources/views/components/form/checkbox.blade.php +++ b/resources/views/components/form/checkbox.blade.php @@ -1,7 +1,16 @@ -@props(['name','label' => false,'description' => '', 'checked' => false]) +@props(['name', +'label' => false, +'description' => '', + 'checked' => false, + 'id' => false]) +@php + if(! $id): + $id = $name; + endif; +@endphp
-
@if($label) - +

{{ $description }}

@endif @error($name) diff --git a/resources/views/components/layout/navbar/menus/setup.blade.php b/resources/views/components/layout/navbar/menus/setup.blade.php index ddcf040..42c4d80 100644 --- a/resources/views/components/layout/navbar/menus/setup.blade.php +++ b/resources/views/components/layout/navbar/menus/setup.blade.php @@ -28,7 +28,7 @@ Scoring Rooms Judges - Run Draw + Run Draw
diff --git a/routes/admin.php b/routes/admin.php index aae16f1..d99f460 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -68,8 +68,15 @@ Route::middleware(['auth', 'verified', CheckIfAdmin::class])->prefix('admin/')-> Route::patch('/{audition}', 'update')->name('admin.auditions.update'); Route::post('/reorder', 'reorder')->name('admin.auditions.reorder'); Route::delete('/{audition}', 'destroy')->name('admin.auditions.destroy'); - Route::get('/run_draw', 'prepareDraw')->name('admin.auditions.prepareDraw'); - Route::post('/run_draw', 'runDraw')->name('admin.auditions.runDraw'); + #Route::get('/run_draw', 'prepareDraw')->name('admin.auditions.prepareDraw'); + #Route::post('/run_draw', 'runDraw')->name('admin.auditions.runDraw'); + }); + + // Admin Audition Draw Routes + Route::prefix('draw')->controller(\App\Http\Controllers\Admin\DrawController::class)->group(function () { + Route::get('/', 'index')->name('admin.draw.index'); + Route::post('/', 'store')->name('admin.draw.store'); + Route::delete('/', 'destroy')->name('admin.draw.destroy'); }); // Admin Entries Routes diff --git a/tests/Feature/Models/EventTest.php b/tests/Feature/Models/EventTest.php index 18fa8ca..a97f644 100644 --- a/tests/Feature/Models/EventTest.php +++ b/tests/Feature/Models/EventTest.php @@ -9,7 +9,7 @@ uses(RefreshDatabase::class); it('has auditions', function () { $event = Event::factory()->create(); - $ddAudition = Audition::factory()->create(['event_id' => $event->id, 'name' => 'Digereedoo']); + Audition::factory()->create(['event_id' => $event->id, 'name' => 'Digereedoo','score_order' => 0]); Audition::factory()->count(7)->create(['event_id' => $event->id]); expect($event->auditions->count())->toBe(8) diff --git a/tests/Feature/Pages/Setup/DrawIndexTest.php b/tests/Feature/Pages/Setup/DrawIndexTest.php new file mode 100644 index 0000000..495b594 --- /dev/null +++ b/tests/Feature/Pages/Setup/DrawIndexTest.php @@ -0,0 +1,153 @@ +get(route('admin.draw.index'))->assertRedirect(route('home')); + actAsNormal(); + $this->get(route('admin.draw.index')) + ->assertSessionHas('error', 'You are not authorized to perform this action') + ->assertRedirect(route('dashboard')); + +}); +it('returns the view admin.draw.index', function () { + actAsAdmin(); + $response = $this->get(route('admin.draw.index')); + $response->assertViewIs('admin.draw.index'); +}); +it('has a section for each event that has auditions', function () { + // Arrange + $events = Event::factory()->count(3)->create(); + Audition::factory()->create(['event_id' => $events[0]->id]); + Audition::factory()->create(['event_id' => $events[1]->id]); + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + // Assert + foreach ($events as $event) { + if ($event->auditions->count() > 0) { + $response->assertElementExists('#event-section-'.$event->id); + } else { + $response->assertDontSee('id="event-section-'.$event->id, false); + } + } +}); +it('lists auditions in each section', function () { + // Arrange + $events = Event::factory()->count(2)->create(); + foreach ($events as $event) { + Audition::factory()->count(5)->create(['event_id' => $event->id]); + } + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + // Assert + foreach ($events as $event) { + $response->assertElementExists('#event-section-'.$event->id, function (AssertElement $element) use ($event) { + foreach ($event->auditions as $audition) { + $element->contains('#auditiongroup-'.$audition->id); + $element->containsText($audition->name); + } + }); + } +}); +it('each audition has a checkbox with its name', function () { + // Arrange + $events = Event::factory()->count(2)->create(); + foreach ($events as $event) { + Audition::factory()->count(5)->create(['event_id' => $event->id]); + } + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + $response->assertOk(); + // Assert + foreach ($events as $event) { + $response->assertElementExists('#event-section-'.$event->id, function (AssertElement $element) use ($event) { + foreach ($event->auditions as $audition) { + $element->contains('#auditiongroup-'.$audition->id, function (AssertElement $element) use ($audition) { + $element->containsText($audition->name); + }); + $element->contains('#auditionCheckbox-'.$audition->id); + } + }); + } +}); +it('lists auditions in score order', function () { + // Arrange + $event = Event::factory()->create(); + $third = Audition::factory()->create(['event_id' => $event->id, 'score_order' => 3]); + $first = Audition::factory()->create(['event_id' => $event->id, 'score_order' => 1]); + $fourth = Audition::factory()->create(['event_id' => $event->id, 'score_order' => 4]); + $second = Audition::factory()->create(['event_id' => $event->id, 'score_order' => 2]); + actAsAdmin(); + // Act & Assert + $response = $this->get(route('admin.draw.index')); + $response->assertOk(); + $response->assertSeeInOrder([ + e($first->name), + e($second->name), + e($third->name), + e($fourth->name), + ], false); +}); +it('has a form wrapping all event sections', function () { + // Arrange + $events = Event::factory()->count(2)->create(); + foreach ($events as $event) { + Audition::factory()->count(5)->create(['event_id' => $event->id]); + } + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + // Assert + $response + ->assertOk() + ->assertElementExists('#draw-form', function (AssertElement $element) use ($events) { + foreach ($events as $event) { + $element->contains('#event-section-'.$event->id); + } + }); + +}); +it('has a submit button in each event section', function () { + // Arrange + $events = Event::factory()->count(3)->create(); + Audition::factory()->create(['event_id' => $events[0]->id]); + Audition::factory()->create(['event_id' => $events[1]->id]); + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + // Assert + foreach ($events as $event) { + if ($event->auditions->count() > 0) { + $response->assertElementExists('#event-section-'.$event->id, function (AssertElement $element) { + $element->contains('button[type="submit"]'); + }); + } + } +}); +it('submits to the route admin.draw.store and has CSRF protection', function () { + // Arrange + $events = Event::factory()->count(3)->create(); + foreach ($events as $event) { + Audition::factory()->create(['event_id' => $event->id]); + } + actAsAdmin(); + // Act + $response = $this->get(route('admin.draw.index')); + // Assert + $response + ->assertOk() + ->assertFormExists('#draw-form', function (AssertForm $form) { + $form->hasAction(route('admin.draw.store')); + $form->hasCSRF(); + }); +});