WIP: Auth page

This commit is contained in:
Mahayoga 2026-05-21 00:27:11 +07:00
parent d07e24e39b
commit f11c3a879d
5 changed files with 382 additions and 69 deletions

View File

@ -28,7 +28,7 @@ public function create(Request $request): View
* *
* @throws \Illuminate\Validation\ValidationException * @throws \Illuminate\Validation\ValidationException
*/ */
public function store(Request $request): RedirectResponse public function store(Request $request)
{ {
$request->validate([ $request->validate([
'token' => ['required'], 'token' => ['required'],
@ -51,12 +51,17 @@ function (User $user) use ($request) {
} }
); );
return response()->json([
'status' => $status == Password::PASSWORD_RESET,
'msg' => $status == Password::PASSWORD_RESET ? 'Password reset successful' : 'Password reset failed'
]);
// If the password was successfully reset, we will redirect the user back to // If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can // the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message. // redirect them back to where they came from with their error message.
return $status == Password::PASSWORD_RESET // return $status == Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status)) // ? redirect()->route('login')->with('status', __($status))
: back()->withInput($request->only('email')) // : back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]); // ->withErrors(['email' => __($status)]);
} }
} }

View File

@ -23,7 +23,7 @@ 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([ $request->validate([
'email' => ['required', 'email'], 'email' => ['required', 'email'],
@ -36,9 +36,14 @@ public function store(Request $request): RedirectResponse
$request->only('email') $request->only('email')
); );
return $status == Password::RESET_LINK_SENT return response()->json([
? back()->with('status', __($status)) 'status' => $status == Password::RESET_LINK_SENT,
: back()->withInput($request->only('email')) 'msg' => __($status)
->withErrors(['email' => __($status)]); ]);
// return $status == Password::RESET_LINK_SENT
// ? back()->with('status', __($status))
// : back()->withInput($request->only('email'))
// ->withErrors(['email' => __($status)]);
} }
} }

View File

@ -1,25 +1,169 @@
<x-guest-layout> <!DOCTYPE html>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400"> <html lang="en">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }} <!-- [Head] start -->
<head>
<title>Lupa Password | {{ env('APP_NAME') }}</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description"
content="Mantis is made using Bootstrap 5 design framework. Download the free admin template & use it for your project.">
<meta name="keywords"
content="Mantis, Dashboard UI Kit, Bootstrap 5, Admin Template, Admin Dashboard, CRM, CMS, Bootstrap Admin Template">
<meta name="author" content="CodedThemes">
<!-- [Favicon] icon -->
<link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
</div> </div>
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('password.email') }}">
@csrf
<!-- Email Address -->
<div>
<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 autofocus />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div> </div>
<!-- [ Pre-loader ] End -->
<div class="flex items-center justify-end mt-4"> <div class="auth-main">
<x-primary-button> <div class="auth-wrapper v3">
{{ __('Email Password Reset Link') }} <div class="auth-form">
</x-primary-button> <div class="auth-header">
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
</div> </div>
</form> <div class="card my-5">
</x-guest-layout> <div class="card-body">
<div class="d-flex justify-content-between align-items-end mb-4">
<h3 class="mb-0"><b>Lupa Password</b></h3>
</div>
<div class="form-group mb-3">
<p class="text-muted">Lupa password Anda? Masukkan email Anda dan kami akan mengirimkan link untuk mereset password.</p>
</div>
<div class="form-group mb-3">
<label class="form-label">Email Address</label>
<input type="email" id="email" class="form-control" placeholder="Email Address">
</div>
<div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doForgotPassword()">Kirim Link Reset Password</button>
</div>
</div>
</div>
<div class="auth-footer row">
<!-- <div class=""> -->
<div class="col my-1">
<p class="m-0">Copyright {{ date('Y') }} © <a href="https://polije.ac.id" target="_blank"> Politeknik Negeri Jember</a></p>
</div>
<div class="col-auto my-1">
<ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
</ul>
</div>
<!-- </div> -->
</div>
</div>
</div>
</div>
<!-- [ Main Content ] end -->
<!-- Required Js -->
<script src="{{ asset('assets/admin/assets/js/plugins/popper.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/simplebar.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/bootstrap.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/fonts/custom-font.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/pcoded.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/feather.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>layout_change('light');</script>
<script>change_box_container('false');</script>
<script>layout_rtl_change('false');</script>
<script>preset_change("preset-1");</script>
<script>font_change("Public-Sans");</script>
<script>
function doForgotPassword() {
try {
Swal.fire({
title: "Loading",
text: "Sedang memproses, tunggu sebentar yaa!",
icon: "info",
showConfirmButton: false,
allowOutsideClick: false
});
let token = document.getElementById('_token').getAttribute('value');
let email = document.getElementById('email').value;
if(email == '' || email == null) {
Swal.fire({
title: "Info",
text: "Email tidak boleh kosong!",
icon: "warning"
});
return;
}
let xhttp = new XMLHttpRequest();
let formData = new FormData();
formData.append('_token', token);
formData.append('email', email);
xhttp.onreadystatechange = function() {
if(this.status == 200) {
let jsonData = JSON.parse(this.responseText);
if(jsonData.status) {
Swal.fire({
title: "Info",
text: "Link reset password telah dikirim ke email Anda!",
icon: "success"
});
} else {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, cek email Anda!",
icon: "error"
});
}
} else {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, koneksi ke server gagal, coba lagi nanti!",
icon: "error"
});
}
}
xhttp.open('POST', '{{ route("password.email") }}', false);
xhttp.send(formData);
} catch(error) {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, kesalahan pada server, coba lagi nanti!",
icon: "error"
});
}
}
</script>
</body>
<!-- [Body] end -->
</html>

View File

@ -3,7 +3,7 @@
<!-- [Head] start --> <!-- [Head] start -->
<head> <head>
<title>Login | Smart Anxiety</title> <title>Login | {{ env('APP_NAME') }}</title>
<!-- [Meta] --> <!-- [Meta] -->
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
@ -50,7 +50,7 @@
<div class="auth-wrapper v3"> <div class="auth-wrapper v3">
<div class="auth-form"> <div class="auth-form">
<div class="auth-header"> <div class="auth-header">
<a href="#"><img src="{{ asset('assets/admin/assets/images/logo-dark.svg') }}" alt="img"></a> <a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
</div> </div>
<div class="card my-5"> <div class="card my-5">
<div class="card-body"> <div class="card-body">
@ -67,7 +67,7 @@
<input type="password" id="password" class="form-control" placeholder="Password"> <input type="password" id="password" class="form-control" placeholder="Password">
</div> </div>
<div class="d-flex mt-1 justify-content-between"> <div class="d-flex mt-1 justify-content-between">
<h5 class="text-secondary f-w-400">Forgot Password?</h5> <h5 class="text-secondary f-w-400"><a href="{{ route('password.request') }}">Forgot Password?</a></h5>
</div> </div>
<div class="d-grid mt-4"> <div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doLogin()">Login</button> <button type="button" class="btn btn-primary" onclick="doLogin()">Login</button>
@ -81,8 +81,8 @@
</div> </div>
<div class="col-auto my-1"> <div class="col-auto my-1">
<ul class="list-inline footer-link mb-0"> <ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="#">Beranda</a></li> <li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="#">Contact us</a></li> <li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
</ul> </ul>
</div> </div>
<!-- </div> --> <!-- </div> -->

View File

@ -1,39 +1,198 @@
<x-guest-layout> <!DOCTYPE html>
<form method="POST" action="{{ route('password.store') }}"> <html lang="en">
@csrf <!-- [Head] start -->
<!-- Password Reset Token --> <head>
<input type="hidden" name="token" value="{{ $request->route('token') }}"> <title>Reset Password | {{ env('APP_NAME') }}</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description"
content="Mantis is made using Bootstrap 5 design framework. Download the free admin template & use it for your project.">
<meta name="keywords"
content="Mantis, Dashboard UI Kit, Bootstrap 5, Admin Template, Admin Dashboard, CRM, CMS, Bootstrap Admin Template">
<meta name="author" content="CodedThemes">
<!-- Email Address --> <!-- [Favicon] icon -->
<div> <link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<x-input-label for="email" :value="__('Email')" /> <link rel="stylesheet"
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus autocomplete="username" /> href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
<x-input-error :messages="$errors->get('email')" class="mt-2" /> id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
</div> </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> </div>
<!-- [ Pre-loader ] End -->
<!-- Confirm Password --> <div class="auth-main">
<div class="mt-4"> <div class="auth-wrapper v3">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" /> <div class="auth-form">
<div class="auth-header">
<x-text-input id="password_confirmation" class="block mt-1 w-full" <a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div> </div>
<div class="card my-5">
<div class="flex items-center justify-end mt-4"> <div class="card-body">
<x-primary-button> <div class="d-flex justify-content-between align-items-end mb-4">
{{ __('Reset Password') }} <h3 class="mb-0"><b>Reset Password</b></h3>
</x-primary-button> {{-- <a href="#" class="link-primary">Don't have an account?</a> --}}
</div> </div>
</form> <div class="form-group mb-3">
</x-guest-layout> <label class="form-label">Email Address</label>
<input type="email" id="email" class="form-control" placeholder="Email Address" value="{{ request()->get('email') }}">
</div>
<div class="form-group mb-3">
<label class="form-label">Password</label>
<input type="password" id="password" class="form-control" placeholder="Password">
</div>
<div class="form-group mb-3">
<label class="form-label">Confirm Password</label>
<input type="password" id="password_confirmation" class="form-control" placeholder="Confirm Password">
</div>
<input type="hidden" id="reset_token" value="{{ request()->route('token') }}">
<div class="d-flex mt-1 justify-content-between">
<h5 class="text-secondary f-w-400"><a href="{{ route('password.request') }}">Forgot Password?</a></h5>
</div>
<div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doResetPassword()">Reset Password</button>
</div>
</div>
</div>
<div class="auth-footer row">
<!-- <div class=""> -->
<div class="col my-1">
<p class="m-0">Copyright {{ date('Y') }} © <a href="https://polije.ac.id" target="_blank"> Politeknik Negeri Jember</a></p>
</div>
<div class="col-auto my-1">
<ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
</ul>
</div>
<!-- </div> -->
</div>
</div>
</div>
</div>
<!-- [ Main Content ] end -->
<!-- Required Js -->
<script src="{{ asset('assets/admin/assets/js/plugins/popper.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/simplebar.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/bootstrap.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/fonts/custom-font.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/pcoded.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/feather.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>layout_change('light');</script>
<script>change_box_container('false');</script>
<script>layout_rtl_change('false');</script>
<script>preset_change("preset-1");</script>
<script>font_change("Public-Sans");</script>
<script>
function doResetPassword() {
try {
let csrfToken = document.getElementById('_token').getAttribute('value');
let resetToken = document.getElementById('reset_token').value;
let email = document.getElementById('email').value;
let password = document.getElementById('password').value;
let password_confirmation = document.getElementById('password_confirmation').value;
if(email == '' || email == null) {
Swal.fire({
title: "Info",
text: "Email tidak boleh kosong!",
icon: "warning"
});
return;
}
if(password == '' || password == null) {
Swal.fire({
title: "Info",
text: "Password tidak boleh kosong!",
icon: "warning"
});
return;
}
if(password !== password_confirmation) {
Swal.fire({
title: "Info",
text: "Password dan konfirmasi password tidak cocok!",
icon: "warning"
});
return;
}
let xhttp = new XMLHttpRequest();
let formData = new FormData();
formData.append('_token', csrfToken);
formData.append('token', resetToken);
formData.append('email', email);
formData.append('password', password);
formData.append('password_confirmation', password_confirmation);
xhttp.onreadystatechange = function() {
if(this.status == 200) {
let jsonData = JSON.parse(this.responseText);
if(jsonData.status) {
Swal.fire({
title: "Info",
text: "Password berhasil direset!",
icon: "success"
});
window.location.href = '{{ route('login') }}';
} else {
Swal.fire({
title: "Info",
text: "Terdapat kesalahan!",
icon: "error"
});
}
} else {
Swal.fire({
title: "Info",
text: "Reset password gagal, koneksi ke server gagal, coba lagi nanti!",
icon: "error"
});
}
}
xhttp.open('POST', '{{ route("password.store") }}', false);
xhttp.send(formData);
} catch(error) {
Swal.fire({
title: "Info",
text: "Reset password gagal, kesalahan pada server, coba lagi nanti!",
icon: "error"
});
}
}
</script>
</body>
<!-- [Body] end -->
</html>