let users = [] // 🔁 Load users from server-side users.json async function loadUsers() { try { const res = await fetch("users.json") users = await res.json() } catch (e) { console.error("Failed to load users.json:", e) users = [] } } // 🔐 Password hashing function hashPassword(password) { const shaObj = new jsSHA("SHA-256", "TEXT") shaObj.update(password) return shaObj.getHash("HEX") } // 👤 Login async function verifyLogin() { const uname = document.getElementById('username').value.trim() const pw = document.getElementById('password').value const hash = hashPassword(pw) const msg = document.getElementById('loginMessage') const user = users.find(u => u.username === uname && u.hash === hash) if (user) { localStorage.setItem('loggedInUser', JSON.stringify(user)) msg.textContent = '' setupSession(user) await showAdmin() } else { msg.textContent = "Invalid username or password." } } // 🧠 On load window.addEventListener('DOMContentLoaded', async () => { await loadUsers() displayUserDropdown() const savedTheme = localStorage.getItem('theme') || 'playground' document.body.className = savedTheme const dropdown = document.getElementById('themeSelect') if (dropdown) dropdown.value = savedTheme const savedUser = localStorage.getItem('loggedInUser') if (savedUser) setupSession(JSON.parse(savedUser)) }) // 🧑🏫 Admin setup async function setupSession(user) { document.getElementById('loginPanel').classList.add('hidden') document.getElementById('nav').classList.remove('hidden') document.getElementById('userInfo').textContent = `${user.username} (${user.role})` if (user.role === "admin") { document.getElementById('adminBtn').classList.remove('hidden') await showAdmin() await loadUsers() displayUserDropdown() populateWordUserDropdown() } else { document.getElementById('adminBtn').classList.add('hidden') showStudent() } } function logoutUser() { localStorage.removeItem('loggedInUser') document.getElementById('loginPanel').classList.remove('hidden') document.getElementById('nav').classList.add('hidden') document.getElementById('adminPanel').classList.add('hidden') document.getElementById('studentPanel').classList.add('hidden') } async function showAdmin() { document.getElementById('adminPanel').classList.remove('hidden') document.getElementById('studentPanel').classList.add('hidden') loadWords() displayWordList() await loadUsers() displayUserDropdown() } // ➕ Add User async function addNewUser() { const username = document.getElementById("newUsername").value.trim() const password = document.getElementById("newPassword").value const role = document.getElementById("newRole").value const msg = document.getElementById("userAddMessage") if (!username || !password) { msg.textContent = "Please fill out all fields." return } const hash = hashPassword(password) await saveUserToServer(username, hash, role) msg.textContent = `✅ User "${username}" added to server.` document.getElementById("newUsername").value = '' document.getElementById("newPassword").value = '' await loadUsers() displayUserDropdown() } async function saveUserToServer(username, hash, role) { const res = await fetch('/addUser', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, hash, role }) }) const msg = await res.text() alert(msg) } // 🗑 User deletion function displayUserDropdown() { const dropdown = document.getElementById("userDropdown") dropdown.innerHTML = `` users.forEach(user => { dropdown.innerHTML += `` }) } function selectUserAction(username) { if (!username) return const confirmDelete = confirm(`Are you sure you want to delete user "${username}"?`) if (!confirmDelete) { document.getElementById("userDropdown").value = "" return } fetch("/deleteUser", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username }) }) .then(res => res.text()) .then(msg => { alert(msg) loadUsers().then(displayUserDropdown) }) } // 🎨 Theme function changeTheme(themeName) { document.body.className = themeName localStorage.setItem('theme', themeName) } // 📚 Word list function loadWords() { const saved = localStorage.getItem('spellingWords') allWords = saved ? JSON.parse(saved) : [] } function saveWords() { const text = document.getElementById('wordInput').value.trim() allWords = text.split('\n').map(w => w.trim()).filter(Boolean) localStorage.setItem('spellingWords', JSON.stringify(allWords)) displayWordList() alert("Word list saved!") } function clearWords() { localStorage.removeItem('spellingWords') allWords = [] displayWordList() alert("Saved words cleared.") } function displayWordList() { const ul = document.getElementById('wordListDisplay') ul.innerHTML = allWords.map(word => `
You got ${correct} out of ${words.length} correct (${Math.round((correct / words.length) * 100)}%)