add new ui

This commit is contained in:
Danamir
2025-11-10 11:28:49 +03:00
parent 3f91dc91ec
commit e428e7f762
19 changed files with 755 additions and 31 deletions

58
frontend/login.js Normal file
View File

@@ -0,0 +1,58 @@
function setStatus(msg, type = "info") {
const el = document.getElementById("status");
el.textContent = msg || "";
el.style.color = type === 'error' ? '#b91c1c' : type === 'ok' ? '#16a34a' : '';
}
function decodeRoleFromJWT(token) {
try {
const payload = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
return payload.role || null;
} catch { return null; }
}
async function login(username, password) {
const params = new URLSearchParams();
params.set('username', username);
params.set('password', password);
try {
const res = await fetch('/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString(),
});
if (!res.ok) {
const txt = await res.text();
throw new Error(`Ошибка входа (${res.status}): ${txt}`);
}
const data = await res.json();
const token = data.access_token;
if (!token) throw new Error('Токен не получен');
localStorage.setItem('access_token', token);
const role = decodeRoleFromJWT(token);
if (role) localStorage.setItem('role', role);
return { token, role };
} catch (e) {
throw e;
}
}
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('login-form');
form.addEventListener('submit', async (ev) => {
ev.preventDefault();
setStatus('Входим…');
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
try {
const { role } = await login(username, password);
setStatus(`Успешный вход${role ? ' (' + role + ')' : ''}`, 'ok');
// Небольшая задержка для визуального отклика
setTimeout(() => { window.location.href = '/app/'; }, 400);
} catch (e) {
console.error(e);
setStatus(e.message || 'Ошибка авторизации', 'error');
}
});
});