From 3e6c02e4d2a21311212ca16d2145baa0c5880641 Mon Sep 17 00:00:00 2001 From: "nate@necloud.us" Date: Wed, 2 Jul 2025 14:15:45 -0400 Subject: [PATCH] adding results --- public/index.html | 103 +++++++++++++++++++++++++++----------------- public/results.json | 4 ++ public/script.js | 42 ++++++++++++++++++ public/styles.css | 33 ++++++++++++++ public/users.json | 5 +++ server.js | 4 ++ 6 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 public/results.json diff --git a/public/index.html b/public/index.html index 8d0fefc..08bee0b 100644 --- a/public/index.html +++ b/public/index.html @@ -30,51 +30,41 @@ - + + + + + + + + diff --git a/public/results.json b/public/results.json new file mode 100644 index 0000000..19fbf59 --- /dev/null +++ b/public/results.json @@ -0,0 +1,4 @@ +{ + "student1": { "score": 8, "completed": true, "answers": ["cat", "dog", "fish"] }, + "nate": { "score": 10, "completed": true, "answers": ["grace", "truth", "peace"] } +} \ No newline at end of file diff --git a/public/script.js b/public/script.js index 2467afe..6d2a80e 100644 --- a/public/script.js +++ b/public/script.js @@ -439,4 +439,46 @@ async function displayWordListForSelectedUser() { list.innerHTML = `
  • โŒ Error loading words: ${err.message}
  • ` console.error("Failed to load word list for user:", username, err) } +} +async function loadStudentResults() { + const list = document.getElementById("resultsList") + list.innerHTML = '' + + try { + const res = await fetch('/getResults') + const results = await res.json() + + if (!Object.keys(results).length) { + list.innerHTML = '
  • No results available yet.
  • ' + return + } + + for (const [username, result] of Object.entries(results)) { + const li = document.createElement('li') + li.innerHTML = `${username} โ€” Score: ${result.score}, Completed: ${result.completed ? 'โœ…' : 'โŒ'}
    + Answers: ${result.answers.join(', ')}` + list.appendChild(li) + } + } catch (err) { + console.error("๐Ÿ”ด Failed to load results:", err) + list.innerHTML = '
  • Error loading results.
  • ' + } +} +function switchTab(targetId) { + // Hide all tabs + document.querySelectorAll('.adminTab').forEach(tab => tab.classList.add('hidden')) + + // Remove active class from buttons + document.querySelectorAll('#adminTabs button').forEach(btn => btn.classList.remove('active')) + + // Show the selected tab + document.getElementById(targetId).classList.remove('hidden') + + // Highlight active tab button + const buttons = document.querySelectorAll('#adminTabs button') + buttons.forEach(btn => { + if (btn.getAttribute('onclick')?.includes(targetId)) { + btn.classList.add('active') + } + }) } \ No newline at end of file diff --git a/public/styles.css b/public/styles.css index 1b0c396..8bebded 100644 --- a/public/styles.css +++ b/public/styles.css @@ -122,4 +122,37 @@ body.nature button { .toast.show { opacity: 1; pointer-events: auto; +} +#adminTabs { + margin: 1em 0; +} +#adminTabs button { + margin-right: 8px; + padding: 10px 16px; + background-color: #f0f0f0; + border: 1px solid #ccc; + border-bottom: none; + border-radius: 6px 6px 0 0; + font-weight: 600; + color: #333; + cursor: pointer; + transition: background-color 0.2s, color 0.2s; +} + +#adminTabs button:hover { + background-color: #e0f2ff; + color: #000; +} + +#adminTabs button.active { + background-color: #ffffff; + color: #000; + border-bottom: 2px solid #fff; + box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.1); +} +.adminTab { + display: none; +} +.adminTab:not(.hidden) { + display: block; } \ No newline at end of file diff --git a/public/users.json b/public/users.json index a0c1874..4f2a0a2 100644 --- a/public/users.json +++ b/public/users.json @@ -8,5 +8,10 @@ "username": "student1", "hash": "8d969eef6ecad3c29a3a629280e686cf", "role": "student" + }, + { + "username": "nate", + "hash": "5a2a558c78d3717db731600c4f354fa1d9c84b556f108091a891f444f1bdec40", + "role": "student" } ] \ No newline at end of file diff --git a/server.js b/server.js index 55de536..d0f9fd2 100644 --- a/server.js +++ b/server.js @@ -49,5 +49,9 @@ app.post('/saveWordList', (req, res) => { fs.writeFileSync('public/wordlists.json', JSON.stringify(data, null, 2)) res.send(`โœ… Word list saved for ${username}`) }) +app.get('/getResults', (req, res) => { + const results = JSON.parse(fs.readFileSync('public/results.json', 'utf-8')) + res.json(results) +}) app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`))