performance updates
This commit is contained in:
@@ -0,0 +1 @@
|
||||
:root{color-scheme:light dark;font-family:Instrument Sans,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#f8fafc;color:#18181b}*{box-sizing:border-box}body{margin:0;min-height:100vh;background:#f8fafc;color:#18181b;-webkit-font-smoothing:antialiased}.auth-main{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.auth-wrap{width:100%;max-width:390px}.auth-brand{display:flex;justify-content:center;margin-bottom:20px}.auth-brand img{width:48px;height:48px}.auth-card{background:#fff;border:1px solid #e4e4e7;border-radius:16px;padding:30px;box-shadow:0 10px 30px rgba(15,23,42,.06)}h1{font-size:24px;line-height:1.2;margin:0 0 8px;text-align:center}p{margin:0}.auth-subtitle{text-align:center;color:#71717a;font-size:14px;margin-bottom:24px}.field{margin-bottom:18px}.field-row{display:flex;align-items:center;justify-content:space-between;gap:12px}label{display:block;font-size:14px;font-weight:600;margin-bottom:7px}input[type=email],input[type=password]{width:100%;height:44px;border:1px solid #d4d4d8;border-radius:9px;padding:0 12px;background:#fff;color:#18181b;font:inherit;outline:none}input:focus{border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.14)}.remember{display:flex;align-items:center;gap:8px;font-size:14px;color:#52525b}.remember input{width:16px;height:16px}.btn{width:100%;min-height:44px;border:0;border-radius:9px;padding:10px 14px;font:inherit;font-weight:600;cursor:pointer}.btn-primary{background:#2563eb;color:#fff}.btn-primary:hover{background:#1d4ed8}.btn-passkey{background:#fff;color:#18181b;border:1px solid #d4d4d8;margin-bottom:18px}.divider{display:flex;align-items:center;gap:12px;color:#71717a;font-size:11px;text-transform:uppercase;margin:2px 0 20px}.divider:before,.divider:after{content:"";height:1px;background:#e4e4e7;flex:1}.link{color:#2563eb;text-decoration:none;font-size:14px}.link:hover{text-decoration:underline}.signup{text-align:center;color:#71717a;font-size:14px;margin-top:22px}.status{padding:10px 12px;border-radius:8px;background:#ecfdf5;color:#047857;font-size:14px;margin-bottom:18px}.error{color:#dc2626;font-size:13px;margin-top:6px}.passkey-error{text-align:center;margin:-8px 0 16px}[hidden]{display:none!important}@media(max-width:480px){.auth-main{padding:16px}.auth-card{padding:24px 20px;border-radius:13px}}@media(prefers-color-scheme:dark){:root{background:#09090b;color:#fafafa}body{background:#09090b;color:#fafafa}.auth-card{background:#18181b;border-color:#27272a;box-shadow:none}.auth-subtitle,.signup,.remember,.divider{color:#a1a1aa}input[type=email],input[type=password]{background:#09090b;border-color:#3f3f46;color:#fafafa}.btn-passkey{background:#18181b;border-color:#3f3f46;color:#fafafa}.divider:before,.divider:after{background:#3f3f46}.status{background:#052e24;color:#6ee7b7}}
|
||||
Executable → Regular
+87
-55
@@ -1,63 +1,95 @@
|
||||
<x-layouts::auth :title="__('Log in')">
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Log in to your account')" :description="__('Enter your email and password below to log in')" />
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Sign in to {{ config('app.name', 'Systems Helpdesk') }} to manage helpdesk tickets and support requests.">
|
||||
<meta name="theme-color" content="#0b1220">
|
||||
<title>{{ __('Log in') }} - {{ config('app.name', 'Systems Helpdesk') }}</title>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('apple-touch-icon.png') }}">
|
||||
@vite('resources/themes/backend/assets/css/auth.css')
|
||||
</head>
|
||||
<body>
|
||||
<main class="auth-main">
|
||||
<div class="auth-wrap">
|
||||
<a class="auth-brand" href="{{ route('home') }}" aria-label="{{ config('app.name', 'Systems Helpdesk') }}">
|
||||
<img src="{{ asset('favicon-96x96.png') }}" width="48" height="48" alt="">
|
||||
</a>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
<section class="auth-card" aria-labelledby="login-heading">
|
||||
<h1 id="login-heading">{{ __('Log in to your account') }}</h1>
|
||||
<p class="auth-subtitle">{{ __('Enter your email and password below to log in') }}</p>
|
||||
|
||||
<div class="hd-auth-passkey">
|
||||
<x-passkey-verify />
|
||||
</div>
|
||||
@if (session('status'))
|
||||
<div class="status" role="status">{{ session('status') }}</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('login.store') }}" class="flex flex-col gap-6">
|
||||
@csrf
|
||||
|
||||
<!-- Email Address -->
|
||||
<flux:input
|
||||
name="email"
|
||||
:label="__('Email address')"
|
||||
:value="old('email')"
|
||||
type="email"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="email"
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="relative">
|
||||
<flux:input
|
||||
name="password"
|
||||
:label="__('Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
:placeholder="__('Password')"
|
||||
viewable
|
||||
/>
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<flux:link class="absolute top-0 text-sm end-0" :href="route('password.request')" wire:navigate>
|
||||
{{ __('Forgot your password?') }}
|
||||
</flux:link>
|
||||
@endif
|
||||
<div id="passkey-area" hidden>
|
||||
<button id="passkey-button" class="btn btn-passkey" type="button">{{ __('Sign in with a passkey') }}</button>
|
||||
<p id="passkey-error" class="error passkey-error" role="alert" hidden></p>
|
||||
<div class="divider"><span>{{ __('Or continue with email') }}</span></div>
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="hd-auth-checkbox">
|
||||
<flux:checkbox name="remember" :label="__('Remember me')" :checked="old('remember')" />
|
||||
</div>
|
||||
<form method="POST" action="{{ route('login.store') }}">
|
||||
@csrf
|
||||
<div class="field">
|
||||
<label for="email">{{ __('Email address') }}</label>
|
||||
<input id="email" name="email" value="{{ old('email') }}" type="email" required autofocus autocomplete="email" inputmode="email">
|
||||
@error('email')<p class="error">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button variant="primary" type="submit" class="hd-auth-primary w-full" data-test="login-button">
|
||||
{{ __('Log in') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="field">
|
||||
<div class="field-row">
|
||||
<label for="password">{{ __('Password') }}</label>
|
||||
@if (Route::has('password.request'))
|
||||
<a class="link" href="{{ route('password.request') }}">{{ __('Forgot your password?') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
<input id="password" name="password" type="password" required autocomplete="current-password">
|
||||
@error('password')<p class="error">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
|
||||
<div class="space-x-1 text-sm text-center rtl:space-x-reverse text-zinc-600 dark:text-zinc-400">
|
||||
<span>{{ __('Don\'t have an account?') }}</span>
|
||||
<flux:link :href="route('register')" wire:navigate>{{ __('Sign up') }}</flux:link>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="remember"><input name="remember" type="checkbox" value="1" @checked(old('remember'))> <span>{{ __('Remember me') }}</span></label>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit" data-test="login-button">{{ __('Log in') }}</button>
|
||||
</form>
|
||||
|
||||
@if (Route::has('register'))
|
||||
<p class="signup">{{ __('Don\'t have an account?') }} <a class="link" href="{{ route('register') }}">{{ __('Sign up') }}</a></p>
|
||||
@endif
|
||||
</section>
|
||||
</div>
|
||||
</x-layouts::auth>
|
||||
</main>
|
||||
|
||||
@vite('resources/themes/backend/assets/js/passkeys.js')
|
||||
<script>
|
||||
window.addEventListener('passkeys:ready', () => {
|
||||
const area = document.getElementById('passkey-area');
|
||||
const button = document.getElementById('passkey-button');
|
||||
const error = document.getElementById('passkey-error');
|
||||
if (!window.Passkeys?.isSupported?.()) return;
|
||||
area.hidden = false;
|
||||
button.addEventListener('click', async () => {
|
||||
button.disabled = true;
|
||||
button.textContent = @json(__('Authenticating...'));
|
||||
error.hidden = true;
|
||||
try {
|
||||
const response = await window.Passkeys.verify({routes:{options:@json(route('passkey.login-options')),submit:@json(route('passkey.login'))}});
|
||||
window.location.assign(response.redirect || @json(route('dashboard')));
|
||||
} catch (e) {
|
||||
if (e?.constructor?.name !== 'UserCancelledError') {
|
||||
error.textContent = e?.message || @json(__('Passkey authentication failed.'));
|
||||
error.hidden = false;
|
||||
}
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
button.textContent = @json(__('Sign in with a passkey'));
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -32,6 +32,7 @@ export default defineConfig({
|
||||
laravel({
|
||||
input:[
|
||||
backendCssEntry,
|
||||
'resources/themes/backend/assets/css/auth.css',
|
||||
'resources/themes/backend/assets/js/passkeys.js',
|
||||
'resources/themes/backend/assets/js/layout.js',
|
||||
...moduleInputs,
|
||||
|
||||
Reference in New Issue
Block a user