Comprehensive view of all assessments, submissions, and certificates.
Show code
Auth =newPromise((resolve, reject) => {const authIsReady = () =>window.__authReady&&typeofwindow.Auth?.getCurrentUser==='function';if (authIsReady()) {resolve(window.Auth);return; }const timeoutMs =10000;const timer =setTimeout(() => {window.removeEventListener('auth:ready', onAuthReady);reject(newError('Sign-in system failed to load. Please refresh the page.')); }, timeoutMs);functiononAuthReady() {clearTimeout(timer);window.removeEventListener('auth:ready', onAuthReady);if (authIsReady()) {resolve(window.Auth); } else {reject(newError('Sign-in system failed to load. Please refresh the page.')); } }window.addEventListener('auth:ready', onAuthReady);})IoTClassAPI =window.IoTClassAPI|| {};// Colorscolors = ({navy:'#2C3E50',teal:'#16A085',gray:'#7F8C8D',green:'#27AE60',orange:'#E67E22',red:'#E74C3C'})// Check authentication and admin statuscurrentUser = {const user = Auth.getCurrentUser();if (!user) returnnull;// B8: the admin role is a database fact -- public.is_admin(), backed by the// user_roles table and evaluated by the same RLS policies that guard every// query below. Auth.isUserAdmin() only string-matches the adminUsers list// that ships in public JavaScript, so it is not a control.const isAdmin =window.IoTClassSupabase?.isAdminServerSide?awaitwindow.IoTClassSupabase.isAdminServerSide():false;return { ...user, isAdmin };}// Load quiz results via SupabaseallQuizResults = {if (!currentUser ||!currentUser.isAdmin) returnnull;try {const results =await IoTClassAPI.Admin.getAllQuizResults();// Map Supabase field names for compatibilityreturn results.map(r => ({...r,username: r.users?.username||'Unknown',quizId: r.quiz_id,chapterId: r.chapter_path,totalQuestions: r.max_score,passed: r.percentage>=80,attemptNumber: r.attempt_number,maxAttempts:3,completedDate: r.created_at })); } catch (error) {console.error('Error loading quiz results:', error);return []; }}// Load lab submissions via SupabaseallLabSubmissions = {if (!currentUser ||!currentUser.isAdmin) returnnull;try {const submissions =await IoTClassAPI.Admin.getAllLabSubmissions();// Map Supabase field names for compatibilityreturn submissions.map(s => ({...s,username: s.users?.username||'Unknown',labTitle: s.lab_title,labType: s.lab_type,submissionUrl: s.submission_url,submittedDate: s.submitted_at })); } catch (error) {console.error('Error loading lab submissions:', error);return []; }}// Load certificates via SupabaseallCertificates = {if (!currentUser ||!currentUser.isAdmin) returnnull;try {const certificates =await IoTClassAPI.Admin.getAllCertificates();// Map Supabase field names for compatibilityreturn certificates.map(c => ({...c,username: c.users?.username||'Unknown',certificateId: c.certificate_id,achievementName: c.achievement_name,issuedDate: c.issued_at })); } catch (error) {console.error('Error loading certificates:', error);return []; }}// Calculate statisticsassessmentStats = {if (!allQuizResults ||!allLabSubmissions ||!allCertificates) returnnull;// Quiz statsconst totalQuizAttempts = allQuizResults.length;const passedQuizzes = allQuizResults.filter(r => r.passed).length;const avgQuizScore = totalQuizAttempts >0?Math.round(allQuizResults.reduce((sum, r) => sum + (r.percentage||0),0) / totalQuizAttempts):0;// Lab statsconst totalLabSubmissions = allLabSubmissions.length;const pendingLabs = allLabSubmissions.filter(s => s.status==='pending').length;const gradedLabs = allLabSubmissions.filter(s => s.status==='graded').length;// Certificate statsconst totalCertificates = allCertificates.length;const certificatesByType = {}; allCertificates.forEach(cert => { certificatesByType[cert.type] = (certificatesByType[cert.type] ||0) +1; });return { totalQuizAttempts, passedQuizzes, avgQuizScore, totalLabSubmissions, pendingLabs, gradedLabs, totalCertificates, certificatesByType };}// Active tabviewState = ({ activeTab:'quizzes' })
Show code
// Render access denied if not adminhtml`${!Auth.isUserAuthenticated() ||!currentUser?.isAdmin?` <div class="access-denied"> <div style="font-size: 72px; margin-bottom: 20px;">🔒</div> <h2 style="color: ${colors.navy}; margin-bottom: 16px;">Access Denied</h2> <p style="color: ${colors.gray};"> You must be an administrator to access this page. </p> </div>`:''}`
Future Features (Coming Soon): - Auto-grading for specific lab criteria - Bulk certificate generation - Detailed analytics and reports - Export to CSV/Excel