Merge pull request #1 from arieeefajar/feat/auth

Feat/auth
This commit is contained in:
Arie Fajar Bachtiar 2025-01-27 12:57:27 +07:00 committed by GitHub
commit a4413389f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 6547 additions and 9 deletions

View File

@ -0,0 +1,57 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Queue\Jobs\RedisJob;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*/
public function create(): View
{
// alert()->success('success', 'success');
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
$user = Auth::user();
if ($user->role == "admin") {
return redirect()->route('dashboard.admin');
}
return redirect()->route('dashboard.petugas');
}
/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
class ConfirmablePasswordController extends Controller
{
/**
* Show the confirm password view.
*/
public function show(): View
{
return view('auth.confirm-password');
}
/**
* Confirm the user's password.
*/
public function store(Request $request): RedirectResponse
{
if (! Auth::guard('web')->validate([
'email' => $request->user()->email,
'password' => $request->password,
])) {
throw ValidationException::withMessages([
'password' => __('auth.password'),
]);
}
$request->session()->put('auth.password_confirmed_at', time());
return redirect()->intended(RouteServiceProvider::HOME);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class EmailVerificationNotificationController extends Controller
{
/**
* Send a new email verification notification.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(RouteServiceProvider::HOME);
}
$request->user()->sendEmailVerificationNotification();
return back()->with('status', 'verification-link-sent');
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class EmailVerificationPromptController extends Controller
{
/**
* Display the email verification prompt.
*/
public function __invoke(Request $request): RedirectResponse|View
{
return $request->user()->hasVerifiedEmail()
? redirect()->intended(RouteServiceProvider::HOME)
: view('auth.verify-email');
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
class NewPasswordController extends Controller
{
/**
* Display the password reset view.
*/
public function create(Request $request): View
{
return view('auth.reset-password', ['request' => $request]);
}
/**
* Handle an incoming new password request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'token' => ['required'],
'email' => ['required', 'email'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user) use ($request) {
$user->forceFill([
'password' => Hash::make($request->password),
'remember_token' => Str::random(60),
])->save();
event(new PasswordReset($user));
}
);
// 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
// redirect them back to where they came from with their error message.
return $status == Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
class PasswordController extends Controller
{
/**
* Update the user's password.
*/
public function update(Request $request): RedirectResponse
{
$validated = $request->validateWithBag('updatePassword', [
'current_password' => ['required', 'current_password'],
'password' => ['required', Password::defaults(), 'confirmed'],
]);
$request->user()->update([
'password' => Hash::make($validated['password']),
]);
return back()->with('status', 'password-updated');
}
}

View File

@ -0,0 +1,93 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Mail\ResetPasswordMail;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\View\View;
class PasswordResetLinkController extends Controller
{
/**
* Display the password reset link request view.
*/
public function create(): View
{
return view('auth.forgot-password');
}
/**
* Handle an incoming password reset link request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$customMessages = [
'email.required' => 'Email tidak boleh kosong',
'email.email' => 'Email tidak valid',
'email.exists' => 'Email tidak terdaftar',
];
$validator = Validator::make($request->all(), [
'email' => ['required', 'email', 'exists:users,email'],
], $customMessages);
if ($validator->fails()) {
toast($validator->messages()->all()[0], 'error')->position('top')->autoclose(3000);
return redirect()->back()->withInput();
}
DB::table('password_reset_tokens')->updateOrInsert(
['email' => $request->email],
[
'token' => Hash::make($request->_token),
'created_at' => now(),
]
);
$resetLink = route('auth.create_new_password_form', ['token' => $request->_token, 'email' => $request->email]);
Mail::to($request->email)->send(new ResetPasswordMail($resetLink));
alert()->success('Berhasil', 'Silahkan cek email anda untuk mereset password');
return redirect()->back();
}
public function createNewPasswordForm(Request $request)
{
return view('auth.reset-password-form', ['token' => $request->token, 'email' => $request->email]);
}
public function storeNewPasswordForm(Request $request)
{
$data = DB::table('password_reset_tokens')->where('email', $request->email)->first();
if ($data == null || !Hash::check($request->token, $data->token)) {
toast('Link reset password tidak valid atau kedaluwarsa', 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
DB::beginTransaction();
$user = User::where('email', $request->email)->first();
$user->password = Hash::make($request->new_password);
try {
$user->save();
DB::table('password_reset_tokens')->where('email', $request->email)->delete();
DB::commit();
alert()->success('Berhasil', 'Password berhasil direset, silahkan login');
return redirect()->route('auth.login');
} catch (\Throwable $th) {
DB::rollBack();
toast('Terjadi kesalahan', 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Mail\ActivationAccountMail;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*/
public function create(): View
{
return view('auth.register');
}
/**
* Handle an incoming registration request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$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'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
], $customMessage);
if ($validator->fails()) {
toast($validator->messages()->all()[0], 'error')->position('top')->autoclose(3000);
return redirect()->back()->withInput();
}
$activationCode = Str::random(4);
DB::beginTransaction();
$user = new User();
$user->username = $request->username;
$user->name = $request->name;
$user->email = $request->email;
$user->password = Hash::make($request->password);
$user->activation_code = $activationCode;
$user->is_active = false;
try {
$user->save();
DB::commit();
Mail::to($request->email)->send(new ActivationAccountMail($user));
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,56 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Mail\ActivationAccountMail;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class TwoStepVerifyController extends Controller
{
public function create($email)
{
return view('auth.two-step-verifycation', compact('email'));
}
public function store(Request $request)
{
DB::beginTransaction();
try {
$user = User::where('email', $request->email)->first();
$userActivationCode = $user->activation_code;
$activationCodeRequest = $request->digit1 . $request->digit2 . $request->digit3 . $request->digit4;
if ($userActivationCode == $activationCodeRequest) {
$user->activation_code = null;
$user->is_active = 1;
$user->save();
DB::commit();
toast('Akun anda telah diaktifkan', 'success')->position('top')->autoclose(3000);
return redirect()->route('auth.login');
}
} catch (\Throwable $th) {
DB::rollBack();
toast($th->getMessage(), 'error')->position('top')->autoclose(3000);
return redirect()->back();
}
}
public function resendEmail(Request $request)
{
DB::beginTransaction();
try {
$user = User::where('email', $request->email)->first();
Mail::to($user->email)->send(new ActivationAccountMail($user));
toast('Kode verifikasi telah dikirim', '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,28 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\RedirectResponse;
class VerifyEmailController extends Controller
{
/**
* Mark the authenticated user's email address as verified.
*/
public function __invoke(EmailVerificationRequest $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(RouteServiceProvider::HOME . '?verified=1');
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect()->intended(RouteServiceProvider::HOME . '?verified=1');
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function admin()
{
return view('dashboard.admin');
}
public function petugas()
{
return view('dashboard.petugas');
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\ProfileUpdateRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
class ProfileController extends Controller
{
/**
* Display the user's profile form.
*/
public function edit(Request $request): View
{
return view('profile.edit', [
'user' => $request->user(),
]);
}
/**
* Update the user's profile information.
*/
public function update(ProfileUpdateRequest $request): RedirectResponse
{
$request->user()->fill($request->validated());
if ($request->user()->isDirty('email')) {
$request->user()->email_verified_at = null;
}
$request->user()->save();
return Redirect::route('profile.edit')->with('status', 'profile-updated');
}
/**
* Delete the user's account.
*/
public function destroy(Request $request): RedirectResponse
{
$request->validateWithBag('userDeletion', [
'password' => ['required', 'current_password'],
]);
$user = $request->user();
Auth::logout();
$user->delete();
$request->session()->invalidate();
$request->session()->regenerateToken();
return Redirect::to('/');
}
}

View File

@ -63,5 +63,6 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'verifiedAcount' => \App\Http\Middleware\verifiedAcount::class,
];
}

View File

@ -12,6 +12,6 @@ class Authenticate extends Middleware
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
return $request->expectsJson() ? null : route('auth.login');
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class verifiedAcount
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next)
{
$user = auth()->user();
if ($user && $user->is_active == 0) {
auth()->logout();
toast('Akun anda belum diaktivasi, silahkan hubungi admin', 'error')->position('top')->autoclose(5000);
return redirect()->route('auth.login');
}
return $next($request);
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace App\Http\Requests\Auth;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class LoginRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
return [
'username' => ['required', 'string', 'exists:users,username'],
'password' => ['required', 'string'],
];
}
/**
* Attempt to authenticate the request's credentials.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('username', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'username' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
/**
* Ensure the login request is not rate limited.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'username' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->string('username')) . '|' . $this->ip());
}
public function messages(): array
{
return [
'username.exists' => 'Username does not exist',
'username.required' => 'Username is required',
'password.required' => 'Password is required',
];
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Http\Requests;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ProfileUpdateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique(User::class)->ignore($this->user()->id)],
];
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ActivationAccountMail extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Activation Account Mail',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'auth.activation-account-mail',
with: [
'name' => $this->user->name,
'activationCode' => $this->user->activation_code
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ResetPasswordMail extends Mailable
{
use Queueable, SerializesModels;
public $resetLink;
/**
* Create a new message instance.
*/
public function __construct($resetLink)
{
$this->resetLink = $resetLink;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Reset Password Mail',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'auth.mail-reset-password',
with: [
'resetLink' => $this->resetLink
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@ -18,9 +18,11 @@ class User extends Authenticatable
* @var array<int, string>
*/
protected $fillable = [
'username',
'name',
'email',
'password',
'role',
];
/**

View File

@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
*
* @var string
*/
public const HOME = '/home';
public const HOME = '/dashboard';
/**
* Define your route model bindings, pattern filters, and other route configuration.

View File

@ -0,0 +1,17 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
class AppLayout extends Component
{
/**
* Get the view / contents that represents the component.
*/
public function render(): View
{
return view('layouts.app');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
class GuestLayout extends Component
{
/**
* Get the view / contents that represents the component.
*/
public function render(): View
{
return view('layouts.guest');
}
}

View File

@ -14,6 +14,7 @@
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
"laravel/breeze": "^1.29",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",

64
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "36d47ca0654f6d7aa9d0c9fbc7ef90a4",
"content-hash": "ea96edc96e7f0cc854db1906b2ad32d3",
"packages": [
{
"name": "brick/math",
@ -5882,6 +5882,68 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
{
"name": "laravel/breeze",
"version": "v1.29.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/breeze.git",
"reference": "22c53b84b7fff91b01a318d71a10dfc251e92849"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/breeze/zipball/22c53b84b7fff91b01a318d71a10dfc251e92849",
"reference": "22c53b84b7fff91b01a318d71a10dfc251e92849",
"shasum": ""
},
"require": {
"illuminate/console": "^10.17",
"illuminate/filesystem": "^10.17",
"illuminate/support": "^10.17",
"illuminate/validation": "^10.17",
"php": "^8.1.0"
},
"require-dev": {
"orchestra/testbench": "^8.0",
"phpstan/phpstan": "^1.10"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Breeze\\BreezeServiceProvider"
]
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Breeze\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.",
"keywords": [
"auth",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/breeze/issues",
"source": "https://github.com/laravel/breeze"
},
"time": "2024-03-04T14:35:21+00:00"
},
{
"name": "laravel/pint",
"version": "v1.18.1",

View File

@ -4,6 +4,8 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use function Laravel\Prompts\table;
return new class extends Migration
{
/**
@ -18,6 +20,8 @@ public function up(): void
$table->string('email')->unique();
$table->string('password');
$table->enum('role', ['admin', 'user'])->default('user');
$table->string('activation_code')->nullable();
$table->boolean('is_active')->default(false);
$table->timestamps();
});
}

View File

@ -18,5 +18,9 @@ public function run(): void
// 'name' => 'Test User',
// 'email' => 'test@example.com',
// ]);
$this->call([
UsersSeeder::class
]);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class UsersSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
[
User::create([
'username' => 'admin',
'name' => 'Admin Sage',
'email' => 'adminSage@gmail.com',
'password' => Hash::make('admin123'),
'role' => 'admin',
'is_active' => true
]),
User::create([
'username' => 'petugas',
'name' => 'Petugas Sage',
'email' => 'petugasSage@gmail.com',
'password' => Hash::make('petugas123'),
'role' => 'user',
'is_active' => true
]),
];
}
}

1829
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,13 @@
"build": "vite build"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.2",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.4.2",
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.2",
"postcss": "^8.4.31",
"tailwindcss": "^3.1.0",
"vite": "^4.0.0"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1 +1,7 @@
import './bootstrap';
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>Kode Aktivasi</title>
</head>
<body>
<h1>Halo, {{ $name }}</h1>
<p>Berikut adalah kode aktivasi untuk akun Anda:</p>
<h2>{{ $activationCode }}</h2>
<p>Masukkan kode ini di aplikasi untuk mengaktifkan akun Anda.</p>
<p>Terima kasih!</p>
</body>
</html>

View File

@ -0,0 +1,154 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<head>
<meta charset="utf-8" />
<title>Lupa Password | 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>
<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="text-center mt-2">
<h5 class="text-primary">Lupa Password?</h5>
<p class="text-muted">Ingin melakukan reset password?</p>
<lord-icon src="https://cdn.lordicon.com/rhvddzym.json" trigger="loop"
colors="primary:#0ab39c" class="avatar-xl">
</lord-icon>
</div>
<div class="alert alert-borderless alert-warning text-center mb-2 mx-2" role="alert">
Masukan email anda dan instruksi akan dikirimkan kepada anda!
</div>
<div class="p-2">
<form action="{{ route('auth.reset_password') }}" class="needs-validation"
novalidate method="POST">
@csrf
<div class="mb-4">
<label class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email"
placeholder="Masukan Email" autofocus required>
<div class="invalid-feedback">
Masukan email anda
</div>
</div>
<div class="text-center mt-4">
<button class="btn btn-success w-100" type="submit">Kirim Reset Password
Link!</button>
</div>
</form><!-- end form -->
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<p class="mb-0">Tunggu, saya ingat password saya... <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 -->
<!-- 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 -->
@include('sweetalert::alert')
<!-- 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>
<script src="assets/js/pages/form-validation.init.js"></script>
</body>
</html>

View File

@ -0,0 +1,182 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<head>
<meta charset="utf-8" />
<title>Login | 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>
<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="text-center mt-2">
<h5 class="text-primary">Selamat Datang Kembali !</h5>
<p class="text-muted">Login untuk melanjutkan.</p>
</div>
<div class="p-2 mt-4">
<form action="{{ route('auth.login_post') }}" class="needs-validation" novalidate
method="POST">
@csrf
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username"
placeholder="Masukan username" value="{{ old('username') }}" autofocus
required>
<div class="invalid-feedback">
Masukan username
</div>
</div>
<div class="mb-3">
<div class="float-end">
<a href="{{ route('auth.forgot_password') }}" class="text-muted">Lupa
Password?</a>
</div>
<label class="form-label" for="password-input">Password</label>
<div class="position-relative auth-pass-inputgroup mb-3">
<input type="password" class="form-control pe-5"
placeholder="Masukan password" id="password-input"
value="{{ old('password') }}" name="password" required>
<button
class="btn btn-link position-absolute end-0 top-0 text-decoration-none text-muted"
type="button" id="password-addon"><i
class="ri-eye-fill align-middle"></i></button>
<div class="invalid-feedback">
Masukan password
</div>
</div>
</div>
<div class="mt-4">
<button class="btn btn-success w-100" type="submit">Login</button>
</div>
</form>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<p class="mb-0">Belum memiliki akun ? <a href="{{ route('auth.register') }}"
class="fw-semibold text-primary text-decoration-underline"> Registrasi sekarang!
</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>
<!-- password-addon init -->
<script src="assets/js/pages/password-addon.init.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="assets/js/pages/form-validation.init.js"></script>
<script>
const errors = @json($errors->all());
if (errors.length > 0) {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: "Username atau Password salah",
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<p>Halo,</p>
<p>Kami menerima permintaan untuk mereset password akun Anda.</p>
<p>Klik tautan di bawah ini untuk mereset password:</p>
<a href="{{ $resetLink }}">{{ $resetLink }}</a>
<p>Tautan ini akan kadaluarsa dalam waktu 60 menit.</p>
<p>Jika Anda tidak meminta reset password, abaikan email ini.</p>
<p>Terima kasih,</p>
<p>Tim {{ config('app.name') }}</p>
</body>
</html>

View File

@ -0,0 +1,186 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<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>
<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="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>
</form>
</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,155 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<head>
<meta charset="utf-8" />
<title>Reset Password | 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="text-center mt-2">
<h5 class="text-primary">Reset Password</h5>
<p class="text-muted">Silahkan password baru anda!</p>
</div>
<div class="p-2">
<form action="{{ route('auth.store_new_password_form') }}" class="needs-validation"
novalidate method="POST">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<input type="hidden" name="email" value="{{ $email }}">
<div class="mb-4">
<label class="form-label">Password Baru</label>
<input type="password" class="form-control" id="new_password"
name="new_password" placeholder="Masukan password baru" autofocus
autocomplete="off" required>
<div class="invalid-feedback">
Harap masukan password baru anda!
</div>
</div>
<div class="mb-4">
<label class="form-label">Konfirmasi Password Baru</label>
<input type="password" class="form-control" id="confirm_password"
name="confirm_password" placeholder="Masukan konfirmasi password"
autofocus required>
<div class="invalid-feedback">
Harap masukan konfirmasi password
</div>
</div>
<div class="text-center mt-4">
<button class="btn btn-success w-100" type="submit">Simpan</button>
</div>
</form><!-- end form -->
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<p class="mb-0">Tunggu, saya ingat password saya... <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 -->
<!-- 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 -->
@include('sweetalert::alert')
<!-- 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>
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
</body>
</html>

View File

@ -0,0 +1,193 @@
<!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 action="{{ route('auth.two_step_verify_post') }}" method="POST">
@csrf
<input type="hidden" name="email" value="{{ $email }}">
<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"
name="digit1" autocomplete="off">
</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"
name="digit2" autocomplete="off">
</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"
name="digit3" autocomplete="off">
</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" name="digit4" autocomplete="off">
</div>
</div><!-- end col -->
</div>
<div class="mt-3">
<button type="submit" class="btn btn-success w-100">Verifikasi</button>
</div>
</form><!-- end form -->
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mt-4 text-center">
<form action="{{ route('auth.two_step_verify_resend') }}" method="POST">
@csrf
<input type="hidden" name="email" value="{{ $email }}">
<p class="mb-0">Belum menerima email ? <input type="submit"
class="btn btn-link m-0 p-0 fw-semibold" value="Kirim ulang">
</p>
</form>
</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 -->
@include('sweetalert::alert')
<!-- 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

@ -0,0 +1,3 @@
<svg viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,7 @@
@props(['status'])
@if ($status)
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
{{ $status }}
</div>
@endif

View File

@ -0,0 +1,3 @@
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@ -0,0 +1 @@
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>

View File

@ -0,0 +1,43 @@
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-700'])
@php
switch ($align) {
case 'left':
$alignmentClasses = 'ltr:origin-top-left rtl:origin-top-right start-0';
break;
case 'top':
$alignmentClasses = 'origin-top';
break;
case 'right':
default:
$alignmentClasses = 'ltr:origin-top-right rtl:origin-top-left end-0';
break;
}
switch ($width) {
case '48':
$width = 'w-48';
break;
}
@endphp
<div class="relative" x-data="{ open: false }" @click.outside="open = false" @close.stop="open = false">
<div @click="open = ! open">
{{ $trigger }}
</div>
<div x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }}"
style="display: none;"
@click="open = false">
<div class="rounded-md ring-1 ring-black ring-opacity-5 {{ $contentClasses }}">
{{ $content }}
</div>
</div>
</div>

View File

@ -0,0 +1,9 @@
@props(['messages'])
@if ($messages)
<ul {{ $attributes->merge(['class' => 'text-sm text-red-600 dark:text-red-400 space-y-1']) }}>
@foreach ((array) $messages as $message)
<li>{{ $message }}</li>
@endforeach
</ul>
@endif

View File

@ -0,0 +1,5 @@
@props(['value'])
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700 dark:text-gray-300']) }}>
{{ $value ?? $slot }}
</label>

View File

@ -0,0 +1,78 @@
@props([
'name',
'show' => false,
'maxWidth' => '2xl'
])
@php
$maxWidth = [
'sm' => 'sm:max-w-sm',
'md' => 'sm:max-w-md',
'lg' => 'sm:max-w-lg',
'xl' => 'sm:max-w-xl',
'2xl' => 'sm:max-w-2xl',
][$maxWidth];
@endphp
<div
x-data="{
show: @js($show),
focusables() {
// All focusable element types...
let selector = 'a, button, input:not([type=\'hidden\']), textarea, select, details, [tabindex]:not([tabindex=\'-1\'])'
return [...$el.querySelectorAll(selector)]
// All non-disabled elements...
.filter(el => ! el.hasAttribute('disabled'))
},
firstFocusable() { return this.focusables()[0] },
lastFocusable() { return this.focusables().slice(-1)[0] },
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() },
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() },
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) },
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 },
}"
x-init="$watch('show', value => {
if (value) {
document.body.classList.add('overflow-y-hidden');
{{ $attributes->has('focusable') ? 'setTimeout(() => firstFocusable().focus(), 100)' : '' }}
} else {
document.body.classList.remove('overflow-y-hidden');
}
})"
x-on:open-modal.window="$event.detail == '{{ $name }}' ? show = true : null"
x-on:close-modal.window="$event.detail == '{{ $name }}' ? show = false : null"
x-on:close.stop="show = false"
x-on:keydown.escape.window="show = false"
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()"
x-on:keydown.shift.tab.prevent="prevFocusable().focus()"
x-show="show"
class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50"
style="display: {{ $show ? 'block' : 'none' }};"
>
<div
x-show="show"
class="fixed inset-0 transform transition-all"
x-on:click="show = false"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
</div>
<div
x-show="show"
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
{{ $slot }}
</div>
</div>

View File

@ -0,0 +1,11 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 dark:border-indigo-600 text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@ -0,0 +1,3 @@
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@ -0,0 +1,11 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-start text-base font-medium text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
: 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@ -0,0 +1,3 @@
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 disabled:opacity-25 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>

View File

@ -0,0 +1,3 @@
@props(['disabled' => false])
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm']) !!}>

View File

@ -0,0 +1,17 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@ -0,0 +1,29 @@
@extends('layouts.app')
@push('title', 'Dashboard Admin')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">Dashboard Admin</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">Pages</a></li>
<li class="breadcrumb-item active">Dashboard Admin</li>
</ol>
</div>
</div>
</div>
</div>
<!-- end page title -->
</div>
<!-- container-fluid -->
</div>
<!-- End Page-content -->
@endsection

View File

@ -0,0 +1,29 @@
@extends('layouts.app')
@push('title', 'Dashboard Petugas')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">Dashboard petugas</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">Pages</a></li>
<li class="breadcrumb-item active">Dashboard petugas</li>
</ol>
</div>
</div>
</div>
</div>
<!-- end page title -->
</div>
<!-- container-fluid -->
</div>
<!-- End Page-content -->
@endsection

View File

@ -0,0 +1,607 @@
<!doctype html>
<html lang="en" data-layout="vertical" data-topbar="light" data-sidebar="light" data-sidebar-size="lg">
<head>
<meta charset="utf-8" />
<title>CornQuest | @stack('title')</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>
<!-- Begin page -->
<div id="layout-wrapper">
@include('partials.navbar')
<!-- ========== App Menu ========== -->
@include('partials.sidebar')
<!-- Left Sidebar End -->
<!-- Vertical Overlay-->
<div class="vertical-overlay"></div>
<!-- ============================================================== -->
<!-- Start right Content here -->
<!-- ============================================================== -->
<div class="main-content">
@yield('content')
@include('partials.footer')
</div>
<!-- end main content-->
</div>
<!-- END layout-wrapper -->
<!--start back-to-top-->
<button onclick="topFunction()" class="btn btn-danger btn-icon" id="back-to-top">
<i class="ri-arrow-up-line"></i>
</button>
<!--end back-to-top-->
<div class="customizer-setting d-none d-md-block">
<div class="btn-primary btn-rounded shadow-lg btn btn-icon btn-lg p-2" data-bs-toggle="offcanvas"
data-bs-target="#theme-settings-offcanvas" aria-controls="theme-settings-offcanvas">
<i class='mdi mdi-spin mdi-cog-outline fs-22'></i>
</div>
</div>
<!-- Theme Settings -->
<div class="offcanvas offcanvas-end border-0" tabindex="-1" id="theme-settings-offcanvas">
<div class="d-flex align-items-center bg-primary bg-gradient p-3 offcanvas-header">
<h5 class="m-0 me-2 text-white">Theme Customizer</h5>
<button type="button" class="btn-close btn-close-white ms-auto" data-bs-dismiss="offcanvas"
aria-label="Close"></button>
</div>
<div class="offcanvas-body p-0">
<div data-simplebar class="h-100">
<div class="p-4">
<h6 class="mb-0 fw-semibold text-uppercase">Layout</h6>
<p class="text-muted">Choose your layout</p>
<div class="row">
<div class="col-4">
<div class="form-check card-radio">
<input id="customizer-layout01" name="data-layout" type="radio" value="vertical"
class="form-check-input">
<label class="form-check-label p-0 avatar-md w-100" for="customizer-layout01">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Vertical</h5>
</div>
<div class="col-4">
<div class="form-check card-radio">
<input id="customizer-layout02" name="data-layout" type="radio" value="horizontal"
class="form-check-input">
<label class="form-check-label p-0 avatar-md w-100" for="customizer-layout02">
<span class="d-flex h-100 flex-column gap-1">
<span class="bg-light d-flex p-1 gap-1 align-items-center">
<span class="d-block p-1 bg-soft-primary rounded me-1"></span>
<span class="d-block p-1 pb-0 px-2 bg-soft-primary ms-auto"></span>
<span class="d-block p-1 pb-0 px-2 bg-soft-primary"></span>
</span>
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Horizontal</h5>
</div>
<div class="col-4">
<div class="form-check card-radio">
<input id="customizer-layout03" name="data-layout" type="radio" value="twocolumn"
class="form-check-input">
<label class="form-check-label p-0 avatar-md w-100" for="customizer-layout03">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1">
<span class="d-block p-1 bg-soft-primary mb-2"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Two Column</h5>
</div>
<!-- end col -->
</div>
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Color Scheme</h6>
<p class="text-muted">Choose Light or Dark Scheme.</p>
<div class="colorscheme-cardradio">
<div class="row">
<div class="col-4">
<div class="form-check card-radio">
<input class="form-check-input" type="radio" name="data-layout-mode"
id="layout-mode-light" value="light">
<label class="form-check-label p-0 avatar-md w-100" for="layout-mode-light">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Light</h5>
</div>
<div class="col-4">
<div class="form-check card-radio dark">
<input class="form-check-input" type="radio" name="data-layout-mode"
id="layout-mode-dark" value="dark">
<label class="form-check-label p-0 avatar-md w-100 bg-dark"
for="layout-mode-dark">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-soft-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-light rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-soft-light d-block p-1"></span>
<span class="bg-soft-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Dark</h5>
</div>
</div>
</div>
<div id="layout-width">
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Layout Width</h6>
<p class="text-muted">Choose Fluid or Boxed layout.</p>
<div class="row">
<div class="col-4">
<div class="form-check card-radio">
<input class="form-check-input" type="radio" name="data-layout-width"
id="layout-width-fluid" value="fluid">
<label class="form-check-label p-0 avatar-md w-100" for="layout-width-fluid">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Fluid</h5>
</div>
<div class="col-4">
<div class="form-check card-radio">
<input class="form-check-input" type="radio" name="data-layout-width"
id="layout-width-boxed" value="boxed">
<label class="form-check-label p-0 avatar-md w-100 px-2" for="layout-width-boxed">
<span class="d-flex gap-1 h-100 border-start border-end">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Boxed</h5>
</div>
</div>
</div>
<div id="layout-position">
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Layout Position</h6>
<p class="text-muted">Choose Fixed or Scrollable Layout Position.</p>
<div class="btn-group radio" role="group">
<input type="radio" class="btn-check" name="data-layout-position"
id="layout-position-fixed" value="fixed">
<label class="btn btn-light w-sm" for="layout-position-fixed">Fixed</label>
<input type="radio" class="btn-check" name="data-layout-position"
id="layout-position-scrollable" value="scrollable">
<label class="btn btn-light w-sm ms-0" for="layout-position-scrollable">Scrollable</label>
</div>
</div>
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Topbar Color</h6>
<p class="text-muted">Choose Light or Dark Topbar Color.</p>
<div class="row">
<div class="col-4">
<div class="form-check card-radio">
<input class="form-check-input" type="radio" name="data-topbar"
id="topbar-color-light" value="light">
<label class="form-check-label p-0 avatar-md w-100" for="topbar-color-light">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Light</h5>
</div>
<div class="col-4">
<div class="form-check card-radio">
<input class="form-check-input" type="radio" name="data-topbar"
id="topbar-color-dark" value="dark">
<label class="form-check-label p-0 avatar-md w-100" for="topbar-color-dark">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-primary d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Dark</h5>
</div>
</div>
<div id="sidebar-size">
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Sidebar Size</h6>
<p class="text-muted">Choose a size of Sidebar.</p>
<div class="row">
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar-size"
id="sidebar-size-default" value="lg">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-size-default">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Default</h5>
</div>
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar-size"
id="sidebar-size-compact" value="md">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-size-compact">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Compact</h5>
</div>
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar-size"
id="sidebar-size-small" value="sm">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-size-small">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1">
<span class="d-block p-1 bg-soft-primary mb-2"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Small (Icon View)</h5>
</div>
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar-size"
id="sidebar-size-small-hover" value="sm-hover">
<label class="form-check-label p-0 avatar-md w-100"
for="sidebar-size-small-hover">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1">
<span class="d-block p-1 bg-soft-primary mb-2"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Small Hover View</h5>
</div>
</div>
</div>
<div id="sidebar-view">
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Sidebar View</h6>
<p class="text-muted">Choose Default or Detached Sidebar view.</p>
<div class="row">
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-layout-style"
id="sidebar-view-default" value="default">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-view-default">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Default</h5>
</div>
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-layout-style"
id="sidebar-view-detached" value="detached">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-view-detached">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-flex p-1 gap-1 align-items-center px-2">
<span class="d-block p-1 bg-soft-primary rounded me-1"></span>
<span class="d-block p-1 pb-0 px-2 bg-soft-primary ms-auto"></span>
<span class="d-block p-1 pb-0 px-2 bg-soft-primary"></span>
</span>
<span class="d-flex gap-1 h-100 p-1 px-2">
<span class="flex-shrink-0">
<span class="bg-light d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
</span>
<span class="bg-light d-block p-1 mt-auto px-2"></span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Detached</h5>
</div>
</div>
</div>
<div id="sidebar-color">
<h6 class="mt-4 mb-0 fw-semibold text-uppercase">Sidebar Color</h6>
<p class="text-muted">Choose Ligth or Dark Sidebar Color.</p>
<div class="row">
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar"
id="sidebar-color-light" value="light">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-color-light">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-white border-end d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-primary rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-primary"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Light</h5>
</div>
<div class="col-4">
<div class="form-check sidebar-setting card-radio">
<input class="form-check-input" type="radio" name="data-sidebar"
id="sidebar-color-dark" value="dark">
<label class="form-check-label p-0 avatar-md w-100" for="sidebar-color-dark">
<span class="d-flex gap-1 h-100">
<span class="flex-shrink-0">
<span class="bg-primary d-flex h-100 flex-column gap-1 p-1">
<span class="d-block p-1 px-2 bg-soft-light rounded mb-2"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
<span class="d-block p-1 px-2 pb-0 bg-soft-light"></span>
</span>
</span>
<span class="flex-grow-1">
<span class="d-flex h-100 flex-column">
<span class="bg-light d-block p-1"></span>
<span class="bg-light d-block p-1 mt-auto"></span>
</span>
</span>
</span>
</label>
</div>
<h5 class="fs-13 text-center mt-2">Dark</h5>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="offcanvas-footer border-top p-3 text-center">
<div class="row">
<div class="col-6">
<button type="button" class="btn btn-light w-100" id="reset-layout">Reset</button>
</div>
<div class="col-6">
<a href="https://1.envato.market/velzon-admin" target="_blank" class="btn btn-primary w-100">Buy
Now</a>
</div>
</div>
</div>
</div>
<!-- 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>
<!-- App js -->
<script src="assets/js/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,16 @@
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<script>
document.write(new Date().getFullYear())
</script> © Velzon.
</div>
<div class="col-sm-6">
<div class="text-sm-end d-none d-sm-block">
Design & Develop by Themesbrand
</div>
</div>
</div>
</div>
</footer>

View File

@ -0,0 +1,222 @@
<header id="page-topbar">
<div class="layout-width">
<div class="navbar-header">
<div class="d-flex">
<!-- LOGO -->
<div class="navbar-brand-box horizontal-logo">
<a href="index.html" class="logo logo-dark">
<span class="logo-sm">
<img src="assets/images/logo-sm.png" alt="" height="22">
</span>
<span class="logo-lg">
<img src="assets/images/logo-dark.png" alt="" height="17">
</span>
</a>
<a href="index.html" class="logo logo-light">
<span class="logo-sm">
<img src="assets/images/logo-sm.png" alt="" height="22">
</span>
<span class="logo-lg">
<img src="assets/images/logo-light.png" alt="" height="17">
</span>
</a>
</div>
<button type="button" class="btn btn-sm px-3 fs-16 header-item vertical-menu-btn topnav-hamburger"
id="topnav-hamburger-icon">
<span class="hamburger-icon">
<span></span>
<span></span>
<span></span>
</span>
</button>
<!-- App Search-->
<form class="app-search d-none d-md-block">
<div class="position-relative d-none">
<input type="text" class="form-control" placeholder="Search..." autocomplete="off"
id="search-options" value="">
<span class="mdi mdi-magnify search-widget-icon"></span>
<span class="mdi mdi-close-circle search-widget-icon search-widget-icon-close d-none"
id="search-close-options"></span>
</div>
<div class="dropdown-menu dropdown-menu-lg" id="search-dropdown">
<div data-simplebar style="max-height: 320px;">
<!-- item-->
<div class="dropdown-header">
<h6 class="text-overflow text-muted mb-0 text-uppercase">Recent Searches</h6>
</div>
<div class="dropdown-item bg-transparent text-wrap">
<a href="index.html" class="btn btn-soft-secondary btn-sm btn-rounded">how to
setup <i class="mdi mdi-magnify ms-1"></i></a>
<a href="index.html" class="btn btn-soft-secondary btn-sm btn-rounded">buttons
<i class="mdi mdi-magnify ms-1"></i></a>
</div>
<!-- item-->
<div class="dropdown-header mt-2">
<h6 class="text-overflow text-muted mb-1 text-uppercase">Pages</h6>
</div>
<!-- item-->
<a href="javascript:void(0);" class="dropdown-item notify-item">
<i class="ri-bubble-chart-line align-middle fs-18 text-muted me-2"></i>
<span>Analytics Dashboard</span>
</a>
<!-- item-->
<a href="javascript:void(0);" class="dropdown-item notify-item">
<i class="ri-lifebuoy-line align-middle fs-18 text-muted me-2"></i>
<span>Help Center</span>
</a>
<!-- item-->
<a href="javascript:void(0);" class="dropdown-item notify-item">
<i class="ri-user-settings-line align-middle fs-18 text-muted me-2"></i>
<span>My account settings</span>
</a>
<!-- item-->
<div class="dropdown-header mt-2">
<h6 class="text-overflow text-muted mb-2 text-uppercase">Members</h6>
</div>
<div class="notification-list">
<!-- item -->
<a href="javascript:void(0);" class="dropdown-item notify-item py-2">
<div class="d-flex">
<img src="assets/images/users/avatar-2.jpg"
class="me-3 rounded-circle avatar-xs" alt="user-pic">
<div class="flex-1">
<h6 class="m-0">Angela Bernier</h6>
<span class="fs-11 mb-0 text-muted">Manager</span>
</div>
</div>
</a>
<!-- item -->
<a href="javascript:void(0);" class="dropdown-item notify-item py-2">
<div class="d-flex">
<img src="assets/images/users/avatar-3.jpg"
class="me-3 rounded-circle avatar-xs" alt="user-pic">
<div class="flex-1">
<h6 class="m-0">David Grasso</h6>
<span class="fs-11 mb-0 text-muted">Web Designer</span>
</div>
</div>
</a>
<!-- item -->
<a href="javascript:void(0);" class="dropdown-item notify-item py-2">
<div class="d-flex">
<img src="assets/images/users/avatar-5.jpg"
class="me-3 rounded-circle avatar-xs" alt="user-pic">
<div class="flex-1">
<h6 class="m-0">Mike Bunch</h6>
<span class="fs-11 mb-0 text-muted">React Developer</span>
</div>
</div>
</a>
</div>
</div>
<div class="text-center pt-3 pb-1">
<a href="pages-search-results.html" class="btn btn-primary btn-sm">View All
Results <i class="ri-arrow-right-line ms-1"></i></a>
</div>
</div>
</form>
</div>
<div class="d-flex align-items-center">
<div class="dropdown d-md-none topbar-head-dropdown header-item">
<button type="button" class="btn btn-icon btn-topbar btn-ghost-secondary rounded-circle"
id="page-header-search-dropdown" data-bs-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
<i class="bx bx-search fs-22"></i>
</button>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end p-0"
aria-labelledby="page-header-search-dropdown">
<form class="p-3">
<div class="form-group m-0">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search ..."
aria-label="Recipient's username">
<button class="btn btn-primary" type="submit"><i
class="mdi mdi-magnify"></i></button>
</div>
</div>
</form>
</div>
</div>
<div class="ms-1 header-item d-none d-sm-flex">
<button type="button" class="btn btn-icon btn-topbar btn-ghost-secondary rounded-circle"
data-toggle="fullscreen">
<i class='bx bx-fullscreen fs-22'></i>
</button>
</div>
<div class="ms-1 header-item d-none d-sm-flex">
<button type="button"
class="btn btn-icon btn-topbar btn-ghost-secondary rounded-circle light-dark-mode">
<i class='bx bx-moon fs-22'></i>
</button>
</div>
<div class="dropdown ms-sm-3 header-item topbar-user">
<button type="button" class="btn" id="page-header-user-dropdown" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="d-flex align-items-center">
<img class="rounded-circle header-profile-user" src="assets/images/users/avatar-1.jpg"
alt="Header Avatar">
<span class="text-start ms-xl-2">
<span
class="d-none d-xl-inline-block ms-1 fw-medium user-name-text">{{ Auth::user()->username }}</span>
<span
class="d-none d-xl-block ms-1 fs-12 text-muted user-name-sub-text">{{ Auth::user()->role }}</span>
</span>
</span>
</button>
<div class="dropdown-menu dropdown-menu-end">
<!-- item-->
<h6 class="dropdown-header">Selamat Datang {{ Auth::user()->name }}!</h6>
<a class="dropdown-item" href="pages-profile.html"><i
class="mdi mdi-account-circle text-muted fs-16 align-middle me-1"></i> <span
class="align-middle">Profile</span></a>
<a class="dropdown-item" href="apps-chat.html"><i
class="mdi mdi-message-text-outline text-muted fs-16 align-middle me-1"></i>
<span class="align-middle">Messages</span></a>
<a class="dropdown-item" href="apps-tasks-kanban.html"><i
class="mdi mdi-calendar-check-outline text-muted fs-16 align-middle me-1"></i>
<span class="align-middle">Taskboard</span></a>
<a class="dropdown-item" href="pages-faqs.html"><i
class="mdi mdi-lifebuoy text-muted fs-16 align-middle me-1"></i> <span
class="align-middle">Help</span></a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="pages-profile.html"><i
class="mdi mdi-wallet text-muted fs-16 align-middle me-1"></i> <span
class="align-middle">Balance : <b>$5971.67</b></span></a>
<a class="dropdown-item" href="pages-profile-settings.html"><span
class="badge bg-soft-success text-success mt-1 float-end">New</span><i
class="mdi mdi-cog-outline text-muted fs-16 align-middle me-1"></i> <span
class="align-middle">Settings</span></a>
<a class="dropdown-item" href="auth-lockscreen-basic.html"><i
class="mdi mdi-lock text-muted fs-16 align-middle me-1"></i> <span
class="align-middle">Lock screen</span></a>
<form action="{{ route('auth.logout') }}" class="d-inline" method="POST">
@csrf
<button type="submit" class="dropdown-item">
<i class="mdi mdi-logout text-muted fs-16 align-middle me-1"></i> <span
class="align-middle" data-key="t-logout">Logout</span>
</button>
</form>
{{-- <a class="dropdown-item" href="auth-logout-basic.html"><i
class="mdi mdi-logout text-muted fs-16 align-middle me-1"></i> <span
class="align-middle" data-key="t-logout">Logout</span></a> --}}
</div>
</div>
</div>
</div>
</div>
</header>

View File

@ -0,0 +1,970 @@
<div class="app-menu navbar-menu">
<!-- LOGO -->
<div class="navbar-brand-box">
<!-- Dark Logo-->
<a href="index.html" class="logo logo-dark">
<span class="logo-sm">
<img src="assets/images/logo-sm.png" alt="" height="22">
</span>
<span class="logo-lg">
<img src="assets/images/logo-dark.png" alt="" height="17">
</span>
</a>
<!-- Light Logo-->
<a href="index.html" class="logo logo-light">
<span class="logo-sm">
<img src="assets/images/logo-sm.png" alt="" height="22">
</span>
<span class="logo-lg">
<img src="assets/images/logo-light.png" alt="" height="17">
</span>
</a>
<button type="button" class="btn btn-sm p-0 fs-20 header-item float-end btn-vertical-sm-hover"
id="vertical-hover">
<i class="ri-record-circle-line"></i>
</button>
</div>
<div id="scrollbar">
<div class="container-fluid">
<div id="two-column-menu">
</div>
<ul class="navbar-nav" id="navbar-nav">
<li class="menu-title"><span data-key="t-menu">Menu</span></li>
@if (Auth::user()->role == 'admin')
<li class="nav-item">
<a class="nav-link menu-link {{ request()->routeIs('dashboard.admin') ? 'active' : '' }}"
href="">
<i data-feather="home" class="icon-dual"></i> <span
data-key="t-dashboards">Dashboards</span>
</a>
</li>
@else
<li class="nav-item">
<a class="nav-link menu-link {{ request()->routeIs('dashboard.petugas') ? 'active' : '' }}"
href="">
<i data-feather="home" class="icon-dual"></i> <span
data-key="t-dashboards">Dashboards</span>
</a>
</li>
@endif <!-- end Dashboard Menu -->
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarApps" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarApps">
<i data-feather="grid" class="icon-dual"></i> <span data-key="t-apps">Apps</span>
</a>
<div class="collapse menu-dropdown" id="sidebarApps">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-calendar.html" class="nav-link" data-key="t-calendar"> Calendar
</a>
</li>
<li class="nav-item">
<a href="apps-chat.html" class="nav-link" data-key="t-chat"> Chat </a>
</li>
<li class="nav-item">
<a href="apps-mailbox.html" class="nav-link" data-key="t-mailbox"> Mailbox
</a>
</li>
<li class="nav-item">
<a href="#sidebarEcommerce" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarEcommerce"
data-key="t-ecommerce">Ecommerce
</a>
<div class="collapse menu-dropdown" id="sidebarEcommerce">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-ecommerce-products.html" class="nav-link"
data-key="t-products"> Products </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-product-details.html" class="nav-link"
data-key="t-product-Details"> Product Details </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-add-product.html" class="nav-link"
data-key="t-create-product"> Create Product </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-orders.html" class="nav-link" data-key="t-orders">
Orders </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-order-details.html" class="nav-link"
data-key="t-order-details"> Order Details </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-customers.html" class="nav-link"
data-key="t-customers"> Customers </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-cart.html" class="nav-link"
data-key="t-shopping-cart"> Shopping Cart </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-checkout.html" class="nav-link"
data-key="t-checkout"> Checkout </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-sellers.html" class="nav-link"
data-key="t-sellers"> Sellers </a>
</li>
<li class="nav-item">
<a href="apps-ecommerce-seller-details.html" class="nav-link"
data-key="t-sellers-details"> Seller Details </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarProjects" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarProjects" data-key="t-projects">
Projects
</a>
<div class="collapse menu-dropdown" id="sidebarProjects">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-projects-list.html" class="nav-link" data-key="t-list">
List </a>
</li>
<li class="nav-item">
<a href="apps-projects-overview.html" class="nav-link"
data-key="t-overview"> Overview </a>
</li>
<li class="nav-item">
<a href="apps-projects-create.html" class="nav-link"
data-key="t-create-project"> Create Project </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarTasks" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarTasks" data-key="t-tasks"> Tasks
</a>
<div class="collapse menu-dropdown" id="sidebarTasks">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-tasks-kanban.html" class="nav-link"
data-key="t-kanbanboard"> Kanban Board </a>
</li>
<li class="nav-item">
<a href="apps-tasks-list-view.html" class="nav-link"
data-key="t-list-view"> List View </a>
</li>
<li class="nav-item">
<a href="apps-tasks-details.html" class="nav-link"
data-key="t-task-details"> Task Details </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarCRM" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarCRM" data-key="t-crm"> CRM
</a>
<div class="collapse menu-dropdown" id="sidebarCRM">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-crm-contacts.html" class="nav-link" data-key="t-contacts">
Contacts </a>
</li>
<li class="nav-item">
<a href="apps-crm-companies.html" class="nav-link"
data-key="t-companies"> Companies </a>
</li>
<li class="nav-item">
<a href="apps-crm-deals.html" class="nav-link" data-key="t-deals"> Deals
</a>
</li>
<li class="nav-item">
<a href="apps-crm-leads.html" class="nav-link" data-key="t-leads"> Leads
</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarCrypto" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarCrypto" data-key="t-crypto"> Crypto
</a>
<div class="collapse menu-dropdown" id="sidebarCrypto">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-crypto-transactions.html" class="nav-link"
data-key="t-transactions"> Transactions </a>
</li>
<li class="nav-item">
<a href="apps-crypto-buy-sell.html" class="nav-link"
data-key="t-buy-sell"> Buy & Sell </a>
</li>
<li class="nav-item">
<a href="apps-crypto-orders.html" class="nav-link" data-key="t-orders">
Orders </a>
</li>
<li class="nav-item">
<a href="apps-crypto-wallet.html" class="nav-link"
data-key="t-my-wallet"> My Wallet </a>
</li>
<li class="nav-item">
<a href="apps-crypto-ico.html" class="nav-link" data-key="t-ico-list">
ICO List </a>
</li>
<li class="nav-item">
<a href="apps-crypto-kyc.html" class="nav-link"
data-key="t-kyc-application"> KYC Application </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarInvoices" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarInvoices" data-key="t-invoices">
Invoices
</a>
<div class="collapse menu-dropdown" id="sidebarInvoices">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-invoices-list.html" class="nav-link"
data-key="t-list-view"> List View </a>
</li>
<li class="nav-item">
<a href="apps-invoices-details.html" class="nav-link"
data-key="t-details"> Details </a>
</li>
<li class="nav-item">
<a href="apps-invoices-create.html" class="nav-link"
data-key="t-create-invoice"> Create Invoice </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarTickets" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarTickets" data-key="t-supprt-tickets">
Support Tickets
</a>
<div class="collapse menu-dropdown" id="sidebarTickets">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="apps-tickets-list.html" class="nav-link" data-key="t-list-view">
List View </a>
</li>
<li class="nav-item">
<a href="apps-tickets-details.html" class="nav-link"
data-key="t-ticket-details"> Ticket Details </a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarLayouts" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarLayouts">
<i data-feather="layout" class="icon-dual"></i> <span data-key="t-layouts">Layouts</span>
</a>
<div class="collapse menu-dropdown" id="sidebarLayouts">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="layouts-horizontal.html" target="_blank" class="nav-link"
data-key="t-horizontal">Horizontal</a>
</li>
<li class="nav-item">
<a href="layouts-detached.html" target="_blank" class="nav-link"
data-key="t-detached">Detached</a>
</li>
<li class="nav-item">
<a href="layouts-two-column.html" target="_blank" class="nav-link"
data-key="t-two-column">Two Column</a>
</li>
<li class="nav-item">
<a href="layouts-vertical-hovered.html" target="_blank" class="nav-link"
data-key="t-hovered">Hovered</a>
</li>
</ul>
</div>
</li> <!-- end Dashboard Menu -->
<li class="menu-title"><i class="ri-more-fill"></i> <span data-key="t-pages">Pages</span>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarAuth" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarAuth">
<i data-feather="users" class="icon-dual"></i> <span
data-key="t-authentication">Authentication</span>
</a>
<div class="collapse menu-dropdown" id="sidebarAuth">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="#sidebarSignIn" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarSignIn" data-key="t-signin"> Sign In
</a>
<div class="collapse menu-dropdown" id="sidebarSignIn">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-signin-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-signin-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarSignUp" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarSignUp" data-key="t-signup"> Sign Up
</a>
<div class="collapse menu-dropdown" id="sidebarSignUp">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-signup-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-signup-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarResetPass" class="nav-link" data-bs-toggle="collapse"
role="button" aria-expanded="false" aria-controls="sidebarResetPass"
data-key="t-password-reset"> Password Reset
</a>
<div class="collapse menu-dropdown" id="sidebarResetPass">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-pass-reset-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-pass-reset-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarLockScreen" class="nav-link" data-bs-toggle="collapse"
role="button" aria-expanded="false" aria-controls="sidebarLockScreen"
data-key="t-lock-screen"> Lock Screen
</a>
<div class="collapse menu-dropdown" id="sidebarLockScreen">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-lockscreen-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-lockscreen-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarLogout" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarLogout" data-key="t-logout"> Logout
</a>
<div class="collapse menu-dropdown" id="sidebarLogout">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-logout-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-logout-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarSuccessMsg" class="nav-link" data-bs-toggle="collapse"
role="button" aria-expanded="false" aria-controls="sidebarSuccessMsg"
data-key="t-success-message"> Success Message
</a>
<div class="collapse menu-dropdown" id="sidebarSuccessMsg">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-success-msg-basic.html" class="nav-link"
data-key="t-basic"> Basic </a>
</li>
<li class="nav-item">
<a href="auth-success-msg-cover.html" class="nav-link"
data-key="t-cover"> Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarTwoStep" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarTwoStep"
data-key="t-two-step-verification"> Two Step Verification
</a>
<div class="collapse menu-dropdown" id="sidebarTwoStep">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-twostep-basic.html" class="nav-link" data-key="t-basic">
Basic </a>
</li>
<li class="nav-item">
<a href="auth-twostep-cover.html" class="nav-link" data-key="t-cover">
Cover </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="#sidebarErrors" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarErrors" data-key="t-errors"> Errors
</a>
<div class="collapse menu-dropdown" id="sidebarErrors">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="auth-404-basic.html" class="nav-link" data-key="t-404-basic">
404 Basic </a>
</li>
<li class="nav-item">
<a href="auth-404-cover.html" class="nav-link" data-key="t-404-cover">
404 Cover </a>
</li>
<li class="nav-item">
<a href="auth-404-alt.html" class="nav-link" data-key="t-404-alt"> 404
Alt </a>
</li>
<li class="nav-item">
<a href="auth-500.html" class="nav-link" data-key="t-500"> 500
</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarPages" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarPages">
<i data-feather="command" class="icon-dual"></i> <span data-key="t-pages">Pages</span>
</a>
<div class="collapse menu-dropdown" id="sidebarPages">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="pages-starter.html" class="nav-link" data-key="t-starter">
Starter </a>
</li>
<li class="nav-item">
<a href="#sidebarProfile" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarProfile" data-key="t-profile">
Profile
</a>
<div class="collapse menu-dropdown" id="sidebarProfile">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="pages-profile.html" class="nav-link" data-key="t-simple-page">
Simple Page </a>
</li>
<li class="nav-item">
<a href="pages-profile-settings.html" class="nav-link"
data-key="t-settings"> Settings </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="pages-team.html" class="nav-link" data-key="t-team"> Team </a>
</li>
<li class="nav-item">
<a href="pages-timeline.html" class="nav-link" data-key="t-timeline">
Timeline </a>
</li>
<li class="nav-item">
<a href="pages-faqs.html" class="nav-link" data-key="t-faqs"> FAQs </a>
</li>
<li class="nav-item">
<a href="pages-pricing.html" class="nav-link" data-key="t-pricing">
Pricing </a>
</li>
<li class="nav-item">
<a href="pages-gallery.html" class="nav-link" data-key="t-gallery">
Gallery </a>
</li>
<li class="nav-item">
<a href="pages-maintenance.html" class="nav-link" data-key="t-maintenance">
Maintenance </a>
</li>
<li class="nav-item">
<a href="pages-coming-soon.html" class="nav-link" data-key="t-coming-soon">
Coming Soon </a>
</li>
<li class="nav-item">
<a href="pages-sitemap.html" class="nav-link" data-key="t-sitemap">
Sitemap </a>
</li>
<li class="nav-item">
<a href="pages-search-results.html" class="nav-link" data-key="t-search-results">
Search Results </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" target="_blank" href="landing.html">
<i class="ri-rocket-line"></i> <span data-key="t-landing">Landing</span>
<span class="badge badge-pill bg-danger" data-key="t-new">New</span>
</a>
</li>
<li class="menu-title"><i class="ri-more-fill"></i> <span data-key="t-components">Components</span>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarUI" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarUI">
<i data-feather="package" class="icon-dual"></i> <span data-key="t-base-ui">Base
UI</span>
</a>
<div class="collapse menu-dropdown mega-dropdown-menu" id="sidebarUI">
<div class="row">
<div class="col-lg-4">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="ui-alerts.html" class="nav-link" data-key="t-alerts">Alerts</a>
</li>
<li class="nav-item">
<a href="ui-badges.html" class="nav-link" data-key="t-badges">Badges</a>
</li>
<li class="nav-item">
<a href="ui-buttons.html" class="nav-link" data-key="t-buttons">Buttons</a>
</li>
<li class="nav-item">
<a href="ui-colors.html" class="nav-link" data-key="t-colors">Colors</a>
</li>
<li class="nav-item">
<a href="ui-cards.html" class="nav-link" data-key="t-cards">Cards</a>
</li>
<li class="nav-item">
<a href="ui-carousel.html" class="nav-link"
data-key="t-carousel">Carousel</a>
</li>
<li class="nav-item">
<a href="ui-dropdowns.html" class="nav-link"
data-key="t-dropdowns">Dropdowns</a>
</li>
<li class="nav-item">
<a href="ui-grid.html" class="nav-link" data-key="t-grid">Grid</a>
</li>
</ul>
</div>
<div class="col-lg-4">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="ui-images.html" class="nav-link" data-key="t-images">Images</a>
</li>
<li class="nav-item">
<a href="ui-tabs.html" class="nav-link" data-key="t-tabs">Tabs</a>
</li>
<li class="nav-item">
<a href="ui-accordions.html" class="nav-link"
data-key="t-accordion-collapse">Accordion & Collapse</a>
</li>
<li class="nav-item">
<a href="ui-modals.html" class="nav-link" data-key="t-modals">Modals</a>
</li>
<li class="nav-item">
<a href="ui-offcanvas.html" class="nav-link"
data-key="t-offcanvas">Offcanvas</a>
</li>
<li class="nav-item">
<a href="ui-placeholders.html" class="nav-link"
data-key="t-placeholders">Placeholders</a>
</li>
<li class="nav-item">
<a href="ui-progress.html" class="nav-link"
data-key="t-progress">Progress</a>
</li>
<li class="nav-item">
<a href="ui-notifications.html" class="nav-link"
data-key="t-notifications">Notifications</a>
</li>
</ul>
</div>
<div class="col-lg-4">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="ui-media.html" class="nav-link" data-key="t-media-object">Media
object</a>
</li>
<li class="nav-item">
<a href="ui-embed-video.html" class="nav-link" data-key="t-embed-video">Embed
Video</a>
</li>
<li class="nav-item">
<a href="ui-typography.html" class="nav-link"
data-key="t-typography">Typography</a>
</li>
<li class="nav-item">
<a href="ui-lists.html" class="nav-link" data-key="t-lists">Lists</a>
</li>
<li class="nav-item">
<a href="ui-general.html" class="nav-link" data-key="t-general">General</a>
</li>
<li class="nav-item">
<a href="ui-ribbons.html" class="nav-link" data-key="t-ribbons">Ribbons</a>
</li>
<li class="nav-item">
<a href="ui-utilities.html" class="nav-link"
data-key="t-utilities">Utilities</a>
</li>
</ul>
</div>
</div>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarAdvanceUI" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarAdvanceUI">
<i data-feather="layers" class="icon-dual"></i> <span data-key="t-advance-ui">Advance
UI</span>
<span class="badge badge-pill bg-primary" data-key="t-new">New</span>
</a>
<div class="collapse menu-dropdown" id="sidebarAdvanceUI">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="advance-ui-sweetalerts.html" class="nav-link"
data-key="t-sweet-alerts">Sweet Alerts</a>
</li>
<li class="nav-item">
<a href="advance-ui-nestable.html" class="nav-link"
data-key="t-nestable-list">Nestable List</a>
</li>
<li class="nav-item">
<a href="advance-ui-scrollbar.html" class="nav-link"
data-key="t-scrollbar">Scrollbar</a>
</li>
<li class="nav-item">
<a href="advance-ui-animation.html" class="nav-link"
data-key="t-animation">Animation</a>
</li>
<li class="nav-item">
<a href="advance-ui-tour.html" class="nav-link" data-key="t-tour">Tour</a>
</li>
<li class="nav-item">
<a href="advance-ui-swiper.html" class="nav-link" data-key="t-swiper-slider">Swiper
Slider</a>
</li>
<li class="nav-item">
<a href="advance-ui-ratings.html" class="nav-link" data-key="t-ratings">Ratings</a>
</li>
<li class="nav-item">
<a href="advance-ui-highlight.html" class="nav-link"
data-key="t-highlight">Highlight</a>
</li>
<li class="nav-item">
<a href="advance-ui-scrollspy.html" class="nav-link"
data-key="t-scrollSpy">ScrollSpy</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="widgets.html">
<i data-feather="copy" class="icon-dual"></i> <span data-key="t-widgets">Widgets</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarForms" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarForms">
<i data-feather="file-text" class="icon-dual"></i> <span data-key="t-forms">Forms</span>
</a>
<div class="collapse menu-dropdown" id="sidebarForms">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="forms-elements.html" class="nav-link" data-key="t-basic-elements">Basic
Elements</a>
</li>
<li class="nav-item">
<a href="forms-select.html" class="nav-link" data-key="t-form-select">
Form Select </a>
</li>
<li class="nav-item">
<a href="forms-checkboxs-radios.html" class="nav-link"
data-key="t-checkboxs-radios">Checkboxs & Radios</a>
</li>
<li class="nav-item">
<a href="forms-pickers.html" class="nav-link" data-key="t-pickers">
Pickers </a>
</li>
<li class="nav-item">
<a href="forms-masks.html" class="nav-link" data-key="t-input-masks">Input
Masks</a>
</li>
<li class="nav-item">
<a href="forms-advanced.html" class="nav-link" data-key="t-advanced">Advanced</a>
</li>
<li class="nav-item">
<a href="forms-range-sliders.html" class="nav-link" data-key="t-range-slider"> Range
Slider </a>
</li>
<li class="nav-item">
<a href="forms-validation.html" class="nav-link"
data-key="t-validation">Validation</a>
</li>
<li class="nav-item">
<a href="forms-wizard.html" class="nav-link" data-key="t-wizard">Wizard</a>
</li>
<li class="nav-item">
<a href="forms-editors.html" class="nav-link" data-key="t-editors">Editors</a>
</li>
<li class="nav-item">
<a href="forms-file-uploads.html" class="nav-link" data-key="t-file-uploads">File
Uploads</a>
</li>
<li class="nav-item">
<a href="forms-layouts.html" class="nav-link" data-key="t-form-layouts">Form
Layouts</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarTables" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarTables">
<i data-feather="database" class="icon-dual"></i> <span data-key="t-tables">Tables</span>
</a>
<div class="collapse menu-dropdown" id="sidebarTables">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="tables-basic.html" class="nav-link" data-key="t-basic-tables">Basic
Tables</a>
</li>
<li class="nav-item">
<a href="tables-gridjs.html" class="nav-link" data-key="t-grid-js">Grid
Js</a>
</li>
<li class="nav-item">
<a href="tables-listjs.html" class="nav-link" data-key="t-list-js">List
Js</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarCharts" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarCharts">
<i data-feather="pie-chart" class="icon-dual"></i> <span data-key="t-charts">Charts</span>
</a>
<div class="collapse menu-dropdown" id="sidebarCharts">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="#sidebarApexcharts" class="nav-link" data-bs-toggle="collapse"
role="button" aria-expanded="false" aria-controls="sidebarApexcharts"
data-key="t-apexcharts"> Apexcharts
</a>
<div class="collapse menu-dropdown" id="sidebarApexcharts">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="charts-apex-line.html" class="nav-link" data-key="t-line"> Line
</a>
</li>
<li class="nav-item">
<a href="charts-apex-area.html" class="nav-link" data-key="t-area"> Area
</a>
</li>
<li class="nav-item">
<a href="charts-apex-column.html" class="nav-link" data-key="t-column">
Column </a>
</li>
<li class="nav-item">
<a href="charts-apex-bar.html" class="nav-link" data-key="t-bar">
Bar </a>
</li>
<li class="nav-item">
<a href="charts-apex-mixed.html" class="nav-link" data-key="t-mixed">
Mixed </a>
</li>
<li class="nav-item">
<a href="charts-apex-timeline.html" class="nav-link"
data-key="t-timeline"> Timeline </a>
</li>
<li class="nav-item">
<a href="charts-apex-candlestick.html" class="nav-link"
data-key="t-candlstick"> Candlstick </a>
</li>
<li class="nav-item">
<a href="charts-apex-boxplot.html" class="nav-link" data-key="t-boxplot">
Boxplot </a>
</li>
<li class="nav-item">
<a href="charts-apex-bubble.html" class="nav-link" data-key="t-bubble">
Bubble </a>
</li>
<li class="nav-item">
<a href="charts-apex-scatter.html" class="nav-link" data-key="t-scatter">
Scatter </a>
</li>
<li class="nav-item">
<a href="charts-apex-heatmap.html" class="nav-link" data-key="t-heatmap">
Heatmap </a>
</li>
<li class="nav-item">
<a href="charts-apex-treemap.html" class="nav-link" data-key="t-treemap">
Treemap </a>
</li>
<li class="nav-item">
<a href="charts-apex-pie.html" class="nav-link" data-key="t-pie">
Pie </a>
</li>
<li class="nav-item">
<a href="charts-apex-radialbar.html" class="nav-link"
data-key="t-radialbar"> Radialbar </a>
</li>
<li class="nav-item">
<a href="charts-apex-radar.html" class="nav-link" data-key="t-radar">
Radar </a>
</li>
<li class="nav-item">
<a href="charts-apex-polar.html" class="nav-link"
data-key="t-polar-area"> Polar Area </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a href="charts-chartjs.html" class="nav-link" data-key="t-chartjs">
Chartjs </a>
</li>
<li class="nav-item">
<a href="charts-echarts.html" class="nav-link" data-key="t-echarts">
Echarts </a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarIcons" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarIcons">
<i data-feather="archive" class="icon-dual"></i> <span data-key="t-icons">Icons</span>
</a>
<div class="collapse menu-dropdown" id="sidebarIcons">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="icons-remix.html" class="nav-link" data-key="t-remix">Remix</a>
</li>
<li class="nav-item">
<a href="icons-boxicons.html" class="nav-link" data-key="t-boxicons">Boxicons</a>
</li>
<li class="nav-item">
<a href="icons-materialdesign.html" class="nav-link"
data-key="t-material-design">Material Design</a>
</li>
<li class="nav-item">
<a href="icons-lineawesome.html" class="nav-link" data-key="t-line-awesome">Line
Awesome</a>
</li>
<li class="nav-item">
<a href="icons-feather.html" class="nav-link" data-key="t-feather">Feather</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarMaps" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarMaps">
<i data-feather="map-pin" class="icon-dual"></i> <span data-key="t-maps">Maps</span>
</a>
<div class="collapse menu-dropdown" id="sidebarMaps">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="maps-google.html" class="nav-link" data-key="t-google">
Google
</a>
</li>
<li class="nav-item">
<a href="maps-vector.html" class="nav-link" data-key="t-vector">
Vector
</a>
</li>
<li class="nav-item">
<a href="maps-leaflet.html" class="nav-link" data-key="t-leaflet">
Leaflet
</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="#sidebarMultilevel" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarMultilevel">
<i data-feather="share-2" class="icon-dual"></i> <span data-key="t-multi-level">Multi
Level</span>
</a>
<div class="collapse menu-dropdown" id="sidebarMultilevel">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="#" class="nav-link" data-key="t-level-1.1"> Level 1.1 </a>
</li>
<li class="nav-item">
<a href="#sidebarAccount" class="nav-link" data-bs-toggle="collapse" role="button"
aria-expanded="false" aria-controls="sidebarAccount" data-key="t-level-1.2">
Level 1.2
</a>
<div class="collapse menu-dropdown" id="sidebarAccount">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="#" class="nav-link" data-key="t-level-2.1">
Level 2.1 </a>
</li>
<li class="nav-item">
<a href="#sidebarCrm" class="nav-link" data-bs-toggle="collapse"
role="button" aria-expanded="false" aria-controls="sidebarCrm"
data-key="t-level-2.2"> Level 2.2
</a>
<div class="collapse menu-dropdown" id="sidebarCrm">
<ul class="nav nav-sm flex-column">
<li class="nav-item">
<a href="#" class="nav-link" data-key="t-level-3.1">
Level 3.1 </a>
</li>
<li class="nav-item">
<a href="#" class="nav-link" data-key="t-level-3.2">
Level 3.2 </a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<!-- Sidebar -->
</div>
</div>

View File

@ -0,0 +1,29 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Profile') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-profile-information-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.update-password-form')
</div>
</div>
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
<div class="max-w-xl">
@include('profile.partials.delete-user-form')
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@ -0,0 +1,55 @@
<section class="space-y-6">
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Delete Account') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }}
</p>
</header>
<x-danger-button
x-data=""
x-on:click.prevent="$dispatch('open-modal', 'confirm-user-deletion')"
>{{ __('Delete Account') }}</x-danger-button>
<x-modal name="confirm-user-deletion" :show="$errors->userDeletion->isNotEmpty()" focusable>
<form method="post" action="{{ route('profile.destroy') }}" class="p-6">
@csrf
@method('delete')
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Are you sure you want to delete your account?') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
</p>
<div class="mt-6">
<x-input-label for="password" value="{{ __('Password') }}" class="sr-only" />
<x-text-input
id="password"
name="password"
type="password"
class="mt-1 block w-3/4"
placeholder="{{ __('Password') }}"
/>
<x-input-error :messages="$errors->userDeletion->get('password')" class="mt-2" />
</div>
<div class="mt-6 flex justify-end">
<x-secondary-button x-on:click="$dispatch('close')">
{{ __('Cancel') }}
</x-secondary-button>
<x-danger-button class="ms-3">
{{ __('Delete Account') }}
</x-danger-button>
</div>
</form>
</x-modal>
</section>

View File

@ -0,0 +1,48 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Update Password') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __('Ensure your account is using a long, random password to stay secure.') }}
</p>
</header>
<form method="post" action="{{ route('password.update') }}" class="mt-6 space-y-6">
@csrf
@method('put')
<div>
<x-input-label for="update_password_current_password" :value="__('Current Password')" />
<x-text-input id="update_password_current_password" name="current_password" type="password" class="mt-1 block w-full" autocomplete="current-password" />
<x-input-error :messages="$errors->updatePassword->get('current_password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password" :value="__('New Password')" />
<x-text-input id="update_password_password" name="password" type="password" class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="update_password_password_confirmation" name="password_confirmation" type="password" class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password_confirmation')" class="mt-2" />
</div>
<div class="flex items-center gap-4">
<x-primary-button>{{ __('Save') }}</x-primary-button>
@if (session('status') === 'password-updated')
<p
x-data="{ show: true }"
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>
</form>
</section>

View File

@ -0,0 +1,64 @@
<section>
<header>
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Profile Information') }}
</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
{{ __("Update your account's profile information and email address.") }}
</p>
</header>
<form id="send-verification" method="post" action="{{ route('verification.send') }}">
@csrf
</form>
<form method="post" action="{{ route('profile.update') }}" class="mt-6 space-y-6">
@csrf
@method('patch')
<div>
<x-input-label for="name" :value="__('Name')" />
<x-text-input id="name" name="name" type="text" class="mt-1 block w-full" :value="old('name', $user->name)" required autofocus autocomplete="name" />
<x-input-error class="mt-2" :messages="$errors->get('name')" />
</div>
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" name="email" type="email" class="mt-1 block w-full" :value="old('email', $user->email)" required autocomplete="username" />
<x-input-error class="mt-2" :messages="$errors->get('email')" />
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && ! $user->hasVerifiedEmail())
<div>
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
{{ __('Your email address is unverified.') }}
<button form="send-verification" 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">
{{ __('Click here to re-send the verification email.') }}
</button>
</p>
@if (session('status') === 'verification-link-sent')
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
{{ __('A new verification link has been sent to your email address.') }}
</p>
@endif
</div>
@endif
</div>
<div class="flex items-center gap-4">
<x-primary-button>{{ __('Save') }}</x-primary-button>
@if (session('status') === 'profile-updated')
<p
x-data="{ show: true }"
x-show="show"
x-transition
x-init="setTimeout(() => show = false, 2000)"
class="text-sm text-gray-600 dark:text-gray-400"
>{{ __('Saved.') }}</p>
@endif
</div>
</form>
</section>

View File

@ -832,8 +832,8 @@ class="relative sm:flex sm:justify-center sm:items-center min-h-screen bg-dots-d
@if (Route::has('login'))
<div class="sm:fixed sm:top-0 sm:right-0 p-6 text-right">
@auth
<a href="{{ url('/home') }}"
class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Home</a>
<a href="{{ url('/dashboard') }}"
class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Dashboard</a>
@else
<a href="{{ route('login') }}"
class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Log

59
routes/auth.php Normal file
View File

@ -0,0 +1,59 @@
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;
Route::middleware('guest')->group(function () {
Route::get('register', [RegisteredUserController::class, 'create'])
->name('register');
Route::post('register', [RegisteredUserController::class, 'store']);
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])
->name('password.request');
Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])
->name('password.email');
Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])
->name('password.reset');
Route::post('reset-password', [NewPasswordController::class, 'store'])
->name('password.store');
});
Route::middleware('auth')->group(function () {
Route::get('verify-email', EmailVerificationPromptController::class)
->name('verification.notice');
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware('throttle:6,1')
->name('verification.send');
Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])
->name('password.confirm');
Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);
Route::put('password', [PasswordController::class, 'update'])->name('password.update');
Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
->name('logout');
});

View File

@ -1,5 +1,10 @@
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\TwoStepVerifyController;
use App\Http\Controllers\DashboardController;
use Illuminate\Support\Facades\Route;
/*
@ -13,6 +18,41 @@
|
*/
Route::get('/', function () {
return view('welcome');
Route::middleware('guest')->group(function () {
Route::name('auth.')->group(function () {
Route::controller(AuthenticatedSessionController::class)->group(function () {
Route::get('/', 'create')->name('login');
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::post('/verifikasi-akun', 'store')->name('two_step_verify_post');
Route::post('/verifikasi-akun/resend', 'resendEmail')->name('two_step_verify_resend');
});
Route::controller(PasswordResetLinkController::class)->group(function () {
Route::get('/forgot-password', 'create')->name('forgot_password');
Route::post('/reset-password', 'store')->name('reset_password');
Route::get('/validasi-lupa-password/{token}', 'createNewPasswordForm')->name('create_new_password_form');
Route::post('/validasi-lupa-password', 'storeNewPasswordForm')->name('store_new_password_form');
});
});
});
Route::middleware(['auth', 'verifiedAcount'])->group(function () {
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])->name('auth.logout');
Route::controller(DashboardController::class)->name('dashboard.')->group(function () {
Route::get('/dashboard-admin', 'admin')->name('admin');
Route::get('/dashboard-petugas', 'petugas')->name('petugas');
});
});

21
tailwind.config.js Normal file
View File

@ -0,0 +1,21 @@
import defaultTheme from 'tailwindcss/defaultTheme';
import forms from '@tailwindcss/forms';
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
theme: {
extend: {
fontFamily: {
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [forms],
};

View File

@ -0,0 +1,55 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class AuthenticationTest extends TestCase
{
use RefreshDatabase;
public function test_login_screen_can_be_rendered(): void
{
$response = $this->get('/login');
$response->assertStatus(200);
}
public function test_users_can_authenticate_using_the_login_screen(): void
{
$user = User::factory()->create();
$response = $this->post('/login', [
'email' => $user->email,
'password' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
public function test_users_can_not_authenticate_with_invalid_password(): void
{
$user = User::factory()->create();
$this->post('/login', [
'email' => $user->email,
'password' => 'wrong-password',
]);
$this->assertGuest();
}
public function test_users_can_logout(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/logout');
$this->assertGuest();
$response->assertRedirect('/');
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL;
use Tests\TestCase;
class EmailVerificationTest extends TestCase
{
use RefreshDatabase;
public function test_email_verification_screen_can_be_rendered(): void
{
$user = User::factory()->create([
'email_verified_at' => null,
]);
$response = $this->actingAs($user)->get('/verify-email');
$response->assertStatus(200);
}
public function test_email_can_be_verified(): void
{
$user = User::factory()->create([
'email_verified_at' => null,
]);
Event::fake();
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
$response = $this->actingAs($user)->get($verificationUrl);
Event::assertDispatched(Verified::class);
$this->assertTrue($user->fresh()->hasVerifiedEmail());
$response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
}
public function test_email_is_not_verified_with_invalid_hash(): void
{
$user = User::factory()->create([
'email_verified_at' => null,
]);
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1('wrong-email')]
);
$this->actingAs($user)->get($verificationUrl);
$this->assertFalse($user->fresh()->hasVerifiedEmail());
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PasswordConfirmationTest extends TestCase
{
use RefreshDatabase;
public function test_confirm_password_screen_can_be_rendered(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/confirm-password');
$response->assertStatus(200);
}
public function test_password_can_be_confirmed(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/confirm-password', [
'password' => 'password',
]);
$response->assertRedirect();
$response->assertSessionHasNoErrors();
}
public function test_password_is_not_confirmed_with_invalid_password(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/confirm-password', [
'password' => 'wrong-password',
]);
$response->assertSessionHasErrors();
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class PasswordResetTest extends TestCase
{
use RefreshDatabase;
public function test_reset_password_link_screen_can_be_rendered(): void
{
$response = $this->get('/forgot-password');
$response->assertStatus(200);
}
public function test_reset_password_link_can_be_requested(): void
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class);
}
public function test_reset_password_screen_can_be_rendered(): void
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
$response = $this->get('/reset-password/'.$notification->token);
$response->assertStatus(200);
return true;
});
}
public function test_password_can_be_reset_with_valid_token(): void
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
$response = $this->post('/reset-password', [
'token' => $notification->token,
'email' => $user->email,
'password' => 'password',
'password_confirmation' => 'password',
]);
$response
->assertSessionHasNoErrors()
->assertRedirect(route('login'));
return true;
});
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class PasswordUpdateTest extends TestCase
{
use RefreshDatabase;
public function test_password_can_be_updated(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->from('/profile')
->put('/password', [
'current_password' => 'password',
'password' => 'new-password',
'password_confirmation' => 'new-password',
]);
$response
->assertSessionHasNoErrors()
->assertRedirect('/profile');
$this->assertTrue(Hash::check('new-password', $user->refresh()->password));
}
public function test_correct_password_must_be_provided_to_update_password(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->from('/profile')
->put('/password', [
'current_password' => 'wrong-password',
'password' => 'new-password',
'password_confirmation' => 'new-password',
]);
$response
->assertSessionHasErrorsIn('updatePassword', 'current_password')
->assertRedirect('/profile');
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Tests\Feature\Auth;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered(): void
{
$response = $this->get('/register');
$response->assertStatus(200);
}
public function test_new_users_can_register(): void
{
$response = $this->post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ProfileTest extends TestCase
{
use RefreshDatabase;
public function test_profile_page_is_displayed(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->get('/profile');
$response->assertOk();
}
public function test_profile_information_can_be_updated(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->patch('/profile', [
'name' => 'Test User',
'email' => 'test@example.com',
]);
$response
->assertSessionHasNoErrors()
->assertRedirect('/profile');
$user->refresh();
$this->assertSame('Test User', $user->name);
$this->assertSame('test@example.com', $user->email);
$this->assertNull($user->email_verified_at);
}
public function test_email_verification_status_is_unchanged_when_the_email_address_is_unchanged(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->patch('/profile', [
'name' => 'Test User',
'email' => $user->email,
]);
$response
->assertSessionHasNoErrors()
->assertRedirect('/profile');
$this->assertNotNull($user->refresh()->email_verified_at);
}
public function test_user_can_delete_their_account(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->delete('/profile', [
'password' => 'password',
]);
$response
->assertSessionHasNoErrors()
->assertRedirect('/');
$this->assertGuest();
$this->assertNull($user->fresh());
}
public function test_correct_password_must_be_provided_to_delete_account(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->from('/profile')
->delete('/profile', [
'password' => 'wrong-password',
]);
$response
->assertSessionHasErrorsIn('userDeletion', 'password')
->assertRedirect('/profile');
$this->assertNotNull($user->fresh());
}
}

View File

@ -4,7 +4,10 @@ import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
],