auditionadmin/app/Http/Controllers/NominationEnsembles/ScobdaNominationEnsembleEnt...

225 lines
8.7 KiB
PHP

<?php
namespace App\Http\Controllers\NominationEnsembles;
use App\Http\Controllers\Controller;
use App\Models\NominationEnsemble;
use App\Models\NominationEnsembleEntry;
use App\Models\School;
use App\Models\Student;
use Illuminate\Support\Carbon;
class ScobdaNominationEnsembleEntryController 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();
// populate an array with each ensemble id as a key. Each item will be a collection of students available to be nominated
$availableStudents = [];
// populate an array with each ensemble id as a key. Each item will be a collection of available instruments
$availableInstruments = [];
// populate an array with each ensemble id as a key. Each item will be a collection of nominationEntries already made
$nominatedStudents = [];
// an array of bool values with each ensemble id as a key. It will be true if additional nominations are available
$nominationsAvailable = [];
foreach ($ensembles as $ensemble) {
// Gather a collection of students who may be nominated for this ensemble
$availableStudents[$ensemble->id] = Student::where('grade', '<=', $ensemble->maximum_grade)
->where('grade', '>=', $ensemble->minimum_grade)
->where('school_id', auth()->user()->school_id)
->orderBy('last_name')
->orderBy('first_name')
->get();
$availableInstruments[$ensemble->id] = $ensemble->data['instruments'];
$nominatedStudents[$ensemble->id] = $this->collapseNominations(auth()->user()->school, $ensemble,
'nominations');
$nominatedStudentIds = [];
// Removed students already nominated from available students
foreach ($nominatedStudents[$ensemble->id] as $nominatedStudent) {
$nominatedStudentIds[] = $nominatedStudent->student_id;
}
$availableStudents[$ensemble->id] = $availableStudents[$ensemble->id]->reject(function ($student) use (
$nominatedStudentIds
) {
return in_array($student->id, $nominatedStudentIds);
});
$nominationsAvailable[$ensemble->id] = $ensemble->data['max_nominations'] > count($nominatedStudents[$ensemble->id]);
}
return view('nomination_ensembles.scobda.entries.index',
compact('ensembles', 'availableStudents', 'availableInstruments', 'nominatedStudents',
'nominationsAvailable', 'currentDate'));
}
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',
]);
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');
}
$proposedEnsemble = NominationEnsemble::find($validData['ensemble']);
$currentDate = Carbon::now('America/Chicago');
$currentDate = $currentDate->format('Y-m-d');
if ($proposedEnsemble->entry_deadline < $currentDate) {
return redirect()->route('nomination.entry.index')->with('error',
'The nomination deadline for that ensemble has passed');
}
if (! in_array($validData['new_instrument'], $proposedEnsemble->data['instruments'])) {
return redirect()->route('nomination.entry.index')->with('error',
'Invalid Instrument specified');
}
$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');
}
$nextRank = $this->collapseNominations($student->school, $proposedEnsemble, 'next');
if ($nextRank > $proposedEnsemble->data['max_nominations']) {
return redirect()->route('nomination.entry.index')->with('error',
'You have already used all of your nominations');
}
$entry = new NominationEnsembleEntry();
$entry->student_id = $validData['new_student'];
$entry->nomination_ensemble_id = $validData['ensemble'];
$data = [];
$data['rank'] = $nextRank;
$data['instrument'] = $validData['new_instrument'];
$entry->data = $data;
$entry->save();
return redirect()->route('nomination.entry.index')->with('success',
'Nomination Recorded');
}
public function edit(NominationEnsembleEntry $entry)
{
// TODO: Implement edit() method.
}
public function update(NominationEnsembleEntry $entry)
{
// TODO: Implement update() method.
}
public function destroy(NominationEnsembleEntry $entry)
{
if ($entry->student->school_id !== auth()->user()->school_id) {
return redirect()->route('nomination.entry.index')->with('error',
'You may only delete nominations from your school');
}
$currentDate = Carbon::now('America/Chicago');
$currentDate = $currentDate->format('Y-m-d');
if ($entry->ensemble->entry_deadline < $currentDate) {
return redirect()->route('nomination.entry.index')->with('error',
'You cannot delete nominations after the deadline');
}
$entry->delete();
return redirect()->route('nomination.entry.index')->with('success', 'Nomination Deleted');
}
/**
* Given a school and nomination ensemble, consolidate the rank valuek
*
* if returnType is next, the next available rank will be returned
* if returnType is nominations, a collection of nominations will be returned
*
* @return int|array
*
* @var returnType = next|nominations
*/
private function collapseNominations(School $school, NominationEnsemble $ensemble, $returnType = 'next')
{
$nominations = $school->nominations()->get()->where('nomination_ensemble_id',
$ensemble->id)->sortBy('data.rank');
$n = 1;
foreach ($nominations as $nomination) {
$nomination->update(['data->rank' => $n]);
$n++;
}
if ($returnType == 'next') {
return $n;
}
return $nominations;
}
public function move()
{
$validData = request()->validate([
'direction' => 'required|in:up,down',
'nominationId' => 'required|exists:App\Models\NominationEnsembleEntry,id',
]);
$direction = $validData['direction'];
$nomination = NominationEnsembleEntry::findOrFail($validData['nominationId']);
// Verify the entry deadline for the ensemble has not passed
$currentDate = Carbon::now('America/Chicago');
$currentDate = $currentDate->format('Y-m-d');
if ($nomination->ensemble->entry_deadline < $currentDate) {
return redirect()->route('nomination.entry.index')->with('error',
'The entry deadline for that nomination ensemble has passed');
}
// Verify the student being moved is from the users school
if (auth()->user()->school_id !== $nomination->student_id) {
return redirect()->route('nomination.entry.index')->with('error',
'You cannot modify nominations of another school');
}
$data = $nomination->data;
if ($validData['direction'] == 'up') {
$data['rank'] = $nomination->data['rank'] - 1.5;
}
if ($validData['direction'] == 'down') {
$data['rank'] = $nomination->data['rank'] + 1.5;
}
$nomination->update(['data' => $data]);
$this->collapseNominations($nomination->student->school, $nomination->ensemble, 'next');
return redirect()->route('nomination.entry.index')->with('success', 'Nomination Moved');
}
}