/** * Admin Reports page * View and export user progress reports */ import { useEffect, useState, useCallback } from 'react'; import { useAuth } from '@/stores/authStore'; import { getAllUserReports, getFullUserReport, exportReportsAsCsv } from '@/lib/api/admin'; import type { UserProgressReport, FullUserReport } from '@/types/api/admin'; export function AdminReportsPage() { const { token } = useAuth(); const [reports, setReports] = useState([]); const [selectedUser, setSelectedUser] = useState(null); const [loading, setLoading] = useState(true); const [reportLoading, setReportLoading] = useState(null); const [exporting, setExporting] = useState(false); const [error, setError] = useState(null); const fetchReports = useCallback(async () => { if (!token) return; try { setLoading(true); setError(null); const data = await getAllUserReports(token); setReports(data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load reports'); } finally { setLoading(false); } }, [token]); useEffect(() => { fetchReports(); }, [fetchReports]); const fetchUserReport = async (userId: number) => { if (!token) return; try { setReportLoading(userId); setError(null); const data = await getFullUserReport(token, userId); setSelectedUser(data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load user report'); } finally { setReportLoading(null); } }; const handleExportCsv = async () => { if (!token) return; try { setExporting(true); setError(null); const { csvContent } = await exportReportsAsCsv(token); // Download CSV file const blob = new Blob([csvContent], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `user-reports-${new Date().toISOString().split('T')[0]}.csv`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to export reports'); } finally { setExporting(false); } }; const formatDate = (dateString: string): string => { const date = new Date(dateString); return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', }); }; const calculateAverageScore = (score: number): string => { return score > 0 ? score.toFixed(1) : 'N/A'; }; if (loading) { return (

Loading reports...

); } return (

User Progress Reports

View and export progress reports for all users

{error && (
{error}
)}
{/* Reports Summary Table */}

All User Reports

{reports.length === 0 ? ( ) : ( reports.map((report) => ( )) )}
User Email Level Lessons Completed Quizzes Completed Avg. Score Points Streak Last Activity Actions
No user reports available
{report.username} {report.email} {report.currentLevel} {report.totalLessonsCompleted} {report.totalQuizzesCompleted} {calculateAverageScore(report.averageQuizScore)} {report.totalPoints} {report.currentStreak} {formatDate(report.lastActivityDate)}
{/* User Detail Modal */} {selectedUser && (
setSelectedUser(null)}>
e.stopPropagation()}>

User Progress Report

{/* User Overview */}

User Overview

Username: {selectedUser.progressReport.username}
Email: {selectedUser.progressReport.email}
Current Level: {selectedUser.progressReport.currentLevel}
Total Points: {selectedUser.progressReport.totalPoints}
Streak: {selectedUser.progressReport.currentStreak} days
Avg. Quiz Score: {calculateAverageScore(selectedUser.progressReport.averageQuizScore)}%
{/* Progress Summary */}

Progress Summary

Lessons Completed

{selectedUser.progressReport.totalLessonsCompleted}

Quizzes Completed

{selectedUser.progressReport.totalQuizzesCompleted}

Last Activity

{formatDate(selectedUser.progressReport.lastActivityDate)}

{/* Lesson Progress */} {selectedUser.lessonProgress.length > 0 && (

Lesson Progress

{selectedUser.lessonProgress.map((lesson) => ( ))}
Lesson Level Status Completed
{lesson.lessonTitle} {lesson.levelCode} {lesson.isCompleted ? 'Completed' : 'Pending'} {lesson.completedAt ? formatDate(lesson.completedAt) : 'N/A'}
)} {/* Quiz Results */} {selectedUser.quizResults.length > 0 && (

Quiz Results

{selectedUser.quizResults.map((result) => ( ))}
Quiz Score Passing Score Status Date
{result.quizTitle} {result.score}% {result.passingScore}% {result.passed ? 'Passed' : 'Failed'} {formatDate(result.attemptDate)}
)}
)}
); }