Adaptive Learning Performance Dashboard

Total Learners

0

Avg. Progress

0%

Avg. Score

0

Avg. Time Spent

0m

All Learners

Select a learner to view their detailed report.

    Please check your internet connection, disable ad-blockers, and refresh the page.

    `; errorWrapper.style.display = 'block'; contentWrapper.style.display = 'none'; return; } // --- STATE MANAGEMENT & SAMPLE DATA --- // The dashboard's data is fully customizable by editing this section. let learners = [ { id: 1, name: 'Amelia Yusuf', modules: [ { id: 101, name: 'Introduction to Algebra', status: 'Completed', score: 95, timeSpent: 45, mastery: 'Mastered' }, { id: 102, name: 'Linear Equations', status: 'Completed', score: 88, timeSpent: 70, mastery: 'Mastered' }, { id: 103, name: 'Quadratic Functions', status: 'In Progress', score: 72, timeSpent: 55, mastery: 'Proficient' }, { id: 104, name: 'Polynomials', status: 'Not Started', score: null, timeSpent: 0, mastery: 'Novice' }, ] }, { id: 2, name: 'Benjamin Carter', modules: [ { id: 101, name: 'Introduction to Algebra', status: 'Completed', score: 75, timeSpent: 65, mastery: 'Proficient' }, { id: 102, name: 'Linear Equations', status: 'In Progress', score: 60, timeSpent: 85, mastery: 'Novice' }, { id: 103, name: 'Quadratic Functions', status: 'Not Started', score: null, timeSpent: 0, mastery: 'Novice' }, { id: 104, name: 'Polynomials', status: 'Not Started', score: null, timeSpent: 0, mastery: 'Novice' }, ] }, { id: 3, name: 'Chloe Sharma', modules: [ { id: 101, name: 'Introduction to Algebra', status: 'Completed', score: 100, timeSpent: 30, mastery: 'Mastered' }, { id: 102, name: 'Linear Equations', status: 'Completed', score: 98, timeSpent: 45, mastery: 'Mastered' }, { id: 103, name: 'Quadratic Functions', status: 'Completed', score: 92, timeSpent: 60, mastery: 'Mastered' }, { id: 104, name: 'Polynomials', status: 'Completed', score: 89, timeSpent: 75, mastery: 'Mastered' }, ] }, ]; let activeTabIndex = 0; let selectedLearnerId = null; let masteryChart, timeChart; const moduleNames = [...new Set(learners.flatMap(l => l.modules.map(m => m.name)))]; // --- DOM ELEMENTS --- const tabButtons = document.querySelectorAll('.al-tab-button'); const tabPanes = document.querySelectorAll('.al-tab-pane'); const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); const learnerListEl = document.getElementById('learner-list'); const learnerDetailsSection = document.getElementById('learner-details-section'); const downloadPdfBtn = document.getElementById('download-pdf-btn'); // --- INITIALIZATION --- function initialize() { initCharts(); render(); attachEventListeners(); } function initCharts() { const commonOptions = { responsive: true, maintainAspectRatio: false }; masteryChart = new Chart(document.getElementById('masteryDistributionChart'), { type: 'doughnut', options: {...commonOptions, plugins: { title: { display: true, text: 'Cohort Mastery Distribution' }}} }); timeChart = new Chart(document.getElementById('timePerModuleChart'), { type: 'bar', options: {...commonOptions, plugins: { title: { display: true, text: 'Average Time Spent per Module' }}, scales: { y: { beginAtZero: true, title: { display: true, text: 'Time (minutes)' }} } } }); } // --- RENDER FUNCTIONS --- function render() { renderCohortDashboard(); renderLearnerList(); renderLearnerDetails(selectedLearnerId); updateNavButtons(); } function renderCohortDashboard() { const totalLearners = learners.length; const allModules = learners.flatMap(l => l.modules); const completedModules = allModules.filter(m => m.status === 'Completed'); const totalProgress = allModules.length > 0 ? (completedModules.length / allModules.length) * 100 : 0; const totalTime = allModules.reduce((sum, m) => sum + m.timeSpent, 0); const avgTime = totalLearners > 0 ? totalTime / totalLearners : 0; const scoredModules = allModules.filter(m => m.score !== null); const avgScore = scoredModules.length > 0 ? scoredModules.reduce((sum, m) => sum + m.score, 0) / scoredModules.length : 0; document.getElementById('cohort-total-learners').textContent = totalLearners; document.getElementById('cohort-avg-progress').textContent = `${totalProgress.toFixed(0)}%`; document.getElementById('cohort-avg-score').textContent = avgScore.toFixed(0); document.getElementById('cohort-avg-time').textContent = `${avgTime.toFixed(0)}m`; // Update charts const masteryCounts = allModules.reduce((acc, m) => { acc[m.mastery] = (acc[m.mastery] || 0) + 1; return acc; }, {}); masteryChart.data = { labels: Object.keys(masteryCounts), datasets: [{ data: Object.values(masteryCounts), backgroundColor: ['#dc3545', '#ffc107', '#28a745'] }] }; masteryChart.update(); const timePerModule = moduleNames.map(name => { const relevantModules = allModules.filter(m => m.name === name && m.timeSpent > 0); return relevantModules.length > 0 ? relevantModules.reduce((sum, m) => sum + m.timeSpent, 0) / relevantModules.length : 0; }); timeChart.data = { labels: moduleNames, datasets: [{ label: 'Avg. Time (minutes)', data: timePerModule, backgroundColor: '#007bff' }] }; timeChart.update(); } function renderLearnerList() { learnerListEl.innerHTML = ''; learners.forEach(learner => { const li = document.createElement('li'); li.textContent = learner.name; li.dataset.learnerId = learner.id; if (learner.id === selectedLearnerId) { li.classList.add('active'); } learnerListEl.appendChild(li); }); } function renderLearnerDetails(learnerId) { if (!learnerId) { learnerDetailsSection.innerHTML = `
    Select a learner to see their details.
    `; return; } const learner = learners.find(l => l.id === learnerId); if (!learner) return; const tableRows = learner.modules.map(m => ` ${m.name} ${m.mastery} ${m.score !== null ? m.score : 'N/A'} ${m.timeSpent} min ${m.status} `).join(''); learnerDetailsSection.innerHTML = `

    Report for: ${learner.name}

    ${tableRows}
    ModuleMasteryScoreTime SpentStatus
    `; } // --- EVENT HANDLERS & NAVIGATION --- function attachEventListeners() { tabButtons.forEach(button => button.addEventListener('click', () => switchTab(parseInt(button.dataset.tab)))); prevBtn.addEventListener('click', () => switchTab(activeTabIndex - 1)); nextBtn.addEventListener('click', () => switchTab(activeTabIndex + 1)); learnerListEl.addEventListener('click', (e) => { if (e.target.tagName === 'LI') { selectedLearnerId = parseInt(e.target.dataset.learnerId); renderLearnerList(); // re-render list to show active state renderLearnerDetails(selectedLearnerId); } }); downloadPdfBtn.addEventListener('click', generatePdf); } function switchTab(index) { if (index < 0 || index >= tabPanes.length) return; activeTabIndex = index; tabButtons.forEach((btn, i) => btn.classList.toggle('active', i === index)); tabPanes.forEach((pane, i) => pane.classList.toggle('active', i === index)); updateNavButtons(); } function updateNavButtons() { prevBtn.disabled = activeTabIndex === 0; nextBtn.disabled = activeTabIndex === tabPanes.length - 1; } // --- PDF GENERATION --- async function generatePdf() { const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'portrait' }); doc.setFontSize(18); if (activeTabIndex === 0) { // Cohort Report doc.text("Cohort Performance Report", 14, 22); doc.addImage(masteryChart.toBase64Image(), 'PNG', 14, 40, 90, 90); doc.addImage(timeChart.toBase64Image(), 'PNG', 105, 40, 90, 90); const summaryData = [ ['Total Learners', document.getElementById('cohort-total-learners').textContent], ['Average Progress', document.getElementById('cohort-avg-progress').textContent], ['Average Score', document.getElementById('cohort-avg-score').textContent], ['Average Time Spent', document.getElementById('cohort-avg-time').textContent] ]; doc.autoTable({ startY: 140, head: [['Metric', 'Value']], body: summaryData, theme: 'striped' }); doc.save(`Cohort_Report_${new Date().toISOString().slice(0,10)}.pdf`); } else if (activeTabIndex === 1) { // Learner Report if (!selectedLearnerId) { alert("Please select a learner to generate a report."); return; } const learner = learners.find(l => l.id === selectedLearnerId); doc.text(`Performance Report for: ${learner.name}`, 14, 22); const tableData = learner.modules.map(m => [m.name, m.mastery, m.score !== null ? m.score : 'N/A', `${m.timeSpent} min`, m.status]); doc.autoTable({ startY: 30, head: [['Module', 'Mastery', 'Score', 'Time Spent', 'Status']], body: tableData }); doc.save(`Learner_Report_${learner.name.replace(' ','_')}.pdf`); } } initialize(); });
    Scroll to Top