Admin users and schoosl working. In progress on students
This commit is contained in:
parent
695a0130c0
commit
93752b5621
|
|
@ -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');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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, '@');
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<x-layout.app>
|
||||||
|
You are on the admin dashboard
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -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--}}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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' }}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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() }} ▼</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>
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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--}}
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,3 @@
|
||||||
|
|
||||||
|
|
||||||
</x-layout.app>
|
</x-layout.app>
|
||||||
d
|
|
||||||
|
|
|
||||||
|
|
@ -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']);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue