Entries listing page nearly complete
This commit is contained in:
parent
a452234c44
commit
7edf166985
|
|
@ -3,8 +3,14 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class EntryController extends Controller
|
class EntryController extends Controller
|
||||||
{
|
{
|
||||||
//
|
// TODO authorization policies
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$entries = Auth::user()->entries()->with(['student','audition'])->get();
|
||||||
|
return view('entries.index',['entries' => $entries]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class StudentController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$students = Auth::user()->students;
|
$students = Auth::user()->students()->with('entries')->get();
|
||||||
return view('students.index',['students' => $students]);
|
return view('students.index',['students' => $students]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
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\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||||
|
|
||||||
class School extends Model
|
class School extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -36,4 +37,10 @@ class School extends Model
|
||||||
{
|
{
|
||||||
return $this->hasMany(Student::class);
|
return $this->hasMany(Student::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function entries(): HasManyThrough
|
||||||
|
{
|
||||||
|
return $this->hasManyThrough(Entry::class,Student::class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
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;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,6 +23,11 @@ class Student extends Model
|
||||||
return $this->hasManyThrough(User::class, School::class);
|
return $this->hasManyThrough(User::class, School::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function entries(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(Entry::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function full_name(Bool $last_name_first = false): String
|
public function full_name(Bool $last_name_first = false): String
|
||||||
{
|
{
|
||||||
if ($last_name_first) return $this->last_name . ', ' . $this->first_name;
|
if ($last_name_first) return $this->last_name . ', ' . $this->first_name;
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,17 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||||
->orderBy('first_name');
|
->orderBy('first_name');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function entries(): HasManyThrough
|
||||||
|
{
|
||||||
|
return $this->hasManyThrough(
|
||||||
|
Entry::class,
|
||||||
|
Student::class,
|
||||||
|
'school_id',
|
||||||
|
'student_id',
|
||||||
|
'school_id',
|
||||||
|
'id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of schools using the users email domain
|
* Return an array of schools using the users email domain
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Policies;
|
||||||
use App\Models\Entry;
|
use App\Models\Entry;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Auth\Access\Response;
|
use Illuminate\Auth\Access\Response;
|
||||||
|
use function is_null;
|
||||||
|
|
||||||
class EntryPolicy
|
class EntryPolicy
|
||||||
{
|
{
|
||||||
|
|
@ -21,7 +22,8 @@ class EntryPolicy
|
||||||
*/
|
*/
|
||||||
public function view(User $user, Entry $entry): bool
|
public function view(User $user, Entry $entry): bool
|
||||||
{
|
{
|
||||||
//
|
if($user->is_admin) return true;
|
||||||
|
return $user->school_id == $entry->student()->school_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,7 +31,8 @@ class EntryPolicy
|
||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
//
|
if($user->is_admin) return true;
|
||||||
|
return ! is_null($user->school_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -37,7 +40,8 @@ class EntryPolicy
|
||||||
*/
|
*/
|
||||||
public function update(User $user, Entry $entry): bool
|
public function update(User $user, Entry $entry): bool
|
||||||
{
|
{
|
||||||
//
|
if($user->is_admin) return true;
|
||||||
|
return $user->school_id == $entry->student()->school_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -45,7 +49,8 @@ class EntryPolicy
|
||||||
*/
|
*/
|
||||||
public function delete(User $user, Entry $entry): bool
|
public function delete(User $user, Entry $entry): bool
|
||||||
{
|
{
|
||||||
//
|
if($user->is_admin) return true;
|
||||||
|
return $user->school_id == $entry->student()->school_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ class EntryFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
//
|
'student_id' => 3,
|
||||||
|
'audition_id' =>3
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ return new class extends Migration
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignIdFor(Student::class)->constrained()->restrictOnDelete()->cascadeOnUpdate();
|
$table->foreignIdFor(Student::class)->constrained()->restrictOnDelete()->cascadeOnUpdate();
|
||||||
$table->foreignIdFor(Audition::class)->constrained()->restrictOnDelete()->cascadeOnUpdate();
|
$table->foreignIdFor(Audition::class)->constrained()->restrictOnDelete()->cascadeOnUpdate();
|
||||||
|
$table->unique(['student_id','audition_id']);
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,13 @@
|
||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Student;
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
use function rand;
|
||||||
|
use function random_int;
|
||||||
|
|
||||||
class EntrySeeder extends Seeder
|
class EntrySeeder extends Seeder
|
||||||
{
|
{
|
||||||
|
|
@ -12,6 +17,47 @@ class EntrySeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
//
|
$students = Student::all();
|
||||||
|
$hs_auditions = Audition::where('maximum_grade', '=', '12');
|
||||||
|
$freshman_auditions = Audition::where('maximum_grade', '>', '8');
|
||||||
|
$jh_auditions = Audition::where('maximum_grade', '=', '9');
|
||||||
|
$seventh_auditions = Audition::where('maximum_grade', '=', '7');
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($students as $student) {
|
||||||
|
if($student->grade > 9) $audition = Audition::where('maximum_grade','=','12')->inRandomOrder()->first();
|
||||||
|
if($student->grade == 9) $audition = Audition::where('maximum_grade','>','8')->inRandomOrder()->first();
|
||||||
|
if($student->grade == 8) $audition = Audition::where('maximum_grade','=','9')->inRandomOrder()->first();
|
||||||
|
if($student->grade == 7) $audition = Audition::where('maximum_grade','=','7')->inRandomOrder()->first();
|
||||||
|
|
||||||
|
Entry::factory()->create([
|
||||||
|
'student_id' => $student->id,
|
||||||
|
'audition_id' => $audition->id
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (random_int(1,100) > 80) {
|
||||||
|
if($student->grade > 9) $audition2 = Audition::where('maximum_grade','=','12')->where('id','!=',$audition->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 9) $audition2 = Audition::where('maximum_grade','>','8')->where('id','!=',$audition->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 8) $audition2 = Audition::where('maximum_grade','=','9')->where('id','!=',$audition->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 7) $audition2 = Audition::where('maximum_grade','=','7')->where('id','!=',$audition->id)->inRandomOrder()->first();
|
||||||
|
|
||||||
|
Entry::factory()->create([
|
||||||
|
'student_id' => $student->id,
|
||||||
|
'audition_id' => $audition2->id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random_int(1,100) > 80) {
|
||||||
|
if($student->grade > 9) $audition3 = Audition::where('maximum_grade','=','12')->where('id','!=',$audition->id)->where('id','!=',$audition2->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 9) $audition3 = Audition::where('maximum_grade','>','8')->where('id','!=',$audition->id)->where('id','!=',$audition2->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 8) $audition3 = Audition::where('maximum_grade','=','9')->where('id','!=',$audition->id)->where('id','!=',$audition2->id)->inRandomOrder()->first();
|
||||||
|
if($student->grade == 7) $audition3 = Audition::where('maximum_grade','=','7')->where('id','!=',$audition->id)->where('id','!=',$audition2->id)->inRandomOrder()->first();
|
||||||
|
|
||||||
|
Entry::factory()->create([
|
||||||
|
'student_id' => $student->id,
|
||||||
|
'audition_id' => $audition3->id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
@php use Illuminate\Support\Facades\Auth; @endphp
|
||||||
|
@push('scripts')
|
||||||
|
{{-- Code from https://codepen.io/ryangjchandler/pen/WNQQKeR--}}
|
||||||
|
<script src="{{ asset('js/sort_table_by_column.js') }}"></script>
|
||||||
|
@endpush
|
||||||
|
<x-layout.app>
|
||||||
|
<x-slot:page_title>Entries</x-slot:page_title>
|
||||||
|
|
||||||
|
<x-layout.page-section-container>
|
||||||
|
<x-layout.page-section>
|
||||||
|
<x-slot:section_name>Add Entry</x-slot:section_name>
|
||||||
|
<x-form.form method="POST" action="/students">
|
||||||
|
<x-form.body-grid columns="8" class="max-w-full">
|
||||||
|
<x-form.field name="first_name" label_text="First Name" colspan="3" />
|
||||||
|
<x-form.field name="last_name" label_text="Last Name" colspan="3" />
|
||||||
|
<x-form.field name="grade" label_text="Grade" colspan="1" />
|
||||||
|
{{-- TODO make grade a dropdown --}}
|
||||||
|
<x-form.button class="mt-6">Save</x-form.button>
|
||||||
|
</x-form.body-grid>
|
||||||
|
</x-form.form>
|
||||||
|
</x-layout.page-section>
|
||||||
|
|
||||||
|
|
||||||
|
<x-layout.page-section>
|
||||||
|
<x-slot:section_name>Entry Listing</x-slot:section_name>
|
||||||
|
<div class="px-4">
|
||||||
|
<x-table.table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th first>Name</x-table.th>
|
||||||
|
<x-table.th>Grade</x-table.th>
|
||||||
|
<x-table.th>Audition</x-table.th>
|
||||||
|
<x-table.th spacer_only>
|
||||||
|
<span class="sr-only">Edit</span>
|
||||||
|
</x-table.th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<x-table.body>
|
||||||
|
@foreach($entries as $entry)
|
||||||
|
<tr>
|
||||||
|
<x-table.td first>{{ $entry->student->full_name(true) }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->student->grade }}</x-table.td>
|
||||||
|
<x-table.td>{{ $entry->audition->name }}</x-table.td>
|
||||||
|
{{-- <x-table.td for_button>--}}
|
||||||
|
{{-- <x-table.button href="/students/{{ $student->id }}/edit">Edit</x-table.button>--}}
|
||||||
|
{{-- |--}}
|
||||||
|
|
||||||
|
{{-- <form method="POST" action="/students/{{ $student->id }}" class="inline">--}}
|
||||||
|
{{-- @csrf--}}
|
||||||
|
{{-- @method('DELETE')--}}
|
||||||
|
{{-- <x-table.button--}}
|
||||||
|
{{-- onclick="return confirm('Please confirm you would like to delete the student {{ $student->full_name() }}');"--}}
|
||||||
|
{{-- >Delete</x-table.button>--}}
|
||||||
|
{{-- </form>--}}
|
||||||
|
|
||||||
|
{{-- </x-table.td>--}}
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
</x-table.table>
|
||||||
|
</div>
|
||||||
|
</x-layout.page-section>
|
||||||
|
</x-layout.page-section-container>
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<x-table.th first>Name</x-table.th>
|
<x-table.th first>Name</x-table.th>
|
||||||
<x-table.th>Grade</x-table.th>
|
<x-table.th>Grade</x-table.th>
|
||||||
|
<x-table.th>Entries</x-table.th>
|
||||||
<x-table.th spacer_only>
|
<x-table.th spacer_only>
|
||||||
<span class="sr-only">Edit</span>
|
<span class="sr-only">Edit</span>
|
||||||
</x-table.th>
|
</x-table.th>
|
||||||
|
|
@ -39,6 +40,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<x-table.td first>{{ $student->full_name(true) }}</x-table.td>
|
<x-table.td first>{{ $student->full_name(true) }}</x-table.td>
|
||||||
<x-table.td>{{ $student->grade }}</x-table.td>
|
<x-table.td>{{ $student->grade }}</x-table.td>
|
||||||
|
<x-table.td>{{ $student->entries->count() }}</x-table.td>
|
||||||
<x-table.td for_button>
|
<x-table.td for_button>
|
||||||
<x-table.button href="/students/{{ $student->id }}/edit">Edit</x-table.button>
|
<x-table.button href="/students/{{ $student->id }}/edit">Edit</x-table.button>
|
||||||
|
|
|
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,14 @@
|
||||||
@php use App\Models\School;use App\Models\SchoolEmailDomain;use App\Models\User;use Illuminate\Support\Facades\Auth; @endphp
|
@php 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
|
||||||
|
$entries = Auth::user()->entries()->with(['student','audition'])->get();
|
||||||
|
// dd($entries->first()->student->full_name())
|
||||||
|
@endphp
|
||||||
|
|
||||||
<x-card.card class="px-4 pt-6" mw="3xl">
|
@foreach ($entries as $e)
|
||||||
<x-table.table with_title_area with_button>
|
{{ $e->student->full_name() }} is entered on {{ $e->audition->name }}<br/>
|
||||||
<x-slot:title>Users</x-slot:title>
|
@endforeach
|
||||||
<x-slot:subtitle>A list of all the users in your account including their name, title, email and role.</x-slot:subtitle>
|
|
||||||
<x-slot:title_block_right><x-form.button>Add User</x-form.button></x-slot:title_block_right>
|
|
||||||
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<x-table.th first>Name</x-table.th>
|
|
||||||
<x-table.th>Title</x-table.th>
|
|
||||||
<x-table.th>Email</x-table.th>
|
|
||||||
<x-table.th>Role</x-table.th>
|
|
||||||
<x-table.th spacer_only>
|
|
||||||
<span class="sr-only">Edit</span>
|
|
||||||
</x-table.th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<x-table.body>
|
|
||||||
<tr>
|
|
||||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-0">Lindsay Walton</td>
|
|
||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">Front-end Developer</td>
|
|
||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">lindsay.walton@example.com</td>
|
|
||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">Member</td>
|
|
||||||
<td class="relative whitespace-nowrap py-4 px-3 text-right text-sm sm:pr-0">
|
|
||||||
<a href="#" class="text-indigo-600 hover:text-indigo-900 font-medium">Edit<span class="sr-only">, Lindsay Walton</span></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<x-table.td first emphasis>Lindsay Walton</x-table.td>
|
|
||||||
<x-table.td>Front-end Developer</x-table.td>
|
|
||||||
<x-table.td>lindsay.walton@example.com</x-table.td>
|
|
||||||
<x-table.td>Member</x-table.td>
|
|
||||||
<x-table.td for_button>
|
|
||||||
<x-table.button href="#" aria_data=", Lindsay Walton">Edit</x-table.button>
|
|
||||||
</x-table.td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- More people... -->
|
|
||||||
</x-table.body>
|
|
||||||
</x-table.table>
|
|
||||||
</x-card.card>
|
|
||||||
|
|
||||||
|
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\DashboardController;
|
use App\Http\Controllers\DashboardController;
|
||||||
|
use App\Http\Controllers\EntryController;
|
||||||
use App\Http\Controllers\SchoolController;
|
use App\Http\Controllers\SchoolController;
|
||||||
use App\Http\Controllers\StudentController;
|
use App\Http\Controllers\StudentController;
|
||||||
use App\Http\Controllers\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
|
|
@ -19,7 +20,15 @@ Route::middleware(['auth','verified'])->group(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Entry Related Routes
|
// Entry Related Routes
|
||||||
|
Route::middleware(['auth','verified'])->controller(EntryController::class)->group(function() {
|
||||||
|
Route::get('/entries','index');
|
||||||
|
Route::get('/entries/create','create');
|
||||||
|
Route::get('/entries/{entry}', 'show');
|
||||||
|
Route::post('/entries', 'store');
|
||||||
|
Route::get('/entries/{entry}/edit', 'edit');
|
||||||
|
Route::patch('/entries/{entry}', 'update');
|
||||||
|
Route::delete('/entries/{entry}', 'destroy');
|
||||||
|
});
|
||||||
|
|
||||||
// User Related Routes
|
// User Related Routes
|
||||||
Route::middleware(['auth','verified'])->controller(UserController::class)->group(function() {
|
Route::middleware(['auth','verified'])->controller(UserController::class)->group(function() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue