Adding entry complete

This commit is contained in:
Matt Young 2024-05-31 10:58:02 -05:00
parent 7edf166985
commit 9f57c930fc
8 changed files with 133 additions and 35 deletions

View File

@ -2,6 +2,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Audition;
use App\Models\Entry;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@ -11,6 +13,25 @@ class EntryController extends Controller
public function index() public function index()
{ {
$entries = Auth::user()->entries()->with(['student','audition'])->get(); $entries = Auth::user()->entries()->with(['student','audition'])->get();
return view('entries.index',['entries' => $entries]); $auditions = Audition::all();
$students = Auth::user()->students;
return view('entries.index',['entries' => $entries, 'students' => $students, 'auditions' => $auditions]);
}
public function store(Request $request)
{
// TODO write custom rule to verify the combination of student and audition is unique
$request->validate([
'student_id' => ['required', 'exists:students,id'],
'audition_id' => ['required', 'exists:auditions,id']
]);
$entry = Entry::create([
'student_id' => request('student_id'),
'audition_id' => request('audition_id')
]);
return redirect('/entries');
} }
} }

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Audition;
use App\Models\School; use App\Models\School;
use App\Models\Student; use App\Models\Student;
use App\Models\User; use App\Models\User;
@ -20,7 +21,8 @@ class StudentController extends Controller
public function index() public function index()
{ {
$students = Auth::user()->students()->with('entries')->get(); $students = Auth::user()->students()->with('entries')->get();
return view('students.index',['students' => $students]); $auditions = Audition::all();
return view('students.index',['students' => $students, 'auditions' => $auditions]);
} }
/** /**

View File

@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Entry extends Model class Entry extends Model
{ {
use HasFactory; use HasFactory;
protected $guarded = [];
public function student(): BelongsTo public function student(): BelongsTo
{ {

View File

@ -2,6 +2,7 @@
namespace App\Policies; namespace App\Policies;
use App\Models\Entry;
use App\Models\Student; use App\Models\Student;
use App\Models\User; use App\Models\User;
use Illuminate\Auth\Access\Response; use Illuminate\Auth\Access\Response;
@ -9,15 +10,6 @@ use function is_null;
class StudentPolicy class StudentPolicy
{ {
// TODO Blanket admin policy is not appropriate for students as it may break things in the audition process
/**
* Grant admin users access to all functions
*/
public function before(User $user, string $ability): bool|null
{
if($user->is_admin) return true;
return null;
}
/** /**
* Determine whether the user can view any models. * Determine whether the user can view any models.
*/ */
@ -39,6 +31,7 @@ class StudentPolicy
*/ */
public function create(User $user): bool public function create(User $user): bool
{ {
if($user->is_admin) return true;
return ! is_null($user->school_id); return ! is_null($user->school_id);
} }
@ -47,6 +40,8 @@ class StudentPolicy
*/ */
public function update(User $user, Student $student): bool public function update(User $user, Student $student): bool
{ {
if (Entry::where('student_id','=',$student->id)->exists()) return false; // Don't allow deletion of a student with entries
if($user->is_admin) return true;
return $user->school_id == $student->school_id; return $user->school_id == $student->school_id;
} }

View File

@ -0,0 +1,37 @@
@props([
'label' => false,
'name',
'colspan' => '1'
])
@php
$colspan_classes = [
'1' => '',
'2' => 'sm:col-span-2',
'3' => 'sm:col-span-3',
'4' => 'sm:col-span-4',
'5' => 'sm:col-span-5',
'6' => 'sm:col-span-6',
'7' => 'sm:col-span-7',
'8' => 'sm:col-span-8',
'9' => 'sm:col-span-9',
'10' => 'sm:col-span-10',
'11' => 'sm:col-span-11',
'12' => 'sm:col-span-12'
];
$label_attribs = [
'class' => 'block text-sm font-medium leading-6 text-gray-900',
'for' => $name
];
$select_attribs = [
'class' => 'mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6',
'id' => $name,
'name' => $name
]
@endphp
<div @if($colspan > 1) class="{{ $colspan_classes["$colspan"] }}" @endif>
@if($label)<label {{ $label->attributes->merge($label_attribs) }}>{{ $label }}</label>@endif
<select {{ $attributes->merge($select_attribs) }}>
{{ $slot }}
</select>
</div>

View File

@ -9,13 +9,27 @@
<x-layout.page-section-container> <x-layout.page-section-container>
<x-layout.page-section> <x-layout.page-section>
<x-slot:section_name>Add Entry</x-slot:section_name> <x-slot:section_name>Add Entry</x-slot:section_name>
<x-form.form method="POST" action="/students"> <x-form.form method="POST" action="/entries">
<x-form.body-grid columns="8" class="max-w-full">
<x-form.field name="first_name" label_text="First Name" colspan="3" /> <x-form.body-grid columns="7" class="max-w-full" x-data="studentAuditionFilter()">
<x-form.field name="last_name" label_text="Last Name" colspan="3" />
<x-form.field name="grade" label_text="Grade" colspan="1" /> <x-form.select name="student_id" colspan="3" x-model="selectedStudentId" @change="filterAuditions">
{{-- TODO make grade a dropdown --}} <x-slot:label>Student</x-slot:label>
<x-form.button class="mt-6">Save</x-form.button> <option value="" disabled selected>Select a student</option>
<template x-for="student in students" :key="student.id">
<option :value="student.id" x-text="student.name"></option>
</template>
</x-form.select>
<x-form.select name="audition_id" colspan="3">
<x-slot:label>Audition</x-slot:label>
<option value="" disabled selected>Select an audition</option>
<template x-for="audition in filteredAuditions" :key="audition.id">
<option :value="audition.id" x-text="audition.name"></option>
</template>
</x-form.select>
<x-form.button class="mt-8">Save</x-form.button>
</x-form.body-grid> </x-form.body-grid>
</x-form.form> </x-form.form>
</x-layout.page-section> </x-layout.page-section>
@ -61,4 +75,5 @@
</div> </div>
</x-layout.page-section> </x-layout.page-section>
</x-layout.page-section-container> </x-layout.page-section-container>
@include('students.student_audition_select_script')
</x-layout.app> </x-layout.app>

View File

@ -0,0 +1,30 @@
<script>
function studentAuditionFilter() {
return {
selectedStudentId: '',
students: [
@foreach($students as $student)
{ id: {{ $student->id }}, name: '{{ $student->full_name() }}', grade: {{ $student->grade }} },
@endforeach
],
auditions: [
@foreach($auditions as $audition)
{ id: {{ $audition->id }}, name: '{{ $audition->name }}', minGrade: {{ $audition->minimum_grade }}, maxGrade: {{ $audition->maximum_grade }} },
@endforeach
],
filteredAuditions: [],
filterAuditions() {
const selectedStudent = this.students.find(student => student.id == this.selectedStudentId);
if (selectedStudent) {
const grade = selectedStudent.grade;
this.filteredAuditions = this.auditions.filter(audition => {
return grade >= audition.minGrade && grade <= audition.maxGrade;
});
} else {
this.filteredAuditions = [];
}
}
}
}
</script>

View File

@ -1,14 +1,11 @@
@php use App\Models\School;use App\Models\SchoolEmailDomain;use App\Models\User;use Illuminate\Support\Facades\Auth; @endphp @php use App\Models\Audition;use App\Models\School;use App\Models\SchoolEmailDomain;use App\Models\User;use Illuminate\Support\Facades\Auth; @endphp
<x-layout.app> <x-layout.app>
<x-slot:page_title>Test Page</x-slot:page_title> <x-slot:page_title>Test Page</x-slot:page_title>
@php @php
$entries = Auth::user()->entries()->with(['student','audition'])->get();
// dd($entries->first()->student->full_name())
@endphp @endphp
@foreach ($entries as $e)
{{ $e->student->full_name() }} is entered on {{ $e->audition->name }}<br/>
@endforeach
</x-layout.app> </x-layout.app>