Seating limits functioning

This commit is contained in:
Matt Young 2024-06-20 02:32:30 -05:00
parent 08ee83851d
commit be108c0827
8 changed files with 126 additions and 23 deletions

View File

@ -5,9 +5,11 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Ensemble; use App\Models\Ensemble;
use App\Models\Event; use App\Models\Event;
use App\Models\SeatingLimit;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use function redirect;
class EnsembleController extends Controller class EnsembleController extends Controller
{ {
@ -60,9 +62,33 @@ class EnsembleController extends Controller
public function seatingLimits(Ensemble $ensemble) public function seatingLimits(Ensemble $ensemble)
{ {
$ensembles = Ensemble::with('event')->orderBy('event_id')->get(); $ensembles = Ensemble::with('event')->orderBy('event_id')->get();
if ($ensemble->exists()) {
$ensemble->load('seatingLimits');
}
return view('admin.ensembles.seatingLimits',compact('ensemble','ensembles')); return view('admin.ensembles.seatingLimits',compact('ensemble','ensembles'));
} }
public function seatingLimitsSet(Request $request, Ensemble $ensemble)
{
$request->validate([
'audition' => 'required',
'audition.*' => ['integer','min:0']
]);
foreach($ensemble->auditions as $audition) {
SeatingLimit::upsert(
[[
'ensemble_id' => $ensemble->id,
'audition_id' => $audition->id,
'maximum_accepted' => $request->audition[$audition->id]
]],
uniqueBy: ['ensemble_id','audition_id'],
update: ['maximum_accepted']
);
}
return redirect()->route('admin.ensembles.seatingLimits')->with('success', 'Seating limits set for ' . $ensemble->name);
}
public function updateEnsembleRank(Request $request) public function updateEnsembleRank(Request $request)
{ {
if(! Auth::user()->is_admin) abort(403); if(! Auth::user()->is_admin) abort(403);

View File

@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\HasManyThrough;
class Ensemble extends Model class Ensemble extends Model
@ -30,4 +31,9 @@ class Ensemble extends Model
)->orderBy('score_order'); )->orderBy('score_order');
} }
public function seatingLimits(): HasMany
{
return $this->hasMany(SeatingLimit::class);
}
} }

View File

@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class SeatingLimit extends Model
{
use HasFactory;
protected $guarded = [];
protected $with = ['audition', 'ensemble'];
public function audition(): BelongsTo
{
return $this->belongsTo(Audition::class);
}
public function ensemble(): BelongsTo
{
return $this->belongsTo(Ensemble::class);
}
}

View File

@ -0,0 +1,33 @@
<?php
use App\Models\Audition;
use App\Models\Ensemble;
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::create('seating_limits', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Ensemble::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->foreignIdFor(Audition::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->integer('maximum_accepted');
$table->timestamps();
$table->unique(['ensemble_id', 'audition_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('seating_limits');
}
};

View File

@ -1,16 +1,41 @@
@php
$limits = [];
foreach ($ensemble->seatingLimits as $lim) {
$limits[$lim->audition_id] = $lim->maximum_accepted;
}
@endphp
<x-card.card class="mt-5 max-w-md mx-auto"> <x-card.card class="mt-5 max-w-md mx-auto">
<x-card.heading>{{ $ensemble->name }}</x-card.heading> <x-card.heading>{{ $ensemble->name }}</x-card.heading>
<form> <x-form.form method="POST" action="{{ route('admin.ensembles.seatingLimits.ensemble.set',['ensemble'=>$ensemble->id]) }}">
@foreach($ensemble->auditions as $audition) <ul role="list" class="divide-y divide-gray-100">
<x-form.field-horizontal name="x" label="{{ $audition->name }}" /> <li class="flex justify-between gap-x-3 py-3">
@endforeach <div class="block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5">Audition Name</div>
<div class="block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5 text-right">
Maximum Accepted
</div>
</li>
@foreach($ensemble->auditions as $audition)
<li class="flex justify-between gap-x-3 py-3">
<div class="block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5">
<label for="audition-{{ $audition->id }}">{{ $audition->name }}</label>
</div>
<div class=" text-right">
<input
id="audition-{{ $audition->id }}"
name="audition[{{ $audition->id }}]"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6"
type="number"
value="{{ $limits[$audition->id] ?? 0 }}">
</div>
</li>
@endforeach
<li>
<x-form.button class="mb-4 mt-2" type="submit">Submit Limits</x-form.button>
</li>
</ul>
<div class="mt-4 flex items-center justify-end gap-x-6 mr-6 mb-4"> </x-form.form>
<button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
<button type="submit" class="inline-flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Save</button>
</div>
</form>
</x-card.card> </x-card.card>

View File

@ -1,5 +1,6 @@
<x-layout.app> <x-layout.app>
<x-slot:page_title>Seating Limits</x-slot:page_title> <x-slot:page_title>Seating Limits</x-slot:page_title>
<x-card.card class="mx-auto max-w-md"> <x-card.card class="mx-auto max-w-md">
<x-card.heading>Choose Ensemble</x-card.heading> <x-card.heading>Choose Ensemble</x-card.heading>
<div class="p-3"> <div class="p-3">

View File

@ -1,14 +0,0 @@
@props(['name','label','type' => 'text'])
<div class="space-y-12 sm:space-y-16 ml-6 mr-6">
<div class="mt-3 space-y-8 border-b border-gray-900/10 pb-12 sm:space-y-0 sm:divide-y sm:divide-gray-900/10 sm:border-t sm:pb-0">
<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6 mb-3">
<label for="{{ $name }}" class="block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5">{{ $label }}</label>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<input type="{{ $type }}"
name="{{ $name }}"
id="{{ $name }}"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6">
</div>
</div>
</div>
</div>

View File

@ -67,6 +67,7 @@ Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->gr
Route::patch('/{ensemble}','updateEnsemble')->name('admin.ensembles.updateEnsemble'); Route::patch('/{ensemble}','updateEnsemble')->name('admin.ensembles.updateEnsemble');
Route::get('/seating-limits','seatingLimits')->name('admin.ensembles.seatingLimits'); Route::get('/seating-limits','seatingLimits')->name('admin.ensembles.seatingLimits');
Route::get('/seating-limits/{ensemble}','seatingLimits')->name('admin.ensembles.seatingLimits.ensemble'); Route::get('/seating-limits/{ensemble}','seatingLimits')->name('admin.ensembles.seatingLimits.ensemble');
Route::post('/seating-limits/{ensemble}','seatingLimitsSet')->name('admin.ensembles.seatingLimits.ensemble.set');
}); });
// Admin Event Routes // Admin Event Routes