{% load stapel_translate %} Login - Translator Dashboard
{% if no_access %}
{% else %}
{% endif %}
{% include "dashboard/_safe_dom.html" %} async function logoutAndSwitch() { try { await fetch('/auth/api/logout/', { method: 'GET', credentials: 'include', }); } catch (err) { // ignore } window.location.href = '{% url "dashboard-login" %}'; } let currentEmail = ''; async function requestOtp(e) { e.preventDefault(); const email = document.getElementById('email').value.trim().toLowerCase(); const btn = document.getElementById('btn-email'); const errorDiv = document.getElementById('error-email'); errorDiv.classList.add('hidden'); btn.disabled = true; stapelDom.replace(btn, [stapelDom.el('span', 'spinner'), document.createTextNode('Sending...')]); try { const response = await fetch('/auth/api/email/request/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ email: email }), }); const data = await response.json(); if (response.ok) { currentEmail = email; document.getElementById('display-email').textContent = email; document.getElementById('step-email').classList.add('hidden'); document.getElementById('step-otp').classList.remove('hidden'); document.getElementById('code').focus(); } else { errorDiv.textContent = data.error || 'Failed to send verification code'; errorDiv.classList.remove('hidden'); } } catch (err) { errorDiv.textContent = 'Network error. Please try again.'; errorDiv.classList.remove('hidden'); } finally { btn.disabled = false; stapelDom.setText(btn, 'Send Verification Code'); } } async function verifyOtp(e) { e.preventDefault(); const code = document.getElementById('code').value.trim(); const btn = document.getElementById('btn-otp'); const errorDiv = document.getElementById('error-otp'); errorDiv.classList.add('hidden'); btn.disabled = true; stapelDom.replace(btn, [stapelDom.el('span', 'spinner'), document.createTextNode('Verifying...')]); try { const response = await fetch('/auth/api/email/verify/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ email: currentEmail, code: code }), }); const data = await response.json(); if (response.ok && data.status !== 'REJECTED') { // Success - cookies are set by auth service, redirect to dashboard window.location.href = '{% url "dashboard-index" %}'; } else { errorDiv.textContent = data.error || 'Invalid verification code'; errorDiv.classList.remove('hidden'); document.getElementById('code').value = ''; document.getElementById('code').focus(); // Show staff login hint on OTP error (for superusers who don't have OTP) document.getElementById('staff-login-hint').classList.remove('hidden'); } } catch (err) { errorDiv.textContent = 'Network error. Please try again.'; errorDiv.classList.remove('hidden'); } finally { btn.disabled = false; stapelDom.setText(btn, 'Verify & Login'); } } function backToEmail() { document.getElementById('step-otp').classList.add('hidden'); document.getElementById('step-email').classList.remove('hidden'); document.getElementById('error-otp').classList.add('hidden'); document.getElementById('staff-login-hint').classList.add('hidden'); document.getElementById('code').value = ''; document.getElementById('email').focus(); } stapelDom.register({ logoutAndSwitch: logoutAndSwitch, requestOtp: (node, event) => requestOtp(event), verifyOtp: (node, event) => verifyOtp(event), backToEmail: backToEmail, });