diff --git a/app/Http/Controllers/NominationEnsembles/NominationEnsembleEntryController.php b/app/Http/Controllers/NominationEnsembles/NominationEnsembleEntryController.php
new file mode 100644
index 0000000..4e77875
--- /dev/null
+++ b/app/Http/Controllers/NominationEnsembles/NominationEnsembleEntryController.php
@@ -0,0 +1,22 @@
+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'));
+ }
+
+ public function show(NominationEnsembleEntry $ensemble)
+ {
+ // 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']);
+
+ 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']);
+ $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 $ensemble)
+ {
+ // TODO: Implement edit() method.
+ }
+
+ public function update(NominationEnsembleEntry $ensemble)
+ {
+ // TODO: Implement update() method.
+ }
+
+ public function destroy(NominationEnsembleEntry $ensemble)
+ {
+ // TODO: Implement destroy() method.
+ }
+
+ /**
+ * 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)
+ {
+ $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;
+ }
+}
diff --git a/app/Models/NominationEnsemble.php b/app/Models/NominationEnsemble.php
index a26a5de..fec8ef7 100644
--- a/app/Models/NominationEnsemble.php
+++ b/app/Models/NominationEnsemble.php
@@ -4,6 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\HasMany;
class NominationEnsemble extends Model
{
@@ -15,4 +16,9 @@ class NominationEnsemble extends Model
'data' => 'array',
];
}
+
+ public function entries(): HasMany
+ {
+ return $this->hasMany(NominationEnsembleEntry::class);
+ }
}
diff --git a/app/Models/NominationEnsembleEntry.php b/app/Models/NominationEnsembleEntry.php
index 1cbf2ce..f6ac68f 100644
--- a/app/Models/NominationEnsembleEntry.php
+++ b/app/Models/NominationEnsembleEntry.php
@@ -4,8 +4,28 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
class NominationEnsembleEntry extends Model
{
use HasFactory;
+
+ protected $guarded = [];
+
+ protected function casts(): array
+ {
+ return [
+ 'data' => 'array',
+ ];
+ }
+
+ protected function ensemble(): BelongsTo
+ {
+ return $this->belongsTo(NominationEnsemble::class);
+ }
+
+ protected function student(): BelongsTo
+ {
+ return $this->belongsTo(Student::class);
+ }
}
diff --git a/app/Models/School.php b/app/Models/School.php
index 93c886e..b359b63 100644
--- a/app/Models/School.php
+++ b/app/Models/School.php
@@ -51,4 +51,15 @@ class School extends Model
'id',
'id');
}
+
+ public function nominations(): HasManyThrough
+ {
+ return $this->hasManyThrough(
+ NominationEnsembleEntry::class,
+ Student::class,
+ 'school_id',
+ 'student_id',
+ 'id',
+ 'id');
+ }
}
diff --git a/app/Models/Student.php b/app/Models/Student.php
index d1e1777..925fc29 100644
--- a/app/Models/Student.php
+++ b/app/Models/Student.php
@@ -35,6 +35,11 @@ class Student extends Model
];
}
+ public function nominations(): HasMany
+ {
+ return $this->hasMany(NominationEnsembleEntry::class);
+ }
+
public function school(): BelongsTo
{
return $this->belongsTo(School::class);
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 0819dc3..4f88a11 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -11,7 +11,9 @@ use App\Actions\Tabulation\CalculateScoreSheetTotal;
use App\Actions\Tabulation\CalculateScoreSheetTotalDivideByTotalWeights;
use App\Actions\Tabulation\CalculateScoreSheetTotalDivideByWeightedPossible;
use App\Http\Controllers\NominationEnsembles\NominationEnsembleController;
+use App\Http\Controllers\NominationEnsembles\NominationEnsembleEntryController;
use App\Http\Controllers\NominationEnsembles\ScobdaNominationEnsembleController;
+use App\Http\Controllers\NominationEnsembles\ScobdaNominationEnsembleEntryController;
use App\Models\Audition;
use App\Models\Entry;
use App\Models\Room;
@@ -63,7 +65,10 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton(CreateEntry::class, CreateEntry::class);
$this->app->singleton(UpdateEntry::class, UpdateEntry::class);
$this->app->singleton(SetHeadDirector::class, SetHeadDirector::class);
+
+ // Nomination Ensemble
$this->app->bind(NominationEnsembleController::class, ScobdaNominationEnsembleController::class);
+ $this->app->bind(NominationEnsembleEntryController::class, ScobdaNominationEnsembleEntryController::class);
}
/**
diff --git a/database/factories/NominationEnsembleEntryFactory.php b/database/factories/NominationEnsembleEntryFactory.php
new file mode 100644
index 0000000..1f04ba9
--- /dev/null
+++ b/database/factories/NominationEnsembleEntryFactory.php
@@ -0,0 +1,23 @@
+ $this->faker->randomNumber(),
+ 'nomination_ensemble_id' => $this->faker->randomNumber(),
+ 'data' => $this->faker->words(),
+ 'created_at' => Carbon::now(),
+ 'updated_at' => Carbon::now(),
+ ];
+ }
+}
diff --git a/resources/views/components/layout/navbar/menus/my_audition.blade.php b/resources/views/components/layout/navbar/menus/my_audition.blade.php
index 00ea2ba..147b5d1 100644
--- a/resources/views/components/layout/navbar/menus/my_audition.blade.php
+++ b/resources/views/components/layout/navbar/menus/my_audition.blade.php
@@ -29,6 +29,9 @@
@if(Auth::user()->school_id)
My Students
My Entries
+ @if(auditionSetting('nomination_ensemble_rules') !== 'disabled')
+ My Nominations
+ @endif
My Doubler Requests
My School
@if(auditionSetting('invoicing_enabled'))
diff --git a/resources/views/nomination_ensembles/scobda/index.blade.php b/resources/views/nomination_ensembles/scobda/admin/ensembles/index.blade.php
similarity index 100%
rename from resources/views/nomination_ensembles/scobda/index.blade.php
rename to resources/views/nomination_ensembles/scobda/admin/ensembles/index.blade.php
diff --git a/resources/views/nomination_ensembles/scobda/entries/index.blade.php b/resources/views/nomination_ensembles/scobda/entries/index.blade.php
new file mode 100644
index 0000000..f8fb115
--- /dev/null
+++ b/resources/views/nomination_ensembles/scobda/entries/index.blade.php
@@ -0,0 +1,66 @@
+@php($n=1)
+
+ Nomination Entries
+
+
+
+ @foreach($ensembles as $ensemble)
+
+ {{ $ensemble->name }}
+ {{ $ensemble->data['max_nominations'] }} nominations accepted
+
+
+
+ Rank
+ Student
+ Instrument
+
+
+
+ @foreach($nominatedStudents[$ensemble->id] as $nomination)
+
+ {{ $nomination->data['rank'] }}
+ {{ $nomination->student->full_name() }}
+ {{ $nomination->data['instrument'] }}
+
+ @endforeach
+
+ {{-- LINE TO ADD A NOMINATION--}}
+ @if($nominationsAvailable[$ensemble->id] && $availableStudents[$ensemble->id]->count() > 0)
+
+
+
+ NEW
+
+
+ @foreach($availableStudents[$ensemble->id] as $student)
+
+ @endforeach
+
+
+
+
+
+ @foreach($availableInstruments[$ensemble->id] as $instrument)
+
+ @endforeach
+
+
+
+
+ Add
+
+
+
+ @endif
+
+
+
+
+ @endforeach
+
+
+
+
diff --git a/routes/nominationEnsemble.php b/routes/nominationEnsemble.php
index 055535e..3d23dae 100644
--- a/routes/nominationEnsemble.php
+++ b/routes/nominationEnsemble.php
@@ -1,6 +1,7 @@
prefix('nomination
});
Route::middleware(['auth', 'verified'])->prefix('nominations/')->group(function () {
-
+ Route::controller(NominationEnsembleEntryController::class)->group(function () {
+ Route::get('/', 'index')->name('nomination.entry.index');
+ Route::post('/', 'store')->name('nomination.entry.store');
+ });
});