Merge pull request 'analytics' (#1) from analytics into main
Reviewed-on: nmemmert/Spelling#1
This commit is contained in:
commit
c4844eecff
2 files changed
+68
No files matched your search
@@ -49,6 +49,7 @@
|
||||
<div id="adminTabs">
|
||||
<button onclick="switchTab('tabUsers')" class="active">👤 Manage Users</button>
|
||||
<button onclick="switchTab('tabWords')">📝 Word Lists</button>
|
||||
<button onclick="switchTab('tabAnalytics')">📊 Analytics</button>
|
||||
<button onclick="switchTab('tabResults')">📊 Results</button>
|
||||
<button onclick="switchTab('tabTheme')">🎨 Theme</button>
|
||||
</div>
|
||||
@@ -104,6 +105,21 @@
|
||||
<ul id="resultsList"></ul>
|
||||
</div>
|
||||
|
||||
<!-- 📊 Analytics Tab -->
|
||||
<div id="tabAnalytics" class="adminTab hidden">
|
||||
<h3>Smart Analytics Overview</h3>
|
||||
<ul id="analyticsSummary">
|
||||
<li><strong>Average Score:</strong> –</li>
|
||||
<li><strong>Total Completed Sessions:</strong> –</li>
|
||||
<li><strong>Most Missed Word:</strong> –</li>
|
||||
</ul>
|
||||
|
||||
<h4>Per-Student Breakdown</h4>
|
||||
<ul id="studentBreakdown"></ul>
|
||||
|
||||
<button onclick="refreshAnalytics()">🔄 Refresh</button>
|
||||
</div>
|
||||
|
||||
<!-- 🎨 Theme Tab -->
|
||||
<div id="tabTheme" class="adminTab hidden">
|
||||
<h3>🎨 Select Theme</h3>
|
||||
|
||||
@@ -226,3 +226,55 @@ async function loadUserDropdowns() {
|
||||
console.error("⚠️ Failed to load user list:", err);
|
||||
}
|
||||
}
|
||||
async function refreshAnalytics() {
|
||||
const summary = document.getElementById("analyticsSummary");
|
||||
const breakdown = document.getElementById("studentBreakdown");
|
||||
summary.innerHTML = "<li>Loading...</li>";
|
||||
breakdown.innerHTML = "";
|
||||
|
||||
try {
|
||||
const res = await fetch('/getResults');
|
||||
const data = await res.json();
|
||||
|
||||
let totalScore = 0, sessionCount = 0;
|
||||
const missMap = {};
|
||||
|
||||
for (const username in data) {
|
||||
const { score, completed, answers } = data[username];
|
||||
if (!completed || !Array.isArray(answers)) continue;
|
||||
|
||||
totalScore += score;
|
||||
sessionCount++;
|
||||
|
||||
// Count missed words
|
||||
answers.forEach(({ word, correct }) => {
|
||||
if (!correct) {
|
||||
missMap[word] = (missMap[word] || 0) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Per-student breakdown
|
||||
const li = document.createElement("li");
|
||||
li.innerHTML = `<strong>${username}</strong>: ${score}/${answers.length} correct`;
|
||||
breakdown.appendChild(li);
|
||||
}
|
||||
|
||||
const avgScore = sessionCount ? (totalScore / sessionCount).toFixed(2) : "0";
|
||||
let mostMissed = "-", highestMisses = 0;
|
||||
for (const word in missMap) {
|
||||
if (missMap[word] > highestMisses) {
|
||||
highestMisses = missMap[word];
|
||||
mostMissed = word;
|
||||
}
|
||||
}
|
||||
|
||||
summary.innerHTML = `
|
||||
<li><strong>Average Score:</strong> ${avgScore}</li>
|
||||
<li><strong>Total Completed Sessions:</strong> ${sessionCount}</li>
|
||||
<li><strong>Most Missed Word:</strong> ${mostMissed} (${highestMisses} misses)</li>
|
||||
`;
|
||||
} catch (err) {
|
||||
console.error("📉 Failed to refresh analytics:", err);
|
||||
summary.innerHTML = '<li style="color:red">Error loading analytics.</li>';
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user