Admin users and schoosl working. In progress on students

This commit is contained in:
Matt Young 2024-06-02 19:42:50 -05:00
parent 695a0130c0
commit 93752b5621
23 changed files with 690 additions and 14 deletions

View File

@ -0,0 +1,52 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\School;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use function abort;
use function redirect;
use function request;
class SchoolController extends Controller
{
public function index()
{
if (! Auth::user()->is_admin) abort(403);
$schools = School::orderBy('name')->get();
return view('admin.schools.index', ['schools' => $schools]);
}
public function edit(School $school)
{
if (! Auth::user()->is_admin) abort(403);
return view('admin.schools.edit', ['school' => $school]);
}
public function update(School $school)
{
if (! Auth::user()->is_admin) abort(403);
request()->validate([
'name' => ['required'],
'address' => ['required'],
'city' => ['required'],
'state' => ['required'],
'zip' => ['required'],
]);
$school->update([
'name' => request('name'),
'address' => request('address'),
'city' => request('city'),
'state' => request('state'),
'zip' => request('zip'),
]);
return redirect('/admin/schools');
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Student;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use function abort;
use function view;
class StudentController extends Controller
{
public function index()
{
if (! Auth::user()->is_admin) abort(403);
$students = Student::orderBy('last_name')->orderBy('first_name')->SimplePaginate(10);
return view('admin.students.index', ['students' => $students]);
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Mail\NewUserPassword;
use App\Models\School;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
class UserController extends Controller
{
public function index()
{
if (! Auth::user()->is_admin) abort(403);
$users = User::orderBy('last_name')->orderBy('first_name')->get();
return view('admin.users.index', ['users' => $users]);
}
public function edit(User $user)
{
if (! Auth::user()->is_admin) abort(403);
$schools = School::orderBy('name')->get();
return view('admin.users.edit', ['user' => $user,'schools' => $schools]);
}
public function create()
{
if (! Auth::user()->is_admin) abort(403);
$schools = School::orderBy('name')->get();
return view('admin.users.create', ['schools' => $schools]);
}
public function update(Request $request, User $user)
{
if (! Auth::user()->is_admin) abort(403);
request()->validate([
'first_name' => ['required'],
'last_name' => ['required'],
'email' => ['required', 'email'],
'cell_phone' => ['required'],
'judging_preference' => ['required'],
'school_id' => ['required','exists:schools,id'],
]);
$user->update([
'first_name' => request('first_name'),
'last_name' => request('last_name'),
'email' => request('email'),
'cell_phone' => request('cell_phone'),
'judging_preference' => request('judging_preference'),
'school_id' => request('school_id')
]);
return redirect('/admin/users');
}
public function store(Request $request)
{
$request->validate([
'first_name' => ['required'],
'last_name' => ['required'],
'email' => ['required', 'email','unique:users'],
]);
// Genearte a random password
$randomPassword = Str::random(12);
$user = \App\Models\User::make([
'first_name' => request('first_name'),
'last_name' => request('last_name'),
'email' => request('email'),
'cell_phone' => request('cell_phone'),
'judging_preference' => request('judging_preference'),
'password' => Hash::make($randomPassword),
]);
if (!is_null(request('school_id'))) {
$request->validate([
'school_id' => ['exists:schools,id']
]);
}
$user->school_id = request('school_id');
$user->save();
Mail::to($user->email)->send(new NewUserPassword($user, $randomPassword));
return redirect('/admin/users');
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class CheckIfAdmin
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if (Auth::check() && Auth::user()->is_admin) {
return $next($request);
}
return redirect('/')->with('error', 'You do not have admin access.');
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class NewUserPassword extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $password;
/**
* Create a new message instance.
*/
public function __construct($user, $password)
{
$this->user = $user;
$this->password = $password;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'New User Password',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'emails.new_user_password',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
public function build()
{
return $this->subject('Your New Account Password')
->view('emails.new_user_password')
->with([
'user' => $this->user,
'password' => $this->password,
]);
}
}

View File

@ -59,6 +59,11 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->first_name . ' ' . $this->last_name; return $this->first_name . ' ' . $this->last_name;
} }
public function has_school(): bool
{
return $this->school_id !== null;
}
public function emailDomain(): string public function emailDomain(): string
{ {
$pos = strpos($this->email, '@'); $pos = strpos($this->email, '@');

View File

@ -18,7 +18,7 @@ class SchoolFactory extends Factory
{ {
return [ return [
'name' => fake()->city(), 'name' => fake()->city(),
'address' => fake()->address(), 'address' => fake()->streetAddress(),
'city' => fake()->city(), 'city' => fake()->city(),
'state' => 'OK', 'state' => 'OK',
'zip' => rand(73001, 74999), 'zip' => rand(73001, 74999),

View File

@ -0,0 +1,3 @@
<x-layout.app>
You are on the admin dashboard
</x-layout.app>

View File

@ -0,0 +1,19 @@
<x-layout.app>
<x-card.card class="mx-auto max-w-xl">
<x-card.heading>Edit School</x-card.heading>
<x-form.form method="PATCH" action="/admin/schools/{{ $school->id }}">
<x-form.body-grid>
<x-form.field name="name" label_text="Name" colspan="6" value="{{ $school->name }}" />
<x-form.field name="address" label_text="Address" colspan="6" value="{{ $school->address }}" />
<x-form.field name="city" label_text="City" colspan="3" value="{{ $school->city }}" />
<x-form.field name="state" label_text="State" colspan="2" value="{{ $school->state }}" />
<x-form.field name="zip" label_text="Zip" colspan="1" value="{{ $school->zip }}" />
</x-form.body-grid>
<x-form.footer>
<x-form.button>Update User</x-form.button>
</x-form.footer>
</x-form.form>
</x-card.card>
</x-layout.app>
{{--TODO Show directors on school page--}}

View File

@ -0,0 +1,36 @@
<x-layout.app>
<x-slot:page_title>School Administration</x-slot:page_title>
<x-card.card>
<x-table.table with_title_area>
<x-slot:title class="ml-3">Schools</x-slot:title>
<x-slot:subtitle class="ml-3">Click school name to edit</x-slot:subtitle>
<x-slot:title_block_right class="mr-3">
<x-form.button href="/admin/schools/create">New School</x-form.button>
</x-slot:title_block_right>
<thead>
<tr>
<x-table.th>Name</x-table.th>
<x-table.th>Directors</x-table.th>
<x-table.th>Students</x-table.th>
<x-table.th>Entries</x-table.th>
</tr>
</thead>
<x-table.body>
@foreach($schools as $school)
<tr>
<x-table.td><a href="/admin/schools/{{ $school->id }}/edit">{{ $school->name }}</a></x-table.td>
<x-table.td>{{ $school->users->count() }}</x-table.td>
<x-table.td>{{ $school->students->count() }}</x-table.td>
<x-table.td>{{ $school->entries->count() }}</x-table.td>
</tr>
@endforeach
</x-table.body>
</x-table.table>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,33 @@
<x-layout.app>
<x-slot:page_title>Student Administration</x-slot:page_title>
<x-card.card>
<x-table.table with_title_area>
<x-slot:title class="ml-3">Students</x-slot:title>
<x-slot:subtitle class="ml-3">Click name to edit</x-slot:subtitle>
<x-slot:title_block_right class="mr-3">
<x-form.button href="/admin/students/create">New Student</x-form.button>
</x-slot:title_block_right>
<thead>
<tr>
<x-table.th>Name</x-table.th>
<x-table.th>School</x-table.th>
<x-table.th>Grade</x-table.th>
<x-table.th>Entries</x-table.th>
</tr>
</thead>
<x-table.body>
@foreach($students as $student)
<tr>
<x-table.td><a href="/admin/students/{{ $student->id }}/edit">{{ $student->full_name(true) }}</a></x-table.td>
<x-table.td>{{ $student->school->name }}</x-table.td>
<x-table.td>{{ $student->grade }}</x-table.td>
<x-table.td>{{ $student->entries->count() }}</x-table.td>
</tr>
@endforeach
</x-table.body>
</x-table.table>
<div>{{ $students->links() }}</div>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,26 @@
<x-layout.app>
<x-card.card class="mx-auto max-w-lg">
<x-card.heading>Edit User</x-card.heading>
<x-form.form method="POST" action="/admin/users">
<x-form.body-grid>
<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="email" label_text="Email Address" colspan="3" />
<x-form.field name="cell_phone" label_text="Cell Phone" colspan="3" />
<x-form.field name="judging_preference" label_text="Judging Preference" colspan="6" />
<x-form.select name="school_id" colspan="6">
<x-slot:label>School</x-slot:label>
<option value="">No School</option>
@foreach ($schools as $school)
<option value="{{ $school->id }}"> {{ $school->name }}</option>
@endforeach
</x-form.select>
</x-form.body-grid>
<x-form.footer>
<x-form.button>Update User</x-form.button>
</x-form.footer>
</x-form.form>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,24 @@
<x-layout.app>
<x-card.card class="mx-auto max-w-lg">
<x-card.heading>Edit User</x-card.heading>
<x-form.form method="PATCH" action="/admin/users/{{ $user->id }}">
<x-form.body-grid>
<x-form.field name="first_name" label_text="First Name" colspan="3" value="{{ $user->first_name }}" />
<x-form.field name="last_name" label_text="Last Name" colspan="3" value="{{ $user->last_name }}" />
<x-form.field name="email" label_text="Email Address" colspan="3" value="{{ $user->email }}" />
<x-form.field name="cell_phone" label_text="Cell Phone" colspan="3" value="{{ $user->cell_phone }}" />
<x-form.field name="judging_preference" label_text="Judging Preference" colspan="6" value="{{ $user->judging_preference }}" />
<x-form.select name="school_id" colspan="6">
<x-slot:label>School</x-slot:label>
@foreach ($schools as $school)
<option value="{{ $school->id }}" @if ($user->school_id == $school->id) selected @endif>{{ $school->name }}</option>
@endforeach
</x-form.select>
</x-form.body-grid>
<x-form.footer>
<x-form.button>Update User</x-form.button>
</x-form.footer>
</x-form.form>
</x-card.card>
</x-layout.app>

View File

@ -0,0 +1,38 @@
<x-layout.app>
<x-slot:page_title>User Administration</x-slot:page_title>
<x-card.card>
<x-table.table with_title_area>
<x-slot:title class="ml-3">Users</x-slot:title>
<x-slot:subtitle class="ml-3">Click name to edit</x-slot:subtitle>
<x-slot:title_block_right class="mr-3">
<x-form.button href="/admin/users/create">New User</x-form.button>
</x-slot:title_block_right>
<thead>
<tr>
<x-table.th>Name</x-table.th>
<x-table.th>School</x-table.th>
<x-table.th>Email</x-table.th>
<x-table.th>Cell Phone</x-table.th>
<x-table.th>Judging Preference</x-table.th>
</tr>
</thead>
<x-table.body>
@foreach($users as $user)
<tr>
<x-table.td><a href="/admin/users/{{ $user->id }}/edit">{{ $user->full_name(true) }}</a></x-table.td>
<x-table.td>{{ $user->has_school() ? $user->school->name : ' ' }}</x-table.td> {{-- TODO link to the school --}}
<x-table.td>{{ $user->email }}</x-table.td>
<x-table.td>{{ $user->cell_phone }}</x-table.td>
<x-table.td>{{ $user->judging_preference }}</x-table.td>
</tr>
@endforeach
</x-table.body>
</x-table.table>
</x-card.card>
</x-layout.app>
{{ $user->has_school() ? $user->school->name : 'No School' }}

View File

@ -19,8 +19,11 @@
<div class="min-h-full"> <div class="min-h-full">
<x-layout.navbar /> @if(request()->is('*admin*'))
<x-layout.navbar-admin />
@else
<x-layout.navbar />
@endif
@if($page_title) @if($page_title)
<x-layout.page-header>{{ $page_title }}</x-layout.page-header> <x-layout.page-header>{{ $page_title }}</x-layout.page-header>
@endif @endif

View File

@ -1,6 +1,7 @@
@props(['active' => false]) @props(['active' => false])
@php($classes = $active ? 'bg-indigo-700' : 'hover:bg-indigo-500 hover:bg-opacity-75')
<a class="{{ $active ? 'bg-indigo-700' : 'hover:bg-indigo-500 hover:bg-opacity-75' }} text-white rounded-md px-3 py-2 text-sm font-medium" @php($classes .= ' text-white rounded-md px-3 py-2 text-sm font-medium')
<a {{ $attributes->merge(['class' => $classes]) }}
aria-current="{{ $active ? 'page':'false' }}" aria-current="{{ $active ? 'page':'false' }}"
{{ $attributes }} {{ $attributes }}
>{{ $slot }}</a> >{{ $slot }}</a>

View File

@ -0,0 +1,183 @@
@php use Illuminate\Support\Facades\Auth; @endphp
{{--TODO Clean up mobile menu area--}}
<nav class="bg-indigo-600"
x-data="{
mobile_menu_open: false
}"
x-id="['mobile-dropdown']"
>
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-16 items-center justify-between">
<div class="flex items-center">
<div class="flex-shrink-0">
<img class="h-8 w-8" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=300" alt="Your Company">
</div>
<div class="hidden md:block">
<div class="ml-10 flex items-baseline space-x-4">
<!-- Current: "bg-indigo-700 text-white",
Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" -->
<x-layout.nav-link href="/dashboard" class="!bg-indigo-900">Exit Admin</x-layout.nav-link>
<x-layout.nav-link href="/admin" :active="request()->is('admin')">Dashboard</x-layout.nav-link>
<x-layout.nav-link href="/admin/users" :active="request()->is('admin/users')">Users</x-layout.nav-link>
<x-layout.nav-link href="/admin/schools" :active="request()->is('admin/schools')">Schools</x-layout.nav-link>
<x-layout.nav-link href="/admin/students" :active="request()->is('admin/students')">Students</x-layout.nav-link>
{{-- <a href="/dashboard" class="bg-indigo-700 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a>--}}
{{-- <a href="/students" class="text-white hover:bg-indigo-500 hover:bg-opacity-75 rounded-md px-3 py-2 text-sm font-medium">Students</a>--}}
</div>
</div>
</div>
<div class="hidden md:block">
<div class="ml-4 flex items-center md:ml-6">
<button type="button" class="relative rounded-full bg-indigo-600 p-1 text-indigo-200 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600">
<span class="absolute -inset-1.5"></span>
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
</svg>
</button>
<!-- Profile dropdown -->
<div
x-data="{
open: false,
toggle() {
this.open = this.open ? this.close() : true
},
close() {
this.open = false
}
}"
x-id="['profile-dropdown']"
class="relative ml-3"
>
<div>
<button type="button"
@click="toggle()"
class="relative flex max-w-xs items-center rounded-full bg-indigo-600 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600"
id="user-menu-button"
:aria-expanded="open"
:aria-controls="$id('profile-dropdown')"
aria-haspopup="true">
<span class="absolute -inset-1.5"></span>
<span class="sr-only">Open user menu</span>
<img class="h-8 w-8 rounded-full" src="{{ Auth::user()->profile_image_url }}" alt="">
{{-- <p class="text-white">{{ Auth::user()->full_name() }} &nbsp; &#9660;</p>--}}
</button>
</div>
<!--
Dropdown menu, show/hide based on menu state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<div
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
@click.outside="close()"
:id="$id('profile-dropdown')"
style="display: none;"
class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
role="menu"
aria-orientation="vertical"
aria-labelledby="user-menu-button"
tabindex="-1">
<!-- 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="/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
class="block px-4 py-2 text-sm text-gray-700"
role="menuitem"
tabindex="-1"
id="user-menu-item-2">
Sign out
</button>
</form>
</div>
</div>
</div>
</div>
<div class="-mr-2 flex md:hidden">
<!-- Mobile menu button -->
<button type="button"
@click="mobile_menu_open = ! mobile_menu_open"
class="relative inline-flex items-center justify-center rounded-md bg-indigo-600 p-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600"
:aria-controls="$id('mobile-dropdown')"
:aria-expanded="mobile_menu_open">
<span class="absolute -inset-0.5"></span>
<span class="sr-only">Open main menu</span>
<!-- Menu open: "hidden", Menu closed: "block" -->
<svg class=" h-6 w-6" :class="mobile_menu_open ? 'hidden' : 'block'" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/>
</svg>
<!-- Menu open: "block", Menu closed: "hidden" -->
<svg class=" h-6 w-6" :class="mobile_menu_open ? 'block' : 'hidden'" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
</div>
</div>
<!-- Mobile menu, show/hide based on menu state. -->
<div class="md:hidden" id="mobile-menu" x-show="mobile_menu_open">
<div class="space-y-1 px-2 pb-3 pt-2 sm:px-3">
<!-- Current: "bg-indigo-700 text-white", Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" -->
<a href="/dashboard" class="bg-indigo-700 text-white block rounded-md px-3 py-2 text-base font-medium" aria-current="page">Dashboard</a>
<a href="/students" class="text-white hover:bg-indigo-500 hover:bg-opacity-75 block rounded-md px-3 py-2 text-base font-medium">Students</a>
</div>
<div class="border-t border-indigo-700 pb-3 pt-4">
<div class="flex items-center px-5">
<div class="flex-shrink-0">
<img class="h-10 w-10 rounded-full" src="{{ Auth::user()->profile_image_url }}" alt="">
</div>
<div class="ml-3">
<div class="text-base font-medium text-white">{{ Auth::user()->full_name() }}</div>
<div class="text-sm font-medium text-indigo-300">{{ Auth::user()->email }}</div>
</div>
<button type="button" class="relative ml-auto flex-shrink-0 rounded-full bg-indigo-600 p-1 text-indigo-200 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600">
<span class="absolute -inset-1.5"></span>
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
</svg>
</button>
</div>
<div class="mt-3 space-y-1 px-2">
<a href="/profile" class="block rounded-md px-3 py-2 text-base font-medium text-white hover:bg-indigo-500 hover:bg-opacity-75">Your Profile</a>
<a href="/my_school" class="block rounded-md px-3 py-2 text-base font-medium text-white hover:bg-indigo-500 hover:bg-opacity-75">Your School</a>
<form method="POST" action="/logout">
@csrf
<button
class="block rounded-md px-3 py-2 text-base font-medium text-white hover:bg-indigo-500 hover:bg-opacity-75"
role="menuitem"
tabindex="-1"
id="user-menu-item-2">
Sign out
</button>
</form>
</div>
</div>
</div>
</nav>

View File

@ -16,6 +16,7 @@
<div class="ml-10 flex items-baseline space-x-4"> <div class="ml-10 flex items-baseline space-x-4">
<!-- Current: "bg-indigo-700 text-white", <!-- Current: "bg-indigo-700 text-white",
Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" --> Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" -->
<x-layout.nav-link href="/admin" class="!bg-indigo-900">Admin</x-layout.nav-link>
<x-layout.nav-link href="/dashboard" :active="request()->is('dashboard')">Dashboard</x-layout.nav-link> <x-layout.nav-link href="/dashboard" :active="request()->is('dashboard')">Dashboard</x-layout.nav-link>
<x-layout.nav-link href="/students" :active="request()->is('students')">Students</x-layout.nav-link> <x-layout.nav-link href="/students" :active="request()->is('students')">Students</x-layout.nav-link>
<x-layout.nav-link href="/entries" :active="request()->is('entries')">Entries</x-layout.nav-link> <x-layout.nav-link href="/entries" :active="request()->is('entries')">Entries</x-layout.nav-link>

View File

@ -7,14 +7,14 @@
]) ])
<div> <div>
@if($with_title_area) @if($with_title_area)
<div class="mb-8 sm:flex sm:items-center"> <div class="mb-4 mt-4 sm:flex sm:items-center">
<div class="sm:flex-auto"> <div class="sm:flex-auto sm:items-center">
@if($title)<h1 {{ $title->attributes->merge(['class' => 'text-base font-semibold leading-6 text-gray-900']) }}>{{ $title }}</h1>@endif @if($title)<h1 {{ $title->attributes->merge(['class' => 'text-base font-semibold leading-6 text-gray-900']) }}>{{ $title }}</h1>@endif
@if($subtitle)<p {{ $subtitle->attributes->merge(['class' => 'mt-2 text-sm text-gray-700']) }}>{{ $subtitle }}</p>@endif @if($subtitle)<p {{ $subtitle->attributes->merge(['class' => 'mt-2 text-sm text-gray-700']) }}>{{ $subtitle }}</p>@endif
</div> </div>
{{-- Title block right often used for add button--}} {{-- Title block right often used for add button--}}
@if($title_block_right) @if($title_block_right)
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none"> <div {{ $title_block_right->attributes->merge(['class' => 'mt-4 sm:ml-16 sm:mt-0 sm:flex-none']) }}>
{{ $title_block_right }} {{ $title_block_right }}
</div> </div>
@endif @endif
@ -30,3 +30,7 @@
</div> </div>
</div> </div>
</div> </div>
@push('scripts')
{{-- Code from https://codepen.io/ryangjchandler/pen/WNQQKeR--}}
<script src="{{ asset('js/sort_table_by_column.js') }}"></script>
@endpush

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Your New Account Password</title>
</head>
<body>
<h1>Hello, {{ $user->first_name }} {{ $user->last_name }}</h1>
<p>Your account has been created. Here are your login details:</p>
<p><strong>Email:</strong> {{ $user->email }}</p>
<p><strong>Password:</strong> {{ $password }}</p>
<p>Please change your password after logging in for the first time.</p>
</body>
</html>
{{--TODO make this template less.... bad--}}

View File

@ -1,8 +1,5 @@
@php use App\Models\Audition;use Illuminate\Support\Facades\Auth; @endphp @php use App\Models\Audition;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-layout.app>
<x-slot:page_title>Students</x-slot:page_title> <x-slot:page_title>Students</x-slot:page_title>

View File

@ -7,4 +7,3 @@
</x-layout.app> </x-layout.app>
d

View File

@ -6,6 +6,7 @@ use App\Http\Controllers\SchoolController;
use App\Http\Controllers\StudentController; use App\Http\Controllers\StudentController;
use App\Http\Controllers\TestController; use App\Http\Controllers\TestController;
use App\Http\Controllers\UserController; use App\Http\Controllers\UserController;
use App\Http\Middleware\CheckIfAdmin;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -13,9 +14,36 @@ Route::get('/test',[TestController::class,'flashTest'])->middleware('auth','veri
Route::view('/','welcome')->middleware('guest'); Route::view('/','welcome')->middleware('guest');
// Admin Routes
Route::middleware(['auth','verified',CheckIfAdmin::class])->prefix('admin/')->group(function() {
Route::view('/','admin.dashboard');
// Admin Student Routes
Route::prefix('students')->controller(\App\Http\Controllers\Admin\StudentController::class)->group(function() {
Route::get('/','index');
});
// Admin School Routes
Route::prefix('schools')->controller(\App\Http\Controllers\Admin\SchoolController::class)->group(function() {
Route::get('/','index');
Route::get('/{school}/edit','edit');
Route::patch('/{school}','update');
});
// Admin User Routes
Route::prefix('users')->controller(\App\Http\Controllers\Admin\UserController::class)->group(function() {
Route::get('/','index');
Route::get('/create','create');
Route::post('/','store');
Route::get('/{user}/edit','edit');
Route::patch('/{user}','update');
Route::delete('/{user}','destroy');
});
});
// Dashboard Related Routes // Dashboard Related Routes
Route::middleware(['auth','verified'])->group(function () { Route::middleware(['auth','verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'dashboard']); Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('dashboard');
Route::get('/profile', [DashboardController::class, 'profile']); Route::get('/profile', [DashboardController::class, 'profile']);
Route::get('/my_school', [DashboardController::class, 'my_school']); Route::get('/my_school', [DashboardController::class, 'my_school']);
}); });