import { navigate } from '../router.js'; import { isLoggedIn, showToast } from '../app.js'; import { apiGet, invalidateSessionCheck } from '../api.js'; const WEBSITE_ROLES = ['admin', 'supervisor']; export async function loginPage() { if (isLoggedIn()) { try { const data = await apiGet('session'); if (data.success && data.valid && !data.mustChangePassword && WEBSITE_ROLES.includes(data.role)) { if (data.user) localStorage.setItem('qdb_user', data.user); if (data.role) localStorage.setItem('qdb_role', data.role); navigate('#/'); return; } } catch { invalidateSessionCheck(); } localStorage.removeItem('qdb_token'); localStorage.removeItem('qdb_user'); localStorage.removeItem('qdb_role'); invalidateSessionCheck(); } const app = document.getElementById('app'); app.innerHTML = `

BW Schützt

Questionnaire Management

`; let pendingUsername = ''; let pendingTempToken = ''; document.getElementById('loginForm').addEventListener('submit', async (e) => { e.preventDefault(); const errEl = document.getElementById('loginError'); errEl.style.display = 'none'; const username = document.getElementById('username').value.trim(); const password = document.getElementById('password').value; try { const res = await fetch('../api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-QDB-Client': 'web', }, body: JSON.stringify({ username, password }), }); const json = await res.json(); if (!json.ok) { const code = json.error?.code || ''; let msg = json.error?.message || 'Login failed'; if (res.status === 429 || code === 'RATE_LIMITED') { const retry = res.headers.get('Retry-After'); if (retry) { msg += ` Try again in about ${retry} seconds.`; } } errEl.textContent = msg; errEl.style.display = ''; return; } const d = json.data; if (d.role === 'coach') { errEl.textContent = 'Coach accounts can only sign in through the mobile app.'; errEl.style.display = ''; return; } if (d.mustChangePassword) { pendingUsername = username; pendingTempToken = d.token; document.getElementById('loginForm').style.display = 'none'; document.getElementById('changePwSection').style.display = ''; return; } localStorage.setItem('qdb_token', d.token); localStorage.setItem('qdb_user', d.user); localStorage.setItem('qdb_role', d.role); invalidateSessionCheck(); navigate('#/'); } catch (err) { errEl.textContent = err.message; errEl.style.display = ''; } }); document.getElementById('changePwForm').addEventListener('submit', async (e) => { e.preventDefault(); const errEl = document.getElementById('changePwError'); errEl.style.display = 'none'; const newPw = document.getElementById('newPw').value; const confirm = document.getElementById('newPwConfirm').value; if (newPw !== confirm) { errEl.textContent = 'Passwords do not match'; errEl.style.display = ''; return; } const oldPw = document.getElementById('password').value; try { const headers = { 'Content-Type': 'application/json', 'X-QDB-Client': 'web', }; if (pendingTempToken) { headers['Authorization'] = `Bearer ${pendingTempToken}`; } const res = await fetch('../api/auth/change-password', { method: 'POST', headers, body: JSON.stringify({ username: pendingUsername, old_password: oldPw, new_password: newPw }), }); const json = await res.json(); if (!json.ok) { errEl.textContent = json.error?.message || 'Password change failed'; errEl.style.display = ''; return; } const d = json.data; if (d.role === 'coach') { errEl.textContent = 'Coach accounts can only sign in through the mobile app.'; errEl.style.display = ''; return; } localStorage.setItem('qdb_token', d.token); localStorage.setItem('qdb_user', d.user); localStorage.setItem('qdb_role', d.role); invalidateSessionCheck(); showToast('Password changed successfully', 'success'); navigate('#/'); } catch (err) { errEl.textContent = err.message; errEl.style.display = ''; } }); }