Halaman Account Settings
This commit is contained in:
parent
2e9086a761
commit
3d4a23ddcd
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Hapus middleware verified karena kita akan mengizinkan user yang belum terverifikasi
|
||||
// untuk mengakses pengaturan akun mereka
|
||||
$this->middleware(['auth']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the account settings page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function settings()
|
||||
{
|
||||
$user = Auth::user();
|
||||
return view('account.settings', compact('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's account information.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
'current_password' => ['nullable', 'required_with:password', 'string'],
|
||||
'password' => ['nullable', 'string', 'min:8', 'confirmed'],
|
||||
]);
|
||||
|
||||
// Check if current password is provided and is correct
|
||||
if ($request->filled('current_password')) {
|
||||
if (!Hash::check($request->current_password, $user->password)) {
|
||||
return back()->withErrors(['current_password' => 'Password saat ini tidak valid.']);
|
||||
}
|
||||
}
|
||||
|
||||
// Update user information
|
||||
$user->name = $validated['name'];
|
||||
|
||||
// Check if email is changed
|
||||
$emailChanged = $user->email !== $validated['email'];
|
||||
if ($emailChanged) {
|
||||
$user->email = $validated['email'];
|
||||
|
||||
// Set email_verified_at ke null hanya jika sebelumnya sudah terverifikasi
|
||||
// Ini untuk memastikan user harus verifikasi email baru
|
||||
if ($user->hasVerifiedEmail()) {
|
||||
$user->email_verified_at = null;
|
||||
$emailNeedsVerification = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update password if provided
|
||||
if ($request->filled('password')) {
|
||||
$user->password = Hash::make($validated['password']);
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
// Jika email diubah dan sebelumnya sudah terverifikasi, kirim email verifikasi baru
|
||||
if ($emailChanged && isset($emailNeedsVerification)) {
|
||||
$user->sendEmailVerificationNotification();
|
||||
session()->flash('success', 'Profil berhasil diperbarui. Silakan verifikasi alamat email baru Anda.');
|
||||
} else {
|
||||
session()->flash('success', 'Profil berhasil diperbarui.');
|
||||
}
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@
|
|||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\ConfirmsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ConfirmPasswordController extends Controller
|
||||
{
|
||||
|
@ -14,7 +16,7 @@ class ConfirmPasswordController extends Controller
|
|||
|
|
||||
| This controller is responsible for handling password confirmations and
|
||||
| uses a simple trait to include the behavior. You're free to explore
|
||||
| this trait and override any functions that require customization.
|
||||
| this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
|
@ -25,7 +27,7 @@ class ConfirmPasswordController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
protected $redirectTo = '/';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
|
@ -36,4 +38,62 @@ public function __construct()
|
|||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the password confirmation view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showConfirmForm()
|
||||
{
|
||||
return view('auth.passwords.confirm');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the given user's password.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function confirm(Request $request)
|
||||
{
|
||||
$request->validate($this->rules(), $this->validationErrorMessages());
|
||||
|
||||
$this->resetPasswordConfirmationTimeout($request);
|
||||
|
||||
return redirect()->intended($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the password confirmation timeout.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
protected function resetPasswordConfirmationTimeout(Request $request)
|
||||
{
|
||||
$request->session()->put('auth.password_confirmed_at', time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password confirmation validation rules.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function rules()
|
||||
{
|
||||
return [
|
||||
'password' => 'required|password',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password confirmation validation error messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function validationErrorMessages()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
|
@ -19,4 +21,73 @@ class ForgotPasswordController extends Controller
|
|||
*/
|
||||
|
||||
use SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the form to request a password reset link.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return view('auth.passwords.email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
$this->validateEmail($request);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
$response = $this->broker()->sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
|
||||
return $response == Password::RESET_LINK_SENT
|
||||
? $this->sendResetLinkResponse($request, $response)
|
||||
: $this->sendResetLinkFailedResponse($request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a successful password reset link.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $response
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function sendResetLinkResponse(Request $request, $response)
|
||||
{
|
||||
session()->flash('success', trans($response));
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a failed password reset link.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $response
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function sendResetLinkFailedResponse(Request $request, $response)
|
||||
{
|
||||
session()->flash('error', trans($response));
|
||||
return back()
|
||||
->withInput($request->only('email'));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@
|
|||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
|
@ -25,5 +27,43 @@ class ResetPasswordController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
protected $redirectTo = '/';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a successful password reset.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $response
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function sendResetResponse(Request $request, $response)
|
||||
{
|
||||
session()->flash('success', trans($response));
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a failed password reset.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $response
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function sendResetFailedResponse(Request $request, $response)
|
||||
{
|
||||
session()->flash('error', trans($response));
|
||||
return redirect()->back()
|
||||
->withInput($request->only('email'))
|
||||
->withErrors(['email' => trans($response)]);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@
|
|||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\VerifiesEmails;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class VerificationController extends Controller
|
||||
{
|
||||
|
@ -25,7 +27,7 @@ class VerificationController extends Controller
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
protected $redirectTo = '/';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
|
@ -38,4 +40,55 @@ public function __construct()
|
|||
$this->middleware('signed')->only('verify');
|
||||
$this->middleware('throttle:6,1')->only('verify', 'resend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the email verification notice.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
// Jika user sudah terverifikasi, redirect ke halaman utama
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect($this->redirectPath())
|
||||
->with('success', 'Email anda sudah terverifikasi.');
|
||||
}
|
||||
|
||||
// Jika user belum terverifikasi dan baru register (email_verified_at adalah null),
|
||||
// tampilkan halaman verifikasi
|
||||
return view('auth.verify');
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has been verified.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
protected function verified(Request $request)
|
||||
{
|
||||
session()->flash('success', 'Email berhasil diverifikasi! Selamat datang di Ayo Venue.');
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resend the email verification notification.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function resend(Request $request)
|
||||
{
|
||||
// Jika user sudah terverifikasi, tidak perlu kirim ulang
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect($this->redirectPath())
|
||||
->with('success', 'Email anda sudah terverifikasi.');
|
||||
}
|
||||
|
||||
// Kirim email verifikasi baru
|
||||
$request->user()->sendEmailVerificationNotification();
|
||||
|
||||
return back()->with('success', 'Link verifikasi baru telah dikirim ke email anda.');
|
||||
}
|
||||
}
|
|
@ -61,7 +61,7 @@ class Kernel extends HttpKernel
|
|||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
|
||||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'is_admin' => \App\Http\Middleware\IsAdmin::class,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class IsAdmin
|
||||
|
@ -10,14 +12,17 @@ class IsAdmin
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (auth()->check() && auth()->user()->role === 'admin') {
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (Auth::check() && Auth::user()->role === 'admin') {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
abort(403); // atau redirect('/login')
|
||||
}
|
||||
session()->flash('error', 'Anda tidak memiliki akses ke halaman tersebut!');
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
|
||||
|
@ -42,4 +42,14 @@ class User extends Authenticatable
|
|||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
|
||||
/**
|
||||
* Check if the user is an admin.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAdmin()
|
||||
{
|
||||
return $this->role === 'admin';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="py-12 animated-bg">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg border-0 rounded-3 overflow-hidden">
|
||||
<div class="card-header bg-gradient-to-r from-indigo-600 to-blue-500 text-white p-3">
|
||||
<h2 class="mb-0 d-flex align-items-center">
|
||||
<i class="fas fa-user-cog me-2"></i>{{ __('Account Settings') }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
|
||||
@if (session('message'))
|
||||
<div class="alert alert-success d-flex align-items-center border-0 shadow-sm mb-4" role="alert">
|
||||
<div class="me-2">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</div>
|
||||
<div>
|
||||
{{ session('message') }}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success d-flex align-items-center border-0 shadow-sm mb-4" role="alert">
|
||||
<div class="me-2">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</div>
|
||||
<div>
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('account.update') }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<!-- Name -->
|
||||
<div class="mb-4">
|
||||
<label for="name" class="form-label fw-medium">
|
||||
<i class="fas fa-user text-primary me-1"></i>{{ __('Name') }}
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="fas fa-user-edit"></i>
|
||||
</span>
|
||||
<input id="name" type="text" name="name" value="{{ old('name', $user->name) }}"
|
||||
required autofocus class="form-control border-start-0"
|
||||
placeholder="Enter your name">
|
||||
</div>
|
||||
@error('name')
|
||||
<div class="text-danger mt-1 small"><i
|
||||
class="fas fa-exclamation-circle me-1"></i>{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="mb-4">
|
||||
<label for="email" class="form-label fw-medium">
|
||||
<i class="fas fa-envelope text-primary me-1"></i>{{ __('Email') }}
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="fas fa-at"></i>
|
||||
</span>
|
||||
<input id="email" type="email" name="email" value="{{ old('email', $user->email) }}"
|
||||
required class="form-control border-start-0" placeholder="Enter your email">
|
||||
</div>
|
||||
@error('email')
|
||||
<div class="text-danger mt-1 small"><i
|
||||
class="fas fa-exclamation-circle me-1"></i>{{ $message }}</div>
|
||||
@enderror
|
||||
@if ($user->email)
|
||||
<div class="mt-2 small d-flex align-items-center">
|
||||
@if ($user->hasVerifiedEmail())
|
||||
<span class="text-success d-flex align-items-center">
|
||||
<i class="fas fa-check-circle me-1"></i> {{ __('Email verified') }}
|
||||
</span>
|
||||
@else
|
||||
<span class="text-warning d-flex align-items-center">
|
||||
<i class="fas fa-exclamation-circle me-1"></i> {{ __('Not Verified') }}
|
||||
</span>
|
||||
<a href="{{ route('verification.resend') }}"
|
||||
class="ms-2 text-primary text-decoration-none">
|
||||
{{ __('Resend verification email') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="card mt-4 mb-4 shadow-sm border-0">
|
||||
<div class="card-header bg-light">
|
||||
<h3 class="mb-0 fs-5 fw-semibold text-primary">
|
||||
<i class="fas fa-lock me-2"></i>{{ __('Change Password') }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Current Password -->
|
||||
<div class="mb-3">
|
||||
<label for="current_password" class="form-label fw-medium">
|
||||
<i class="fas fa-key text-primary me-1"></i>{{ __('Current Password') }}
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
<input id="current_password" type="password" name="current_password"
|
||||
class="form-control border-start-0"
|
||||
placeholder="Enter current password">
|
||||
<button class="btn btn-outline-secondary" type="button"
|
||||
id="toggleCurrentPassword">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
@error('current_password')
|
||||
<div class="text-danger mt-1 small"><i
|
||||
class="fas fa-exclamation-circle me-1"></i>{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- New Password -->
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label fw-medium">
|
||||
<i class="fas fa-lock-open text-primary me-1"></i>{{ __('New Password') }}
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="fas fa-key"></i>
|
||||
</span>
|
||||
<input id="password" type="password" name="password"
|
||||
class="form-control border-start-0" placeholder="Enter new password">
|
||||
<button class="btn btn-outline-secondary" type="button"
|
||||
id="toggleNewPassword">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
@error('password')
|
||||
<div class="text-danger mt-1 small"><i
|
||||
class="fas fa-exclamation-circle me-1"></i>{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Confirm New Password -->
|
||||
<div class="mb-3">
|
||||
<label for="password_confirmation" class="form-label fw-medium">
|
||||
<i class="fas fa-check-double text-primary me-1"></i>{{ __('Confirm New Password') }}
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="fas fa-key"></i>
|
||||
</span>
|
||||
<input id="password_confirmation" type="password" name="password_confirmation"
|
||||
class="form-control border-start-0" placeholder="Confirm new password">
|
||||
<button class="btn btn-outline-secondary" type="button"
|
||||
id="toggleConfirmPassword">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-4">
|
||||
<button type="submit"
|
||||
class="btn btn-primary-custom d-flex align-items-center">
|
||||
<i class="fas fa-save me-2"></i>{{ __('Update Account') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@keyframes fade-in-down {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in-down {
|
||||
animation: fade-in-down 0.5s ease-out;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Toggle password visibility
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const toggleCurrentPassword = document.getElementById('toggleCurrentPassword');
|
||||
const toggleNewPassword = document.getElementById('toggleNewPassword');
|
||||
const toggleConfirmPassword = document.getElementById('toggleConfirmPassword');
|
||||
|
||||
const currentPassword = document.getElementById('current_password');
|
||||
const newPassword = document.getElementById('password');
|
||||
const confirmPassword = document.getElementById('password_confirmation');
|
||||
|
||||
if(toggleCurrentPassword) {
|
||||
toggleCurrentPassword.addEventListener('click', function() {
|
||||
togglePasswordVisibility(currentPassword, this);
|
||||
});
|
||||
}
|
||||
|
||||
if(toggleNewPassword) {
|
||||
toggleNewPassword.addEventListener('click', function() {
|
||||
togglePasswordVisibility(newPassword, this);
|
||||
});
|
||||
}
|
||||
|
||||
if(toggleConfirmPassword) {
|
||||
toggleConfirmPassword.addEventListener('click', function() {
|
||||
togglePasswordVisibility(confirmPassword, this);
|
||||
});
|
||||
}
|
||||
|
||||
function togglePasswordVisibility(input, button) {
|
||||
const type = input.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
input.setAttribute('type', type);
|
||||
|
||||
// Toggle icon
|
||||
const icon = button.querySelector('i');
|
||||
if (type === 'text') {
|
||||
icon.classList.remove('fa-eye');
|
||||
icon.classList.add('fa-eye-slash');
|
||||
} else {
|
||||
icon.classList.remove('fa-eye-slash');
|
||||
icon.classList.add('fa-eye');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
|
@ -1,23 +1,26 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Confirm Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
{{ __('Please confirm your password before continuing.') }}
|
||||
<p class="mb-3">{{ __('Please confirm your password before continuing.') }}</p>
|
||||
|
||||
<form method="POST" action="{{ route('password.confirm') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
<label for="password"
|
||||
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
|
||||
<input id="password" type="password"
|
||||
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||
required autocomplete="current-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
|
@ -28,7 +31,7 @@
|
|||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Confirm Password') }}
|
||||
</button>
|
||||
|
@ -45,5 +48,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -1,7 +1,7 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
|
@ -18,10 +18,12 @@
|
|||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
<label for="email"
|
||||
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
|
@ -43,5 +45,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -1,7 +1,7 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
|
@ -14,10 +14,13 @@
|
|||
<input type="hidden" name="token" value="{{ $token }}">
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
<label for="email"
|
||||
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror"
|
||||
name="email" value="{{ $email ?? old('email') }}" required autocomplete="email"
|
||||
autofocus>
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
|
@ -28,10 +31,13 @@
|
|||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
<label for="password"
|
||||
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
|
||||
<input id="password" type="password"
|
||||
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||
required autocomplete="new-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
|
@ -42,10 +48,12 @@
|
|||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||
<label for="password-confirm"
|
||||
class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
<input id="password-confirm" type="password" class="form-control"
|
||||
name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -61,5 +69,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -1,28 +1,49 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-md mx-auto bg-white shadow-lg rounded-lg overflow-hidden">
|
||||
<div class="bg-blue-600 px-6 py-4">
|
||||
<h2 class="text-xl font-bold text-white">{{ __('Verifikasi Email Anda') }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="p-6">
|
||||
@if (session('resent'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ __('A fresh verification link has been sent to your email address.') }}
|
||||
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-4" role="alert">
|
||||
<p>{{ __('Link verifikasi baru telah dikirim ke alamat email Anda.') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ __('Before proceeding, please check your email for a verification link.') }}
|
||||
{{ __('If you did not receive the email') }},
|
||||
<form class="d-inline" method="POST" action="{{ route('verification.resend') }}">
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center mb-4">
|
||||
<i class="fas fa-envelope-open-text text-blue-500 text-3xl mr-4"></i>
|
||||
<div>
|
||||
<p class="text-gray-700">
|
||||
{{ __('Sebelum melanjutkan, silakan periksa email Anda untuk link verifikasi.') }}</p>
|
||||
<p class="text-sm text-gray-500 mt-1">
|
||||
{{ __('Email verifikasi biasanya dikirim dalam beberapa menit.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 p-4 rounded-lg mb-4">
|
||||
<p class="text-gray-600 text-sm">
|
||||
<i class="fas fa-info-circle text-blue-500 mr-2"></i>
|
||||
{{ __('Tidak perlu khawatir. Anda sudah dapat login dan menggunakan fitur dasar Ayo Venue. Verifikasi email ini hanya diperlukan untuk fitur tertentu dan keamanan akun Anda.') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<p class="text-gray-700 mb-4">{{ __('Tidak menerima email verifikasi?') }}</p>
|
||||
<form method="POST" action="{{ route('verification.resend') }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>.
|
||||
<button type="submit"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition duration-200">
|
||||
{{ __('Kirim Ulang Verifikasi') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -4,27 +4,220 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- CSRF Token -->
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #4F46E5;
|
||||
--primary-hover: #4338CA;
|
||||
--secondary-color: #38BDF8;
|
||||
--accent-color: #8B5CF6;
|
||||
--bg-gradient-start: #EEF2FF;
|
||||
--bg-gradient-end: #E0E7FF;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: linear-gradient(135deg, var(--bg-gradient-start) 0%, var(--bg-gradient-end) 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-weight: 700;
|
||||
font-size: 1.5rem;
|
||||
background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.navbar-brand:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-link:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: var(--primary-color);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-link:hover:after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
border: none;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
border-radius: 0.375rem;
|
||||
transition: all 0.2s ease;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: #EEF2FF;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
main {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* Custom animated navbar */
|
||||
.custom-navbar {
|
||||
background-color: rgba(255, 255, 255, 0.9) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
padding: 1rem 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.custom-navbar.scrolled {
|
||||
padding: 0.5rem 0;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.btn-primary-custom {
|
||||
background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
padding: 0.5rem 1.25rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-primary-custom:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 15px -3px rgba(79, 70, 229, 0.4);
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
background: var(--accent-color);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background-color: #10B981;
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 1.5rem 0;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
/* Animated background for special sections */
|
||||
.animated-bg {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.animated-bg:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(45deg,
|
||||
rgba(79, 70, 229, 0.1) 0%,
|
||||
rgba(56, 189, 248, 0.1) 33%,
|
||||
rgba(139, 92, 246, 0.1) 66%,
|
||||
rgba(79, 70, 229, 0.1) 100%);
|
||||
animation: rotate 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
|
||||
<nav class="navbar navbar-expand-md custom-navbar navbar-light sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
<a class="navbar-brand d-flex align-items-center" href="{{ url('/') }}">
|
||||
<i class="fas fa-cube me-2"></i>
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
|
||||
|
@ -34,7 +227,16 @@
|
|||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<!-- Left Side Of Navbar -->
|
||||
<ul class="navbar-nav me-auto">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url('/') }}">
|
||||
<i class="fas fa-tachometer-alt me-1"></i> Venue
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url('/booking/history') }}">
|
||||
<i class="fas fa-tasks me-1"></i> Riwayat Booking
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
|
@ -43,26 +245,44 @@
|
|||
@guest
|
||||
@if (Route::has('login'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
|
||||
<a class="nav-link" href="{{ route('login') }}">
|
||||
<i class="fas fa-sign-in-alt me-1"></i> {{ __('Login') }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if (Route::has('register'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
|
||||
<a class="btn btn-primary-custom" href="{{ route('register') }}">
|
||||
<i class="fas fa-user-plus me-1"></i> {{ __('Register') }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
|
||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||
{{ Auth::user()->name }}
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle d-flex align-items-center" href="#"
|
||||
role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
|
||||
v-pre>
|
||||
<div class="avatar-wrapper">
|
||||
<img src="https://ui-avatars.com/api/?name={{ urlencode(Auth::user()->name) }}&background=4F46E5&color=fff"
|
||||
alt="User Avatar" class="user-avatar">
|
||||
<span class="status-indicator"></span>
|
||||
</div>
|
||||
<span>{{ Auth::user()->name }}</span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault();
|
||||
<a class="dropdown-item" href="{{ route('account.settings') }}">
|
||||
<i class="fas fa-cog me-2"></i> {{ __('Settings') }}
|
||||
</a>
|
||||
<a class="dropdown-item" href="{{ route('account.settings') }}">
|
||||
<i class="fas fa-user-circle me-2"></i> {{ __('Profile') }}
|
||||
</a>
|
||||
<hr class="dropdown-divider">
|
||||
<a class="dropdown-item text-danger" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
{{ __('Logout') }}
|
||||
<i class="fas fa-sign-out-alt me-2"></i> {{ __('Logout') }}
|
||||
</a>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
|
@ -79,7 +299,36 @@
|
|||
<main class="py-4">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<footer class="mt-auto">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p class="mb-0">© {{ date('Y') }} {{ config('app.name', 'Laravel') }}. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
<a href="#" class="text-decoration-none me-3"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="#" class="text-decoration-none me-3"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#" class="text-decoration-none me-3"><i class="fab fa-instagram"></i></a>
|
||||
<a href="#" class="text-decoration-none"><i class="fab fa-linkedin-in"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Navbar scroll effect
|
||||
window.addEventListener('scroll', function () {
|
||||
const navbar = document.querySelector('.custom-navbar');
|
||||
if (window.scrollY > 10) {
|
||||
navbar.classList.add('scrolled');
|
||||
} else {
|
||||
navbar.classList.remove('scrolled');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -39,9 +39,6 @@ class="block lg:hidden border-l pl-4 border-gray-300 focus:outline-none">
|
|||
<!-- Desktop buttons -->
|
||||
<div class="hidden lg:flex items-center space-x-4">
|
||||
@auth
|
||||
<a href="{{ route('booking.history') }}"
|
||||
class="text-sm font-medium text-gray-700 hover:text-primary transition">Riwayat Booking</a>
|
||||
|
||||
<div x-data="{ open: false }" class="relative">
|
||||
<button @click="open = !open"
|
||||
class="flex items-center space-x-2 text-sm font-medium text-gray-700 hover:text-primary focus:outline-none">
|
||||
|
@ -58,6 +55,17 @@ class="absolute right-0 mt-2 w-40 bg-white rounded-lg shadow-lg py-2 z-50">
|
|||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
Riwayat Booking
|
||||
</a>
|
||||
<a href="{{ route('account.settings') }}"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
Pengaturan Akun
|
||||
</a>
|
||||
@if (Auth::user()->email_verified_at === null)
|
||||
<a href="{{ route('verification.notice') }}"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
<span class="text-orange-500"><i class="fas fa-exclamation-circle mr-1"></i></span>
|
||||
Verifikasi Email
|
||||
</a>
|
||||
@endif
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit"
|
||||
|
@ -83,6 +91,17 @@ class="absolute top-full left-0 right-0 bg-white shadow-md mt-1 p-4 z-50">
|
|||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
Riwayat Booking
|
||||
</a>
|
||||
<a href="{{ route('account.settings') }}"
|
||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
Pengaturan Akun
|
||||
</a>
|
||||
@if (Auth::user()->email_verified_at === null)
|
||||
<a href="{{ route('verification.notice') }}"
|
||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
<span class="text-orange-500"><i class="fas fa-exclamation-circle mr-1"></i></span>
|
||||
Verifikasi Email
|
||||
</a>
|
||||
@endif
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit"
|
||||
|
@ -125,6 +144,19 @@ class="absolute top-3 right-4 text-gray-500 hover:text-gray-700 text-xl">
|
|||
required>
|
||||
<input type="password" name="password" placeholder="Password"
|
||||
class="w-full border px-4 py-2 rounded" required>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<input class="mr-2" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
<label class="text-sm text-gray-600" for="remember">
|
||||
Ingat saya
|
||||
</label>
|
||||
</div>
|
||||
<a href="{{ route('password.request') }}" class="text-sm text-primary hover:underline">
|
||||
Lupa Password?
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Masuk</button>
|
||||
</form>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\AccountController;
|
||||
use App\Http\Controllers\pages\HomeController;
|
||||
use App\Http\Controllers\pages\VenueController;
|
||||
use App\Http\Controllers\pages\BookingController;
|
||||
|
@ -10,7 +11,9 @@
|
|||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
Auth::routes();
|
||||
// Authentication Routes (dengan verifikasi email aktif)
|
||||
Auth::routes(['verify' => true]);
|
||||
|
||||
Route::get('/', [HomeController::class, "index"])->name('index');
|
||||
Route::get('/venue/{venueName}', [VenueController::class, "venue"])->name('venue');
|
||||
|
||||
|
@ -20,7 +23,7 @@
|
|||
Route::get('/booking/schedules', [BookingController::class, 'getBookedSchedules'])->name('booking.schedules');
|
||||
Route::post('/payment/notification', [BookingController::class, 'handleNotification'])->name('payment.notification');
|
||||
|
||||
// Booking history routes (authenticated only)
|
||||
// Booking history routes (authenticated only, tidak perlu verified)
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/booking/history', [BookingHistoryController::class, 'index'])->name('booking.history');
|
||||
|
||||
|
@ -28,9 +31,20 @@
|
|||
Route::get('/booking/pending', [BookingController::class, 'getPendingBookings'])->name('booking.pending');
|
||||
Route::get('/booking/pending/{id}/resume', [BookingController::class, 'resumeBooking'])->name('booking.resume');
|
||||
Route::delete('/booking/pending/{id}', [BookingController::class, 'deletePendingBooking'])->name('booking.pending.delete');
|
||||
|
||||
// Profile route definition - use the existing account settings as the profile page
|
||||
Route::get('/profile', [AccountController::class, 'settings'])->name('profile');
|
||||
|
||||
// Routes that require password confirmation
|
||||
Route::middleware(['password.confirm'])->group(function () {
|
||||
// Add routes that require password confirmation here
|
||||
// For example, account settings, deleting accounts, etc.
|
||||
Route::get('/account/settings', [AccountController::class, 'settings'])->name('account.settings');
|
||||
Route::put('/account/update', [AccountController::class, 'update'])->name('account.update');
|
||||
});
|
||||
});
|
||||
|
||||
// Admin routes
|
||||
// Admin routes (admin tetap perlu verified untuk keamanan)
|
||||
Route::middleware(['auth', 'is_admin'])->prefix('admin')->group(function () {
|
||||
Route::get('/', [AdminController::class, 'index'])->name('admin.dashboard');
|
||||
Route::get('/bookings', [BookingsController::class, 'index'])->name('admin.bookings.index');
|
||||
|
|
Loading…
Reference in New Issue