Meobda nomination ensemble #107

Merged
okorpheus merged 16 commits from meobda_nomination_ensemble into master 2025-02-17 16:20:06 +00:00
3 changed files with 238 additions and 0 deletions
Showing only changes of commit 7eff16289f - Show all commits

View File

@ -0,0 +1,172 @@
<?php
namespace App\Http\Controllers\NominationEnsembles;
use App\Http\Controllers\Controller;
use App\Models\NominationEnsemble;
use App\Models\NominationEnsembleEntry;
use App\Models\Student;
use Illuminate\Support\Carbon;
class MeobdaNominationEnsembleEntryController extends Controller implements NominationEnsembleEntryController
{
public function index()
{
// Get current date for checking deadlines
$currentDate = Carbon::now('America/Chicago');
$currentDate = $currentDate->format('Y-m-d');
$ensembles = NominationEnsemble::all();
$availableInstruments = [];
$availableStudents = [];
$existingNominations = [];
$nominationsAvailable = [];
foreach ($ensembles as $ensemble) {
// Get existing nominations
$existingNominations[$ensemble->id] = auth()->user()->school->nominations()
->where('nomination_ensemble_id', $ensemble->id)
->get()
->keyBy('student_id');
// Count how many nominations exist on each instrument
$nominatedInstrumentCount = [];
foreach ($existingNominations[$ensemble->id] as $nom) {
$nominatedInstrumentCount[$nom->data['instrument']] =
($nominatedInstrumentCount[$nom->data['instrument']] ?? 0) + 1;
}
// Set available instruments
foreach ($ensemble->data['instruments'] as $instrument) {
// Skip it if we're at the limit on this instrument
if (! is_null($instrument['max']) && $instrument['max'] <= ($nominatedInstrumentCount[$instrument['name']] ?? 0)) {
continue;
}
$availableInstruments[$ensemble->id][] = $instrument['name'];
}
// Set available students
$students = Student::where('school_id', auth()->user()->school_id)
->where('grade', '>=', $ensemble->minimum_grade)
->where('grade', '<=', $ensemble->maximum_grade)
->orderBy('last_name', 'asc')
->orderBy('first_name', 'asc')
->get();
foreach ($existingNominations[$ensemble->id] as $checknom) {
$students = $students->reject(function ($student) use ($checknom) {
return $checknom->student_id == $student->id;
});
}
$availableStudents[$ensemble->id] = $students;
$nominationsAvailable[$ensemble->id] = $existingNominations[$ensemble->id]->count() < $ensemble->data['max_nominations'];
}
return view('nomination_ensembles.meobda.entries.index',
compact('ensembles', 'currentDate', 'availableInstruments', 'availableStudents', 'existingNominations',
'nominationsAvailable'));
}
public function show(NominationEnsembleEntry $entry)
{
// TODO: Implement show() method.
}
public function create()
{
// TODO: Implement create() method.
}
public function store()
{
$validData = request()->validate([
'ensemble' => [
'required',
'exists:App\Models\NominationEnsemble,id',
],
'new_student' => [
'required',
'exists:App\Models\Student,id',
],
'new_instrument' => 'required',
]);
$ensemble = NominationEnsemble::find($validData['ensemble']);
// Check that the deadline is not past
$currentDate = Carbon::now('America/Chicago');
$currentDate = $currentDate->format('Y-m-d');
if ($ensemble->entry_deadline < $currentDate) {
return redirect()->route('nomination.entry.index')->with('error',
'The nomination deadline for that ensemble has passed');
}
// Check if new_instrument is valid
foreach ($ensemble->data['instruments'] as $instrument) {
$availableInstruments[] = $instrument['name'];
}
if (! in_array($validData['new_instrument'], $availableInstruments)) {
return redirect()->route('nomination.entry.index')->with('error',
'Invalid Instrument Specified');
}
// Check if the student belongs to the current user
$student = Student::find($validData['new_student']);
if (auth()->user()->school_id !== $student->school_id) {
return redirect()->route('nomination.entry.index')->with('error',
'You may only nominate students from your school');
}
// Check that the user's school has nominations available
$existing_nominations = auth()->user()->school->nominations;
if ($existing_nominations->count() >= $ensemble->data['max_nominations']) {
return redirect()->route('nomination.entry.index')->with('error',
'You have already used all of your nominations for this ensemble');
}
// Check that the user's school isn't over limit for the requested instrument
$instrumentLimit = collect($ensemble->data['instruments'])->firstWhere('name',
$validData['new_instrument'])['max'];
if ($instrumentLimit) {
$used = 0;
foreach ($existing_nominations as $nom) {
if ($nom->data['instrument'] == $validData['new_instrument']) {
$used++;
}
if ($used >= $instrumentLimit) {
return redirect()->route('nomination.entry.index')->with('error',
'You may not nominate any more students on that instrument');
}
}
}
// Check that the student isn't already nominated for this ensemble
if (NominationEnsembleEntry::where('student_id', $validData['new_student'])
->where('nomination_ensemble_id', $validData['ensemble'])
->count() > 0) {
return redirect()->route('nomination.entry.index')->with('error',
'Student already nominated for that ensemble');
}
$newEntry = new NominationEnsembleEntry();
$newEntry->student_id = $validData['new_student'];
$newEntry->nomination_ensemble_id = $validData['ensemble'];
$newEntry->data = ['instrument' => $validData['new_instrument']];
$newEntry->save();
return redirect()->route('nomination.entry.index')->with('success',
'Nomination entered');
}
public function edit(NominationEnsembleEntry $entry)
{
// TODO: Implement edit() method.
}
public function update(NominationEnsembleEntry $entry)
{
// TODO: Implement update() method.
}
public function destroy(NominationEnsembleEntry $entry)
{
// TODO: Implement destroy() method.
}
}

View File

@ -3,6 +3,7 @@
namespace App\Providers; namespace App\Providers;
use App\Http\Controllers\NominationEnsembles\MeobdaNominationEnsembleController; use App\Http\Controllers\NominationEnsembles\MeobdaNominationEnsembleController;
use App\Http\Controllers\NominationEnsembles\MeobdaNominationEnsembleEntryController;
use App\Http\Controllers\NominationEnsembles\NominationAdminController; use App\Http\Controllers\NominationEnsembles\NominationAdminController;
use App\Http\Controllers\NominationEnsembles\NominationEnsembleController; use App\Http\Controllers\NominationEnsembles\NominationEnsembleController;
use App\Http\Controllers\NominationEnsembles\NominationEnsembleEntryController; use App\Http\Controllers\NominationEnsembles\NominationEnsembleEntryController;
@ -38,6 +39,7 @@ class NominationEnsembleServiceProvider extends ServiceProvider
// meobda implementation // meobda implementation
$this->app->bind(NominationEnsembleController::class, MeobdaNominationEnsembleController::class); $this->app->bind(NominationEnsembleController::class, MeobdaNominationEnsembleController::class);
$this->app->bind(NominationEnsembleEntryController::class, MeobdaNominationEnsembleEntryController::class);
} }
} }
} }

View File

@ -0,0 +1,64 @@
<x-layout.app>
<x-slot:page_title>Nominations</x-slot:page_title>
<x-layout.page-section-container>
@foreach($ensembles as $ensemble)
<x-layout.page-section>
<x-slot:section_name>{{ $ensemble->name }}</x-slot:section_name>
<x-slot:section_description>
{{ $ensemble->data['max_nominations'] }} nominations accepted<br>
Entry Deadline {{ \Carbon\Carbon::parse($ensemble->entry_deadline)->format('M j, Y') }}
</x-slot:section_description>
<x-card.card>
<x-card.heading>Existing Nominations</x-card.heading>
<x-table.table>
<thead>
<tr>
<x-table.th>Student</x-table.th>
<x-table.th>Grade</x-table.th>
<x-table.th>Instrument</x-table.th>
</tr>
</thead>
<x-table.body>
@foreach($existingNominations[$ensemble->id] as $nom)
<tr>
<x-table.td>{{ $nom->student->full_name() }}</x-table.td>
<x-table.td>{{ $nom->student->grade }}</x-table.td>
<x-table.td>{{ $nom->data['instrument'] }}</x-table.td>
</tr>
@endforeach
</x-table.body>
</x-table.table>
</x-card.card>
@if($nominationsAvailable[$ensemble->id])
<x-card.card>
<x-card.heading>New Entry</x-card.heading>
<x-form.form method="POST" action="{{ route('nomination.entry.store') }}">
<x-form.body-grid columns="5" class="mb-4 mt-4">
<input type="hidden" name="ensemble" value="{{ $ensemble->id }}"/>
<x-form.select name="new_student" colspan="2">
@foreach($availableStudents[$ensemble->id] as $student)
<option value="{{$student->id}}">{{ $student->full_name() }}
(Grade {{ $student->grade }})
</option>
@endforeach
</x-form.select>
<x-form.select name="new_instrument" colspan="2">
@foreach($availableInstruments[$ensemble->id] as $instrument)
<option value="{{$instrument}}">{{ $instrument }}</option>
@endforeach
</x-form.select>
<x-form.button>Add Nomination</x-form.button>
</x-form.body-grid>
</x-form.form>
</x-card.card>
@endif
</x-layout.page-section>
@endforeach
</x-layout.page-section-container>
</x-layout.app>