From 93752b5621fd16e97d6c8a9a99a6ca50b8ec01f0 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Sun, 2 Jun 2024 19:42:50 -0500 Subject: [PATCH] Admin users and schoosl working. In progress on students --- .../Controllers/Admin/SchoolController.php | 52 +++++ .../Controllers/Admin/StudentController.php | 21 ++ app/Http/Controllers/Admin/UserController.php | 95 +++++++++ app/Http/Middleware/CheckIfAdmin.php | 26 +++ app/Mail/NewUserPassword.php | 67 +++++++ app/Models/User.php | 5 + database/factories/SchoolFactory.php | 2 +- resources/views/admin/dashboard.blade.php | 3 + resources/views/admin/schools/edit.blade.php | 19 ++ resources/views/admin/schools/index.blade.php | 36 ++++ .../views/admin/students/index.blade.php | 33 ++++ resources/views/admin/users/create.blade.php | 26 +++ resources/views/admin/users/edit.blade.php | 24 +++ resources/views/admin/users/index.blade.php | 38 ++++ .../views/components/layout/app.blade.php | 7 +- .../components/layout/nav-link.blade.php | 5 +- .../components/layout/navbar-admin.blade.php | 183 ++++++++++++++++++ .../views/components/layout/navbar.blade.php | 1 + .../views/components/table/table.blade.php | 10 +- .../views/emails/new_user_password.blade.php | 15 ++ resources/views/students/index.blade.php | 5 +- resources/views/test.blade.php | 1 - routes/web.php | 30 ++- 23 files changed, 690 insertions(+), 14 deletions(-) create mode 100644 app/Http/Controllers/Admin/SchoolController.php create mode 100644 app/Http/Controllers/Admin/StudentController.php create mode 100644 app/Http/Controllers/Admin/UserController.php create mode 100644 app/Http/Middleware/CheckIfAdmin.php create mode 100644 app/Mail/NewUserPassword.php create mode 100644 resources/views/admin/dashboard.blade.php create mode 100644 resources/views/admin/schools/edit.blade.php create mode 100644 resources/views/admin/schools/index.blade.php create mode 100644 resources/views/admin/students/index.blade.php create mode 100644 resources/views/admin/users/create.blade.php create mode 100644 resources/views/admin/users/edit.blade.php create mode 100644 resources/views/admin/users/index.blade.php create mode 100644 resources/views/components/layout/navbar-admin.blade.php create mode 100644 resources/views/emails/new_user_password.blade.php diff --git a/app/Http/Controllers/Admin/SchoolController.php b/app/Http/Controllers/Admin/SchoolController.php new file mode 100644 index 0000000..8c8e5ef --- /dev/null +++ b/app/Http/Controllers/Admin/SchoolController.php @@ -0,0 +1,52 @@ +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'); + } + + +} diff --git a/app/Http/Controllers/Admin/StudentController.php b/app/Http/Controllers/Admin/StudentController.php new file mode 100644 index 0000000..58349dc --- /dev/null +++ b/app/Http/Controllers/Admin/StudentController.php @@ -0,0 +1,21 @@ +is_admin) abort(403); + $students = Student::orderBy('last_name')->orderBy('first_name')->SimplePaginate(10); + return view('admin.students.index', ['students' => $students]); + } +} diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php new file mode 100644 index 0000000..9ce4079 --- /dev/null +++ b/app/Http/Controllers/Admin/UserController.php @@ -0,0 +1,95 @@ +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'); + } +} diff --git a/app/Http/Middleware/CheckIfAdmin.php b/app/Http/Middleware/CheckIfAdmin.php new file mode 100644 index 0000000..36baeb2 --- /dev/null +++ b/app/Http/Middleware/CheckIfAdmin.php @@ -0,0 +1,26 @@ +is_admin) { + return $next($request); + } + + return redirect('/')->with('error', 'You do not have admin access.'); + + } +} diff --git a/app/Mail/NewUserPassword.php b/app/Mail/NewUserPassword.php new file mode 100644 index 0000000..16da5b9 --- /dev/null +++ b/app/Mail/NewUserPassword.php @@ -0,0 +1,67 @@ +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 + */ + 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, + ]); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index cb76543..2679295 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -59,6 +59,11 @@ class User extends Authenticatable implements MustVerifyEmail return $this->first_name . ' ' . $this->last_name; } + public function has_school(): bool + { + return $this->school_id !== null; + } + public function emailDomain(): string { $pos = strpos($this->email, '@'); diff --git a/database/factories/SchoolFactory.php b/database/factories/SchoolFactory.php index 03cf831..5dd36a0 100644 --- a/database/factories/SchoolFactory.php +++ b/database/factories/SchoolFactory.php @@ -18,7 +18,7 @@ class SchoolFactory extends Factory { return [ 'name' => fake()->city(), - 'address' => fake()->address(), + 'address' => fake()->streetAddress(), 'city' => fake()->city(), 'state' => 'OK', 'zip' => rand(73001, 74999), diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php new file mode 100644 index 0000000..a469209 --- /dev/null +++ b/resources/views/admin/dashboard.blade.php @@ -0,0 +1,3 @@ + + You are on the admin dashboard + diff --git a/resources/views/admin/schools/edit.blade.php b/resources/views/admin/schools/edit.blade.php new file mode 100644 index 0000000..49798e9 --- /dev/null +++ b/resources/views/admin/schools/edit.blade.php @@ -0,0 +1,19 @@ + + + Edit School + + + + + + + + + + Update User + + + + + +{{--TODO Show directors on school page--}} diff --git a/resources/views/admin/schools/index.blade.php b/resources/views/admin/schools/index.blade.php new file mode 100644 index 0000000..98b54db --- /dev/null +++ b/resources/views/admin/schools/index.blade.php @@ -0,0 +1,36 @@ + + School Administration + + + + Schools + Click school name to edit + + New School + + + + + Name + Directors + Students + Entries + + + + + @foreach($schools as $school) + + {{ $school->name }} + {{ $school->users->count() }} + {{ $school->students->count() }} + {{ $school->entries->count() }} + + @endforeach + + + + + + + diff --git a/resources/views/admin/students/index.blade.php b/resources/views/admin/students/index.blade.php new file mode 100644 index 0000000..1954ed3 --- /dev/null +++ b/resources/views/admin/students/index.blade.php @@ -0,0 +1,33 @@ + + Student Administration + + + + Students + Click name to edit + + New Student + + + + + Name + School + Grade + Entries + + + + @foreach($students as $student) + + {{ $student->full_name(true) }} + {{ $student->school->name }} + {{ $student->grade }} + {{ $student->entries->count() }} + + @endforeach + + +
{{ $students->links() }}
+
+
diff --git a/resources/views/admin/users/create.blade.php b/resources/views/admin/users/create.blade.php new file mode 100644 index 0000000..69d0f65 --- /dev/null +++ b/resources/views/admin/users/create.blade.php @@ -0,0 +1,26 @@ + + + Edit User + + + + + + + + + School + + @foreach ($schools as $school) + + + @endforeach + + + + + Update User + + + + diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php new file mode 100644 index 0000000..9d6f140 --- /dev/null +++ b/resources/views/admin/users/edit.blade.php @@ -0,0 +1,24 @@ + + + Edit User + + + + + + + + + School + @foreach ($schools as $school) + + @endforeach + + + + + Update User + + + + diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php new file mode 100644 index 0000000..26fdece --- /dev/null +++ b/resources/views/admin/users/index.blade.php @@ -0,0 +1,38 @@ + + User Administration + + + + Users + Click name to edit + + New User + + + + + Name + School + Email + Cell Phone + Judging Preference + + + + @foreach($users as $user) + + {{ $user->full_name(true) }} + {{ $user->has_school() ? $user->school->name : ' ' }} {{-- TODO link to the school --}} + {{ $user->email }} + {{ $user->cell_phone }} + {{ $user->judging_preference }} + + @endforeach + + + + + + + +{{ $user->has_school() ? $user->school->name : 'No School' }} diff --git a/resources/views/components/layout/app.blade.php b/resources/views/components/layout/app.blade.php index f879833..cced3c0 100644 --- a/resources/views/components/layout/app.blade.php +++ b/resources/views/components/layout/app.blade.php @@ -19,8 +19,11 @@
- - + @if(request()->is('*admin*')) + + @else + + @endif @if($page_title) {{ $page_title }} @endif diff --git a/resources/views/components/layout/nav-link.blade.php b/resources/views/components/layout/nav-link.blade.php index e17f0c6..7880d95 100644 --- a/resources/views/components/layout/nav-link.blade.php +++ b/resources/views/components/layout/nav-link.blade.php @@ -1,6 +1,7 @@ @props(['active' => false]) - -merge(['class' => $classes]) }} aria-current="{{ $active ? 'page':'false' }}" {{ $attributes }} >{{ $slot }} diff --git a/resources/views/components/layout/navbar-admin.blade.php b/resources/views/components/layout/navbar-admin.blade.php new file mode 100644 index 0000000..400e454 --- /dev/null +++ b/resources/views/components/layout/navbar-admin.blade.php @@ -0,0 +1,183 @@ +@php use Illuminate\Support\Facades\Auth; @endphp +{{--TODO Clean up mobile menu area--}} + diff --git a/resources/views/components/layout/navbar.blade.php b/resources/views/components/layout/navbar.blade.php index daac20e..20c9031 100644 --- a/resources/views/components/layout/navbar.blade.php +++ b/resources/views/components/layout/navbar.blade.php @@ -16,6 +16,7 @@
+ Admin Dashboard Students Entries diff --git a/resources/views/components/table/table.blade.php b/resources/views/components/table/table.blade.php index 8e224b4..5d715b3 100644 --- a/resources/views/components/table/table.blade.php +++ b/resources/views/components/table/table.blade.php @@ -7,14 +7,14 @@ ])
@if($with_title_area) -
-
+
+
@if($title)

attributes->merge(['class' => 'text-base font-semibold leading-6 text-gray-900']) }}>{{ $title }}

@endif @if($subtitle)

attributes->merge(['class' => 'mt-2 text-sm text-gray-700']) }}>{{ $subtitle }}

@endif
{{-- Title block right often used for add button--}} @if($title_block_right) -
+
attributes->merge(['class' => 'mt-4 sm:ml-16 sm:mt-0 sm:flex-none']) }}> {{ $title_block_right }}
@endif @@ -30,3 +30,7 @@
+@push('scripts') + {{-- Code from https://codepen.io/ryangjchandler/pen/WNQQKeR--}} + +@endpush diff --git a/resources/views/emails/new_user_password.blade.php b/resources/views/emails/new_user_password.blade.php new file mode 100644 index 0000000..236b709 --- /dev/null +++ b/resources/views/emails/new_user_password.blade.php @@ -0,0 +1,15 @@ + + + + Your New Account Password + + +

Hello, {{ $user->first_name }} {{ $user->last_name }}

+

Your account has been created. Here are your login details:

+

Email: {{ $user->email }}

+

Password: {{ $password }}

+

Please change your password after logging in for the first time.

+ + + +{{--TODO make this template less.... bad--}} diff --git a/resources/views/students/index.blade.php b/resources/views/students/index.blade.php index c665ffb..dd60e95 100644 --- a/resources/views/students/index.blade.php +++ b/resources/views/students/index.blade.php @@ -1,8 +1,5 @@ @php use App\Models\Audition;use Illuminate\Support\Facades\Auth; @endphp -@push('scripts') - {{-- Code from https://codepen.io/ryangjchandler/pen/WNQQKeR--}} - -@endpush + Students diff --git a/resources/views/test.blade.php b/resources/views/test.blade.php index 5fced4e..8c62fbe 100644 --- a/resources/views/test.blade.php +++ b/resources/views/test.blade.php @@ -7,4 +7,3 @@ -d diff --git a/routes/web.php b/routes/web.php index eca2f82..7a70092 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,7 @@ use App\Http\Controllers\SchoolController; use App\Http\Controllers\StudentController; use App\Http\Controllers\TestController; use App\Http\Controllers\UserController; +use App\Http\Middleware\CheckIfAdmin; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; @@ -13,9 +14,36 @@ Route::get('/test',[TestController::class,'flashTest'])->middleware('auth','veri 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 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('/my_school', [DashboardController::class, 'my_school']); });