107 lines
3.4 KiB
JavaScript
107 lines
3.4 KiB
JavaScript
(() => {
|
||
'use strict';
|
||
|
||
const form = document.getElementById('login-form');
|
||
const usernameInput = document.getElementById('username');
|
||
const passwordInput = document.getElementById('password');
|
||
const usernameError = document.getElementById('username-error');
|
||
const passwordError = document.getElementById('password-error');
|
||
const formAlert = document.getElementById('form-alert');
|
||
const btnSubmit = document.getElementById('btn-submit');
|
||
const btnText = btnSubmit.querySelector('.btn-text');
|
||
const btnLoader = btnSubmit.querySelector('.btn-loader');
|
||
const togglePassword = document.getElementById('toggle-password');
|
||
|
||
togglePassword.addEventListener('click', () => {
|
||
const isPassword = passwordInput.type === 'password';
|
||
passwordInput.type = isPassword ? 'text' : 'password';
|
||
togglePassword.setAttribute('aria-label', isPassword ? 'Скрыть пароль' : 'Показать пароль');
|
||
});
|
||
|
||
usernameInput.addEventListener('input', () => clearFieldError(usernameInput, usernameError));
|
||
passwordInput.addEventListener('input', () => clearFieldError(passwordInput, passwordError));
|
||
|
||
function clearFieldError(input, errorEl) {
|
||
input.closest('.form-group').classList.remove('has-error');
|
||
errorEl.textContent = '';
|
||
}
|
||
|
||
function setFieldError(input, errorEl, message) {
|
||
input.closest('.form-group').classList.add('has-error');
|
||
errorEl.textContent = message;
|
||
}
|
||
|
||
function showAlert(message, type) {
|
||
formAlert.className = 'form-alert ' + type;
|
||
formAlert.textContent = message;
|
||
}
|
||
|
||
function hideAlert() {
|
||
formAlert.className = 'form-alert';
|
||
formAlert.textContent = '';
|
||
}
|
||
|
||
function setLoading(loading) {
|
||
btnSubmit.disabled = loading;
|
||
btnText.hidden = loading;
|
||
btnLoader.hidden = !loading;
|
||
}
|
||
|
||
function validate() {
|
||
let valid = true;
|
||
hideAlert();
|
||
|
||
if (!usernameInput.value.trim()) {
|
||
setFieldError(usernameInput, usernameError, 'Введите имя пользователя');
|
||
valid = false;
|
||
}
|
||
|
||
if (!passwordInput.value) {
|
||
setFieldError(passwordInput, passwordError, 'Введите пароль');
|
||
valid = false;
|
||
} else if (passwordInput.value.length < 4) {
|
||
setFieldError(passwordInput, passwordError, 'Минимум 4 символа');
|
||
valid = false;
|
||
}
|
||
|
||
return valid;
|
||
}
|
||
|
||
form.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
if (!validate()) return;
|
||
|
||
setLoading(true);
|
||
hideAlert();
|
||
|
||
try {
|
||
const response = await fetch('/api/auth/login', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
username: usernameInput.value.trim(),
|
||
password: passwordInput.value,
|
||
}),
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (response.ok) {
|
||
showAlert('Вход выполнен успешно!', 'success');
|
||
|
||
if (data.token) localStorage.setItem('token', data.token);
|
||
if (data.role) localStorage.setItem('role', data.role);
|
||
|
||
const redirect = data.redirect || '/';
|
||
setTimeout(() => { window.location.href = redirect; }, 400);
|
||
} else {
|
||
showAlert(data.message || 'Неверное имя пользователя или пароль', 'error');
|
||
}
|
||
} catch (err) {
|
||
showAlert('Ошибка соединения с сервером', 'error');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
});
|
||
})();
|