/* Auth. */ function switchTab(tab) { const loginForm = document.getElementById('login-form'); const registerForm = document.getElementById('register-form'); const loginTab = document.getElementById('login-tab'); const registerTab = document.getElementById('register-tab'); if (tab === 'login') { loginForm.style.display = 'flex'; registerForm.style.display = 'none'; loginTab.classList.add('active'); registerTab.classList.remove('active'); } else { loginForm.style.display = 'none'; registerForm.style.display = 'flex'; loginTab.classList.remove('active'); registerTab.classList.add('active'); } document.getElementById('auth-error').textContent = ''; } async function register(e) { e.preventDefault(); const username = document.getElementById('reg-username').value; const password = document.getElementById('reg-password').value; const res = await fetch('/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); if (res.ok) { document.getElementById('auth-error').textContent = ''; showTasks(); } else { const data = await res.json(); document.getElementById('auth-error').textContent = data.error || 'Registration failed'; } } async function login(e) { e.preventDefault(); const username = document.getElementById('login-username').value; const password = document.getElementById('login-password').value; const res = await fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); if (res.ok) { document.getElementById('auth-error').textContent = ''; showTasks(); } else { const data = await res.json(); document.getElementById('auth-error').textContent = data.error || 'Login failed'; } } async function logout() { await fetch('/auth/logout', { method: 'POST' }); document.getElementById('tasks-section').style.display = 'none'; document.getElementById('auth-section').style.display = 'block'; } /* Tasks. */ async function showTasks() { document.getElementById('auth-section').style.display = 'none'; document.getElementById('tasks-section').style.display = 'block'; await loadTasks(); } async function loadTasks() { const res = await fetch('/tasks'); const tasks = await res.json(); const list = document.getElementById('task-list'); if (tasks.length === 0) { list.innerHTML = '

No tasks yet. Add one above!

'; return; } list.innerHTML = tasks.map(task => `
  • ${escapeHtml(task.title)}
    ${task.description ? `
    ${escapeHtml(task.description)}
    ` : ''}
  • `).join(''); } async function createTask(e) { e.preventDefault(); const title = document.getElementById('task-title').value; const description = document.getElementById('task-desc').value; const res = await fetch('/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, description }) }); if (res.ok) { document.getElementById('task-title').value = ''; document.getElementById('task-desc').value = ''; await loadTasks(); } } async function toggleDone(id, done) { const res = await fetch(`/tasks/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ done: done ? 1 : 0 }) }); if (res.ok) { await loadTasks(); } } async function deleteTask(id) { const res = await fetch(`/tasks/${id}`, { method: 'DELETE' }); if (res.ok) { await loadTasks(); } } /* Helpers. */ function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } /* Init. */ /* Check if already logged in on page load. */ (async function init() { const res = await fetch('/auth/check'); if (res.ok) { showTasks(); } })();