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

@@ -0,0 +1,62 @@
const debounce = (fn, wait = 350) => {
let timeoutId
return (...args) => {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn(...args), wait)
}
}
const setStatus = (target, message, tone = 'neutral') => {
if (!target) return
target.textContent = message || ''
target.classList.remove('text-green-600', 'text-red-600', 'text-gray-500')
if (tone === 'success') target.classList.add('text-green-600')
else if (tone === 'error') target.classList.add('text-red-600')
else target.classList.add('text-gray-500')
}
const initUsernameAvailability = () => {
const fields = document.querySelectorAll('[data-username-field="true"]')
fields.forEach((field) => {
const url = field.getAttribute('data-availability-url') || '/api/username/availability'
const statusId = field.getAttribute('data-availability-target')
const statusEl = statusId ? document.getElementById(statusId) : null
const check = debounce(async () => {
const raw = String(field.value || '')
const username = raw.trim().toLowerCase()
if (!username) {
setStatus(statusEl, '')
return
}
setStatus(statusEl, 'Checking availability...')
try {
const response = await window.axios.get(url, { params: { username } })
const data = response?.data || {}
if (data.available) {
setStatus(statusEl, `Available: ${data.normalized || username}`, 'success')
} else {
setStatus(statusEl, `Taken: ${data.normalized || username}`, 'error')
}
} catch (error) {
if (error?.response?.status === 422) {
const message = error?.response?.data?.errors?.username?.[0] || 'Invalid username.'
setStatus(statusEl, message, 'error')
return
}
setStatus(statusEl, 'Could not check availability right now.', 'error')
}
})
field.addEventListener('input', check)
})
}
document.addEventListener('DOMContentLoaded', initUsernameAvailability)