(function () { function authBase() { return document.body.getAttribute('data-auth-base') || ''; } function apiBase() { var bp = document.body.getAttribute('data-base-path') || ''; return bp.replace(/\/issues\/?$/, '') + '/api/auth_register.php'; } function formatCountdown(totalSeconds) { var s = Math.max(0, totalSeconds); var m = Math.floor(s / 60); var r = s % 60; return m + ':' + String(r).padStart(2, '0'); } function parseExpiresMs(iso) { if (!iso) return 0; var t = Date.parse(iso.replace(' ', 'T') + 'Z'); if (Number.isNaN(t)) { t = Date.parse(iso); } return t; } function initCountdown(expiresTs, countdownEl, onExpired) { var expMs = expiresTs > 0 ? expiresTs * 1000 : 0; if (!expMs) { countdownEl.textContent = '—'; return null; } function tick() { var left = Math.ceil((expMs - Date.now()) / 1000); if (left <= 0) { countdownEl.textContent = '0:00'; if (onExpired) onExpired(); return; } countdownEl.textContent = formatCountdown(left); } tick(); return window.setInterval(tick, 1000); } async function postJson(body) { var res = await fetch(apiBase(), { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); var data = await res.json().catch(function () { return {}; }); return { ok: res.ok && data.ok !== false, status: res.status, data: data }; } document.addEventListener('DOMContentLoaded', function () { var pending = document.getElementById('register-pending'); var form = document.getElementById('register-form'); var countdownEl = document.getElementById('register-countdown'); var resendBtn = document.getElementById('register-resend-btn'); var resendStatus = document.getElementById('register-resend-status'); var emailEl = document.getElementById('register-pending-email'); if (!pending || !countdownEl) return; var email = document.body.getAttribute('data-register-email') || ''; var expiresTs = parseInt(document.body.getAttribute('data-register-expires-ts') || '0', 10); var timerId = null; function showPending(nextEmail, nextExpiresTs) { if (form) form.hidden = true; pending.hidden = false; email = nextEmail || email; expiresTs = nextExpiresTs || expiresTs; if (emailEl && email) emailEl.textContent = email; if (timerId) window.clearInterval(timerId); timerId = initCountdown(expiresTs, countdownEl, function () { if (resendStatus) { resendStatus.textContent = 'Verification link expired — use Resend to get a new one.'; resendStatus.classList.add('error'); } if (resendBtn) resendBtn.disabled = false; }); } if (document.body.getAttribute('data-register-pending') === '1') { showPending(email, expiresTs); } if (resendBtn) { resendBtn.addEventListener('click', async function () { if (!email) { var input = form && form.querySelector('input[name="email"]'); email = input ? input.value.trim() : ''; } if (!email) { if (resendStatus) resendStatus.textContent = 'Enter your email on the registration form first.'; return; } resendBtn.disabled = true; if (resendStatus) { resendStatus.textContent = 'Sending…'; resendStatus.classList.remove('error'); } var out = await postJson({ action: 'resend', email: email }); if (out.ok && out.data.expires_at) { var ts = out.data.expires_at ? Math.floor(Date.parse(String(out.data.expires_at).replace(' ', 'T')) / 1000) : 0; if (!ts && out.data.ttl_seconds) { ts = Math.floor(Date.now() / 1000) + Number(out.data.ttl_seconds); } showPending(email, ts); if (resendStatus) resendStatus.textContent = 'Verification email sent.'; resendBtn.disabled = false; return; } var err = (out.data && out.data.error) || 'resend_failed'; if (resendStatus) { resendStatus.textContent = err === 'rate_limited' ? 'Too many attempts — wait a few minutes.' : err === 'not_pending' ? 'No pending registration for this email.' : err === 'mail_failed' ? 'Could not send email — contact support.' : 'Could not resend verification email.'; resendStatus.classList.add('error'); } resendBtn.disabled = false; }); } }); })();