Auth: convert auth views and verification email to Nova layout

This commit is contained in:
2026-02-21 07:37:08 +01:00
parent 93b009d42a
commit 795c7a835f
117 changed files with 5385 additions and 1291 deletions

View File

@@ -2,6 +2,19 @@
@section('content')
@php
$birthDay = $birthDay ?? null;
$birthMonth = $birthMonth ?? null;
$birthYear = $birthYear ?? null;
$avatarUserId = (int) ($user->id ?? auth()->id() ?? 0);
$avatarHash = $user->icon
?? optional(auth()->user())->profile->avatar_hash
?? null;
$currentAvatarUrl = !empty($avatarHash)
? \App\Support\AvatarUrl::forUser($avatarUserId, $avatarHash, 128)
: \App\Support\AvatarUrl::default();
@endphp
<div class="min-h-screen bg-deep text-white py-12">
<!-- Container -->
@@ -146,7 +159,30 @@
<!-- Avatar -->
<div>
<label class="form-label">Avatar</label>
<input type="file" name="avatar" class="form-file">
<div class="rounded-xl border border-sb-line bg-black/10 p-4">
<div class="flex items-center gap-4">
<img
id="avatarPreviewImage"
src="{{ $currentAvatarUrl }}"
alt="{{ $user->name ?? $user->username ?? 'Avatar' }}"
class="w-24 h-24 rounded-full object-cover ring-1 ring-white/10"
loading="lazy"
decoding="async"
>
<div class="min-w-0 flex-1">
<button
type="button"
id="avatarDropzone"
class="w-full rounded-lg border border-dashed border-sb-line px-4 py-4 text-left hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-sb-blue/50"
>
<div class="text-sm text-white/90">Drag & drop a new avatar here</div>
<div class="text-xs text-soft mt-1">or click to browse (JPG, PNG, WEBP)</div>
<div id="avatarFileName" class="text-xs text-sb-muted mt-2 truncate">No file selected</div>
</button>
<input id="avatarInput" type="file" name="avatar" class="sr-only" accept="image/jpeg,image/png,image/webp">
</div>
</div>
</div>
</div>
<!-- Emoticon -->
@@ -245,3 +281,65 @@
</div>
@endsection
@push('scripts')
<script>
(() => {
const input = document.getElementById('avatarInput');
const dropzone = document.getElementById('avatarDropzone');
const preview = document.getElementById('avatarPreviewImage');
const fileName = document.getElementById('avatarFileName');
if (!input || !dropzone || !preview || !fileName) {
return;
}
const updatePreview = (file) => {
if (!file || !file.type || !file.type.startsWith('image/')) {
return;
}
const objectUrl = URL.createObjectURL(file);
preview.src = objectUrl;
fileName.textContent = file.name;
preview.onload = () => URL.revokeObjectURL(objectUrl);
};
dropzone.addEventListener('click', () => input.click());
input.addEventListener('change', () => {
const file = input.files && input.files[0] ? input.files[0] : null;
if (file) {
updatePreview(file);
}
});
['dragenter', 'dragover'].forEach((eventName) => {
dropzone.addEventListener(eventName, (event) => {
event.preventDefault();
event.stopPropagation();
dropzone.classList.add('ring-2', 'ring-sb-blue/50');
});
});
['dragleave', 'drop'].forEach((eventName) => {
dropzone.addEventListener(eventName, (event) => {
event.preventDefault();
event.stopPropagation();
dropzone.classList.remove('ring-2', 'ring-sb-blue/50');
});
});
dropzone.addEventListener('drop', (event) => {
const file = event.dataTransfer && event.dataTransfer.files ? event.dataTransfer.files[0] : null;
if (!file) {
return;
}
const dt = new DataTransfer();
dt.items.add(file);
input.files = dt.files;
updatePreview(file);
});
})();
</script>
@endpush