Work on Schools
This commit is contained in:
parent
59d2e5a92c
commit
d95185d6e8
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ class School extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function directors(): HasMany
|
||||
{
|
||||
return $this->hasMany(User::class);
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ use Illuminate\Database\Eloquent\Model;
|
|||
class SchoolEmailDomain extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
protected $guarded = [];
|
||||
public $timestamps = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue