feat(auth): register page with function

This commit is contained in:
arieeefajar 2025-01-24 15:24:44 +07:00
parent 78923e7276
commit e03b4d2ac1
9 changed files with 433 additions and 100 deletions

View File

@ -4,14 +4,13 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules; use Illuminate\Validation\Rules;
use Illuminate\View\View; use Illuminate\View\View;
use PhpParser\Node\Expr\FuncCall;
class RegisteredUserController extends Controller class RegisteredUserController extends Controller
{ {
@ -28,24 +27,49 @@ public function create(): View
* *
* @throws \Illuminate\Validation\ValidationException * @throws \Illuminate\Validation\ValidationException
*/ */
public function store(Request $request): RedirectResponse public function store(Request $request)
{ {
$request->validate([ $customMessage = [
'name.required' => 'Nama wajib diisi',
'name.max' => 'Nama maksimal 255 karakter',
'name.string' => 'Nama harus berupa string',
'email.required' => 'Email wajib diisi',
'email.email' => 'Email tidak valid',
'email.unique' => 'Email sudah terdaftar',
'password.required' => 'Password wajib diisi',
'password.confirmed' => 'Password tidak cocok',
'password.min' => 'Password minimal 8 karakter',
];
$validator = Validator::make($request->all(), [
'name' => ['required', 'string', 'max:255'], 'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()], 'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
]); ], $customMessage);
$user = User::create([ if ($validator->fails()) {
'name' => $request->name, toast($validator->messages()->all()[0], 'error')->position('top')->autoclose(3000);
'email' => $request->email, return redirect()->back()->withInput();
'password' => Hash::make($request->password), }
]);
event(new Registered($user)); DB::beginTransaction();
$user = new User();
$user->username = $request->username;
$user->name = $request->name;
$user->email = $request->email;
$user->password = Hash::make($request->password);
Auth::login($user); try {
$user->save();
return redirect(RouteServiceProvider::HOME); DB::commit();
toast('Registrasi berhasil', 'success')->position('top')->autoclose(3000);
return redirect()->route('auth.two_step_verify', ['email' => $request->email]);
} catch (\Throwable $th) {
DB::rollBack();
toast($th->getMessage(), 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
} }
} }

View File

@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class TwoStepVerifyController extends Controller
{
public function create($email)
{
return view('auth.two-step-verifycation', compact('email'));
}
}

View File

@ -16,13 +16,13 @@ class VerifyEmailController extends Controller
public function __invoke(EmailVerificationRequest $request): RedirectResponse public function __invoke(EmailVerificationRequest $request): RedirectResponse
{ {
if ($request->user()->hasVerifiedEmail()) { if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(RouteServiceProvider::HOME.'?verified=1'); return redirect()->intended(RouteServiceProvider::HOME . '?verified=1');
} }
if ($request->user()->markEmailAsVerified()) { if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user())); event(new Verified($request->user()));
} }
return redirect()->intended(RouteServiceProvider::HOME.'?verified=1'); return redirect()->intended(RouteServiceProvider::HOME . '?verified=1');
} }
} }

View File

@ -18,7 +18,7 @@ public function run(): void
User::create([ User::create([
'username' => 'admin', 'username' => 'admin',
'name' => 'Admin Sage', 'name' => 'Admin Sage',
'email' => 'ariefajar739@gmail.com', 'email' => 'adminSage@gmail.com',
'password' => Hash::make('admin123'), 'password' => Hash::make('admin123'),
'role' => 'admin' 'role' => 'admin'
]), ]),

View File

@ -111,10 +111,11 @@ class="ri-eye-fill align-middle"></i></button>
</div> </div>
<!-- end card --> <!-- end card -->
{{-- <div class="mt-4 text-center"> <div class="mt-4 text-center">
<p class="mb-0">Don't have an account ? <a href="auth-signup-basic.html" <p class="mb-0">Belum memiliki akun ? <a href="{{ route('auth.register') }}"
class="fw-semibold text-primary text-decoration-underline"> Signup </a> </p> class="fw-semibold text-primary text-decoration-underline"> Registrasi sekarang!
</div> --}} </a> </p>
</div>
</div> </div>
</div> </div>

View File

@ -1,52 +1,186 @@
<x-guest-layout> <!doctype html>
<form method="POST" action="{{ route('register') }}"> <html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
@csrf
<!-- Name --> <head>
<meta charset="utf-8" />
<title>Registrasi | CornQuest</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="Premium Multipurpose Admin & Dashboard Template" name="description" />
<meta content="Themesbrand" name="author" />
<!-- App favicon -->
<link rel="shortcut icon" href="assets/images/favicon.ico">
<!-- Layout config Js -->
<script src="assets/js/layout.js"></script>
<!-- Bootstrap Css -->
<link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<!-- Icons Css -->
<link href="assets/css/icons.min.css" rel="stylesheet" type="text/css" />
<!-- App Css-->
<link href="assets/css/app.min.css" rel="stylesheet" type="text/css" />
<!-- custom Css-->
<link href="assets/css/custom.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="auth-page-wrapper pt-5">
<!-- auth page bg -->
<div class="auth-one-bg-position auth-one-bg" id="auth-particles">
<div class="bg-overlay"></div>
<div class="shape">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1440 120">
<path d="M 0,36 C 144,53.6 432,123.2 720,124 C 1008,124.8 1296,56.8 1440,40L1440 140L0 140z"></path>
</svg>
</div>
</div>
<!-- auth page content -->
<div class="auth-page-content">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="text-center mt-sm-5 mb-4 text-white-50">
<div> <div>
<x-input-label for="name" :value="__('Name')" /> <a href="index.html" class="d-inline-block auth-logo">
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" /> <img src="assets/images/logo-light.png" alt="" height="20">
<x-input-error :messages="$errors->get('name')" class="mt-2" />
</div>
<!-- Email Address -->
<div class="mt-4">
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
<div class="flex items-center justify-end mt-4">
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('login') }}">
{{ __('Already registered?') }}
</a> </a>
</div>
</div>
</div>
</div>
<!-- end row -->
<x-primary-button class="ms-4"> <div class="row justify-content-center">
{{ __('Register') }} <div class="col-md-8 col-lg-6 col-xl-5">
</x-primary-button> <div class="card mt-4">
<div class="card-body p-4">
<div class="text-center mt-2">
<h5 class="text-primary">Buat Akun Baru</h5>
<p class="text-muted">Silahkan isi form dibawah ini</p>
</div>
<div class="p-2 mt-4">
<form class="needs-validation" novalidate action="{{ route('auth.register_post') }}"
method="POST">
@csrf
<div class="mb-3">
<label for="useremail" class="form-label">Email <span
class="text-danger">*</span></label>
<input type="email" class="form-control" id="useremail" name="email"
value="{{ old('email') }}" placeholder="Masukan email" autofocus
autocomplete="off" required>
<div class="invalid-feedback">
Harap masukan email
</div>
</div>
<div class="mb-3">
<label for="fullname" class="form-label">Nama Lengkap <span
class="text-danger">*</span></label>
<input type="text" class="form-control" id="fullname" name="name"
value="{{ old('name') }}" placeholder="Masukan nama lengkap" required>
<div class="invalid-feedback">
Harap masukan nama lengkap
</div>
</div>
<div class="mb-3">
<label for="username" class="form-label">Username <span
class="text-danger">*</span></label>
<input type="text" class="form-control" id="username" name="username"
value="{{ old('username') }}" placeholder="Masukan username" required>
<div class="invalid-feedback">
Harap masukan username
</div>
</div>
<div class="mb-2">
<label for="userpassword" class="form-label">Password <span
class="text-danger">*</span></label>
<input type="password" class="form-control" id="userpassword"
name="password" placeholder="Masukan password" required>
<div class="invalid-feedback">
Harap masukan password
</div>
</div>
<div class="mb-2">
<label for="userpassword" class="form-label">Konfirmasi Password <span
class="text-danger">*</span></label>
<input type="password" class="form-control" id="userkonfirpassword"
name="password_confirmation" placeholder="Masukan konfirmasi password"
required>
<div class="invalid-feedback">
Harap masukan password
</div>
</div>
<div class="mt-4">
<button class="btn btn-success w-100" type="submit">Registrasi</button>
</div> </div>
</form> </form>
</x-guest-layout>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<p class="mb-0">Sudah punya akun ? <a href="{{ route('auth.login') }}"
class="fw-semibold text-primary text-decoration-underline"> Login </a> </p>
</div>
</div>
</div>
<!-- end row -->
</div>
<!-- end container -->
</div>
<!-- end auth page content -->
@include('sweetalert::alert')
<!-- footer -->
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<p class="mb-0 text-muted">&copy;
<script>
document.write(new Date().getFullYear())
</script> CornQuest. Crafted with <i
class="mdi mdi-heart text-danger"></i>
by LAB KSI Politeknik Negeri Jember
</p>
</div>
</div>
</div>
</div>
</footer>
<!-- end Footer -->
</div>
<!-- end auth-page-wrapper -->
<!-- JAVASCRIPT -->
<script src="assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/libs/simplebar/simplebar.min.js"></script>
<script src="assets/libs/node-waves/waves.min.js"></script>
<script src="assets/libs/feather-icons/feather.min.js"></script>
<script src="assets/js/pages/plugins/lord-icon-2.1.0.js"></script>
<script src="assets/js/plugins.js"></script>
<!-- particles js -->
<script src="assets/libs/particles.js/particles.js"></script>
<!-- particles app js -->
<script src="assets/js/pages/particles.app.js"></script>
<!-- validation init -->
<script src="assets/js/pages/form-validation.init.js"></script>
</body>
</html>

View File

@ -0,0 +1,180 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<head>
<meta charset="utf-8" />
<title>Two Step Verification | CornQuest</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="Premium Multipurpose Admin & Dashboard Template" name="description" />
<meta content="Themesbrand" name="author" />
<!-- App favicon -->
<link rel="shortcut icon" href="{{ asset('assets/images/favicon.ico') }}">
<!-- Layout config Js -->
<script src="{{ asset('assets/js/layout.js') }}"></script>
<!-- Bootstrap Css -->
<link href="{{ asset('assets/css/bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
<!-- Icons Css -->
<link href="{{ asset('assets/css/icons.min.css') }}" rel="stylesheet" type="text/css" />
<!-- App Css-->
<link href="{{ asset('assets/css/app.min.css') }}" rel="stylesheet" type="text/css" />
<!-- custom Css-->
<link href="{{ asset('assets/css/custom.min.css') }}" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="auth-page-wrapper pt-5">
<!-- auth page bg -->
<div class="auth-one-bg-position auth-one-bg" id="auth-particles">
<div class="bg-overlay"></div>
<div class="shape">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1440 120">
<path d="M 0,36 C 144,53.6 432,123.2 720,124 C 1008,124.8 1296,56.8 1440,40L1440 140L0 140z"></path>
</svg>
</div>
</div>
<!-- auth page content -->
<div class="auth-page-content">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="text-center mt-sm-5 mb-4 text-white-50">
<div>
<a href="index.html" class="d-inline-block auth-logo">
<img src="assets/images/logo-light.png" alt="" height="20">
</a>
</div>
</div>
</div>
</div>
<!-- end row -->
<div class="row justify-content-center">
<div class="col-md-8 col-lg-6 col-xl-5">
<div class="card mt-4">
<div class="card-body p-4">
<div class="mb-4">
<div class="avatar-lg mx-auto">
<div class="avatar-title bg-light text-primary display-5 rounded-circle">
<i class="ri-mail-line"></i>
</div>
</div>
</div>
<div class="p-2 mt-4">
<div class="text-muted text-center mb-4 mx-lg-3">
<h4>Verifikasi Akun Anda</h4>
<p>Masukkan kode verifikasi yang dikirimkan ke <span
class="fw-semibold">{{ $email }}</span></p>
</div>
<form>
<div class="row">
<div class="col-3">
<div class="mb-3">
<label for="digit1-input" class="visually-hidden">Dight 1</label>
<input type="text"
class="form-control form-control-lg bg-light border-light text-center"
onkeyup="moveToNext(this, 2)" maxLength="1" id="digit1-input">
</div>
</div><!-- end col -->
<div class="col-3">
<div class="mb-3">
<label for="digit2-input" class="visually-hidden">Dight 2</label>
<input type="text"
class="form-control form-control-lg bg-light border-light text-center"
onkeyup="moveToNext(this, 3)" maxLength="1" id="digit2-input">
</div>
</div><!-- end col -->
<div class="col-3">
<div class="mb-3">
<label for="digit3-input" class="visually-hidden">Dight 3</label>
<input type="text"
class="form-control form-control-lg bg-light border-light text-center"
onkeyup="moveToNext(this, 4)" maxLength="1" id="digit3-input">
</div>
</div><!-- end col -->
<div class="col-3">
<div class="mb-3">
<label for="digit4-input" class="visually-hidden">Dight 4</label>
<input type="text"
class="form-control form-control-lg bg-light border-light text-center"
onkeyup="moveToNext(this, 4)" maxLength="1" id="digit4-input">
</div>
</div><!-- end col -->
</div>
</form><!-- end form -->
<div class="mt-3">
<button type="button" class="btn btn-success w-100">Verifikasi</button>
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<p class="mb-0">Tidak menerima email ? <a href="auth-pass-reset-basic.html"
class="fw-semibold text-primary text-decoration-underline">Kirim ulang</a> </p>
</div>
</div>
</div>
<!-- end row -->
</div>
<!-- end container -->
</div>
<!-- end auth page content -->
<!-- footer -->
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<p class="mb-0 text-muted">&copy;
<script>
document.write(new Date().getFullYear())
</script> CornQuest. Crafted with <i
class="mdi mdi-heart text-danger"></i>
by LAB KSI Politeknik Negeri Jember
</p>
</div>
</div>
</div>
</div>
</footer>
<!-- end Footer -->
</div>
<!-- end auth-page-wrapper -->
<!-- JAVASCRIPT -->
<script src="{{ asset('assets/libs/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('assets/libs/simplebar/simplebar.min.js') }}"></script>
<script src="{{ asset('assets/libs/node-waves/waves.min.js') }}"></script>
<script src="{{ asset('assets/libs/feather-icons/feather.min.js') }}"></script>
<script src="{{ asset('assets/js/pages/plugins/lord-icon-2.1.0.js') }}"></script>
<script src="{{ asset('assets/js/plugins.js') }}"></script>
<!-- particles js -->
<script src="{{ asset('assets/libs/particles.js/particles.js') }}"></script>
<!-- particles app js -->
<script src="{{ asset('assets/js/pages/particles.app.js') }}"></script>
<!-- two-step-verification js -->
<script src="{{ asset('assets/js/pages/two-step-verification.init.js') }}"></script>
</body>
</html>

View File

@ -1,31 +0,0 @@
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
</div>
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
</div>
@endif
<div class="mt-4 flex items-center justify-between">
<form method="POST" action="{{ route('verification.send') }}">
@csrf
<div>
<x-primary-button>
{{ __('Resend Verification Email') }}
</x-primary-button>
</div>
</form>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
{{ __('Log Out') }}
</button>
</form>
</div>
</x-guest-layout>

View File

@ -2,6 +2,8 @@
use App\Http\Controllers\Auth\AuthenticatedSessionController; use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\PasswordResetLinkController; use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\TwoStepVerifyController;
use App\Http\Controllers\DashboardController; use App\Http\Controllers\DashboardController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -25,6 +27,15 @@
Route::post('/', 'store')->name('login_post'); Route::post('/', 'store')->name('login_post');
}); });
Route::controller(RegisteredUserController::class)->group(function () {
Route::get('/registrasi', 'create')->name('register');
Route::post('/registrasi', 'store')->name('register_post');
});
Route::controller(TwoStepVerifyController::class)->group(function () {
Route::get('/verifikasi-akun/{email}', 'create')->name('two_step_verify');
});
Route::controller(PasswordResetLinkController::class)->group(function () { Route::controller(PasswordResetLinkController::class)->group(function () {
Route::get('/forgot-password', 'create')->name('forgot_password'); Route::get('/forgot-password', 'create')->name('forgot_password');
Route::post('/reset-password', 'store')->name('reset_password'); Route::post('/reset-password', 'store')->name('reset_password');