Spaces:
Running
Running
File size: 2,191 Bytes
d646dd7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | /* Login page — form submission, error handling */
(function() {
var form = document.getElementById('login-form');
var btn = document.getElementById('btn-login');
var errorBox = document.getElementById('login-error');
var errorText = document.getElementById('login-error-text');
var usernameEl = document.getElementById('username');
var passwordEl = document.getElementById('password');
var rememberEl = document.getElementById('remember-me');
function showError(msg) {
errorText.textContent = msg;
errorBox.classList.remove('hidden');
}
function hideError() {
errorBox.classList.add('hidden');
}
function setLoading(loading) {
btn.disabled = loading;
btn.textContent = loading ? 'Signing in...' : 'Sign In';
}
form.addEventListener('submit', function(e) {
e.preventDefault();
hideError();
var username = usernameEl.value.trim();
var password = passwordEl.value;
if (!username || !password) {
showError('Please enter username and password');
return;
}
setLoading(true);
fetch('/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: username,
password: password,
remember_me: rememberEl.checked
})
})
.then(function(res) {
if (!res.ok) {
return res.json().then(function(data) {
throw new Error(data.detail || 'Invalid credentials');
}, function() {
throw new Error('Invalid credentials');
});
}
return res.json();
})
.then(function(data) {
// Success — redirect to home
window.location.href = '/';
})
.catch(function(err) {
showError(err.message || 'Login failed');
setLoading(false);
});
});
// Focus first input
if (usernameEl && !usernameEl.value) {
usernameEl.focus();
}
})();
|