Work on Schools

This commit is contained in:
Matt Young 2024-05-28 01:21:39 -05:00
parent 59d2e5a92c
commit d95185d6e8
16 changed files with 230 additions and 25 deletions

View File

@ -2,9 +2,93 @@
namespace App\Http\Controllers;
use App\Models\School;
use App\Models\SchoolEmailDomain;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use function dd;
use function redirect;
use function request;
class SchoolController extends Controller
{
//
public function store()
{
request()->validate([
'name' => ['required', 'min:3', 'max:30'],
'address' => ['required'],
'city' => ['required'],
'state' => ['required', 'min:2', 'max:2'],
'zip' => ['required', 'min:5', 'max:10'],
]);
$school = School::create([
'name' => request('name'),
'address' => request('address'),
'city' => request('city'),
'state' => request('state'),
'zip' => request('zip'),
]);
// TODO allow for an audition administrator that is not connected to school and needs to create a school without associating with it
if (! Auth::user()->school) {
Auth::user()->update([
'school_id' => $school->id
]);
SchoolEmailDomain::create([
'school_id' => $school->id,
'domain' => Auth::user()->emailDomain()
]);
}
return redirect('/schools/' . $school->id);
}
public function show(School $school)
{
return view('schools.show', ['school' => $school]);
}
public function create()
{
return view('schools.create');
}
public function edit(School $school)
{
// TODO Restrict the editing of schools to directors or admin
return view('schools.edit', ['school' => $school]);
}
public function update(School $school)
{
request()->validate([
'name' => ['required', 'min:3', 'max:30'],
'address' => ['required'],
'city' => ['required'],
'state' => ['required', 'min:2', 'max:2'],
'zip' => ['required', 'min:5', 'max:10'],
]);
$school->update([
'name' => request('name'),
'address' => request('address'),
'city' => request('city'),
'state' => request('state'),
'zip' => request('zip'),
]);
// TODO Handle redirect after updating school more elegantly
return redirect('/schools/' . $school->id);
}
public function my_school()
{
if (Auth::user()->school) {
return redirect('/schools/' . Auth::user()->school->id);
}
return redirect('/schools/create');
}
}

View File

@ -10,6 +10,8 @@ class School extends Model
{
use HasFactory;
protected $guarded = [];
public function directors(): HasMany
{
return $this->hasMany(User::class);

View File

@ -8,4 +8,6 @@ use Illuminate\Database\Eloquent\Model;
class SchoolEmailDomain extends Model
{
use HasFactory;
protected $guarded = [];
public $timestamps = false;
}

View File

@ -25,7 +25,8 @@ class User extends Authenticatable implements MustVerifyEmail
'cell_phone',
'email',
'password',
'profile_image_url'
'profile_image_url',
'school_id'
];
/**
@ -56,6 +57,12 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->first_name . ' ' . $this->last_name;
}
public function emailDomain(): string
{
$pos = strpos($this->email, '@');
return substr($this->email, $pos+1);
}
public function school(): BelongsTo
{
return $this->belongsTo(School::class);

View File

@ -16,6 +16,7 @@ return new class extends Migration
$table->id();
$table->foreignIdFor(School::class)->constrained()->onDelete('cascade')->onUpdate('cascade');
$table->string('domain');
$table->unique(['school_id','domain']);
});
}

View File

@ -20,6 +20,7 @@
@if($buttons)
{{ $buttons }}
@else
<!-- TODO make the cancel button do something -->
<x-auth.form-button-nocolor type="button">Cancel</x-auth.form-button-nocolor>
<x-auth.form-button>{{ $submitButtonText }}</x-auth.form-button>
@endif

View File

@ -0,0 +1,12 @@
@props(['heading' => false, 'subheading' => false])
<div class="overflow-hidden bg-white shadow sm:rounded-lg">
@if($heading)
@include('components.info-card.header', ['heading' => $heading, 'subheading' => $subheading])
@endif
<div class="border-t border-gray-100">
<dl class="divide-y divide-gray-100">
{{ $slot }}
</dl>
</div>
</div>

View File

@ -0,0 +1,6 @@
<div class="px-4 py-6 sm:px-6"> <!-- HEADING -->
<h3 class="text-base font-semibold leading-7 text-gray-900">{{ $heading }}</h3>
@if($subheading)
<p class="mt-1 max-w-2xl text-sm leading-6 text-gray-500">{{ $subheading }}</p>
@endif
</div>

View File

@ -0,0 +1,6 @@
@props(['row_name' => ''])
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-900">{{ $row_name }}</dt>
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{{ $slot }}</dd>
</div>

View File

@ -91,8 +91,8 @@
<!-- Active: "bg-gray-100", Not Active: "" -->
<a href="/profile" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1"
id="user-menu-item-0">Your Profile</a>
{{-- <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1"--}}
{{-- id="user-menu-item-1">Settings</a>--}}
<a href="/my_school" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1"
id="user-menu-item-1">Your School</a>
<form method="POST" action="/logout">
@csrf
<button

View File

@ -0,0 +1,12 @@
@php use Illuminate\Support\Facades\Auth; @endphp
@php $school = Auth::user()->school; @endphp
<x-layout.app>
<x-slot:page_title>My School</x-slot:page_title>
<div class="space-y-10 divide-y divide-gray-900/10">
@if($school)
<a href="/schools/{{ $school->id }}/edit">Edit my school</a>
@endif
</div>
</x-layout.app>

View File

@ -1,28 +1,10 @@
@php use Illuminate\Support\Facades\Auth; @endphp
<x-layout.app>
<x-slot:page_title>User Profile</x-slot:page_title>
<!--
This example requires some changes to your config:
```
// tailwind.config.js
module.exports = {
// ...
plugins: [
// ...
require('@tailwindcss/forms'),
],
}
```
-->
<div class="space-y-10 divide-y divide-gray-900/10">
<x-layout.page-section
section_name="Personal Information"
section_description="Use a permanent address where you receive mail"
:first="true"
>
@if (session('status') === 'profile-information-updated')
<div class="mt-4 px-8 font-medium text-sm text-green-600">
@ -67,8 +49,5 @@
</x-auth.form-card>
</x-layout.page-section>
</div>
</x-layout.app>

View File

@ -0,0 +1,23 @@
<x-layout.app>
<x-slot:page_title>Create School</x-slot:page_title>
<div class="space-y-10 divide-y divide-gray-900/10">
<x-layout.page-section
section_name="School Information"
section_description=""
:first="true">
<x-auth.form-card
submit-button-text="Create School"
method="POST"
action="/schools"
>
<x-auth.form-field name="name" label="School Name" div_classes="sm:col-span-6"/>
<x-auth.form-field name="address" label="School Address" div_classes="sm:col-span-6"/>
<x-auth.form-field name="city" label="City" div_classes="sm:col-span-3"/>
<x-auth.form-field name="state" label="State" div_classes="sm:col-span-2"/>
<x-auth.form-field name="zip" label="Zip" div_classes="sm:col-span-1"/>
</x-auth.form-card>
</x-layout.page-section>
</div>
</x-layout.app>

View File

@ -0,0 +1,23 @@
<x-layout.app>
<x-slot:page_title>Edit School - {{ $school->name }}</x-slot:page_title>
<div class="space-y-10 divide-y divide-gray-900/10">
<x-layout.page-section
section_name="School Information"
section_description=""
:first="true">
<x-auth.form-card
submit-button-text="Update School"
method="PATCH"
action="/schools/{{ $school->id }}"
>
<x-auth.form-field name="name" label="School Name" value="{{ $school->name }}" div_classes="sm:col-span-6"/>
<x-auth.form-field name="address" label="School Address" value="{{ $school->address }}" div_classes="sm:col-span-6"/>
<x-auth.form-field name="city" label="City" value="{{ $school->city }}" div_classes="sm:col-span-3"/>
<x-auth.form-field name="state" label="State" value="{{ $school->state }}" div_classes="sm:col-span-2"/>
<x-auth.form-field name="zip" label="Zip" value="{{ $school->zip }}" div_classes="sm:col-span-1"/>
</x-auth.form-card>
</x-layout.page-section>
</div>
</x-layout.app>

View File

@ -0,0 +1,37 @@
<x-layout.app>
<x-slot:page_title>School Info - {{ $school->name }}</x-slot:page_title>
<x-info-card.card>
<x-info-card.row row_name="School Address">
<div class="md:grid md:grid-cols-3">
<div class="md:col-span-2">
{{ $school->name }}<br />
{{ $school->address }}<br />
{{ $school->city }}, {{ $school->state }} {{ $school->zip }}
</div>
<div class="text-indigo-600">
<a href="/schools/{{$school->id}}/edit"> [ Edit School ] </a>
</div>
</div>
</x-info-card.row>
<x-info-card.row row_name="Directors">
<ul>
@foreach($school->directors as $director)
<li>{{ $director->full_name() }} - <a class='text-indigo-600' href="mailto:{{ $director->email }}">{{ $director->email }}</a></li>
@endforeach
</ul>
</x-info-card.row>
<x-info-card.row row_name="Associated Email Domains">
<ul>
@foreach($school->emailDomains as $domain)
<li>{{ $domain->domain }}</li>
@endforeach
</ul>
</x-info-card.row>
</x-info-card.card>
</x-layout.app>

View File

@ -1,5 +1,6 @@
<?php
use App\Http\Controllers\SchoolController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
@ -9,3 +10,12 @@ Route::get('/', function () {
Route::view('/test','test');
Route::view('/profile','profile')->middleware('auth','verified');
Route::view('/dashboard', 'dashboard')->middleware('auth', 'verified');
Route::get('/my_school', [SchoolController::class, 'my_school'])->middleware('auth','verified');
Route::get('/schools/create', [SchoolController::class, 'create'])->middleware('auth','verified');
Route::post('/schools', [SchoolController::class, 'store'])->middleware('auth','verified');
Route::get('/schools/{school}/edit', [SchoolController::class, 'edit'])->middleware('auth','verified');
Route::get('/schools/{school}', [SchoolController::class, 'show'])->middleware('auth','verified');
Route::patch('/schools/{school}', [SchoolController::class, 'update'])->middleware('auth','verified');