initial commit

parents
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore
*.log
.DS_Store
.env
.env.backup
.env.production
.phpactor.json
.phpunit.result.cache
/.fleet
/.idea
/.nova
/.phpunit.cache
/.vscode
/.zed
/auth.json
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/storage/pail
/vendor
Homestead.json
Homestead.yaml
Thumbs.db
/public/laravolt
/build/coverage
/phpunit-coverage-result.xml
/phpunit-execution-result.xml
# My Awesome Laravolt Application
## Server Requirements
1. PHP 8.4
1. Composer 2
1. SQLite, PostgreSQL, MySQL or MariaDB
## Local Setup
1. Clone repository
1. Jalankan `composer install`
1. Jalankan `cp .env.example .env`
1. Sesuaikan konfigurasi database dan lain-lain
1. Jalankan `php artisan key:generate`
1. Jalankan `php artisan migrate:fresh --seed`
1. Jalankan `php artisan laravolt:link`
1. Jalankan `php artisan vendor:publish --tag=laravolt-assets`
1. Pastikan folder-folder berikut _writeable_:
1. `bootstrap/cache`
1. `storage`
1. php artisan laravolt:admin Administrator admin@laravolt.dev secret
<?php
namespace App\Enums;
use BenSampo\Enum\Enum;
/**
* @extends Enum<string>
*/
final class Permission extends Enum
{
// sample permission
// const POST_MANAGE = 'post.manage';
}
<?php
namespace App\Enums;
use BenSampo\Enum\Enum;
/**
* @extends Enum<string>
*/
final class UserStatus extends Enum
{
const PENDING = 'PENDING';
const ACTIVE = 'ACTIVE';
const BLOCKED = 'BLOCKED';
}
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
class ForgotPasswordController extends Controller
{
/**
* Display the form to request a password reset link.
*
* @return \Illuminate\Contracts\View\View
*/
public function show()
{
return view('auth.forgot');
}
/**
* Send a reset link to the given user.
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate(['email' => ['required', 'email', 'exists:users']]);
$response = Password::INVALID_USER;
$user = User::whereEmail($request->email)->first();
if ($user) {
$response = app('laravolt.password')->sendResetLink($user);
}
if ($response === Password::RESET_LINK_SENT && $user) {
$email = $user->getEmailForPasswordReset();
return redirect()
->route('auth::forgot.show')
->with('success', trans($response, ['email' => $email, 'emailMasked' => Str::maskEmail($email)]));
}
return redirect()
->route('auth::forgot.show')
->with('error', ['email' => trans($response)]);
}
}
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Requests\Auth\LoginRequest;
use Illuminate\Routing\Controller;
class LoginController extends Controller
{
/**
* Display the login view.
*
* @return \Illuminate\Contracts\View\View
*/
public function show()
{
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(\App\Providers\AppServiceProvider::HOME);
}
}
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class Logout
{
public function __invoke(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class RegistrationController extends Controller
{
/**
* Display the registration view.
*
* @return \Illuminate\Contracts\View\View
*/
public function show()
{
return view('auth.register');
}
/**
* Handle an incoming registration request.
*
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|confirmed|min:8',
]);
/** @var string $password */
$password = $request->password;
Auth::login(
$user = User::query()->create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($password),
'status' => 'ACTIVE',
])
);
if (config('laravolt.platform.features.verification') === false) {
$user->markEmailAsVerified();
}
event(new Registered($user));
return redirect(\App\Providers\AppServiceProvider::HOME)
->with('success', __('Your account successfully created'));
}
}
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
class ResetPasswordController extends Controller
{
/**
* Display the password reset view.
*
* @return \Illuminate\Contracts\View\View
*/
public function show(Request $request, ?string $token = null)
{
return view('auth.reset', ['token' => $token]);
}
/**
* Handle an incoming new password request.
*
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$request->validate(
[
'token' => 'required',
'email' => 'required|email',
'password' => 'required|string|confirmed|min:8',
]
);
/** @var string $password */
$password = $request->password;
// 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.
/** @var string $status */
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user) use ($password) {
$attributes = [
'password' => Hash::make($password),
'remember_token' => Str::random(60),
];
$user->forceFill($attributes)->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('auth::login.show')->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}
<?php
namespace App\Http\Controllers\Auth;
use App\Providers\AppServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Controller;
use function PHPUnit\Framework\assertInstanceOf;
class VerificationController extends Controller
{
public function show(): View|RedirectResponse
{
/** @var MustVerifyEmail $user */
$user = auth()->user();
if ($user->hasVerifiedEmail()) {
return redirect()->intended(AppServiceProvider::HOME);
}
return view('auth.verify-email');
}
public function store(): RedirectResponse
{
/** @var MustVerifyEmail $user */
$user = auth()->user();
assertInstanceOf(MustVerifyEmail::class, $user);
return $this->handle($user);
}
public function update(EmailVerificationRequest $request): RedirectResponse
{
/** @var MustVerifyEmail $user */
$user = auth()->user();
if ($user->hasVerifiedEmail()) {
return redirect()->intended(AppServiceProvider::HOME.'?verified=1');
}
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
return redirect()->intended(AppServiceProvider::HOME.'?verified=1');
}
private function handle(MustVerifyEmail $user): RedirectResponse
{
if ($user->hasVerifiedEmail()) {
return redirect()->intended(AppServiceProvider::HOME);
}
$user->sendEmailVerificationNotification();
return back()->withSuccess(
__(
'Link verifikasi sudah dikirim ke alamat email :email',
[
'email' => $user->getEmailForVerification(),
]
)
);
}
}
<?php
namespace App\Http\Controllers;
abstract class Controller
{
//
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function __invoke(Request $request)
{
return view('dashboard');
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
class Home extends Controller
{
public function __invoke(Request $request): View
{
return view('home');
}
}
<?php
namespace App\Http\Controllers\My;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Controller;
use Laravolt\Epicentrum\Http\Requests\My\Password\Update;
class PasswordController extends Controller
{
public function edit(): View
{
$user = auth()->user();
return view('my.password.edit', compact('user'));
}
public function update(Update $request): RedirectResponse
{
/** @var string $password */
$password = $request->input('password_current');
/** @var \App\Models\User $user */
$user = auth()->user();
if (app('hash')->check($password, $user->password)) {
$user->setPassword($request->password);
return redirect()->route('my::password.edit')->withSuccess(__('laravolt::message.password_updated'));
}
return redirect()->route('my::password.edit')->withError(
__('laravolt::message.current_password_mismatch')
);
}
}
<?php
namespace App\Http\Controllers\My;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Controller;
use Laravolt\Epicentrum\Http\Requests\My\Profile\Update;
use Laravolt\Support\Contracts\TimezoneRepository;
class ProfileController extends Controller
{
public function edit(TimezoneRepository $timezone): View
{
$user = auth()->user();
$timezones = $timezone->all();
return view('my.profile.edit', compact('user', 'timezones'));
}
public function update(Update $request): RedirectResponse
{
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var array<string, mixed> $validated */
$validated = $request->validated();
$user->update($validated);
return redirect()->back()->withSuccess(__('Profil berhasil diperbarui'));
}
}
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('auth::login.show');
}
}
<?php
namespace App\Http\Middleware;
use App\Providers\AppServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string ...$guards): Response
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(AppServiceProvider::HOME);
}
}
return $next($request);
}
}
<?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
{
protected int $maxAttempts = 5;
protected int $decaySeconds = 60;
/**
* Get the validation rules that apply to the request.
*
* @return array<string, string|array<mixed>>
*/
public function rules(): array
{
return [
'email' => 'required|string|email',
'password' => 'required|string',
];
}
/**
* Attempt to authenticate the request's credentials.
*
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password') + ['status' => 'ACTIVE'], $this->filled('remember'))) {
RateLimiter::hit($this->throttleKey(), $this->decaySeconds);
throw ValidationException::withMessages(
[
'email' => __('auth.failed'),
]
);
}
RateLimiter::clear($this->throttleKey());
}
/**
* Ensure the login request is not rate limited.
*
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited()
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), $this->maxAttempts)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages(
[
'email' => trans(
'auth.throttle',
[
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]
),
]
);
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey(): string
{
/** @var string $email */
$email = $this->input('email');
return Str::lower($email).'|'.$this->ip();
}
}
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Laravolt\Platform\Models\User as BaseUser;
use Laravolt\Suitable\AutoFilter;
use Laravolt\Suitable\AutoSearch;
use Laravolt\Suitable\AutoSort;
/**
* @use HasFactory<UserFactory>
*/
class User extends BaseUser
{
use AutoFilter, AutoSearch, AutoSort;
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
// use \Laravel\Sanctum\HasApiTokens;
/**
* The attributes that are mass assignable.
*/
protected $fillable = ['name', 'email', 'username', 'password', 'status', 'timezone'];
/**
* The attributes that should be hidden for serialization.
*/
protected $hidden = ['password', 'remember_token'];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/home';
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*/
public function boot(): void
{
$this->registerPolicies();
}
}
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravolt\Listeners\SendEmailVerificationNotification;
class EventServiceProvider extends ServiceProvider
{
/**
* The event handler mappings for the application.
*
* @var array<string, array<int, string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Boot any application services.
*/
public function boot(): void
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool
{
return false;
}
}
#!/usr/bin/env php
<?php
use Illuminate\Foundation\Application;
use Symfony\Component\Console\Input\ArgvInput;
define('LARAVEL_START', microtime(true));
// Register the Composer autoloader...
require __DIR__.'/vendor/autoload.php';
// Bootstrap Laravel and handle the command...
/** @var Application $app */
$app = require_once __DIR__.'/bootstrap/app.php';
$status = $app->handleCommand(new ArgvInput);
exit($status);
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->appendToGroup('web', [
\Laravolt\Middleware\DetectFlashMessage::class,
\Laravolt\Middleware\CheckPassword::class,
]);
$middleware->alias([
'auth' => \App\Http\Middleware\Authenticate::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
$exceptions->dontReportDuplicates();
$exceptions->reportable(function (\Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
$exceptions->render(function (\Illuminate\Session\TokenMismatchException $e) {
return back()->with(
'error',
__('Kami mendeteksi tidak ada aktivitas cukup lama, silakan kirim ulang form.')
);
});
$exceptions->render(function (\Illuminate\Auth\AuthenticationException $e, Request $request) {
if ($request->expectsJson()) {
return response()->json(['message' => $e->getMessage()], 401);
}
return redirect()
->guest($e->redirectTo($request) ?? route('auth::login.show'))
->with('warning', __('Silakan login terlebih dahulu') ?? '');
});
$exceptions->render(function (\Illuminate\Auth\Access\AuthorizationException $e, Request $request) {
if ($request->wantsJson()) {
return response()->json(['message' => $e->getMessage()], 403);
}
if ($request->is('livewire/*')) {
return abort(403);
}
return redirect()
->back(302, [], route('home'))
->withInput()
->with('error', $e->getMessage());
});
})->create();
<?php
return [
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
];
{
"$schema": "https://getcomposer.org/schema.json",
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.2",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1",
"laravolt/laravolt": "^6.14"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"laravel/pail": "^1.2.2",
"laravel/pint": "^1.13",
"laravel/sail": "^1.41",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^11.5.3"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"@php artisan config:clear",
"@php artisan clear-compiled",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
],
"test": [
"@php artisan config:clear --ansi",
"@php artisan test"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "stable",
"prefer-stable": true
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application, which will be used when the
| framework needs to place the application's name in a notification or
| other UI elements where an application name needs to be displayed.
|
*/
'name' => env('APP_NAME', 'Laravel'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => (bool) env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| the application so that it's available within Artisan commands.
|
*/
'url' => env('APP_URL', 'http://localhost'),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
|
*/
'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
|
*/
'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is utilized by Laravel's encryption services and should be set
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
|
*/
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'),
'previous_keys' => [
...array_filter(
explode(',', (string) env('APP_PREVIOUS_KEYS', ''))
),
],
/*
|--------------------------------------------------------------------------
| Maintenance Mode Driver
|--------------------------------------------------------------------------
|
| These configuration options determine the driver used to determine and
| manage Laravel's "maintenance mode" status. The "cache" driver will
| allow maintenance mode to be controlled across multiple machines.
|
| Supported drivers: "file", "cache"
|
*/
'maintenance' => [
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
'store' => env('APP_MAINTENANCE_STORE', 'database'),
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option defines the default authentication "guard" and password
| reset "broker" for your application. You may change these values
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => env('AUTH_GUARD', 'web'),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| which utilizes session storage plus the Eloquent user provider.
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| If you have multiple user tables or models you may configure multiple
| providers to represent the model / table. These providers may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| These configuration options specify the behavior of Laravel's password
| reset functionality, including the table utilized for token storage
| and the user provider that is invoked to actually retrieve users.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the number of seconds before a password confirmation
| window expires and users are asked to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
];
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache store that will be used by the
| framework. This connection is utilized if another isn't explicitly
| specified when running a cache operation inside the application.
|
*/
'default' => env('CACHE_STORE', 'database'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "array", "database", "file", "memcached",
| "redis", "dynamodb", "octane", "null"
|
*/
'stores' => [
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'connection' => env('DB_CACHE_CONNECTION'),
'table' => env('DB_CACHE_TABLE', 'cache'),
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
'lock_path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
'octane' => [
'driver' => 'octane',
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
| stores, there might be other applications using the same cache. For
| that reason, you may prefix every cache key to avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'),
];
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for database operations. This is
| the connection which will be utilized unless another connection
| is explicitly specified when you execute a query / statement.
|
*/
'default' => env('DB_CONNECTION', 'sqlite'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Below are all of the database connections defined for your application.
| An example configuration is provided for each database system which
| is supported by Laravel. You're free to add / remove connections.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DB_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
'busy_timeout' => null,
'journal_mode' => null,
'synchronous' => null,
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mariadb' => [
'driver' => 'mariadb',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'sslmode' => 'prefer',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DB_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run on the database.
|
*/
'migrations' => [
'table' => 'migrations',
'update_date_on_publish' => true,
],
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as Memcached. You may define your connection settings here.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'),
'persistent' => env('REDIS_PERSISTENT', false),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application for file storage.
|
*/
'default' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Below you may configure as many filesystem disks as necessary, and you
| may even configure multiple disks for the same driver. Examples for
| most supported storage drivers are configured here for reference.
|
| Supported drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
'report' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
'report' => false,
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
'report' => false,
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
<?php
return [
// Configuration for the default group. Feel free to add more groups.
// Each group can have different settings.
'default' => [
/**
* Regex to match against a filename/url to determine if it is an asset.
*
* @var string
*/
'asset_regex' => '/.\.(css|js)$/i',
/**
* Absolute path to the public directory of your App (WEBROOT).
* Required if you enable the pipeline.
* No trailing slash!.
*
* @var string
*/
'public_dir' => public_path(),
/**
* Directory for local CSS assets.
* Relative to your public directory ('public_dir').
* No trailing slash!.
*
* @var string
*/
'css_dir' => 'css',
/**
* Directory for local JavaScript assets.
* Relative to your public directory ('public_dir').
* No trailing slash!.
*
* @var string
*/
'js_dir' => 'js',
/**
* Available collections.
* Each collection is an array of assets.
* Collections may also contain other collections.
*
* @var array
*/
'collections' => [
// jQuery (CDN)
// 'jquery-cdn' => array('//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'),
// jQuery UI (CDN)
// 'jquery-ui-cdn' => array(
// 'jquery-cdn',
// '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
// ),
// Twitter Bootstrap (CDN)
// 'bootstrap-cdn' => array(
// 'jquery-cdn',
// '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css',
// '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css',
// '//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'
// ),
// Redactor
'redactor' => [
'/laravolt/css/redactor.min.css',
'/laravolt/js/redactor.min.js',
],
],
/**
* Preload assets.
* Here you may set which assets (CSS files, JavaScript files or collections)
* should be loaded by default even if you don't explicitly add them on run time.
*
* @var array
*/
'autoload' => [
// 'jquery-cdn',
],
], // End of default group
];
<?php
return [
'routes' => [
'enabled' => true,
'middleware' => ['web', 'auth'],
'prefix' => 'resource',
],
'menu' => [
'enabled' => true,
'label' => 'Resources',
],
'permission' => \Laravolt\Platform\Enums\Permission::MANAGE_SYSTEM,
];
<?php
/*
* Set specific configuration variables here
*/
return [
'routes' => [
'enabled' => true,
'middleware' => config('laravolt.platform.middleware'),
'prefix' => 'database-monitor',
],
'view' => [
'layout' => 'laravolt::layouts.app',
],
'menu' => [
'enabled' => true,
],
'disk' => env('DB_BACKUP_DISK', 'local'),
];
<?php
/*
* Set specific configuration variables here
*/
return [
'role' => [
'multiple' => true,
'editable' => true,
],
'repository' => [
'user' => \Laravolt\Epicentrum\Repositories\EloquentRepository::class,
'role' => \Laravolt\Epicentrum\Repositories\RoleRepository::class,
'timezone' => \Laravolt\Support\Repositories\TimezoneRepository::class,
'searchable' => ['name', 'email', 'status'],
],
'requests' => [
'account' => [
'store' => \Laravolt\Epicentrum\Http\Requests\Account\Store::class,
'update' => \Laravolt\Epicentrum\Http\Requests\Account\Update::class,
'delete' => \Laravolt\Epicentrum\Http\Requests\Account\Delete::class,
],
],
// Max user allowed
// null or 0 mean unlimited
'user_limit' => null,
'user_available_status' => [
'PENDING' => 'PENDING',
'ACTIVE' => 'ACTIVE',
'BLOCKED' => 'BLOCKED',
],
'models' => [
'user' => \App\Models\User::class,
'role' => \Laravolt\Platform\Models\Role::class,
'permission' => \Laravolt\Platform\Models\Permission::class,
],
'table_view' => \Laravolt\Epicentrum\Livewire\UserTable::class,
];
<?php
return [
'routes' => [
'enabled' => true,
'middleware' => config('laravolt.platform.middleware'),
'prefix' => '',
],
'view' => [
'layout' => 'laravolt::layouts.app',
],
'menu' => [
'enabled' => true,
],
'permission' => \Laravolt\Platform\Enums\Permission::MANAGE_LOOKUP,
'collections' => [
// Sample lookup collections
'pekerjaan' => [
'label' => 'Pekerjaan',
],
],
];
<?php
return [
'System' => [
'order' => 99,
'menu' => [
'Users' => [
'route' => 'epicentrum::users.index',
'active' => 'epicentrum/users/*',
'icon' => 'user-friends',
'permissions' => [\Laravolt\Platform\Enums\Permission::MANAGE_USER],
],
'Roles' => [
'route' => 'epicentrum::roles.index',
'config' => 'epicentrum/roles/*',
'icon' => 'user-astronaut',
'permissions' => [\Laravolt\Platform\Enums\Permission::MANAGE_ROLE],
],
'Permissions' => [
'route' => 'epicentrum::permissions.edit',
'active' => 'epicentrum/permissions/*',
'icon' => 'shield-check',
'permissions' => [\Laravolt\Platform\Enums\Permission::MANAGE_PERMISSION],
],
'Settings' => [
'route' => 'platform::settings.edit',
'active' => 'platform/settings/*',
'icon' => 'sliders-v',
'permissions' => [\Laravolt\Platform\Enums\Permission::MANAGE_SETTINGS],
],
],
],
'Application' => [
'order' => 1,
'menu' => [
'Dashboard' => [
'route' => 'dashboard',
'icon' => 'home',
],
],
],
];
<?php
/*
* Set specific configuration variables here
*/
return [
// ask user to change their password periodically
// leave null to skip checking or fill with integer (in days)
'duration' => null,
// where to redirect user to change their current password, if CheckPassword middleware applied
'redirect' => 'my/password',
// don't apply CheckPassword middleware to following url pattern
'except' => [
'auth/logout',
'_debugbar/*',
],
];
<?php
return [
'middleware' => ['web', 'auth'],
'features' => [
'database-monitor' => false,
'epicentrum' => true,
'mailkeeper' => false,
'lookup' => false,
'kitchen_sink' => false,
'spa' => false,
'quick_switcher' => false,
'registration' => true,
'verification' => true,
'captcha' => false,
'workflow' => false,
'enable_default_menu' => true,
],
'settings' => [
[
'type' => 'html',
'content' => '<h3 class="ui horizontal divider section m-t-3">Informasi Umum</h3>',
],
[
'type' => 'text',
'name' => 'brand_name',
'label' => 'Name',
],
[
'type' => 'text',
'name' => 'brand_description',
'label' => 'Description',
],
[
'type' => 'uploader',
'name' => 'brand_image',
'label' => 'Logo',
],
[
'type' => 'html',
'content' => '<h3 class="ui horizontal divider hidden m-t-3">Tampilan Sidebar</h3>',
],
[
'type' => 'dropdown',
'name' => 'font_size',
'label' => 'Ukuran Font',
'options' => ['sm' => 'Kecil', 'md' => 'Sedang', 'lg' => 'Besar'],
'inline' => true,
],
[
'type' => 'dropdown',
'name' => 'sidebar_density',
'label' => 'Density',
'options' => ['compact' => 'Compact', 'default' => 'Default'],
'rules' => ['required'],
],
[
'type' => \Laravolt\Fields\Field::RADIO_GROUP,
'name' => 'theme',
'options' => ['dark' => 'Dark', 'light' => 'Light', 'cool' => 'Cool'],
'label' => 'Tema',
'inline' => true,
],
[
'type' => \Laravolt\Fields\Field::DROPDOWN_COLOR,
'name' => 'color',
'label' => 'Warna Aksen',
'inline' => true,
],
[
'type' => 'html',
'content' => '<h3 class="ui horizontal divider section m-t-3">Halaman Login</h3>',
],
[
'type' => 'dropdown',
'options' => ['fullscreen' => 'Fullscreen', 'modern' => 'Modern', 'classic' => 'Classic'],
'name' => 'login_layout',
'label' => 'Layout',
'inline' => true,
],
],
];
<?php
return [
'brand_name' => env('APP_NAME', 'Laravolt'),
'brand_image' => '<svg height="50" viewBox="0 0 138 30" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.99 23.759L3.05 11.384C1.232 10.13 1.85 7.51898 4.117 6.90498L23.184 1.72998C23.5879 1.58424 24.0207 1.53693 24.4466 1.59198C24.8724 1.64703 25.279 1.80285 25.6326 2.04651C25.9861 2.29017 26.2765 2.61464 26.4795 2.99299C26.6825 3.37134 26.7924 3.79266 26.8 4.22198L25.67 21.771C25.536 23.854 22.808 25.013 20.99 23.759Z" class="ccompli2" fill="#E9327C"></path> <path d="M15.3 26.814L4.73098 6.14504C4.48938 5.6722 4.38307 5.14181 4.42376 4.61238C4.46445 4.08295 4.65057 3.57504 4.96158 3.14467C5.2726 2.7143 5.69643 2.37818 6.18634 2.17338C6.67625 1.96858 7.2132 1.90306 7.73798 1.98405L27.325 5.00704C27.7759 5.07665 28.2039 5.2523 28.5738 5.51955C28.9436 5.78681 29.2447 6.13803 29.4524 6.54434C29.66 6.95065 29.7683 7.40044 29.7682 7.85674C29.7681 8.31303 29.6597 8.7628 29.452 9.16904L20.429 26.815C20.1867 27.2865 19.8191 27.6821 19.3666 27.9582C18.9141 28.2344 18.3943 28.3804 17.8642 28.3803C17.3341 28.3802 16.8143 28.234 16.3619 27.9577C15.9095 27.6813 15.5421 27.2856 15.3 26.814V26.814Z" class="ccompli1" fill="#1DACE3"></path> <path d="M26.752 4.91801L16.988 3.41101L5 6.66601L9.785 16.027L20.99 23.759C21.2372 23.9277 21.5091 24.0569 21.796 24.142L26.052 15.819L26.752 4.91801Z" class="ccustom" fill="#001A49"></path> <path d="M76.209 7.33402C76.209 6.97109 76.3166 6.61632 76.5182 6.31455C76.7199 6.01279 77.0065 5.77759 77.3418 5.6387C77.6771 5.49982 78.046 5.46348 78.402 5.53428C78.7579 5.60509 79.0849 5.77986 79.3415 6.03648C79.5982 6.29311 79.7729 6.62008 79.8437 6.97603C79.9145 7.33199 79.8782 7.70095 79.7393 8.03625C79.6004 8.37155 79.3652 8.65814 79.0635 8.85977C78.7617 9.0614 78.4069 9.16902 78.044 9.16902C77.5588 9.16408 77.095 8.96916 76.7519 8.6261C76.4089 8.28303 76.2139 7.81916 76.209 7.33402V7.33402ZM76.515 10.066H79.574V20.26H76.515V10.066Z" class="ccustom" fill="#001A49"></path> <path d="M92.7839 15.163C92.8195 15.8368 92.7214 16.511 92.4955 17.1468C92.2695 17.7825 91.9201 18.3674 91.4674 18.8677C91.0146 19.3679 90.4674 19.7737 89.8572 20.0618C89.247 20.3498 88.5859 20.5144 87.9119 20.546C87.345 20.5768 86.7783 20.4812 86.2528 20.2661C85.7274 20.0509 85.2564 19.7216 84.8739 19.302V24.338H81.8159V10.066H84.8739V11.024C85.2565 10.6045 85.7275 10.2754 86.253 10.0604C86.7784 9.84545 87.3451 9.74999 87.9119 9.78098C88.5859 9.81247 89.2469 9.97691 89.8571 10.2648C90.4673 10.5528 91.0145 10.9585 91.4673 11.4587C91.9201 11.9589 92.2695 12.5436 92.4955 13.1794C92.7214 13.8151 92.8195 14.4892 92.7839 15.163ZM89.7259 15.163C89.7139 14.6857 89.5614 14.2226 89.2875 13.8315C89.0136 13.4405 88.6304 13.1389 88.186 12.9646C87.7415 12.7902 87.2555 12.7509 86.7888 12.8514C86.3221 12.9519 85.8953 13.1878 85.562 13.5296C85.2287 13.8714 85.0036 14.304 84.9149 14.7731C84.8262 15.2422 84.8779 15.7271 85.0634 16.167C85.2489 16.6069 85.56 16.9823 85.9578 17.2463C86.3557 17.5103 86.8225 17.651 87.2999 17.651C87.6278 17.6658 87.955 17.611 88.2602 17.4904C88.5654 17.3697 88.8416 17.1858 89.0707 16.9509C89.2998 16.7159 89.4766 16.4352 89.5896 16.127C89.7025 15.8189 89.749 15.4903 89.7259 15.163V15.163Z" class="ccustom" fill="#001A49"></path> <path d="M102.223 17.2C102.223 19.545 100.184 20.544 97.9821 20.544C97.0926 20.6245 96.1993 20.4362 95.4179 20.0035C94.6365 19.5709 94.003 18.9137 93.5991 18.117L96.2491 16.609C96.3569 16.9773 96.5877 17.2974 96.9032 17.5158C97.2186 17.7342 97.5995 17.8377 97.9821 17.809C98.7161 17.809 99.0821 17.584 99.0821 17.177C99.0821 16.055 94.0671 16.647 94.0671 13.119C94.0671 10.897 95.9421 9.776 98.0671 9.776C98.8642 9.75098 99.6533 9.94011 100.352 10.3237C101.052 10.7073 101.635 11.2713 102.042 11.957L99.4331 13.364C99.319 13.0964 99.1286 12.8683 98.8857 12.7083C98.6427 12.5482 98.358 12.4633 98.0671 12.464C97.5371 12.464 97.2111 12.664 97.2111 13.035C97.2081 14.205 102.223 13.43 102.223 17.2Z" class="ccustom" fill="#001A49"></path> <path d="M113.4 10.066V20.26H110.342V19.3C109.989 19.7229 109.54 20.0561 109.033 20.2724C108.527 20.4886 107.976 20.5817 107.426 20.544C105.367 20.544 103.614 19.076 103.614 16.323V10.066H106.672V15.877C106.646 16.12 106.674 16.3657 106.753 16.5969C106.832 16.8281 106.96 17.0394 107.129 17.216C107.298 17.3926 107.503 17.5302 107.73 17.6193C107.958 17.7085 108.202 17.7469 108.446 17.732C109.567 17.732 110.346 17.08 110.346 15.632V10.066H113.4Z" class="ccustom" fill="#001A49"></path> <path d="M130.928 14V20.26H127.87V14.266C127.87 13.247 127.38 12.594 126.402 12.594C125.382 12.594 124.812 13.308 124.812 14.511V20.26H121.753V14.266C121.753 13.247 121.264 12.594 120.285 12.594C119.266 12.594 118.695 13.308 118.695 14.511V20.26H115.637V10.066H118.7V11C119.017 10.5841 119.433 10.2543 119.91 10.0406C120.387 9.827 120.911 9.73636 121.432 9.77701C121.955 9.75142 122.477 9.86186 122.945 10.0976C123.413 10.3333 123.812 10.6862 124.103 11.122C124.442 10.6661 124.891 10.3035 125.408 10.0683C125.925 9.83305 126.494 9.73284 127.06 9.77701C129.4 9.78101 130.928 11.452 130.928 14Z" class="ccustom" fill="#001A49"></path> <path d="M133.519 10.003C134.773 10.003 135.789 8.9867 135.789 7.73301C135.789 6.47933 134.773 5.46301 133.519 5.46301C132.265 5.46301 131.249 6.47933 131.249 7.73301C131.249 8.9867 132.265 10.003 133.519 10.003Z" class="ccustom" fill="#001A49"></path> <path d="M34.457 5.37695H37.516V20.26H34.457V5.37695ZM39.248 15.163C39.2447 14.0942 39.5585 13.0485 40.1498 12.1583C40.7411 11.268 41.5833 10.5732 42.5697 10.1619C43.5562 9.75058 44.6424 9.64121 45.6911 9.84765C46.7397 10.0541 47.7035 10.567 48.4604 11.3216C49.2173 12.0761 49.7333 13.0382 49.943 14.0862C50.1527 15.1342 50.0468 16.2208 49.6386 17.2085C49.2304 18.1962 48.5383 19.0406 47.6499 19.6347C46.7615 20.2288 45.7168 20.546 44.648 20.546C43.9382 20.5535 43.234 20.4196 42.5765 20.152C41.9191 19.8844 41.3215 19.4884 40.8188 18.9873C40.316 18.4861 39.9182 17.8898 39.6485 17.2332C39.3788 16.5766 39.2427 15.8728 39.248 15.163V15.163ZM46.996 15.163C46.984 14.7019 46.8364 14.2547 46.5715 13.8772C46.3067 13.4997 45.9364 13.2086 45.507 13.0404C45.0775 12.8723 44.6081 12.8344 44.1573 12.9317C43.7065 13.0289 43.2944 13.257 42.9725 13.5872C42.6506 13.9175 42.4333 14.3353 42.3476 14.7884C42.262 15.2416 42.3118 15.7099 42.491 16.1349C42.6701 16.5598 42.9706 16.9225 43.3548 17.1776C43.739 17.4327 44.1899 17.5688 44.651 17.569C44.9668 17.578 45.2811 17.5214 45.5739 17.4029C45.8668 17.2845 46.1319 17.1066 46.3526 16.8805C46.5733 16.6545 46.7448 16.3852 46.8562 16.0896C46.9676 15.7939 47.0166 15.4784 47 15.163H46.996ZM62.245 10.063V19.748C62.245 23.173 59.574 24.62 56.863 24.62C55.9088 24.692 54.9531 24.4999 54.1007 24.0647C53.2484 23.6296 52.5323 22.9681 52.031 22.153L54.64 20.644C54.8506 21.0694 55.1861 21.4204 55.6016 21.6501C56.0171 21.8797 56.4927 21.977 56.965 21.929C57.2665 21.9701 57.5733 21.9431 57.8629 21.8498C58.1525 21.7565 58.4174 21.5995 58.6382 21.3901C58.8589 21.1808 59.0298 20.9246 59.1383 20.6403C59.2468 20.3561 59.2901 20.0511 59.265 19.748V18.81C58.9068 19.248 58.4509 19.596 57.934 19.8261C57.417 20.0562 56.8533 20.162 56.288 20.135C54.9425 20.0931 53.666 19.5292 52.729 18.5626C51.792 17.596 51.268 16.3027 51.268 14.9565C51.268 13.6102 51.792 12.3169 52.729 11.3503C53.666 10.3837 54.9425 9.81977 56.288 9.77795C56.8533 9.75091 57.417 9.85667 57.934 10.0868C58.4509 10.3169 58.9068 10.6649 59.265 11.103V10.063H62.245ZM59.269 14.956C59.2892 14.4636 59.1616 13.9765 58.9027 13.5572C58.6438 13.1379 58.2654 12.8056 57.8161 12.6031C57.3669 12.4006 56.8673 12.3371 56.3817 12.4208C55.8961 12.5045 55.4466 12.7315 55.091 13.0727C54.7354 13.4139 54.49 13.8536 54.3864 14.3353C54.2827 14.8171 54.3255 15.3188 54.5093 15.7761C54.693 16.2333 55.0094 16.6251 55.4176 16.9011C55.8258 17.1771 56.3073 17.3247 56.8 17.325C57.1213 17.3475 57.4438 17.3026 57.7467 17.1931C58.0496 17.0836 58.3262 16.9119 58.5588 16.689C58.7913 16.4662 58.9747 16.1971 59.097 15.8992C59.2193 15.6012 59.2779 15.2809 59.269 14.959V14.956ZM63.977 15.156C63.9737 14.0872 64.2875 13.0415 64.8788 12.1513C65.4701 11.261 66.3123 10.5662 67.2987 10.1549C68.2852 9.74358 69.3714 9.63421 70.4201 9.84065C71.4687 10.0471 72.4324 10.56 73.1894 11.3146C73.9463 12.0691 74.4623 13.0312 74.672 14.0792C74.8817 15.1272 74.7758 16.2138 74.3676 17.2015C73.9594 18.1892 73.2673 19.0336 72.3789 19.6277C71.4905 20.2218 70.4458 20.539 69.377 20.539C68.6678 20.5465 67.9642 20.4128 67.3072 20.1456C66.6502 19.8785 66.0529 19.4831 65.5503 18.9827C65.0476 18.4823 64.6497 17.8869 64.3796 17.231C64.1094 16.5752 63.9726 15.8722 63.977 15.163V15.156ZM71.725 15.156C71.7132 14.6947 71.5656 14.2471 71.3008 13.8692C71.0359 13.4914 70.6654 13.2001 70.2358 13.0317C69.8061 12.8633 69.3364 12.8254 68.8853 12.9227C68.4342 13.0199 68.0218 13.2481 67.6998 13.5785C67.3777 13.909 67.1602 14.3271 67.0746 14.7805C66.9889 15.2339 67.0389 15.7026 67.2182 16.1277C67.3976 16.5529 67.6983 16.9157 68.0828 17.1709C68.4674 17.426 68.9186 17.562 69.38 17.562C69.6949 17.5703 70.008 17.5136 70.2999 17.3953C70.5918 17.277 70.8561 17.0996 71.0763 16.8744C71.2964 16.6492 71.4677 16.3809 71.5793 16.0864C71.691 15.7919 71.7406 15.4775 71.725 15.163V15.156Z" class="ccustom" fill="#001A49"></path> </svg>',
'brand_description' => env('APP_DESCRIPTION', 'Sample application powered by Laravolt'),
/*
* Font Size
* Available options: xs, sm, md, xl, lg
* */
'font_size' => 'sm',
/*
* Sidebar menu density
* Available options: "compact", "default", or "cozy"
* */
'sidebar_density' => 'default',
/*
* Set default theme
* Available themes: dark, light
* */
'theme' => 'light',
/*
* Button color
* Choose one of the following colors that match closely with the theme
* Available colors: red, orange, yellow, olive, green, teal, blue, violet, purple, brow, grey, black
* */
'color' => 'teal',
/*
* Login page settings
*/
// Layout, Available options: 'modern', 'fullscreen', 'classic'
'login_layout' => 'modern',
// Background image
'login_background' => '/laravolt/img/wallpaper/animated-svg/dark.svg',
/*
* Iconset
* Available options: fad (two tone), fal (light), far (regular), fas (solid)
* Browse icons at https://fontawesome.com/v5/search
*/
'iconset' => 'fad',
'default_menu_icon' => 'circle',
'system_menu' => [
'order' => 99,
],
'flash' => [
'attributes' => [
'class' => 'black',
],
'except' => [],
],
'mail' => [
'header' => '#345',
'body' => '#F2F5F7',
'content' => [
'color' => '#2E3C4A',
'background' => '#FFFFFF',
],
'button' => [
'color' => '#FFFFFF',
'background' => '#0570D4',
],
],
'colors' => [
'red' => '#DB2828',
'orange' => '#F2711C',
'yellow' => '#FBBD08',
'olive' => '#B5CC18',
'green' => '#21BA45',
'teal' => '#00B5AD',
'blue' => '#0052CC',
'violet' => '#6435C9',
'purple' => '#A333C8',
'pink' => '#E03997',
'brown' => '#A5673F',
'grey' => '#767676',
'black' => '#1B1C1D',
],
];
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
use Monolog\Processor\PsrLogMessageProcessor;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that is utilized to write
| messages to your logs. The value provided here should match one of
| the channels present in the list of "channels" configured below.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Deprecations Log Channel
|--------------------------------------------------------------------------
|
| This option controls the log channel that should be used to log warnings
| regarding deprecated PHP and library features. This allows you to get
| your application ready for upcoming major versions of dependencies.
|
*/
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Laravel
| utilizes the Monolog PHP logging library, which includes a variety
| of powerful log handlers and formatters that you're free to use.
|
| Available drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => explode(',', (string) env('LOG_STACK', 'single')),
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => env('LOG_DAILY_DAYS', 14),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
],
'processors' => [PsrLogMessageProcessor::class],
],
'stderr' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'handler_with' => [
'stream' => 'php://stderr',
],
'formatter' => env('LOG_STDERR_FORMATTER'),
'processors' => [PsrLogMessageProcessor::class],
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'errorlog' => [
'driver' => 'errorlog',
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mailer
|--------------------------------------------------------------------------
|
| This option controls the default mailer that is used to send all email
| messages unless another mailer is explicitly specified when sending
| the message. All additional mailers can be configured within the
| "mailers" array. Examples of each type of mailer are provided.
|
*/
'default' => env('MAIL_MAILER', 'log'),
/*
|--------------------------------------------------------------------------
| Mailer Configurations
|--------------------------------------------------------------------------
|
| Here you may configure all of the mailers used by your application plus
| their respective settings. Several examples have been configured for
| you and you are free to add your own as your application requires.
|
| Laravel supports a variety of mail "transport" drivers that can be used
| when delivering an email. You may specify which one you're using for
| your mailers below. You may also add additional mailers if needed.
|
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
| "postmark", "resend", "log", "array",
| "failover", "roundrobin"
|
*/
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'scheme' => env('MAIL_SCHEME'),
'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
],
'ses' => [
'transport' => 'ses',
],
'postmark' => [
'transport' => 'postmark',
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
'resend' => [
'transport' => 'resend',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
],
'log' => [
'transport' => 'log',
'channel' => env('MAIL_LOG_CHANNEL'),
],
'array' => [
'transport' => 'array',
],
'failover' => [
'transport' => 'failover',
'mailers' => [
'smtp',
'log',
],
'retry_after' => 60,
],
'roundrobin' => [
'transport' => 'roundrobin',
'mailers' => [
'ses',
'postmark',
],
'retry_after' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all emails sent by your application to be sent from
| the same address. Here you may specify a name and address that is
| used globally for all emails that are sent by your application.
|
*/
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue supports a variety of backends via a single, unified
| API, giving you convenient access to each backend using identical
| syntax for each. The default queue connection is defined below.
|
*/
'default' => env('QUEUE_CONNECTION', 'database'),
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection options for every queue backend
| used by your application. An example configuration is provided for
| each backend supported by Laravel. You're also free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'connection' => env('DB_QUEUE_CONNECTION'),
'table' => env('DB_QUEUE_TABLE', 'jobs'),
'queue' => env('DB_QUEUE', 'default'),
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
'after_commit' => false,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
'queue' => env('BEANSTALKD_QUEUE', 'default'),
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
'block_for' => 0,
'after_commit' => false,
],
'sqs' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
'queue' => env('SQS_QUEUE', 'default'),
'suffix' => env('SQS_SUFFIX'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'after_commit' => false,
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
'block_for' => null,
'after_commit' => false,
],
],
/*
|--------------------------------------------------------------------------
| Job Batching
|--------------------------------------------------------------------------
|
| The following options configure the database and table that store job
| batching information. These options can be updated to any database
| connection and table which has been defined by your application.
|
*/
'batching' => [
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'job_batches',
],
/*
|--------------------------------------------------------------------------
| Failed Queue Jobs
|--------------------------------------------------------------------------
|
| These options configure the behavior of failed queue job logging so you
| can control how and where failed jobs are stored. Laravel ships with
| support for storing failed jobs in a simple file or in a database.
|
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
*/
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'failed_jobs',
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Mailgun, Postmark, AWS and more. This file provides the de facto
| location for this type of information, allowing packages to have
| a conventional file to locate the various service credentials.
|
*/
'postmark' => [
'token' => env('POSTMARK_TOKEN'),
],
'resend' => [
'key' => env('RESEND_KEY'),
],
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
];
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option determines the default session driver that is utilized for
| incoming requests. Laravel supports a variety of storage options to
| persist session data. Database storage is a great default choice.
|
| Supported: "file", "cookie", "database", "memcached",
| "redis", "dynamodb", "array"
|
*/
'driver' => env('SESSION_DRIVER', 'database'),
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to expire immediately when the browser is closed then you may
| indicate that via the expire_on_close configuration option.
|
*/
'lifetime' => (int) env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
/*
|--------------------------------------------------------------------------
| Session Encryption
|--------------------------------------------------------------------------
|
| This option allows you to easily specify that all of your session data
| should be encrypted before it's stored. All encryption is performed
| automatically by Laravel and you may use the session like normal.
|
*/
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
| Session File Location
|--------------------------------------------------------------------------
|
| When utilizing the "file" session driver, the session files are placed
| on disk. The default storage location is defined here; however, you
| are free to provide another location where they should be stored.
|
*/
'files' => storage_path('framework/sessions'),
/*
|--------------------------------------------------------------------------
| Session Database Connection
|--------------------------------------------------------------------------
|
| When using the "database" or "redis" session drivers, you may specify a
| connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options.
|
*/
'connection' => env('SESSION_CONNECTION'),
/*
|--------------------------------------------------------------------------
| Session Database Table
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the table to
| be used to store sessions. Of course, a sensible default is defined
| for you; however, you're welcome to change this to another table.
|
*/
'table' => env('SESSION_TABLE', 'sessions'),
/*
|--------------------------------------------------------------------------
| Session Cache Store
|--------------------------------------------------------------------------
|
| When using one of the framework's cache driven session backends, you may
| define the cache store which should be used to store the session data
| between requests. This must match one of your defined cache stores.
|
| Affects: "dynamodb", "memcached", "redis"
|
*/
'store' => env('SESSION_STORE'),
/*
|--------------------------------------------------------------------------
| Session Sweeping Lottery
|--------------------------------------------------------------------------
|
| Some session drivers must manually sweep their storage location to get
| rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100.
|
*/
'lottery' => [2, 100],
/*
|--------------------------------------------------------------------------
| Session Cookie Name
|--------------------------------------------------------------------------
|
| Here you may change the name of the session cookie that is created by
| the framework. Typically, you should not need to change this value
| since doing so does not grant a meaningful security improvement.
|
*/
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel')).'-session'
),
/*
|--------------------------------------------------------------------------
| Session Cookie Path
|--------------------------------------------------------------------------
|
| The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of
| your application, but you're free to change this when necessary.
|
*/
'path' => env('SESSION_PATH', '/'),
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| This value determines the domain and subdomains the session cookie is
| available to. By default, the cookie will be available to the root
| domain and all subdomains. Typically, this shouldn't be changed.
|
*/
'domain' => env('SESSION_DOMAIN'),
/*
|--------------------------------------------------------------------------
| HTTPS Only Cookies
|--------------------------------------------------------------------------
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you when it can't be done securely.
|
*/
'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------
| HTTP Access Only
|--------------------------------------------------------------------------
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. It's unlikely you should disable this option.
|
*/
'http_only' => env('SESSION_HTTP_ONLY', true),
/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" to permit secure cross-site requests.
|
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
| Supported: "lax", "strict", "none", null
|
*/
'same_site' => env('SESSION_SAME_SITE', 'lax'),
/*
|--------------------------------------------------------------------------
| Partitioned Cookies
|--------------------------------------------------------------------------
|
| Setting this value to true will tie the cookie to the top-level site for
| a cross-site context. Partitioned cookies are accepted by the browser
| when flagged "secure" and the Same-Site attribute is set to "none".
|
*/
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
];
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->ulid('id')->primary();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->ulid('id')->primary();
$table->foreignUlid('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->foreignUlid('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users_activation', function (Blueprint $table) {
$table->integer('user_id')->index();
$table->string('token')->index();
$table->timestamp('created_at');
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users_activation');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('acl_roles', function (Blueprint $table) {
$table->ulid('id')->primary();
$table->string('name')->unique();
$table->string('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('acl_roles');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('acl_permissions', function (Blueprint $table) {
$table->ulid('id')->primary();
$table->string('name')->unique();
$table->string('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('acl_permissions');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('acl_permission_role', function (Blueprint $table) {
$table->ulid('permission_id');
$table->ulid('role_id');
$table->foreign('permission_id')->references('id')->on('acl_permissions')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('acl_roles')->onDelete('cascade');
$table->primary(['permission_id', 'role_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('acl_permission_role');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('acl_role_user', function (Blueprint $table) {
$table->ulid('role_id');
$table->ulid('user_id');
$table->foreign('role_id')->references('id')->on('acl_roles')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->primary(['role_id', 'user_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('acl_role_user');
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
protected $table;
/**
* AddStatusToUsers constructor.
*/
public function __construct()
{
$this->table = app(config('laravolt.epicentrum.models.user'))->getTable();
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table($this->table, function (Blueprint $table) {
if (! Schema::hasColumn($this->table, 'status')) {
$table->string('status')->after('email')->index()->nullable();
}
if (! Schema::hasColumn($this->table, 'timezone')) {
$table->string('timezone')->default(config('app.timezone'))->after('status');
}
if (! Schema::hasColumn($this->table, 'password_changed_at')) {
$table->timestamp('password_changed_at')->nullable()->after('password');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table($this->table, function (Blueprint $table) {
$table->dropColumn(['status', 'timezone', 'password_changed_at']);
});
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSettingsTable extends Migration
{
/**
* Set up the options.
*/
public function __construct()
{
$this->table = config('setting.database.table');
$this->key = config('setting.database.key');
$this->value = config('setting.database.value');
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create($this->table, function (Blueprint $table) {
$table->increments('id');
$table->string($this->key)->index();
$table->text($this->value);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop($this->table);
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('media', function (Blueprint $table) {
$table->id();
$table->ulidMorphs('model');
$table->uuid()->nullable()->unique();
$table->string('collection_name');
$table->string('name');
$table->string('file_name');
$table->string('mime_type')->nullable();
$table->string('disk');
$table->string('conversions_disk')->nullable();
$table->unsignedBigInteger('size');
$table->json('manipulations');
$table->json('custom_properties');
$table->json('generated_conversions');
$table->json('responsive_images');
$table->unsignedInteger('order_column')->nullable()->index();
$table->nullableTimestamps();
});
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('sessions');
}
};
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.0",
"axios": "^1.11.0",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^2.0.0",
"tailwindcss": "^4.0.0",
"vite": "^7.0.4"
}
}
includes:
- ./vendor/larastan/larastan/extension.neon
- ./vendor/spaze/phpstan-disallowed-calls/extension.neon
parameters:
paths:
- app
# Level 8 for development - maintaining high standards throughout development
# Better to catch issues early than in production
level: 8
# Strict settings for quality code
treatPhpDocTypesAsCertain: true
reportMaybes: true
reportStaticMethodSignatures: true
# Only allow very specific exceptions for Laravel's dynamic nature
# ignoreErrors:
# - '#Call to an undefined method.*Builder#' # Only if using complex query builders
disallowedFunctionCalls:
-
function: 'env()'
message: 'Use config() instead - see: https://laravel.com/docs/configuration#retrieving-configuration-values'
-
function: 'dd()'
message: 'Remove debug statements - use proper logging instead'
-
function: 'dump()'
message: 'Remove debug statements - use proper logging instead'
-
function: 'var_dump()'
message: 'Remove debug statements - use proper logging or testing assertions'
-
function: 'print_r()'
message: 'Use proper logging instead: Log::info() or logger()'
-
function: 'exit()'
message: 'Avoid exit() - use proper exception handling and HTTP responses'
-
function: 'die()'
message: 'Avoid die() - use proper exception handling and HTTP responses'
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Modules">
<directory>modules/*/Tests</directory>
</testsuite>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>app</directory>
<directory>modules</directory>
</include>
<exclude>
<directory suffix=".blade.php">modules/*/resources</directory>
<directory suffix="Factory.php">modules/*/Models</directory>
<directory suffix="Test.php">modules/*/Tests</directory>
<directory>modules/*/routes</directory>
</exclude>
</source>
<coverage>
<report>
<html outputDirectory="build/coverage" />
<clover outputFile="phpunit-coverage-result.xml" />
</report>
</coverage>
<logging>
<junit outputFile="phpunit-execution-result.xml" />
</logging>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Handle X-XSRF-Token Header
RewriteCond %{HTTP:x-xsrf-token} .
RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
<?php
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
// Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance;
}
// Register the Composer autoloader...
require __DIR__.'/../vendor/autoload.php';
// Bootstrap Laravel and handle the request...
/** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php';
$app->handleRequest(Request::capture());
User-agent: *
Disallow:
@import 'tailwindcss';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
}
import './bootstrap';
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
<?php
return [
/*
|--------------------------------------------------------------------------
| Baris-baris bahasa untuk autentifikasi
|--------------------------------------------------------------------------
|
| Baris bahasa berikut digunakan selama proses autentifikasi untuk beberapa
| pesan yang perlu kita tampilkan ke pengguna. Anda bebas untuk memodifikasi
| baris bahasa sesuai dengan keperluan aplikasi anda.
|
*/
'failed' => 'Identitas tersebut tidak cocok dengan data kami.',
'throttle' => 'Terlalu banyak usaha masuk. Silahkan coba lagi dalam :seconds detik.',
];
<?php
return [
/*
|---------------------------------------------------------------------------------------
| Baris Bahasa untuk Penomoran Halaman
|---------------------------------------------------------------------------------------
|
| Baris bahasa berikut meggunakan pustaka penomoran untuk membuat
| tautan yang sederhana. Anda bebas untuk mengubahnya kapan pun yang Anda
| inginkan menyesuaikan dengan pandangan Anda agar lebih cocok ke aplikasi Anda.
|
*/
'previous' => '&laquo; Sebelumnya',
'next' => 'Berikutnya &raquo;',
];
<?php
return [
/*
|---------------------------------------------------------------------------------------
| Baris Bahasa untuk Pengingat Kata Sandi
|---------------------------------------------------------------------------------------
|
| Baris bahasa berikut adalah baris standar yang cocok dengan alasan yang
| diberikan oleh pembongkar kata sandi yang telah gagal dalam upaya pembaruan
| kata sandi, misalnya token tidak valid atau kata sandi baru tidak valid.
|
*/
'password' => 'Kata sandi minimal harus memiliki enam karakter dan cocok dengan konfirmasi.',
'reset' => 'Kata sandi Anda sudah direset!',
'sent' => 'Kami sudah mengirim surel yang berisi tautan untuk mereset kata sandi Anda!',
'token' => 'Token pengaturan ulang kata sandi tidak sah.',
'user' => 'Kami tidak dapat menemukan pengguna dengan alamat surel tersebut.',
];
<?php
return [
/*
|---------------------------------------------------------------------------------------
| Baris Bahasa untuk Validasi
|---------------------------------------------------------------------------------------
|
| Baris bahasa berikut ini berisi standar pesan kesalahan yang digunakan oleh
| kelas validasi. Beberapa aturan mempunyai banyak versi seperti aturan 'size'.
| Jangan ragu untuk mengoptimalkan setiap pesan yang ada di sini.
|
*/
'accepted' => ':attribute harus diterima.',
'active_url' => ':attribute bukan URL yang valid.',
'after' => ':attribute harus berisi tanggal setelah :date.',
'after_or_equal' => ':attribute harus berisi tanggal setelah atau sama dengan :date.',
'alpha' => ':attribute hanya boleh berisi huruf.',
'alpha_dash' => ':attribute hanya boleh berisi huruf, angka, strip, dan garis bawah.',
'alpha_num' => ':attribute hanya boleh berisi huruf dan angka.',
'array' => ':attribute harus berisi sebuah array.',
'before' => ':attribute harus berisi tanggal sebelum :date.',
'before_or_equal' => ':attribute harus berisi tanggal sebelum atau sama dengan :date.',
'between' => [
'numeric' => ':attribute harus bernilai antara :min sampai :max.',
'file' => ':attribute harus berukuran antara :min sampai :max kilobita.',
'string' => ':attribute harus berisi antara :min sampai :max karakter.',
'array' => ':attribute harus memiliki :min sampai :max anggota.',
],
'boolean' => ':attribute harus bernilai true atau false',
'confirmed' => 'Konfirmasi :attribute tidak cocok.',
'date' => ':attribute bukan tanggal yang valid.',
'date_equals' => ':attribute harus berisi tanggal yang sama dengan :date.',
'date_format' => ':attribute tidak cocok dengan format :format.',
'different' => ':attribute dan :other harus berbeda.',
'digits' => ':attribute harus terdiri dari :digits angka.',
'digits_between' => ':attribute harus terdiri dari :min sampai :max angka.',
'dimensions' => ':attribute tidak memiliki dimensi gambar yang valid.',
'distinct' => ':attribute memiliki nilai yang duplikat.',
'email' => ':attribute harus berupa alamat surel yang valid.',
'ends_with' => ':attribute harus diakhiri salah satu dari berikut: :values',
'exists' => ':attribute yang dipilih tidak valid.',
'file' => ':attribute harus berupa sebuah berkas.',
'filled' => ':attribute harus memiliki nilai.',
'gt' => [
'numeric' => ':attribute harus bernilai lebih besar dari :value.',
'file' => ':attribute harus berukuran lebih besar dari :value kilobita.',
'string' => ':attribute harus berisi lebih besar dari :value karakter.',
'array' => ':attribute harus memiliki lebih dari :value anggota.',
],
'gte' => [
'numeric' => ':attribute harus bernilai lebih besar dari atau sama dengan :value.',
'file' => ':attribute harus berukuran lebih besar dari atau sama dengan :value kilobita.',
'string' => ':attribute harus berisi lebih besar dari atau sama dengan :value karakter.',
'array' => ':attribute harus terdiri dari :value anggota atau lebih.',
],
'image' => ':attribute harus berupa gambar.',
'in' => ':attribute yang dipilih tidak valid.',
'in_array' => ':attribute tidak ada di dalam :other.',
'integer' => ':attribute harus berupa bilangan bulat.',
'ip' => ':attribute harus berupa alamat IP yang valid.',
'ipv4' => ':attribute harus berupa alamat IPv4 yang valid.',
'ipv6' => ':attribute harus berupa alamat IPv6 yang valid.',
'json' => ':attribute harus berupa JSON string yang valid.',
'lookup' => ':attribute harus berupa lookup yang valid.',
'lt' => [
'numeric' => ':attribute harus bernilai kurang dari :value.',
'file' => ':attribute harus berukuran kurang dari :value kilobita.',
'string' => ':attribute harus berisi kurang dari :value karakter.',
'array' => ':attribute harus memiliki kurang dari :value anggota.',
],
'lte' => [
'numeric' => ':attribute harus bernilai kurang dari atau sama dengan :value.',
'file' => ':attribute harus berukuran kurang dari atau sama dengan :value kilobita.',
'string' => ':attribute harus berisi kurang dari atau sama dengan :value karakter.',
'array' => ':attribute harus tidak lebih dari :value anggota.',
],
'max' => [
'numeric' => ':attribute maskimal bernilai :max.',
'file' => ':attribute maksimal berukuran :max kilobita.',
'string' => ':attribute maskimal berisi :max karakter.',
'array' => ':attribute maksimal terdiri dari :max anggota.',
],
'mimes' => ':attribute harus berupa berkas berjenis: :values.',
'mimetypes' => ':attribute harus berupa berkas berjenis: :values.',
'min' => [
'numeric' => ':attribute minimal bernilai :min.',
'file' => ':attribute minimal berukuran :min kilobita.',
'string' => ':attribute minimal berisi :min karakter.',
'array' => ':attribute minimal terdiri dari :min anggota.',
],
'not_in' => ':attribute yang dipilih tidak valid.',
'not_regex' => 'Format :attribute tidak valid.',
'numeric' => ':attribute harus berupa angka.',
'password' => 'Kata sandi salah.',
'present' => ':attribute wajib ada.',
'regex' => 'Format :attribute tidak valid.',
'required' => ':attribute wajib diisi.',
'required_if' => ':attribute wajib diisi bila :other adalah :value.',
'required_unless' => ':attribute wajib diisi kecuali :other memiliki nilai :values.',
'required_with' => ':attribute wajib diisi bila terdapat :values.',
'required_with_all' => ':attribute wajib diisi bila terdapat :values.',
'required_without' => ':attribute wajib diisi bila tidak terdapat :values.',
'required_without_all' => ':attribute wajib diisi bila sama sekali tidak terdapat :values.',
'same' => ':attribute dan :other harus sama.',
'size' => [
'numeric' => ':attribute harus berukuran :size.',
'file' => ':attribute harus berukuran :size kilobyte.',
'string' => ':attribute harus berukuran :size karakter.',
'array' => ':attribute harus mengandung :size anggota.',
],
'starts_with' => ':attribute harus diawali salah satu dari berikut: :values',
'string' => ':attribute harus berupa string.',
'timezone' => ':attribute harus berisi zona waktu yang valid.',
'unique' => ':attribute sudah ada sebelumnya.',
'uploaded' => ':attribute gagal diunggah.',
'url' => 'Format :attribute tidak valid.',
'uuid' => ':attribute harus merupakan UUID yang valid.',
/*
|---------------------------------------------------------------------------------------
| Baris Bahasa untuk Validasi Kustom
|---------------------------------------------------------------------------------------
|
| Di sini Anda dapat menentukan pesan validasi untuk atribut sesuai keinginan dengan
| menggunakan konvensi "attribute.rule" dalam penamaan barisnya. Hal ini mempercepat
| dalam menentukan baris bahasa kustom yang spesifik untuk aturan atribut yang diberikan.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|---------------------------------------------------------------------------------------
| Kustom Validasi Atribut
|---------------------------------------------------------------------------------------
|
| Baris bahasa berikut digunakan untuk menukar 'placeholder' atribut dengan sesuatu
| yang lebih mudah dimengerti oleh pembaca seperti "Alamat Surel" daripada "surel" saja.
| Hal ini membantu kita dalam membuat pesan menjadi lebih ekspresif.
|
*/
'attributes' => [
],
];
<x-volt-auth>
<h3 class="ui header horizontal divider section">@lang('laravolt::auth.forgot_password')</h3>
{!! form()->open(route('auth::forgot.store')) !!}
{!! form()->email('email')->label(__('laravolt::auth.email')) !!}
<div class="field action">
<x-volt-button class="fluid">@lang('laravolt::auth.send_reset_password_link')</x-volt-button>
</div>
@if(config('laravolt.platform.features.registration'))
<div class="ui divider section"></div>
@lang('laravolt::auth.not_registered_yet?')
<a themed href="{{ route('auth::registration.show') }}" class="link">@lang('laravolt::auth.register_here')</a>
@endif
{!! form()->close() !!}
</x-volt-auth>>
<x-volt-auth>
<h3 class="ui header horizontal divider section">@lang('laravolt::auth.login')</h3>
{!! form()->open(route('auth::login.store'))->attribute('up-target', 'body') !!}
{!! form()->email('email')->label(__('laravolt::auth.identifier')) !!}
{!! form()->password('password')->label(__('laravolt::auth.password')) !!}
@if(config('laravolt.platform.features.captcha'))
<div class="field">
{!! app('captcha')->display() !!}
{!! app('captcha')->renderJs() !!}
</div>
@endif
<div class="ui field m-b-2">
<div class="ui equal width grid">
<div class="column left aligned">
<div class="ui checkbox">
<input type="checkbox" name="remember" {{ request()->old('remember')?'checked':'' }}>
<label>@lang('laravolt::auth.remember')</label>
</div>
</div>
<div class="column right aligned">
<a themed href="{{ route('auth::forgot.show') }}"
class="link">@lang('laravolt::auth.forgot_password')</a>
</div>
</div>
</div>
<div class="field action">
<x-volt-button class="fluid">@lang('laravolt::auth.login')</x-volt-button>
</div>
@if(config('laravolt.platform.features.registration'))
<div class="ui divider section"></div>
<div>
@lang('laravolt::auth.not_registered_yet?')
<a themed href="{{ route('auth::registration.show') }}"
class="link">@lang('laravolt::auth.register_here')</a>
</div>
@endif
{!! form()->close() !!}
</x-volt-auth>
<x-volt-auth>
<h3 class="ui header horizontal divider section">@lang('laravolt::auth.register')</h3>
{!! form()->open(route('auth::registration.store')) !!}
{!! form()->text('name')->label(__('Name')) !!}
{!! form()->email('email')->label(__('Email')) !!}
{!! form()->password('password')->label(__('Password')) !!}
{!! form()->password('password_confirmation')->label(__('Confirm Your Password')) !!}
<div class="field action">
<x-volt-button class="fluid">@lang('laravolt::auth.register')</x-volt-button>
</div>
<div class="ui divider section"></div>
<div>
@lang('laravolt::auth.already_registered?')
<a themed href="{{ route('auth::login.show') }}" class="link">@lang('laravolt::auth.login_here')</a>
</div>
{!! form()->close() !!}
</x-volt-auth>>
<x-volt-auth>
<h3 class="ui header horizontal divider section">@lang('laravolt::auth.reset_password')</h3>
{!! form()->open(route('auth::reset.store', $token)) !!}
{!! form()->hidden('token', $token) !!}
{!! form()->email('email', request('email'))->label(__('Email'))->required() !!}
{!! form()->password('password')->label(__('New Password'))->required() !!}
{!! form()->password('password_confirmation')->label(__('Confirm New Password'))->required() !!}
{!! form()->action(form()->submit(__('Reset Password'))) !!}
{!! form()->close() !!}
<div class="ui divider section"></div>
@lang('laravolt::auth.already_registered?')
<a href="{{ route('auth::login.show') }}">@lang('laravolt::auth.login_here')</a>
</x-volt-auth>
<x-volt-auth>
<h3 class="ui header horizontal divider section">@lang('Verifikasi Email')</h3>
<div class="ui message p-3">
<strong>{{ __('Anda sudah terdaftar di aplikasi. ') }}</strong>
<p>{{ __('Sebelum bisa melanjutkan, silakan verifikasi akun Anda dengan mengklik link yang kami kirimkan ke alamat email :email.', ['email' => auth()->user()->getEmailForVerification()]) }}</p>
<p>@lang('Jika Anda belum menerima email, silakan klik tombol di bawah ini.')</p>
</div>
{!! form()->post(route('verification.send')) !!}
<x-volt-button class="fluid">@lang('Kirim Ulang Email Verifikasi')</x-volt-button>
{!! form()->close() !!}
<div class="ui divider section"></div>
<x-volt-link :url="route('auth::logout')" class="fluid">Logout</x-volt-link>
</x-volt-auth>
<x-volt-app title="Dashboard">
Hello world!
</x-volt-app>
<x-volt-app title="Home">
@extends('laravolt::layout')
@section('content')
<h1>🏠 Selamat Datang ke Training Base</h1>
<p>Anda login sebagai <b>{{ auth()->user()->name }}</b></p>
@endsection
</x-volt-app>
<x-volt-app :title="__('Edit Password')">
<x-volt-panel title="{{ __('Edit Password') }}" icon="user-lock">
{!! form()->open()->action(route('my::password.update'))->horizontal() !!}
{!! form()->password('password_current')->label(__('Current Password')) !!}
{!! form()->password('password')->label(__('New Password')) !!}
{!! form()->password('password_confirmation')->label(__('Confirm New Password')) !!}
{!! form()->action(form()->submit(__('Save'))) !!}
{!! form()->close() !!}
</x-volt-panel>
</x-volt-app>
<x-volt-app :title="__('Edit Profile')">
<x-volt-panel title="{{ __('Edit Profile') }}" icon="user-edit">
{!! form()->bind($user)->put(route('my::profile.update'))->horizontal() !!}
{!! form()->text('name')->label('Name') !!}
{!! form()->text('email')->label('Email')->readonly() !!}
{!! form()->dropdown('timezone', $timezones)->label('Timezone') !!}
{!! form()->action(form()->submit('Save')) !!}
{!! form()->close() !!}
</x-volt-panel>
</x-volt-app>
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />
<!-- Styles / Scripts -->
@if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot')))
@vite(['resources/css/app.css', 'resources/js/app.js'])
@else
<style>
/*! tailwindcss v4.0.7 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--font-sans:'Instrument Sans',ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-serif:ui-serif,Georgia,Cambria,"Times New Roman",Times,serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(.971 .013 17.38);--color-red-100:oklch(.936 .032 17.717);--color-red-200:oklch(.885 .062 18.334);--color-red-300:oklch(.808 .114 19.571);--color-red-400:oklch(.704 .191 22.216);--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-red-700:oklch(.505 .213 27.518);--color-red-800:oklch(.444 .177 26.899);--color-red-900:oklch(.396 .141 25.723);--color-red-950:oklch(.258 .092 26.042);--color-orange-50:oklch(.98 .016 73.684);--color-orange-100:oklch(.954 .038 75.164);--color-orange-200:oklch(.901 .076 70.697);--color-orange-300:oklch(.837 .128 66.29);--color-orange-400:oklch(.75 .183 55.934);--color-orange-500:oklch(.705 .213 47.604);--color-orange-600:oklch(.646 .222 41.116);--color-orange-700:oklch(.553 .195 38.402);--color-orange-800:oklch(.47 .157 37.304);--color-orange-900:oklch(.408 .123 38.172);--color-orange-950:oklch(.266 .079 36.259);--color-amber-50:oklch(.987 .022 95.277);--color-amber-100:oklch(.962 .059 95.617);--color-amber-200:oklch(.924 .12 95.746);--color-amber-300:oklch(.879 .169 91.605);--color-amber-400:oklch(.828 .189 84.429);--color-amber-500:oklch(.769 .188 70.08);--color-amber-600:oklch(.666 .179 58.318);--color-amber-700:oklch(.555 .163 48.998);--color-amber-800:oklch(.473 .137 46.201);--color-amber-900:oklch(.414 .112 45.904);--color-amber-950:oklch(.279 .077 45.635);--color-yellow-50:oklch(.987 .026 102.212);--color-yellow-100:oklch(.973 .071 103.193);--color-yellow-200:oklch(.945 .129 101.54);--color-yellow-300:oklch(.905 .182 98.111);--color-yellow-400:oklch(.852 .199 91.936);--color-yellow-500:oklch(.795 .184 86.047);--color-yellow-600:oklch(.681 .162 75.834);--color-yellow-700:oklch(.554 .135 66.442);--color-yellow-800:oklch(.476 .114 61.907);--color-yellow-900:oklch(.421 .095 57.708);--color-yellow-950:oklch(.286 .066 53.813);--color-lime-50:oklch(.986 .031 120.757);--color-lime-100:oklch(.967 .067 122.328);--color-lime-200:oklch(.938 .127 124.321);--color-lime-300:oklch(.897 .196 126.665);--color-lime-400:oklch(.841 .238 128.85);--color-lime-500:oklch(.768 .233 130.85);--color-lime-600:oklch(.648 .2 131.684);--color-lime-700:oklch(.532 .157 131.589);--color-lime-800:oklch(.453 .124 130.933);--color-lime-900:oklch(.405 .101 131.063);--color-lime-950:oklch(.274 .072 132.109);--color-green-50:oklch(.982 .018 155.826);--color-green-100:oklch(.962 .044 156.743);--color-green-200:oklch(.925 .084 155.995);--color-green-300:oklch(.871 .15 154.449);--color-green-400:oklch(.792 .209 151.711);--color-green-500:oklch(.723 .219 149.579);--color-green-600:oklch(.627 .194 149.214);--color-green-700:oklch(.527 .154 150.069);--color-green-800:oklch(.448 .119 151.328);--color-green-900:oklch(.393 .095 152.535);--color-green-950:oklch(.266 .065 152.934);--color-emerald-50:oklch(.979 .021 166.113);--color-emerald-100:oklch(.95 .052 163.051);--color-emerald-200:oklch(.905 .093 164.15);--color-emerald-300:oklch(.845 .143 164.978);--color-emerald-400:oklch(.765 .177 163.223);--color-emerald-500:oklch(.696 .17 162.48);--color-emerald-600:oklch(.596 .145 163.225);--color-emerald-700:oklch(.508 .118 165.612);--color-emerald-800:oklch(.432 .095 166.913);--color-emerald-900:oklch(.378 .077 168.94);--color-emerald-950:oklch(.262 .051 172.552);--color-teal-50:oklch(.984 .014 180.72);--color-teal-100:oklch(.953 .051 180.801);--color-teal-200:oklch(.91 .096 180.426);--color-teal-300:oklch(.855 .138 181.071);--color-teal-400:oklch(.777 .152 181.912);--color-teal-500:oklch(.704 .14 182.503);--color-teal-600:oklch(.6 .118 184.704);--color-teal-700:oklch(.511 .096 186.391);--color-teal-800:oklch(.437 .078 188.216);--color-teal-900:oklch(.386 .063 188.416);--color-teal-950:oklch(.277 .046 192.524);--color-cyan-50:oklch(.984 .019 200.873);--color-cyan-100:oklch(.956 .045 203.388);--color-cyan-200:oklch(.917 .08 205.041);--color-cyan-300:oklch(.865 .127 207.078);--color-cyan-400:oklch(.789 .154 211.53);--color-cyan-500:oklch(.715 .143 215.221);--color-cyan-600:oklch(.609 .126 221.723);--color-cyan-700:oklch(.52 .105 223.128);--color-cyan-800:oklch(.45 .085 224.283);--color-cyan-900:oklch(.398 .07 227.392);--color-cyan-950:oklch(.302 .056 229.695);--color-sky-50:oklch(.977 .013 236.62);--color-sky-100:oklch(.951 .026 236.824);--color-sky-200:oklch(.901 .058 230.902);--color-sky-300:oklch(.828 .111 230.318);--color-sky-400:oklch(.746 .16 232.661);--color-sky-500:oklch(.685 .169 237.323);--color-sky-600:oklch(.588 .158 241.966);--color-sky-700:oklch(.5 .134 242.749);--color-sky-800:oklch(.443 .11 240.79);--color-sky-900:oklch(.391 .09 240.876);--color-sky-950:oklch(.293 .066 243.157);--color-blue-50:oklch(.97 .014 254.604);--color-blue-100:oklch(.932 .032 255.585);--color-blue-200:oklch(.882 .059 254.128);--color-blue-300:oklch(.809 .105 251.813);--color-blue-400:oklch(.707 .165 254.624);--color-blue-500:oklch(.623 .214 259.815);--color-blue-600:oklch(.546 .245 262.881);--color-blue-700:oklch(.488 .243 264.376);--color-blue-800:oklch(.424 .199 265.638);--color-blue-900:oklch(.379 .146 265.522);--color-blue-950:oklch(.282 .091 267.935);--color-indigo-50:oklch(.962 .018 272.314);--color-indigo-100:oklch(.93 .034 272.788);--color-indigo-200:oklch(.87 .065 274.039);--color-indigo-300:oklch(.785 .115 274.713);--color-indigo-400:oklch(.673 .182 276.935);--color-indigo-500:oklch(.585 .233 277.117);--color-indigo-600:oklch(.511 .262 276.966);--color-indigo-700:oklch(.457 .24 277.023);--color-indigo-800:oklch(.398 .195 277.366);--color-indigo-900:oklch(.359 .144 278.697);--color-indigo-950:oklch(.257 .09 281.288);--color-violet-50:oklch(.969 .016 293.756);--color-violet-100:oklch(.943 .029 294.588);--color-violet-200:oklch(.894 .057 293.283);--color-violet-300:oklch(.811 .111 293.571);--color-violet-400:oklch(.702 .183 293.541);--color-violet-500:oklch(.606 .25 292.717);--color-violet-600:oklch(.541 .281 293.009);--color-violet-700:oklch(.491 .27 292.581);--color-violet-800:oklch(.432 .232 292.759);--color-violet-900:oklch(.38 .189 293.745);--color-violet-950:oklch(.283 .141 291.089);--color-purple-50:oklch(.977 .014 308.299);--color-purple-100:oklch(.946 .033 307.174);--color-purple-200:oklch(.902 .063 306.703);--color-purple-300:oklch(.827 .119 306.383);--color-purple-400:oklch(.714 .203 305.504);--color-purple-500:oklch(.627 .265 303.9);--color-purple-600:oklch(.558 .288 302.321);--color-purple-700:oklch(.496 .265 301.924);--color-purple-800:oklch(.438 .218 303.724);--color-purple-900:oklch(.381 .176 304.987);--color-purple-950:oklch(.291 .149 302.717);--color-fuchsia-50:oklch(.977 .017 320.058);--color-fuchsia-100:oklch(.952 .037 318.852);--color-fuchsia-200:oklch(.903 .076 319.62);--color-fuchsia-300:oklch(.833 .145 321.434);--color-fuchsia-400:oklch(.74 .238 322.16);--color-fuchsia-500:oklch(.667 .295 322.15);--color-fuchsia-600:oklch(.591 .293 322.896);--color-fuchsia-700:oklch(.518 .253 323.949);--color-fuchsia-800:oklch(.452 .211 324.591);--color-fuchsia-900:oklch(.401 .17 325.612);--color-fuchsia-950:oklch(.293 .136 325.661);--color-pink-50:oklch(.971 .014 343.198);--color-pink-100:oklch(.948 .028 342.258);--color-pink-200:oklch(.899 .061 343.231);--color-pink-300:oklch(.823 .12 346.018);--color-pink-400:oklch(.718 .202 349.761);--color-pink-500:oklch(.656 .241 354.308);--color-pink-600:oklch(.592 .249 .584);--color-pink-700:oklch(.525 .223 3.958);--color-pink-800:oklch(.459 .187 3.815);--color-pink-900:oklch(.408 .153 2.432);--color-pink-950:oklch(.284 .109 3.907);--color-rose-50:oklch(.969 .015 12.422);--color-rose-100:oklch(.941 .03 12.58);--color-rose-200:oklch(.892 .058 10.001);--color-rose-300:oklch(.81 .117 11.638);--color-rose-400:oklch(.712 .194 13.428);--color-rose-500:oklch(.645 .246 16.439);--color-rose-600:oklch(.586 .253 17.585);--color-rose-700:oklch(.514 .222 16.935);--color-rose-800:oklch(.455 .188 13.697);--color-rose-900:oklch(.41 .159 10.272);--color-rose-950:oklch(.271 .105 12.094);--color-slate-50:oklch(.984 .003 247.858);--color-slate-100:oklch(.968 .007 247.896);--color-slate-200:oklch(.929 .013 255.508);--color-slate-300:oklch(.869 .022 252.894);--color-slate-400:oklch(.704 .04 256.788);--color-slate-500:oklch(.554 .046 257.417);--color-slate-600:oklch(.446 .043 257.281);--color-slate-700:oklch(.372 .044 257.287);--color-slate-800:oklch(.279 .041 260.031);--color-slate-900:oklch(.208 .042 265.755);--color-slate-950:oklch(.129 .042 264.695);--color-gray-50:oklch(.985 .002 247.839);--color-gray-100:oklch(.967 .003 264.542);--color-gray-200:oklch(.928 .006 264.531);--color-gray-300:oklch(.872 .01 258.338);--color-gray-400:oklch(.707 .022 261.325);--color-gray-500:oklch(.551 .027 264.364);--color-gray-600:oklch(.446 .03 256.802);--color-gray-700:oklch(.373 .034 259.733);--color-gray-800:oklch(.278 .033 256.848);--color-gray-900:oklch(.21 .034 264.665);--color-gray-950:oklch(.13 .028 261.692);--color-zinc-50:oklch(.985 0 0);--color-zinc-100:oklch(.967 .001 286.375);--color-zinc-200:oklch(.92 .004 286.32);--color-zinc-300:oklch(.871 .006 286.286);--color-zinc-400:oklch(.705 .015 286.067);--color-zinc-500:oklch(.552 .016 285.938);--color-zinc-600:oklch(.442 .017 285.786);--color-zinc-700:oklch(.37 .013 285.805);--color-zinc-800:oklch(.274 .006 286.033);--color-zinc-900:oklch(.21 .006 285.885);--color-zinc-950:oklch(.141 .005 285.823);--color-neutral-50:oklch(.985 0 0);--color-neutral-100:oklch(.97 0 0);--color-neutral-200:oklch(.922 0 0);--color-neutral-300:oklch(.87 0 0);--color-neutral-400:oklch(.708 0 0);--color-neutral-500:oklch(.556 0 0);--color-neutral-600:oklch(.439 0 0);--color-neutral-700:oklch(.371 0 0);--color-neutral-800:oklch(.269 0 0);--color-neutral-900:oklch(.205 0 0);--color-neutral-950:oklch(.145 0 0);--color-stone-50:oklch(.985 .001 106.423);--color-stone-100:oklch(.97 .001 106.424);--color-stone-200:oklch(.923 .003 48.717);--color-stone-300:oklch(.869 .005 56.366);--color-stone-400:oklch(.709 .01 56.259);--color-stone-500:oklch(.553 .013 58.071);--color-stone-600:oklch(.444 .011 73.639);--color-stone-700:oklch(.374 .01 67.558);--color-stone-800:oklch(.268 .007 34.298);--color-stone-900:oklch(.216 .006 56.043);--color-stone-950:oklch(.147 .004 49.25);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-sm:40rem;--breakpoint-md:48rem;--breakpoint-lg:64rem;--breakpoint-xl:80rem;--breakpoint-2xl:96rem;--container-3xs:16rem;--container-2xs:18rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--text-7xl:4.5rem;--text-7xl--line-height:1;--text-8xl:6rem;--text-8xl--line-height:1;--text-9xl:8rem;--text-9xl--line-height:1;--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-tighter:-.05em;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--leading-loose:2;--radius-xs:.125rem;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--radius-4xl:2rem;--shadow-2xs:0 1px #0000000d;--shadow-xs:0 1px 2px 0 #0000000d;--shadow-sm:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a;--shadow-2xl:0 25px 50px -12px #00000040;--inset-shadow-2xs:inset 0 1px #0000000d;--inset-shadow-xs:inset 0 1px 1px #0000000d;--inset-shadow-sm:inset 0 2px 4px #0000000d;--drop-shadow-xs:0 1px 1px #0000000d;--drop-shadow-sm:0 1px 2px #00000026;--drop-shadow-md:0 3px 3px #0000001f;--drop-shadow-lg:0 4px 4px #00000026;--drop-shadow-xl:0 9px 7px #0000001a;--drop-shadow-2xl:0 25px 25px #00000026;--ease-in:cubic-bezier(.4,0,1,1);--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--animate-bounce:bounce 1s infinite;--blur-xs:4px;--blur-sm:8px;--blur-md:12px;--blur-lg:16px;--blur-xl:24px;--blur-2xl:40px;--blur-3xl:64px;--perspective-dramatic:100px;--perspective-near:300px;--perspective-normal:500px;--perspective-midrange:800px;--perspective-distant:1200px;--aspect-video:16/9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-font-feature-settings:var(--font-sans--font-feature-settings);--default-font-variation-settings:var(--font-sans--font-variation-settings);--default-mono-font-family:var(--font-mono);--default-mono-font-feature-settings:var(--font-mono--font-feature-settings);--default-mono-font-variation-settings:var(--font-mono--font-variation-settings)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1;color:color-mix(in oklab,currentColor 50%,transparent)}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.-mt-\[4\.9rem\]{margin-top:-4.9rem}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.-ml-8{margin-left:calc(var(--spacing)*-8)}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-\[335\/376\]{aspect-ratio:335/376}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-14{height:calc(var(--spacing)*14)}.h-14\.5{height:calc(var(--spacing)*14.5)}.min-h-screen{min-height:100vh}.w-1{width:calc(var(--spacing)*1)}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-2{width:calc(var(--spacing)*2)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-\[448px\]{width:448px}.w-full{width:100%}.max-w-\[335px\]{max-width:335px}.max-w-none{max-width:none}.flex-1{flex:1}.shrink-0{flex-shrink:0}.translate-y-0{--tw-translate-y:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*1)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-x-reverse)))}.overflow-hidden{overflow:hidden}.rounded-full{border-radius:3.40282e38px}.rounded-sm{border-radius:var(--radius-sm)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-br-lg{border-bottom-right-radius:var(--radius-lg)}.rounded-bl-lg{border-bottom-left-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-\[\#19140035\]{border-color:#19140035}.border-\[\#e3e3e0\]{border-color:#e3e3e0}.border-black{border-color:var(--color-black)}.border-transparent{border-color:#0000}.bg-\[\#1b1b18\]{background-color:#1b1b18}.bg-\[\#FDFDFC\]{background-color:#fdfdfc}.bg-\[\#dbdbd7\]{background-color:#dbdbd7}.bg-\[\#fff2f2\]{background-color:#fff2f2}.bg-white{background-color:var(--color-white)}.p-6{padding:calc(var(--spacing)*6)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pb-12{padding-bottom:calc(var(--spacing)*12)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-\[13px\]{font-size:13px}.leading-\[20px\]{--tw-leading:20px;line-height:20px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.text-\[\#1b1b18\]{color:#1b1b18}.text-\[\#706f6c\]{color:#706f6c}.text-\[\#F53003\],.text-\[\#f53003\]{color:#f53003}.text-white{color:var(--color-white)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-100{opacity:1}.shadow-\[0px_0px_1px_0px_rgba\(0\,0\,0\,0\.03\)\,0px_1px_2px_0px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow:0px 0px 1px 0px var(--tw-shadow-color,#00000008),0px 1px 2px 0px var(--tw-shadow-color,#0000000f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[inset_0px_0px_0px_1px_rgba\(26\,26\,0\,0\.16\)\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#1a1a0029);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.\!filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)!important}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.delay-300{transition-delay:.3s}.duration-750{--tw-duration:.75s;transition-duration:.75s}.not-has-\[nav\]\:hidden:not(:has(:is(nav))){display:none}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-0:before{content:var(--tw-content);top:calc(var(--spacing)*0)}.before\:top-1\/2:before{content:var(--tw-content);top:50%}.before\:bottom-0:before{content:var(--tw-content);bottom:calc(var(--spacing)*0)}.before\:bottom-1\/2:before{content:var(--tw-content);bottom:50%}.before\:left-\[0\.4rem\]:before{content:var(--tw-content);left:.4rem}.before\:border-l:before{content:var(--tw-content);border-left-style:var(--tw-border-style);border-left-width:1px}.before\:border-\[\#e3e3e0\]:before{content:var(--tw-content);border-color:#e3e3e0}@media (hover:hover){.hover\:border-\[\#1915014a\]:hover{border-color:#1915014a}.hover\:border-\[\#19140035\]:hover{border-color:#19140035}.hover\:border-black:hover{border-color:var(--color-black)}.hover\:bg-black:hover{background-color:var(--color-black)}}@media (width>=64rem){.lg\:-mt-\[6\.6rem\]{margin-top:-6.6rem}.lg\:mb-0{margin-bottom:calc(var(--spacing)*0)}.lg\:mb-6{margin-bottom:calc(var(--spacing)*6)}.lg\:-ml-px{margin-left:-1px}.lg\:ml-0{margin-left:calc(var(--spacing)*0)}.lg\:block{display:block}.lg\:aspect-auto{aspect-ratio:auto}.lg\:w-\[438px\]{width:438px}.lg\:max-w-4xl{max-width:var(--container-4xl)}.lg\:grow{flex-grow:1}.lg\:flex-row{flex-direction:row}.lg\:justify-center{justify-content:center}.lg\:rounded-t-none{border-top-left-radius:0;border-top-right-radius:0}.lg\:rounded-tl-lg{border-top-left-radius:var(--radius-lg)}.lg\:rounded-r-lg{border-top-right-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.lg\:rounded-br-none{border-bottom-right-radius:0}.lg\:p-8{padding:calc(var(--spacing)*8)}.lg\:p-20{padding:calc(var(--spacing)*20)}}@media (prefers-color-scheme:dark){.dark\:block{display:block}.dark\:hidden{display:none}.dark\:border-\[\#3E3E3A\]{border-color:#3e3e3a}.dark\:border-\[\#eeeeec\]{border-color:#eeeeec}.dark\:bg-\[\#0a0a0a\]{background-color:#0a0a0a}.dark\:bg-\[\#1D0002\]{background-color:#1d0002}.dark\:bg-\[\#3E3E3A\]{background-color:#3e3e3a}.dark\:bg-\[\#161615\]{background-color:#161615}.dark\:bg-\[\#eeeeec\]{background-color:#eeeeec}.dark\:text-\[\#1C1C1A\]{color:#1c1c1a}.dark\:text-\[\#A1A09A\]{color:#a1a09a}.dark\:text-\[\#EDEDEC\]{color:#ededec}.dark\:text-\[\#F61500\]{color:#f61500}.dark\:text-\[\#FF4433\]{color:#f43}.dark\:shadow-\[inset_0px_0px_0px_1px_\#fffaed2d\]{--tw-shadow:inset 0px 0px 0px 1px var(--tw-shadow-color,#fffaed2d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\:before\:border-\[\#3E3E3A\]:before{content:var(--tw-content);border-color:#3e3e3a}@media (hover:hover){.dark\:hover\:border-\[\#3E3E3A\]:hover{border-color:#3e3e3a}.dark\:hover\:border-\[\#62605b\]:hover{border-color:#62605b}.dark\:hover\:border-white:hover{border-color:var(--color-white)}.dark\:hover\:bg-white:hover{background-color:var(--color-white)}}}@starting-style{.starting\:translate-y-4{--tw-translate-y:calc(var(--spacing)*4);translate:var(--tw-translate-x)var(--tw-translate-y)}}@starting-style{.starting\:translate-y-6{--tw-translate-y:calc(var(--spacing)*6);translate:var(--tw-translate-x)var(--tw-translate-y)}}@starting-style{.starting\:opacity-0{opacity:0}}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}
</style>
@endif
</head>
<body class="bg-[#FDFDFC] dark:bg-[#0a0a0a] text-[#1b1b18] flex p-6 lg:p-8 items-center lg:justify-center min-h-screen flex-col">
<header class="w-full lg:max-w-4xl max-w-[335px] text-sm mb-6 not-has-[nav]:hidden">
@if (Route::has('login'))
<nav class="flex items-center justify-end gap-4">
@auth
<a
href="{{ url('/dashboard') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] border-[#19140035] hover:border-[#1915014a] border text-[#1b1b18] dark:border-[#3E3E3A] dark:hover:border-[#62605b] rounded-sm text-sm leading-normal"
>
Dashboard
</a>
@else
<a
href="{{ route('login') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] text-[#1b1b18] border border-transparent hover:border-[#19140035] dark:hover:border-[#3E3E3A] rounded-sm text-sm leading-normal"
>
Log in
</a>
@if (Route::has('register'))
<a
href="{{ route('register') }}"
class="inline-block px-5 py-1.5 dark:text-[#EDEDEC] border-[#19140035] hover:border-[#1915014a] border text-[#1b1b18] dark:border-[#3E3E3A] dark:hover:border-[#62605b] rounded-sm text-sm leading-normal">
Register
</a>
@endif
@endauth
</nav>
@endif
</header>
<div class="flex items-center justify-center w-full transition-opacity opacity-100 duration-750 lg:grow starting:opacity-0">
<main class="flex max-w-[335px] w-full flex-col-reverse lg:max-w-4xl lg:flex-row">
<div class="text-[13px] leading-[20px] flex-1 p-6 pb-12 lg:p-20 bg-white dark:bg-[#161615] dark:text-[#EDEDEC] shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d] rounded-bl-lg rounded-br-lg lg:rounded-tl-lg lg:rounded-br-none">
<h1 class="mb-1 font-medium">Let's get started</h1>
<p class="mb-2 text-[#706f6c] dark:text-[#A1A09A]">Laravel has an incredibly rich ecosystem. <br>We suggest starting with the following.</p>
<ul class="flex flex-col mb-4 lg:mb-6">
<li class="flex items-center gap-4 py-2 relative before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A] before:top-1/2 before:bottom-0 before:left-[0.4rem] before:absolute">
<span class="relative py-1 bg-white dark:bg-[#161615]">
<span class="flex items-center justify-center rounded-full bg-[#FDFDFC] dark:bg-[#161615] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] w-3.5 h-3.5 border dark:border-[#3E3E3A] border-[#e3e3e0]">
<span class="rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A] w-1.5 h-1.5"></span>
</span>
</span>
<span>
Read the
<a href="https://laravel.com/docs" target="_blank" class="inline-flex items-center space-x-1 font-medium underline underline-offset-4 text-[#f53003] dark:text-[#FF4433] ml-1">
<span>Documentation</span>
<svg
width="10"
height="11"
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-2.5 h-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
stroke-linecap="square"
/>
</svg>
</a>
</span>
</li>
<li class="flex items-center gap-4 py-2 relative before:border-l before:border-[#e3e3e0] dark:before:border-[#3E3E3A] before:bottom-1/2 before:top-0 before:left-[0.4rem] before:absolute">
<span class="relative py-1 bg-white dark:bg-[#161615]">
<span class="flex items-center justify-center rounded-full bg-[#FDFDFC] dark:bg-[#161615] shadow-[0px_0px_1px_0px_rgba(0,0,0,0.03),0px_1px_2px_0px_rgba(0,0,0,0.06)] w-3.5 h-3.5 border dark:border-[#3E3E3A] border-[#e3e3e0]">
<span class="rounded-full bg-[#dbdbd7] dark:bg-[#3E3E3A] w-1.5 h-1.5"></span>
</span>
</span>
<span>
Watch video tutorials at
<a href="https://laracasts.com" target="_blank" class="inline-flex items-center space-x-1 font-medium underline underline-offset-4 text-[#f53003] dark:text-[#FF4433] ml-1">
<span>Laracasts</span>
<svg
width="10"
height="11"
viewBox="0 0 10 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-2.5 h-2.5"
>
<path
d="M7.70833 6.95834V2.79167H3.54167M2.5 8L7.5 3.00001"
stroke="currentColor"
stroke-linecap="square"
/>
</svg>
</a>
</span>
</li>
</ul>
<ul class="flex gap-3 text-sm leading-normal">
<li>
<a href="https://cloud.laravel.com" target="_blank" class="inline-block dark:bg-[#eeeeec] dark:border-[#eeeeec] dark:text-[#1C1C1A] dark:hover:bg-white dark:hover:border-white hover:bg-black hover:border-black px-5 py-1.5 bg-[#1b1b18] rounded-sm border border-black text-white text-sm leading-normal">
Deploy now
</a>
</li>
</ul>
</div>
<div class="bg-[#fff2f2] dark:bg-[#1D0002] relative lg:-ml-px -mb-px lg:mb-0 rounded-t-lg lg:rounded-t-none lg:rounded-r-lg aspect-[335/376] lg:aspect-auto w-full lg:w-[438px] shrink-0 overflow-hidden">
{{-- Laravel Logo --}}
<svg class="w-full text-[#F53003] dark:text-[#F61500] transition-all translate-y-0 opacity-100 max-w-none duration-750 starting:opacity-0 starting:translate-y-6" viewBox="0 0 438 104" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.2036 -3H0V102.197H49.5189V86.7187H17.2036V-3Z" fill="currentColor" />
<path d="M110.256 41.6337C108.061 38.1275 104.945 35.3731 100.905 33.3681C96.8667 31.3647 92.8016 30.3618 88.7131 30.3618C83.4247 30.3618 78.5885 31.3389 74.201 33.2923C69.8111 35.2456 66.0474 37.928 62.9059 41.3333C59.7643 44.7401 57.3198 48.6726 55.5754 53.1293C53.8287 57.589 52.9572 62.274 52.9572 67.1813C52.9572 72.1925 53.8287 76.8995 55.5754 81.3069C57.3191 85.7173 59.7636 89.6241 62.9059 93.0293C66.0474 96.4361 69.8119 99.1155 74.201 101.069C78.5885 103.022 83.4247 103.999 88.7131 103.999C92.8016 103.999 96.8667 102.997 100.905 100.994C104.945 98.9911 108.061 96.2359 110.256 92.7282V102.195H126.563V32.1642H110.256V41.6337ZM108.76 75.7472C107.762 78.4531 106.366 80.8078 104.572 82.8112C102.776 84.8161 100.606 86.4183 98.0637 87.6206C95.5202 88.823 92.7004 89.4238 89.6103 89.4238C86.5178 89.4238 83.7252 88.823 81.2324 87.6206C78.7388 86.4183 76.5949 84.8161 74.7998 82.8112C73.004 80.8078 71.6319 78.4531 70.6856 75.7472C69.7356 73.0421 69.2644 70.1868 69.2644 67.1821C69.2644 64.1758 69.7356 61.3205 70.6856 58.6154C71.6319 55.9102 73.004 53.5571 74.7998 51.5522C76.5949 49.5495 78.738 47.9451 81.2324 46.7427C83.7252 45.5404 86.5178 44.9396 89.6103 44.9396C92.7012 44.9396 95.5202 45.5404 98.0637 46.7427C100.606 47.9451 102.776 49.5487 104.572 51.5522C106.367 53.5571 107.762 55.9102 108.76 58.6154C109.756 61.3205 110.256 64.1758 110.256 67.1821C110.256 70.1868 109.756 73.0421 108.76 75.7472Z" fill="currentColor" />
<path d="M242.805 41.6337C240.611 38.1275 237.494 35.3731 233.455 33.3681C229.416 31.3647 225.351 30.3618 221.262 30.3618C215.974 30.3618 211.138 31.3389 206.75 33.2923C202.36 35.2456 198.597 37.928 195.455 41.3333C192.314 44.7401 189.869 48.6726 188.125 53.1293C186.378 57.589 185.507 62.274 185.507 67.1813C185.507 72.1925 186.378 76.8995 188.125 81.3069C189.868 85.7173 192.313 89.6241 195.455 93.0293C198.597 96.4361 202.361 99.1155 206.75 101.069C211.138 103.022 215.974 103.999 221.262 103.999C225.351 103.999 229.416 102.997 233.455 100.994C237.494 98.9911 240.611 96.2359 242.805 92.7282V102.195H259.112V32.1642H242.805V41.6337ZM241.31 75.7472C240.312 78.4531 238.916 80.8078 237.122 82.8112C235.326 84.8161 233.156 86.4183 230.614 87.6206C228.07 88.823 225.251 89.4238 222.16 89.4238C219.068 89.4238 216.275 88.823 213.782 87.6206C211.289 86.4183 209.145 84.8161 207.35 82.8112C205.554 80.8078 204.182 78.4531 203.236 75.7472C202.286 73.0421 201.814 70.1868 201.814 67.1821C201.814 64.1758 202.286 61.3205 203.236 58.6154C204.182 55.9102 205.554 53.5571 207.35 51.5522C209.145 49.5495 211.288 47.9451 213.782 46.7427C216.275 45.5404 219.068 44.9396 222.16 44.9396C225.251 44.9396 228.07 45.5404 230.614 46.7427C233.156 47.9451 235.326 49.5487 237.122 51.5522C238.917 53.5571 240.312 55.9102 241.31 58.6154C242.306 61.3205 242.806 64.1758 242.806 67.1821C242.805 70.1868 242.305 73.0421 241.31 75.7472Z" fill="currentColor" />
<path d="M438 -3H421.694V102.197H438V-3Z" fill="currentColor" />
<path d="M139.43 102.197H155.735V48.2834H183.712V32.1665H139.43V102.197Z" fill="currentColor" />
<path d="M324.49 32.1665L303.995 85.794L283.498 32.1665H266.983L293.748 102.197H314.242L341.006 32.1665H324.49Z" fill="currentColor" />
<path d="M376.571 30.3656C356.603 30.3656 340.797 46.8497 340.797 67.1828C340.797 89.6597 356.094 104 378.661 104C391.29 104 399.354 99.1488 409.206 88.5848L398.189 80.0226C398.183 80.031 389.874 90.9895 377.468 90.9895C363.048 90.9895 356.977 79.3111 356.977 73.269H411.075C413.917 50.1328 398.775 30.3656 376.571 30.3656ZM357.02 61.0967C357.145 59.7487 359.023 43.3761 376.442 43.3761C393.861 43.3761 395.978 59.7464 396.099 61.0967H357.02Z" fill="currentColor" />
</svg>
{{-- Light Mode 12 SVG --}}
<svg class="w-[448px] max-w-none relative -mt-[4.9rem] -ml-8 lg:ml-0 lg:-mt-[6.6rem] dark:hidden" viewBox="0 0 440 376" fill="none" xmlns="http://www.w3.org/2000/svg">
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M188.263 355.73L188.595 355.73C195.441 348.845 205.766 339.761 219.569 328.477C232.93 317.193 242.978 308.205 249.714 301.511C256.34 294.626 260.867 287.358 263.296 279.708C265.725 272.058 264.565 264.121 259.816 255.896C254.516 246.716 247.062 239.352 237.454 233.805C227.957 228.067 217.908 225.198 207.307 225.198C196.927 225.197 190.136 227.97 186.934 233.516C183.621 238.872 184.726 246.331 190.247 255.894L125.647 255.891C116.371 239.825 112.395 225.481 113.72 212.858C115.265 200.235 121.559 190.481 132.602 183.596C143.754 176.52 158.607 172.982 177.159 172.983C196.594 172.984 215.863 176.523 234.968 183.6C253.961 190.486 271.299 200.241 286.98 212.864C302.661 225.488 315.14 239.833 324.416 255.899C333.03 270.817 336.841 283.918 335.847 295.203C335.075 306.487 331.376 316.336 324.75 324.751C318.346 333.167 308.408 343.494 294.936 355.734L377.094 355.737L405.917 405.656L217.087 405.649L188.263 355.73Z" fill="black" />
<path d="M9.11884 226.339L-13.7396 226.338L-42.7286 176.132L43.0733 176.135L175.595 405.649L112.651 405.647L9.11884 226.339Z" fill="black" />
<path d="M188.263 355.73L188.595 355.73C195.441 348.845 205.766 339.761 219.569 328.477C232.93 317.193 242.978 308.205 249.714 301.511C256.34 294.626 260.867 287.358 263.296 279.708C265.725 272.058 264.565 264.121 259.816 255.896C254.516 246.716 247.062 239.352 237.454 233.805C227.957 228.067 217.908 225.198 207.307 225.198C196.927 225.197 190.136 227.97 186.934 233.516C183.621 238.872 184.726 246.331 190.247 255.894L125.647 255.891C116.371 239.825 112.395 225.481 113.72 212.858C115.265 200.235 121.559 190.481 132.602 183.596C143.754 176.52 158.607 172.982 177.159 172.983C196.594 172.984 215.863 176.523 234.968 183.6C253.961 190.486 271.299 200.241 286.98 212.864C302.661 225.488 315.14 239.833 324.416 255.899C333.03 270.817 336.841 283.918 335.847 295.203C335.075 306.487 331.376 316.336 324.75 324.751C318.346 333.167 308.408 343.494 294.936 355.734L377.094 355.737L405.917 405.656L217.087 405.649L188.263 355.73Z" stroke="#1B1B18" stroke-width="1" />
<path d="M9.11884 226.339L-13.7396 226.338L-42.7286 176.132L43.0733 176.135L175.595 405.649L112.651 405.647L9.11884 226.339Z" stroke="#1B1B18" stroke-width="1" />
<path d="M204.592 327.449L204.923 327.449C211.769 320.564 222.094 311.479 235.897 300.196C249.258 288.912 259.306 279.923 266.042 273.23C272.668 266.345 277.195 259.077 279.624 251.427C282.053 243.777 280.893 235.839 276.145 227.615C270.844 218.435 263.39 211.071 253.782 205.524C244.285 199.786 234.236 196.917 223.635 196.916C213.255 196.916 206.464 199.689 203.262 205.235C199.949 210.59 201.054 218.049 206.575 227.612L141.975 227.61C132.699 211.544 128.723 197.2 130.048 184.577C131.593 171.954 137.887 162.2 148.93 155.315C160.083 148.239 174.935 144.701 193.487 144.702C212.922 144.703 232.192 148.242 251.296 155.319C270.289 162.205 287.627 171.96 303.308 184.583C318.989 197.207 331.468 211.552 340.745 227.618C349.358 242.536 353.169 255.637 352.175 266.921C351.403 278.205 347.704 288.055 341.078 296.47C334.674 304.885 324.736 315.213 311.264 327.453L393.422 327.456L422.246 377.375L233.415 377.368L204.592 327.449Z" fill="#F8B803" />
<path d="M25.447 198.058L2.58852 198.057L-26.4005 147.851L59.4015 147.854L191.923 377.368L128.979 377.365L25.447 198.058Z" fill="#F8B803" />
<path d="M204.592 327.449L204.923 327.449C211.769 320.564 222.094 311.479 235.897 300.196C249.258 288.912 259.306 279.923 266.042 273.23C272.668 266.345 277.195 259.077 279.624 251.427C282.053 243.777 280.893 235.839 276.145 227.615C270.844 218.435 263.39 211.071 253.782 205.524C244.285 199.786 234.236 196.917 223.635 196.916C213.255 196.916 206.464 199.689 203.262 205.235C199.949 210.59 201.054 218.049 206.575 227.612L141.975 227.61C132.699 211.544 128.723 197.2 130.048 184.577C131.593 171.954 137.887 162.2 148.93 155.315C160.083 148.239 174.935 144.701 193.487 144.702C212.922 144.703 232.192 148.242 251.296 155.319C270.289 162.205 287.627 171.96 303.308 184.583C318.989 197.207 331.468 211.552 340.745 227.618C349.358 242.536 353.169 255.637 352.175 266.921C351.403 278.205 347.704 288.055 341.078 296.47C334.674 304.885 324.736 315.213 311.264 327.453L393.422 327.456L422.246 377.375L233.415 377.368L204.592 327.449Z" stroke="#1B1B18" stroke-width="1" />
<path d="M25.447 198.058L2.58852 198.057L-26.4005 147.851L59.4015 147.854L191.923 377.368L128.979 377.365L25.447 198.058Z" stroke="#1B1B18" stroke-width="1" />
</g>
<g style="mix-blend-mode: hard-light" class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M217.342 305.363L217.673 305.363C224.519 298.478 234.844 289.393 248.647 278.11C262.008 266.826 272.056 257.837 278.792 251.144C285.418 244.259 289.945 236.991 292.374 229.341C294.803 221.691 293.643 213.753 288.895 205.529C283.594 196.349 276.14 188.985 266.532 183.438C257.035 177.7 246.986 174.831 236.385 174.83C226.005 174.83 219.214 177.603 216.012 183.149C212.699 188.504 213.804 195.963 219.325 205.527L154.725 205.524C145.449 189.458 141.473 175.114 142.798 162.491C144.343 149.868 150.637 140.114 161.68 133.229C172.833 126.153 187.685 122.615 206.237 122.616C225.672 122.617 244.942 126.156 264.046 133.233C283.039 140.119 300.377 149.874 316.058 162.497C331.739 175.121 344.218 189.466 353.495 205.532C362.108 220.45 365.919 233.551 364.925 244.835C364.153 256.12 360.454 265.969 353.828 274.384C347.424 282.799 337.486 293.127 324.014 305.367L406.172 305.37L434.996 355.289L246.165 355.282L217.342 305.363Z" fill="#F0ACB8" />
<path d="M38.197 175.972L15.3385 175.971L-13.6505 125.765L72.1515 125.768L204.673 355.282L141.729 355.279L38.197 175.972Z" fill="#F0ACB8" />
<path d="M217.342 305.363L217.673 305.363C224.519 298.478 234.844 289.393 248.647 278.11C262.008 266.826 272.056 257.837 278.792 251.144C285.418 244.259 289.945 236.991 292.374 229.341C294.803 221.691 293.643 213.753 288.895 205.529C283.594 196.349 276.14 188.985 266.532 183.438C257.035 177.7 246.986 174.831 236.385 174.83C226.005 174.83 219.214 177.603 216.012 183.149C212.699 188.504 213.804 195.963 219.325 205.527L154.725 205.524C145.449 189.458 141.473 175.114 142.798 162.491C144.343 149.868 150.637 140.114 161.68 133.229C172.833 126.153 187.685 122.615 206.237 122.616C225.672 122.617 244.942 126.156 264.046 133.233C283.039 140.119 300.377 149.874 316.058 162.497C331.739 175.121 344.218 189.466 353.495 205.532C362.108 220.45 365.919 233.551 364.925 244.835C364.153 256.12 360.454 265.969 353.828 274.384C347.424 282.799 337.486 293.127 324.014 305.367L406.172 305.37L434.996 355.289L246.165 355.282L217.342 305.363Z" stroke="#1B1B18" stroke-width="1" />
<path d="M38.197 175.972L15.3385 175.971L-13.6505 125.765L72.1515 125.768L204.673 355.282L141.729 355.279L38.197 175.972Z" stroke="#1B1B18" stroke-width="1" />
</g>
<g style="mix-blend-mode: plus-darker" class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M230.951 281.792L231.282 281.793C238.128 274.907 248.453 265.823 262.256 254.539C275.617 243.256 285.666 234.267 292.402 227.573C299.027 220.688 303.554 213.421 305.983 205.771C308.412 198.12 307.253 190.183 302.504 181.959C297.203 172.778 289.749 165.415 280.142 159.868C270.645 154.13 260.596 151.26 249.995 151.26C239.615 151.26 232.823 154.033 229.621 159.579C226.309 164.934 227.413 172.393 232.935 181.956L168.335 181.954C159.058 165.888 155.082 151.543 156.407 138.92C157.953 126.298 164.247 116.544 175.289 109.659C186.442 102.583 201.294 99.045 219.846 99.0457C239.281 99.0464 258.551 102.585 277.655 109.663C296.649 116.549 313.986 126.303 329.667 138.927C345.349 151.551 357.827 165.895 367.104 181.961C375.718 196.88 379.528 209.981 378.535 221.265C377.762 232.549 374.063 242.399 367.438 250.814C361.033 259.229 351.095 269.557 337.624 281.796L419.782 281.8L448.605 331.719L259.774 331.712L230.951 281.792Z" fill="#F3BEC7" />
<path d="M51.8063 152.402L28.9479 152.401L-0.0411453 102.195L85.7608 102.198L218.282 331.711L155.339 331.709L51.8063 152.402Z" fill="#F3BEC7" />
<path d="M230.951 281.792L231.282 281.793C238.128 274.907 248.453 265.823 262.256 254.539C275.617 243.256 285.666 234.267 292.402 227.573C299.027 220.688 303.554 213.421 305.983 205.771C308.412 198.12 307.253 190.183 302.504 181.959C297.203 172.778 289.749 165.415 280.142 159.868C270.645 154.13 260.596 151.26 249.995 151.26C239.615 151.26 232.823 154.033 229.621 159.579C226.309 164.934 227.413 172.393 232.935 181.956L168.335 181.954C159.058 165.888 155.082 151.543 156.407 138.92C157.953 126.298 164.247 116.544 175.289 109.659C186.442 102.583 201.294 99.045 219.846 99.0457C239.281 99.0464 258.551 102.585 277.655 109.663C296.649 116.549 313.986 126.303 329.667 138.927C345.349 151.551 357.827 165.895 367.104 181.961C375.718 196.88 379.528 209.981 378.535 221.265C377.762 232.549 374.063 242.399 367.438 250.814C361.033 259.229 351.095 269.557 337.624 281.796L419.782 281.8L448.605 331.719L259.774 331.712L230.951 281.792Z" stroke="#1B1B18" stroke-width="1" />
<path d="M51.8063 152.402L28.9479 152.401L-0.0411453 102.195L85.7608 102.198L218.282 331.711L155.339 331.709L51.8063 152.402Z" stroke="#1B1B18" stroke-width="1" />
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M188.467 355.363L188.798 355.363C195.644 348.478 205.969 339.393 219.772 328.11C233.133 316.826 243.181 307.837 249.917 301.144C253.696 297.217 256.792 293.166 259.205 288.991C261.024 285.845 262.455 282.628 263.499 279.341C265.928 271.691 264.768 263.753 260.02 255.529C254.719 246.349 247.265 238.985 237.657 233.438C228.16 227.7 218.111 224.831 207.51 224.83C197.13 224.83 190.339 227.603 187.137 233.149C183.824 238.504 184.929 245.963 190.45 255.527L125.851 255.524C116.574 239.458 112.598 225.114 113.923 212.491C114.615 206.836 116.261 201.756 118.859 197.253C122.061 191.704 126.709 187.03 132.805 183.229C143.958 176.153 158.81 172.615 177.362 172.616C196.797 172.617 216.067 176.156 235.171 183.233C254.164 190.119 271.502 199.874 287.183 212.497C302.864 225.121 315.343 239.466 324.62 255.532C333.233 270.45 337.044 283.551 336.05 294.835C335.46 303.459 333.16 311.245 329.151 318.194C327.915 320.337 326.515 322.4 324.953 324.384C318.549 332.799 308.611 343.127 295.139 355.367L377.297 355.37L406.121 405.289L217.29 405.282L188.467 355.363Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M9.32197 225.972L-13.5365 225.971L-42.5255 175.765L43.2765 175.768L175.798 405.282L112.854 405.279L9.32197 225.972Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M345.247 111.915C329.566 99.2919 312.229 89.5371 293.235 82.6512L235.167 183.228C254.161 190.114 271.498 199.869 287.179 212.492L345.247 111.915Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M382.686 154.964C373.41 138.898 360.931 124.553 345.25 111.93L287.182 212.506C302.863 225.13 315.342 239.475 324.618 255.541L382.686 154.964Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M293.243 82.6472C274.139 75.57 254.869 72.031 235.434 72.0303L177.366 172.607C196.801 172.608 216.071 176.147 235.175 183.224L293.243 82.6472Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M394.118 194.257C395.112 182.973 391.301 169.872 382.688 154.953L324.619 255.53C333.233 270.448 337.044 283.55 336.05 294.834L394.118 194.257Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M235.432 72.0311C216.88 72.0304 202.027 75.5681 190.875 82.6442L132.806 183.221C143.959 176.145 158.812 172.607 177.363 172.608L235.432 72.0311Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M265.59 124.25C276.191 124.251 286.24 127.12 295.737 132.858L237.669 233.435C228.172 227.697 218.123 224.828 207.522 224.827L265.59 124.25Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M295.719 132.859C305.326 138.406 312.78 145.77 318.081 154.95L260.013 255.527C254.712 246.347 247.258 238.983 237.651 233.436L295.719 132.859Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M387.218 217.608C391.227 210.66 393.527 202.874 394.117 194.25L336.049 294.827C335.459 303.451 333.159 311.237 329.15 318.185L387.218 217.608Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M245.211 132.577C248.413 127.03 255.204 124.257 265.584 124.258L207.516 224.835C197.136 224.834 190.345 227.607 187.143 233.154L245.211 132.577Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M318.094 154.945C322.842 163.17 324.002 171.107 321.573 178.757L263.505 279.334C265.934 271.684 264.774 263.746 260.026 255.522L318.094 154.945Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M176.925 96.6737C180.127 91.1249 184.776 86.4503 190.871 82.6499L132.803 183.227C126.708 187.027 122.059 191.702 118.857 197.25L176.925 96.6737Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M387.226 217.606C385.989 219.749 384.59 221.813 383.028 223.797L324.96 324.373C326.522 322.39 327.921 320.326 329.157 318.183L387.226 217.606Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M317.269 188.408C319.087 185.262 320.519 182.045 321.562 178.758L263.494 279.335C262.451 282.622 261.019 285.839 259.201 288.985L317.269 188.408Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M245.208 132.573C241.895 137.928 243 145.387 248.522 154.95L190.454 255.527C184.932 245.964 183.827 238.505 187.14 233.15L245.208 132.573Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M176.93 96.6719C174.331 101.175 172.686 106.255 171.993 111.91L113.925 212.487C114.618 206.831 116.263 201.752 118.862 197.249L176.93 96.6719Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M317.266 188.413C314.853 192.589 311.757 196.64 307.978 200.566L249.91 301.143C253.689 297.216 256.785 293.166 259.198 288.99L317.266 188.413Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M464.198 304.708L435.375 254.789L377.307 355.366L406.13 405.285L464.198 304.708Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M353.209 254.787C366.68 242.548 376.618 232.22 383.023 223.805L324.955 324.382C318.55 332.797 308.612 343.124 295.141 355.364L353.209 254.787Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M435.37 254.787L353.212 254.784L295.144 355.361L377.302 355.364L435.37 254.787Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M183.921 154.947L248.521 154.95L190.453 255.527L125.853 255.524L183.921 154.947Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M171.992 111.914C170.668 124.537 174.643 138.881 183.92 154.947L125.852 255.524C116.575 239.458 112.599 225.114 113.924 212.491L171.992 111.914Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M307.987 200.562C301.251 207.256 291.203 216.244 277.842 227.528L219.774 328.105C233.135 316.821 243.183 307.832 249.919 301.139L307.987 200.562Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M15.5469 75.1797L44.5359 125.386L-13.5321 225.963L-42.5212 175.756L15.5469 75.1797Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M277.836 227.536C264.033 238.82 253.708 247.904 246.862 254.789L188.794 355.366C195.64 348.481 205.965 339.397 219.768 328.113L277.836 227.536Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M275.358 304.706L464.189 304.713L406.12 405.29L217.29 405.283L275.358 304.706Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M44.5279 125.39L67.3864 125.39L9.31834 225.967L-13.5401 225.966L44.5279 125.39Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M101.341 75.1911L233.863 304.705L175.795 405.282L43.2733 175.768L101.341 75.1911ZM15.5431 75.19L-42.525 175.767L43.277 175.77L101.345 75.1932L15.5431 75.19Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M246.866 254.784L246.534 254.784L188.466 355.361L188.798 355.361L246.866 254.784Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M246.539 254.781L275.362 304.701L217.294 405.277L188.471 355.358L246.539 254.781Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M67.3906 125.391L170.923 304.698L112.855 405.275L9.32257 225.967L67.3906 125.391Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
<path d="M170.921 304.699L233.865 304.701L175.797 405.278L112.853 405.276L170.921 304.699Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="bevel" />
</g>
<g style="mix-blend-mode: hard-light" class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M246.544 254.79L246.875 254.79C253.722 247.905 264.046 238.82 277.849 227.537C291.21 216.253 301.259 207.264 307.995 200.57C314.62 193.685 319.147 186.418 321.577 178.768C324.006 171.117 322.846 163.18 318.097 154.956C312.796 145.775 305.342 138.412 295.735 132.865C286.238 127.127 276.189 124.258 265.588 124.257C255.208 124.257 248.416 127.03 245.214 132.576C241.902 137.931 243.006 145.39 248.528 154.953L183.928 154.951C174.652 138.885 170.676 124.541 172 111.918C173.546 99.2946 179.84 89.5408 190.882 82.6559C202.035 75.5798 216.887 72.0421 235.439 72.0428C254.874 72.0435 274.144 75.5825 293.248 82.6598C312.242 89.5457 329.579 99.3005 345.261 111.924C360.942 124.548 373.421 138.892 382.697 154.958C391.311 169.877 395.121 182.978 394.128 194.262C393.355 205.546 389.656 215.396 383.031 223.811C376.627 232.226 366.688 242.554 353.217 254.794L435.375 254.797L464.198 304.716L275.367 304.709L246.544 254.79Z" fill="#F0ACB8" />
<path d="M246.544 254.79L246.875 254.79C253.722 247.905 264.046 238.82 277.849 227.537C291.21 216.253 301.259 207.264 307.995 200.57C314.62 193.685 319.147 186.418 321.577 178.768C324.006 171.117 322.846 163.18 318.097 154.956C312.796 145.775 305.342 138.412 295.735 132.865C286.238 127.127 276.189 124.258 265.588 124.257C255.208 124.257 248.416 127.03 245.214 132.576C241.902 137.931 243.006 145.39 248.528 154.953L183.928 154.951C174.652 138.885 170.676 124.541 172 111.918C173.546 99.2946 179.84 89.5408 190.882 82.6559C202.035 75.5798 216.887 72.0421 235.439 72.0428C254.874 72.0435 274.144 75.5825 293.248 82.6598C312.242 89.5457 329.579 99.3005 345.261 111.924C360.942 124.548 373.421 138.892 382.697 154.958C391.311 169.877 395.121 182.978 394.128 194.262C393.355 205.546 389.656 215.396 383.031 223.811C376.627 232.226 366.688 242.554 353.217 254.794L435.375 254.797L464.198 304.716L275.367 304.709L246.544 254.79Z" stroke="#1B1B18" stroke-width="1" stroke-linejoin="round" />
</g>
<g style="mix-blend-mode: hard-light" class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M67.41 125.402L44.5515 125.401L15.5625 75.1953L101.364 75.1985L233.886 304.712L170.942 304.71L67.41 125.402Z" fill="#F0ACB8" />
<path d="M67.41 125.402L44.5515 125.401L15.5625 75.1953L101.364 75.1985L233.886 304.712L170.942 304.71L67.41 125.402Z" stroke="#1B1B18" stroke-width="1" />
</g>
</svg>
{{-- Dark Mode 12 SVG --}}
<svg class="w-[448px] max-w-none relative -mt-[4.9rem] -ml-8 lg:ml-0 lg:-mt-[6.6rem] hidden dark:block" viewBox="0 0 440 376" fill="none" xmlns="http://www.w3.org/2000/svg">
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M188.263 355.73L188.595 355.73C195.441 348.845 205.766 339.761 219.569 328.477C232.93 317.193 242.978 308.205 249.714 301.511C256.34 294.626 260.867 287.358 263.296 279.708C265.725 272.058 264.565 264.121 259.816 255.896C254.516 246.716 247.062 239.352 237.454 233.805C227.957 228.067 217.908 225.198 207.307 225.198C196.927 225.197 190.136 227.97 186.934 233.516C183.621 238.872 184.726 246.331 190.247 255.894L125.647 255.891C116.371 239.825 112.395 225.481 113.72 212.858C115.265 200.235 121.559 190.481 132.602 183.596C143.754 176.52 158.607 172.982 177.159 172.983C196.594 172.984 215.863 176.523 234.968 183.6C253.961 190.486 271.299 200.241 286.98 212.864C302.661 225.488 315.14 239.833 324.416 255.899C333.03 270.817 336.841 283.918 335.847 295.203C335.075 306.487 331.376 316.336 324.75 324.751C318.346 333.167 308.408 343.494 294.936 355.734L377.094 355.737L405.917 405.656L217.087 405.649L188.263 355.73Z" fill="black"/>
<path d="M9.11884 226.339L-13.7396 226.338L-42.7286 176.132L43.0733 176.135L175.595 405.649L112.651 405.647L9.11884 226.339Z" fill="black"/>
<path d="M188.263 355.73L188.595 355.73C195.441 348.845 205.766 339.761 219.569 328.477C232.93 317.193 242.978 308.205 249.714 301.511C256.34 294.626 260.867 287.358 263.296 279.708C265.725 272.058 264.565 264.121 259.816 255.896C254.516 246.716 247.062 239.352 237.454 233.805C227.957 228.067 217.908 225.198 207.307 225.198C196.927 225.197 190.136 227.97 186.934 233.516C183.621 238.872 184.726 246.331 190.247 255.894L125.647 255.891C116.371 239.825 112.395 225.481 113.72 212.858C115.265 200.235 121.559 190.481 132.602 183.596C143.754 176.52 158.607 172.982 177.159 172.983C196.594 172.984 215.863 176.523 234.968 183.6C253.961 190.486 271.299 200.241 286.98 212.864C302.661 225.488 315.14 239.833 324.416 255.899C333.03 270.817 336.841 283.918 335.847 295.203C335.075 306.487 331.376 316.336 324.75 324.751C318.346 333.167 308.408 343.494 294.936 355.734L377.094 355.737L405.917 405.656L217.087 405.649L188.263 355.73Z" stroke="#FF750F" stroke-width="1"/>
<path d="M9.11884 226.339L-13.7396 226.338L-42.7286 176.132L43.0733 176.135L175.595 405.649L112.651 405.647L9.11884 226.339Z" stroke="#FF750F" stroke-width="1"/>
<path d="M204.592 327.449L204.923 327.449C211.769 320.564 222.094 311.479 235.897 300.196C249.258 288.912 259.306 279.923 266.042 273.23C272.668 266.345 277.195 259.077 279.624 251.427C282.053 243.777 280.893 235.839 276.145 227.615C270.844 218.435 263.39 211.071 253.782 205.524C244.285 199.786 234.236 196.917 223.635 196.916C213.255 196.916 206.464 199.689 203.262 205.235C199.949 210.59 201.054 218.049 206.575 227.612L141.975 227.61C132.699 211.544 128.723 197.2 130.048 184.577C131.593 171.954 137.887 162.2 148.93 155.315C160.083 148.239 174.935 144.701 193.487 144.702C212.922 144.703 232.192 148.242 251.296 155.319C270.289 162.205 287.627 171.96 303.308 184.583C318.989 197.207 331.468 211.552 340.745 227.618C349.358 242.536 353.169 255.637 352.175 266.921C351.403 278.205 347.704 288.055 341.078 296.47C334.674 304.885 324.736 315.213 311.264 327.453L393.422 327.456L422.246 377.375L233.415 377.368L204.592 327.449Z" fill="#391800"/>
<path d="M25.447 198.058L2.58852 198.057L-26.4005 147.851L59.4015 147.854L191.923 377.368L128.979 377.365L25.447 198.058Z" fill="#391800"/>
<path d="M204.592 327.449L204.923 327.449C211.769 320.564 222.094 311.479 235.897 300.196C249.258 288.912 259.306 279.923 266.042 273.23C272.668 266.345 277.195 259.077 279.624 251.427C282.053 243.777 280.893 235.839 276.145 227.615C270.844 218.435 263.39 211.071 253.782 205.524C244.285 199.786 234.236 196.917 223.635 196.916C213.255 196.916 206.464 199.689 203.262 205.235C199.949 210.59 201.054 218.049 206.575 227.612L141.975 227.61C132.699 211.544 128.723 197.2 130.048 184.577C131.593 171.954 137.887 162.2 148.93 155.315C160.083 148.239 174.935 144.701 193.487 144.702C212.922 144.703 232.192 148.242 251.296 155.319C270.289 162.205 287.627 171.96 303.308 184.583C318.989 197.207 331.468 211.552 340.745 227.618C349.358 242.536 353.169 255.637 352.175 266.921C351.403 278.205 347.704 288.055 341.078 296.47C334.674 304.885 324.736 315.213 311.264 327.453L393.422 327.456L422.246 377.375L233.415 377.368L204.592 327.449Z" stroke="#FF750F" stroke-width="1"/>
<path d="M25.447 198.058L2.58852 198.057L-26.4005 147.851L59.4015 147.854L191.923 377.368L128.979 377.365L25.447 198.058Z" stroke="#FF750F" stroke-width="1"/>
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4" style="mix-blend-mode:hard-light">
<path d="M217.342 305.363L217.673 305.363C224.519 298.478 234.844 289.393 248.647 278.11C262.008 266.826 272.056 257.837 278.792 251.144C285.418 244.259 289.945 236.991 292.374 229.341C294.803 221.691 293.643 213.753 288.895 205.529C283.594 196.349 276.14 188.985 266.532 183.438C257.035 177.7 246.986 174.831 236.385 174.83C226.005 174.83 219.214 177.603 216.012 183.149C212.699 188.504 213.804 195.963 219.325 205.527L154.725 205.524C145.449 189.458 141.473 175.114 142.798 162.491C144.343 149.868 150.637 140.114 161.68 133.229C172.833 126.153 187.685 122.615 206.237 122.616C225.672 122.617 244.942 126.156 264.046 133.233C283.039 140.119 300.377 149.874 316.058 162.497C331.739 175.121 344.218 189.466 353.495 205.532C362.108 220.45 365.919 233.551 364.925 244.835C364.153 256.12 360.454 265.969 353.828 274.384C347.424 282.799 337.486 293.127 324.014 305.367L406.172 305.37L434.996 355.289L246.165 355.282L217.342 305.363Z" fill="#733000"/>
<path d="M38.197 175.972L15.3385 175.971L-13.6505 125.765L72.1515 125.768L204.673 355.282L141.729 355.279L38.197 175.972Z" fill="#733000"/>
<path d="M217.342 305.363L217.673 305.363C224.519 298.478 234.844 289.393 248.647 278.11C262.008 266.826 272.056 257.837 278.792 251.144C285.418 244.259 289.945 236.991 292.374 229.341C294.803 221.691 293.643 213.753 288.895 205.529C283.594 196.349 276.14 188.985 266.532 183.438C257.035 177.7 246.986 174.831 236.385 174.83C226.005 174.83 219.214 177.603 216.012 183.149C212.699 188.504 213.804 195.963 219.325 205.527L154.725 205.524C145.449 189.458 141.473 175.114 142.798 162.491C144.343 149.868 150.637 140.114 161.68 133.229C172.833 126.153 187.685 122.615 206.237 122.616C225.672 122.617 244.942 126.156 264.046 133.233C283.039 140.119 300.377 149.874 316.058 162.497C331.739 175.121 344.218 189.466 353.495 205.532C362.108 220.45 365.919 233.551 364.925 244.835C364.153 256.12 360.454 265.969 353.828 274.384C347.424 282.799 337.486 293.127 324.014 305.367L406.172 305.37L434.996 355.289L246.165 355.282L217.342 305.363Z" stroke="#FF750F" stroke-width="1"/>
<path d="M38.197 175.972L15.3385 175.971L-13.6505 125.765L72.1515 125.768L204.673 355.282L141.729 355.279L38.197 175.972Z" stroke="#FF750F" stroke-width="1"/>
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M217.342 305.363L217.673 305.363C224.519 298.478 234.844 289.393 248.647 278.11C262.008 266.826 272.056 257.837 278.792 251.144C285.418 244.259 289.945 236.991 292.374 229.341C294.803 221.691 293.643 213.753 288.895 205.529C283.594 196.349 276.14 188.985 266.532 183.438C257.035 177.7 246.986 174.831 236.385 174.83C226.005 174.83 219.214 177.603 216.012 183.149C212.699 188.504 213.804 195.963 219.325 205.527L154.726 205.524C145.449 189.458 141.473 175.114 142.798 162.491C144.343 149.868 150.637 140.114 161.68 133.229C172.833 126.153 187.685 122.615 206.237 122.616C225.672 122.617 244.942 126.156 264.046 133.233C283.039 140.119 300.377 149.874 316.058 162.497C331.739 175.121 344.218 189.466 353.495 205.532C362.108 220.45 365.919 233.551 364.925 244.835C364.153 256.12 360.454 265.969 353.828 274.384C347.424 282.799 337.486 293.127 324.014 305.367L406.172 305.37L434.996 355.289L246.165 355.282L217.342 305.363Z" stroke="#FF750F" stroke-width="1"/>
<path d="M38.197 175.972L15.3385 175.971L-13.6505 125.765L72.1515 125.768L204.673 355.282L141.729 355.279L38.197 175.972Z" stroke="#FF750F" stroke-width="1"/>
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4">
<path d="M188.467 355.363L188.798 355.363C195.644 348.478 205.969 339.393 219.772 328.11C233.133 316.826 243.181 307.837 249.917 301.144C253.696 297.217 256.792 293.166 259.205 288.991C261.024 285.845 262.455 282.628 263.499 279.341C265.928 271.691 264.768 263.753 260.02 255.529C254.719 246.349 247.265 238.985 237.657 233.438C228.16 227.7 218.111 224.831 207.51 224.83C197.13 224.83 190.339 227.603 187.137 233.149C183.824 238.504 184.929 245.963 190.45 255.527L125.851 255.524C116.574 239.458 112.598 225.114 113.923 212.491C114.615 206.836 116.261 201.756 118.859 197.253C122.061 191.704 126.709 187.03 132.805 183.229C143.958 176.153 158.81 172.615 177.362 172.616C196.797 172.617 216.067 176.156 235.171 183.233C254.164 190.119 271.502 199.874 287.183 212.497C302.864 225.121 315.343 239.466 324.62 255.532C333.233 270.45 337.044 283.551 336.05 294.835C335.46 303.459 333.16 311.245 329.151 318.194C327.915 320.337 326.515 322.4 324.953 324.384C318.549 332.799 308.611 343.127 295.139 355.367L377.297 355.37L406.121 405.289L217.29 405.282L188.467 355.363Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M9.32197 225.972L-13.5365 225.971L-42.5255 175.765L43.2765 175.768L175.798 405.282L112.854 405.279L9.32197 225.972Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M345.247 111.915C329.566 99.2919 312.229 89.5371 293.235 82.6512L235.167 183.228C254.161 190.114 271.498 199.869 287.179 212.492L345.247 111.915Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M382.686 154.964C373.41 138.898 360.931 124.553 345.25 111.93L287.182 212.506C302.863 225.13 315.342 239.475 324.618 255.541L382.686 154.964Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M293.243 82.6472C274.139 75.57 254.869 72.031 235.434 72.0303L177.366 172.607C196.801 172.608 216.071 176.147 235.175 183.224L293.243 82.6472Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M394.118 194.257C395.112 182.973 391.301 169.872 382.688 154.953L324.619 255.53C333.233 270.448 337.044 283.55 336.05 294.834L394.118 194.257Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M235.432 72.0311C216.88 72.0304 202.027 75.5681 190.875 82.6442L132.806 183.221C143.959 176.145 158.812 172.607 177.363 172.608L235.432 72.0311Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M265.59 124.25C276.191 124.251 286.24 127.12 295.737 132.858L237.669 233.435C228.172 227.697 218.123 224.828 207.522 224.827L265.59 124.25Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M295.719 132.859C305.326 138.406 312.78 145.77 318.081 154.95L260.013 255.527C254.712 246.347 247.258 238.983 237.651 233.436L295.719 132.859Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M387.218 217.608C391.227 210.66 393.527 202.874 394.117 194.25L336.049 294.827C335.459 303.451 333.159 311.237 329.15 318.185L387.218 217.608Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M245.211 132.577C248.413 127.03 255.204 124.257 265.584 124.258L207.516 224.835C197.136 224.834 190.345 227.607 187.143 233.154L245.211 132.577Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M318.094 154.945C322.842 163.17 324.002 171.107 321.573 178.757L263.505 279.334C265.934 271.684 264.774 263.746 260.026 255.522L318.094 154.945Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M176.925 96.6737C180.127 91.1249 184.776 86.4503 190.871 82.6499L132.803 183.227C126.708 187.027 122.059 191.702 118.857 197.25L176.925 96.6737Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M387.226 217.606C385.989 219.749 384.59 221.813 383.028 223.797L324.96 324.373C326.522 322.39 327.921 320.326 329.157 318.183L387.226 217.606Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M317.269 188.408C319.087 185.262 320.519 182.045 321.562 178.758L263.494 279.335C262.451 282.622 261.019 285.839 259.201 288.985L317.269 188.408Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M245.208 132.573C241.895 137.928 243 145.387 248.522 154.95L190.454 255.527C184.932 245.964 183.827 238.505 187.14 233.15L245.208 132.573Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M176.93 96.6719C174.331 101.175 172.686 106.255 171.993 111.91L113.925 212.487C114.618 206.831 116.263 201.752 118.862 197.249L176.93 96.6719Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M317.266 188.413C314.853 192.589 311.757 196.64 307.978 200.566L249.91 301.143C253.689 297.216 256.785 293.166 259.198 288.99L317.266 188.413Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M464.198 304.708L435.375 254.789L377.307 355.366L406.13 405.285L464.198 304.708Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M353.209 254.787C366.68 242.548 376.618 232.22 383.023 223.805L324.955 324.382C318.55 332.797 308.612 343.124 295.141 355.364L353.209 254.787Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M435.37 254.787L353.212 254.784L295.144 355.361L377.302 355.364L435.37 254.787Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M183.921 154.947L248.521 154.95L190.453 255.527L125.853 255.524L183.921 154.947Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M171.992 111.914C170.668 124.537 174.643 138.881 183.92 154.947L125.852 255.524C116.575 239.458 112.599 225.114 113.924 212.491L171.992 111.914Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M307.987 200.562C301.251 207.256 291.203 216.244 277.842 227.528L219.774 328.105C233.135 316.821 243.183 307.832 249.919 301.139L307.987 200.562Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M15.5469 75.1797L44.5359 125.386L-13.5321 225.963L-42.5212 175.756L15.5469 75.1797Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M277.836 227.536C264.033 238.82 253.708 247.904 246.862 254.789L188.794 355.366C195.64 348.481 205.965 339.397 219.768 328.113L277.836 227.536Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M275.358 304.706L464.189 304.713L406.12 405.29L217.29 405.283L275.358 304.706Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M44.5279 125.39L67.3864 125.39L9.31834 225.967L-13.5401 225.966L44.5279 125.39Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M101.341 75.1911L233.863 304.705L175.795 405.282L43.2733 175.768L101.341 75.1911ZM15.5431 75.19L-42.525 175.767L43.277 175.77L101.345 75.1932L15.5431 75.19Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M246.866 254.784L246.534 254.784L188.466 355.361L188.798 355.361L246.866 254.784Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M246.539 254.781L275.362 304.701L217.294 405.277L188.471 355.358L246.539 254.781Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M67.3906 125.391L170.923 304.698L112.855 405.275L9.32257 225.967L67.3906 125.391Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
<path d="M170.921 304.699L233.865 304.701L175.797 405.278L112.853 405.276L170.921 304.699Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="bevel"/>
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4" style="mix-blend-mode:hard-light">
<path d="M246.544 254.79L246.875 254.79C253.722 247.905 264.046 238.82 277.849 227.537C291.21 216.253 301.259 207.264 307.995 200.57C314.62 193.685 319.147 186.418 321.577 178.768C324.006 171.117 322.846 163.18 318.097 154.956C312.796 145.775 305.342 138.412 295.735 132.865C286.238 127.127 276.189 124.258 265.588 124.257C255.208 124.257 248.416 127.03 245.214 132.576C241.902 137.931 243.006 145.39 248.528 154.953L183.928 154.951C174.652 138.885 170.676 124.541 172 111.918C173.546 99.2946 179.84 89.5408 190.882 82.6559C202.035 75.5798 216.887 72.0421 235.439 72.0428C254.874 72.0435 274.144 75.5825 293.248 82.6598C312.242 89.5457 329.579 99.3005 345.261 111.924C360.942 124.548 373.421 138.892 382.697 154.958C391.311 169.877 395.121 182.978 394.128 194.262C393.355 205.546 389.656 215.396 383.031 223.811C376.627 232.226 366.688 242.554 353.217 254.794L435.375 254.797L464.198 304.716L275.367 304.709L246.544 254.79Z" fill="#4B0600"/>
<path d="M246.544 254.79L246.875 254.79C253.722 247.905 264.046 238.82 277.849 227.537C291.21 216.253 301.259 207.264 307.995 200.57C314.62 193.685 319.147 186.418 321.577 178.768C324.006 171.117 322.846 163.18 318.097 154.956C312.796 145.775 305.342 138.412 295.735 132.865C286.238 127.127 276.189 124.258 265.588 124.257C255.208 124.257 248.416 127.03 245.214 132.576C241.902 137.931 243.006 145.39 248.528 154.953L183.928 154.951C174.652 138.885 170.676 124.541 172 111.918C173.546 99.2946 179.84 89.5408 190.882 82.6559C202.035 75.5798 216.887 72.0421 235.439 72.0428C254.874 72.0435 274.144 75.5825 293.248 82.6598C312.242 89.5457 329.579 99.3005 345.261 111.924C360.942 124.548 373.421 138.892 382.697 154.958C391.311 169.877 395.121 182.978 394.128 194.262C393.355 205.546 389.656 215.396 383.031 223.811C376.627 232.226 366.688 242.554 353.217 254.794L435.375 254.797L464.198 304.716L275.367 304.709L246.544 254.79Z" stroke="#FF750F" stroke-width="1" stroke-linejoin="round"/>
</g>
<g class="transition-all delay-300 translate-y-0 opacity-100 duration-750 starting:opacity-0 starting:translate-y-4" style="mix-blend-mode:hard-light">
<path d="M67.41 125.402L44.5515 125.401L15.5625 75.1953L101.364 75.1985L233.886 304.712L170.942 304.71L67.41 125.402Z" fill="#4B0600"/>
<path d="M67.41 125.402L44.5515 125.401L15.5625 75.1953L101.364 75.1985L233.886 304.712L170.942 304.71L67.41 125.402Z" stroke="#FF750F" stroke-width="1"/>
</g>
</svg>
<div class="absolute inset-0 rounded-t-lg lg:rounded-t-none lg:rounded-r-lg shadow-[inset_0px_0px_0px_1px_rgba(26,26,0,0.16)] dark:shadow-[inset_0px_0px_0px_1px_#fffaed2d]"></div>
</div>
</main>
</div>
@if (Route::has('login'))
<div class="h-14.5 hidden lg:block"></div>
@endif
</body>
</html>
<?php
use App\Http\Controllers\Auth\ForgotPasswordController;
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\Logout;
use App\Http\Controllers\Auth\RegistrationController;
use App\Http\Controllers\Auth\ResetPasswordController;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
Route::group(
[
'prefix' => 'auth',
'middleware' => 'guest',
],
function (Router $router) {
$router->get('login', [LoginController::class, 'show'])->name('auth::login.show');
$router->post('login', [LoginController::class, 'store'])->name('auth::login.store');
$router->get('login-base', fn () => to_route('auth::login.show'))->name('login');
// Password Reset Routes...
$router->get('forgot', [ForgotPasswordController::class, 'show'])->name('auth::forgot.show');
$router->post('forgot', [ForgotPasswordController::class, 'store'])->name('auth::forgot.store');
$router->get('reset/{token}', [ResetPasswordController::class, 'show'])->name('auth::reset.show');
$router->post('reset/{token}', [ResetPasswordController::class, 'store'])->name('auth::reset.store');
if (config('laravolt.platform.features.registration')) {
$router->get('register', [RegistrationController::class, 'show'])->name('auth::registration.show');
$router->post('register', [RegistrationController::class, 'store'])->name('auth::registration.store');
}
}
);
Route::group(
[
'prefix' => 'auth',
'middleware' => 'auth',
],
function (Router $router) {
$router->any('logout', Logout::class)->name('auth::logout');
if (config('laravolt.platform.features.verification')) {
$router->get('/verify-email', [\App\Http\Controllers\Auth\VerificationController::class, 'show'])
->name('verification.notice');
$router->post('/verify-email', [\App\Http\Controllers\Auth\VerificationController::class, 'store'])
->middleware(['throttle:6,1'])
->name('verification.send');
$router->get('/verify-email/{id}/{hash}', [\App\Http\Controllers\Auth\VerificationController::class, 'update'])
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
}
}
);
<?php
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
<?php
use Illuminate\Support\Facades\Route;
Route::middleware(['auth'])->group(function () {
// My Profile
Route::get('my/profile', [\App\Http\Controllers\My\ProfileController::class, 'edit'])->name('my::profile.edit');
Route::put('my/profile', [\App\Http\Controllers\My\ProfileController::class, 'update'])->name('my::profile.update');
// My Password
Route::get('my/password', [\App\Http\Controllers\My\PasswordController::class, 'edit'])->name('my::password.edit');
Route::post('my/password', [\App\Http\Controllers\My\PasswordController::class, 'update'])->name('my::password.update');
});
<?php
use App\Http\Controllers\Home;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::redirect('/', '/login');
Route::middleware(['auth', 'verified'])->group(fn () => Route::get('/home', Home::class)->name('home'));
Route::get('dashboard', \App\Http\Controllers\DashboardController::class)->name('dashboard');
include __DIR__.'/auth.php';
include __DIR__.'/my.php';
*
!private/
!public/
!.gitignore
compiled.php
config.php
down
events.scanned.php
maintenance.php
routes.php
routes.scanned.php
schedule-*
services.json
<?php
namespace Tests\Feature\Auth;
use Tests\TestCase;
class ApiRateLimiterTest extends TestCase
{
#[\PHPUnit\Framework\Attributes\Test]
public function it_has_api_rate_limiter()
{
$this->assertTrue(true);
// TODO: This test is not working because of we need registering providers
// Route::get('sample-api', fn () => 'hello')->middleware('throttle:api');
// $this->get('sample-api')->assertOk();
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Laravolt\Platform\Services\Password;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class ForgotPasswordTest extends TestCase
{
use LazilyRefreshDatabase;
#[Test]
public function it_can_get_forgot_password_page()
{
$this->get(route('auth::forgot.store'))
->assertSee('email')
->assertStatus(200);
}
#[Test]
public function it_can_handle_correct_email()
{
$payload = [
'email' => 'admin@laravolt.dev',
];
User::factory()->create($payload);
$this->post(route('auth::forgot.store'), $payload)
->assertRedirect(route('auth::forgot.show'))
->assertSessionHas('success');
}
#[Test]
public function it_can_handle_wrong_email()
{
$payload = [
'email' => 'zombie@laravolt.dev',
];
// We must visit form at first, to mimic browser history a.k.a redirect back
$this->get(route('auth::forgot.show'));
$this->post(route('auth::forgot.store'), $payload)
->assertRedirect(route('auth::forgot.show'))
->assertSessionHasErrors('email');
}
#[Test]
public function it_has_errors_if_failed()
{
$this->post(route('auth::forgot.store'))->assertSessionHasErrors();
}
#[Test]
public function it_can_handle_send_email_failure()
{
$payload = [
'email' => 'admin@laravolt.dev',
];
$this->instance('laravolt.password', \Mockery::mock(Password::class, function (MockInterface $mock) {
$mock->shouldReceive('sendResetLink')->once()->andReturn(\Password::RESET_THROTTLED);
}));
User::factory()->create($payload);
$this->post(route('auth::forgot.store'), $payload)
->assertRedirect(route('auth::forgot.show'))
->assertSessionHas('error');
}
#[Test]
public function it_has_register_link()
{
$this->get(route('auth::forgot.show'))->assertSeeText(trans('laravolt::auth.register_here'));
}
#[Test]
public function it_does_not_have_register_link_if_registration_disabled()
{
$this->app['config']->set('laravolt.platform.features.registration', false);
$this->get(route('auth::forgot.show'))->assertDontSeeText(trans('laravolt::auth.register_here'));
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use App\Providers\AppServiceProvider;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class LoginTest extends TestCase
{
use LazilyRefreshDatabase;
protected function setUp(): void
{
parent::setUp();
Route::get('login-success', function () {
return 'login success';
});
}
#[Test]
public function it_can_display_login_page()
{
$this->get(route('auth::login.show'))
->assertOk()
->assertSeeText('Email')
->assertSeeText('Password');
}
#[Test]
public function it_can_handle_correct_login()
{
$payload = [
'email' => 'admin@laravolt.dev',
'status' => 'ACTIVE',
];
User::factory()->create($payload + ['password' => bcrypt('asdf1234')]);
RateLimiter::shouldReceive('tooManyAttempts')->andReturnFalse();
RateLimiter::shouldReceive('availableIn')->andReturn(3);
RateLimiter::shouldReceive('clear');
$response = $this->post(route('auth::login.store'), $payload + ['password' => 'asdf1234']);
$response->assertRedirect(AppServiceProvider::HOME);
$this->get(AppServiceProvider::HOME)->assertSee('Home');
}
#[Test]
public function it_can_handle_wrong_login()
{
$payload = [
'email' => 'admin@laravolt.dev',
];
User::factory()->create($payload + ['password' => bcrypt('asdf1234')]);
$this->get(route('auth::login.show'));
$response = $this->post(route('auth::login.store'), $payload + ['password' => 'wrong-password']);
$response->assertRedirect(route('auth::login.show'));
}
#[Test]
public function ensure_password_required()
{
$this->post(route('auth::login.store'), ['email' => 'user@laravolt.dev'])
->assertSessionHasErrors('password');
}
#[Test]
public function it_has_errors_if_failed()
{
$this->post(route('auth::login.store'))->assertSessionHasErrors();
}
#[Test]
public function it_has_register_link()
{
$this->app['config']->set('laravolt.platform.features.registration', true);
$this->get(route('auth::login.show'))
->assertSeeText(trans('laravolt::auth.register_here'));
}
#[Test]
public function it_does_not_have_register_link()
{
$this->app['config']->set('laravolt.platform.features.registration', false);
$this->get(route('auth::login.show'))
->assertDontSeeText(trans('laravolt::auth.register_here'));
}
#[Test]
public function it_has_forgot_password_link()
{
$this->get(route('auth::login.show'))
->assertSeeText(trans('laravolt::auth.forgot_password'));
}
#[Test]
public function ensure_rate_limiter()
{
$limit = 5;
$payload = [
'email' => 'admin@laravolt.dev',
'password' => 'etalazen',
];
for ($i = 0; $i < $limit; $i++) {
$this->post(route('auth::login.store'), $payload);
}
$lastRequest = $this->post(route('auth::login.store'), $payload);
$lastRequest->assertSessionHasErrors('email');
}
}
<?php
namespace Tests\Feature\Auth;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Tests\TestCase;
class LogoutTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_logout()
{
$this->actingAs(\App\Models\User::factory()->create());
$this->post(route('auth::logout'))
->assertRedirect('/');
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Tests\TestCase;
class RedirectToHomeTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_redirected_to_home()
{
/** @var \Illuminate\Contracts\Auth\Authenticatable $user */
$user = User::factory()->create();
$this->actingAs($user);
$response = $this->get(route('auth::login.show'));
$response->assertRedirect(\App\Providers\AppServiceProvider::HOME);
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use App\Providers\AppServiceProvider;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use InteractsWithDatabase;
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_display_registration_page()
{
$this->get(route('auth::registration.show'))
->assertOk()
->assertSeeText(__('Name'))
->assertSeeText(__('Email'))
->assertSeeText(__('Password'));
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_correct_registration()
{
$payload = [
'name' => 'Jon Dodo',
'email' => 'jon@laravolt.dev',
'password' => 'asdf1234',
'password_confirmation' => 'asdf1234',
];
$response = $this->post(route('auth::registration.store'), $payload);
$response->assertSessionHas('success')
->assertRedirect(AppServiceProvider::HOME);
$this->assertDatabaseHas('users', collect($payload)->only(['name', 'email'])->toArray());
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_correct_registration_with_activation()
{
Notification::fake();
$email = 'jon@laravolt.dev';
$payload = [
'name' => 'Jon Dodo',
'email' => $email,
'password' => 'asdf1234',
'password_confirmation' => 'asdf1234',
];
$response = $this->post(route('auth::registration.store'), $payload);
$response->assertSessionHas('success')
->assertRedirect(AppServiceProvider::HOME);
$this->assertDatabaseHas('users', collect($payload)->only(['name', 'email'])->toArray());
Notification::assertSentTo(User::first(), VerifyEmail::class);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_auto_verify_email()
{
config(['laravolt.platform.features.verification' => false]);
Notification::fake();
$email = 'jon@laravolt.dev';
$payload = [
'name' => 'Jon Dodo',
'email' => $email,
'password' => 'asdf1234',
'password_confirmation' => 'asdf1234',
];
$this->post(route('auth::registration.store'), $payload);
$this->assertDatabaseMissing(
'users',
collect($payload)->only(['name', 'email'])->toArray() + ['email_verified_at' => null]
);
Notification::assertNotSentTo(User::first(), VerifyEmail::class);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_has_errors_if_failed()
{
$this->post(route('auth::registration.store'))
->assertSessionHasErrors();
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Tests\TestCase;
class ResetPasswordTest extends TestCase
{
use LazilyRefreshDatabase;
protected $email = 'fulan@example.com';
protected $token;
protected $table;
protected function setUp(): void
{
parent::setUp();
$this->table = (new User)->getTable();
$user = User::factory()->create(['email' => $this->email]);
$this->token = app('auth.password.broker')->createToken($user);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_display_page()
{
$this->get(route('auth::reset.show', $this->token))
->assertOk()
->assertSeeText(__('Email'))
->assertSeeText(__('Password'))
->assertSeeText(__('Confirm New Password'));
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_reset_password()
{
$payload = [
'token' => $this->token,
'email' => $this->email,
'password' => 'asdf1234',
'password_confirmation' => 'asdf1234',
];
$this->post(route('auth::reset.store', $this->token), $payload)
->assertRedirect(route('auth::login.show'));
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_failed_passwor_reset()
{
$payload = [
'token' => $this->token,
'email' => $this->email,
'password' => 'asdf1234',
'password_confirmation' => 'asdf1234',
];
\Password::shouldReceive('reset')->andReturn(\Password::RESET_THROTTLED);
$this->get(route('auth::reset.show', $this->token));
$this->post(route('auth::reset.store', $this->token), $payload)
->assertRedirect(route('auth::reset.show', $this->token))
->assertSessionHasErrors('email')
->assertSessionHasInput('email');
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_has_errors_if_failed()
{
$this->post(route('auth::reset.store', 'asdf1234'))->assertSessionHasErrors();
}
}
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use App\Providers\AppServiceProvider;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class VerificationTest extends TestCase
{
use LazilyRefreshDatabase;
protected function setUp(): void
{
parent::setUp();
config(['laravolt.platform.features.verification' => true]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_visit_verification_page()
{
$this->actingAs(User::factory()->create(['email_verified_at' => null]));
$this->get(route('verification.notice'))
->assertSeeText(__('Verifikasi Email'))
->assertStatus(200);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_cannot_visit_verification_page_if_already_verified()
{
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$this->get(route('verification.notice'))
->assertRedirect(AppServiceProvider::HOME);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_resend_verification_email()
{
$this->actingAs($user = User::factory()->create(['email_verified_at' => null]));
Notification::fake();
$this->post(route('verification.send'))
->assertSessionHas('success');
Notification::assertSentTo($user, VerifyEmail::class);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_cannot_resend_verification_email_if_already_verified()
{
$this->actingAs(User::factory()->create());
$this->post(route('verification.send'))
->assertRedirect(AppServiceProvider::HOME);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_verify_email()
{
$this->actingAs($user = User::factory()->create(['email_verified_at' => null]));
$this->mock(EmailVerificationRequest::class, function ($mock) use ($user) {
$mock->shouldReceive('authorize')->andReturnTrue();
$mock->shouldReceive('user')->andReturn($user);
});
$this->withoutMiddleware()
->get(route('verification.verify', ['id', 'hash']))
->assertRedirect(AppServiceProvider::HOME.'?verified=1');
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_cannot_verify_email_if_already_verified()
{
$this->actingAs($user = User::factory()->create());
$this->mock(EmailVerificationRequest::class, function ($mock) use ($user) {
$mock->shouldReceive('authorize')->andReturnTrue();
$mock->shouldReceive('user')->andReturn($user);
});
$this->withoutMiddleware()
->get(route('verification.verify', ['id', 'hash']))
->assertRedirect(AppServiceProvider::HOME.'?verified=1');
}
#[\PHPUnit\Framework\Attributes\Test]
public function validate_user_model_concerns()
{
config(['app.debug' => true]);
Auth::shouldReceive('user')->andReturn(new \stdClass);
$this->withoutMiddleware()->post(route('verification.send'))
->assertSeeText(MustVerifyEmail::class)
->assertStatus(500);
}
}
<?php
namespace Tests\Feature;
use App\Providers\AppServiceProvider;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Tests\TestCase;
class AuthenticateMiddlewareTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function test_redirect_to_login()
{
$response = $this->get(AppServiceProvider::HOME);
$response->assertRedirect(route('auth::login.show'));
}
#[\PHPUnit\Framework\Attributes\Test]
public function test_return_nothing()
{
$response = $this->getJson(\App\Providers\AppServiceProvider::HOME);
$response->assertStatus(401);
}
}
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_the_application_returns_a_successful_response(): void
{
$response = $this->get('/');
$response->assertStatus(302);
}
}
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Route;
use Tests\TestCase;
class ExceptionHandlerTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_authorization_exception()
{
Route::get('admin/page', static fn () => 'hello')->middleware('can:access-admin');
Route::get('livewire/foo', static fn () => 'hello')->middleware('can:access-admin');
// web visit
$this->get('admin/page')->assertStatus(403);
// JSON (API) visit
$this->json('GET', 'admin/page')
->assertStatus(403)
->assertJson(['message' => 'This action is unauthorized.']);
// Livewire visit
$this->get('livewire/foo')
->assertStatus(403);
}
}
<?php
namespace Tests\Feature\My;
use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class MyPasswordTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_visit_my_password_page()
{
/** @var User|Authenticatable */
$user = User::factory()->create();
$this->actingAs($user);
$this->get(route('my::password.edit'))
->assertSee('password_current')
->assertSee('password')
->assertSee('password_confirmation')
->assertStatus(200);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_update_my_password()
{
/** @var User|Authenticatable */
$user = User::factory()->create();
$this->actingAs($user);
$payload = [
'password_current' => 'password',
'password' => 'new password',
'password_confirmation' => 'new password',
];
$this->post(route('my::password.update'), $payload)
->assertRedirect(route('my::password.edit'))
->assertSessionHas('success');
$user = User::first();
$this->assertTrue(Hash::check('new password', $user->password));
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_wrong_current_password()
{
/** @var User|Authenticatable */
$user = User::factory()->create();
$this->actingAs($user);
$payload = [
'password_current' => 'foobar',
'password' => 'new password',
'password_confirmation' => 'new password',
];
$this->post(route('my::password.update'), $payload)
->assertRedirect(route('my::password.edit'))
->assertSessionHas('error');
}
}
<?php
namespace Tests\Feature\My;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Tests\TestCase;
class MyProfileTest extends TestCase
{
use LazilyRefreshDatabase;
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_visit_my_profile_page()
{
$this->actingAs(\App\Models\User::factory()->create());
$this->get(route('my::profile.edit'))
->assertSee('name')
->assertSee('email')
->assertSee('timezone')
->assertStatus(200);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_update_my_profile()
{
$this->actingAs(\App\Models\User::factory()->create());
$payload = [
'name' => 'fulan',
'timezone' => 'UTC',
];
$this->get(route('my::profile.edit'));
$this->put(route('my::profile.update'), $payload)
->assertRedirect(route('my::profile.edit'))
->assertSessionHas('success');
$this->assertDatabaseHas('users', $payload);
}
#[\PHPUnit\Framework\Attributes\Test]
public function it_can_handle_wrong_current_password()
{
$this->actingAs(\App\Models\User::factory()->create());
$payload = [
'password_current' => 'foobar',
'password' => 'new password',
'password_confirmation' => 'new password',
];
$this->post(route('my::password.update'), $payload)
->assertRedirect(route('my::password.edit'))
->assertSessionHas('error');
}
}
<?php
namespace Tests\Feature\Password;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class CanChangePasswordTest extends TestCase
{
use LazilyRefreshDatabase;
public function test_password_changed_at_filled()
{
$user = User::factory()->create();
$this->assertNotNull($user->password_changed_at);
}
public function test_can_change_password()
{
$user = User::factory()->create();
$user->setPassword('secret2', true);
$this->assertNull($user->password_changed_at);
$user->setPassword('secret2', false);
$this->assertNotNull($user->password_changed_at);
$this->assertTrue(Hash::check('secret2', $user->password));
}
public function test_password_must_be_changed()
{
$user = User::factory()->create();
$user->setPassword('secret2', true);
$this->assertTrue($user->passwordMustBeChanged(1));
$user->setPassword('secret2', false);
$this->assertFalse($user->passwordMustBeChanged(1));
$user->setPassword('secret2', false);
$this->assertFalse($user->passwordMustBeChanged(null));
$user->setPassword('secret2', true);
$this->assertTrue($user->passwordMustBeChanged(null));
}
public function test_password_must_be_changed_duration()
{
$user = User::factory()->create();
// Lets assume user changed their password 2 days ago,
$user->password_changed_at = Carbon::now()->subDays(2);
// So, when we have password duration = 2 days, user must change their password
// because it is already equal with the limit
$this->assertTrue($user->passwordMustBeChanged(2));
// But, if we have password duration = 3 days, user still allowed to use their passwrod
// because it has 1 day remaining.
$this->assertFalse($user->passwordMustBeChanged(3));
}
}
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
//
}
<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_that_true_is_true(): void
{
$this->assertTrue(true);
}
}
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
tailwindcss(),
],
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment