Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions class_manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// class_manager.js – Handles teacher class sessions and progress aggregation

const CLASS_SESSIONS_KEY = 'learnsphere_class_sessions_v1';

function _loadClasses() {
try {
const raw = localStorage.getItem(CLASS_SESSIONS_KEY);
return raw ? JSON.parse(raw) : [];
} catch (e) {
console.warn('LearnSphere: Failed to load class sessions', e);
return [];
}
}

function _saveClasses(classes) {
try {
localStorage.setItem(CLASS_SESSIONS_KEY, JSON.stringify(classes));
} catch (e) {
console.warn('LearnSphere: Failed to save class sessions', e);
}
}

function generateInviteCode(length = 6) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < length; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
return code;
}

function createClassSession({ name, topics = [], dueDate }) {
const classes = _loadClasses();
const id = 'cls_' + Date.now();
const inviteCode = generateInviteCode();
const newClass = {
id,
name,
inviteCode,
topics,
dueDate: dueDate || null,
attempts: [], // each { studentId, quizId, score }
createdAt: new Date().toISOString()
};
classes.push(newClass);
_saveClasses(classes);
return newClass;
}

function recordClassAttempt(classId, { studentId = 'anonymous', quizId, score }) {
if (!classId) return;
const classes = _loadClasses();
const cls = classes.find(c => c.id === classId);
if (!cls) return;
cls.attempts.push({ studentId, quizId, score, timestamp: Date.now() });
_saveClasses(classes);
}

function getClassStats(classId) {
const classes = _loadClasses();
const cls = classes.find(c => c.id === classId);
if (!cls) return null;
const total = cls.attempts.length;
const avgScore = total ? (cls.attempts.reduce((a, b) => a + b.score, 0) / total).toFixed(2) : '-';
const bestScore = total ? Math.max(...cls.attempts.map(a => a.score)).toFixed(2) : '-';
return { ...cls, totalAttempts: total, avgScore, bestScore };
}

function getAllClassStats() {
const classes = _loadClasses();
return classes.map(c => {
const total = c.attempts.length;
const avgScore = total ? (c.attempts.reduce((a, b) => a + b.score, 0) / total).toFixed(2) : '-';
const bestScore = total ? Math.max(...c.attempts.map(a => a.score)).toFixed(2) : '-';
return { id: c.id, name: c.name, inviteCode: c.inviteCode, totalAttempts: total, avgScore, bestScore };
});
}

// Expose globally for other modules
window.classManager = {
createClassSession,
recordClassAttempt,
getClassStats,
getAllClassStats
};
2 changes: 2 additions & 0 deletions teachers.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ <h1>Empowering Teachers</h1>
</div>
<div class="hero-image">
<img src="images/teacher.jpeg" alt="Teacher guiding students">
<button id="createClassBtn" style="margin-top:12px;background:var(--accent-color);color:#fff;padding:10px 16px;border:none;border-radius:8px;cursor:pointer;box-shadow:0 4px 12px rgba(0,0,0,0.2);transition:transform 0.2s;" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">Create Class</button>
<div id="leaderboardContainer" style="margin-top:24px;"></div>
</div>
</section>

Expand Down
Loading