/* eslint-disable @next/next/no-img-element */ import Head from "next/head"; import {BsFileEarmarkText, BsPencil, BsStar} from "react-icons/bs"; import {LinearScale, Chart as ChartJS, CategoryScale, PointElement, LineElement, Legend, Tooltip, LineController} from "chart.js"; import {withIronSessionSsr} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {useEffect, useState} from "react"; import useStats from "@/hooks/useStats"; import {averageScore, totalExamsByModule, groupBySession, groupByModule} from "@/utils/stats"; import useUser from "@/hooks/useUser"; import {ToastContainer} from "react-toastify"; import {capitalize} from "lodash"; import {Module} from "@/interfaces"; import ProgressBar from "@/components/Low/ProgressBar"; import Layout from "@/components/High/Layout"; import {calculateAverageLevel, calculateBandScore} from "@/utils/score"; import {MODULE_ARRAY} from "@/utils/moduleUtils"; import {Chart} from "react-chartjs-2"; import useUsers from "@/hooks/useUsers"; import Select from "react-select"; import useGroups from "@/hooks/useGroups"; import DatePicker from "react-datepicker"; import {shouldRedirectHome} from "@/utils/navigation.disabled"; import ProfileSummary from "@/components/ProfileSummary"; ChartJS.register(LinearScale, CategoryScale, PointElement, LineElement, LineController, Legend, Tooltip); const COLORS = ["#1EB3FF", "#FF790A", "#3D9F11", "#EF5DA8"]; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; if (!user || !user.isVerified) { res.setHeader("location", "/login"); res.statusCode = 302; res.end(); return { props: { user: null, }, }; } if (shouldRedirectHome(user)) { res.setHeader("location", "/"); res.statusCode = 302; res.end(); return { props: { user: null, }, }; } return { props: {user: req.session.user}, }; }, sessionOptions); export default function Stats() { const [statsUserId, setStatsUserId] = useState(); const [startDate, setStartDate] = useState(null); const [endDate, setEndDate] = useState(new Date()); const {user} = useUser({redirectTo: "/login"}); const {users} = useUsers(); const {groups} = useGroups(user?.id); const {stats} = useStats(statsUserId); const {stats: userStats} = useStats(user?.id); useEffect(() => { if (user) setStatsUserId(user.id); }, [user]); // useEffect(() => { // if (stats && stats.length > 0) { // const sortedStats = stats.sort((a, b) => a.date - b.date); // const firstStat = sortedStats.shift()!; // setStartDate(moment.unix(firstStat.date).toDate()); // console.log(stats.filter((x) => moment.unix(x.date).isAfter(startDate))); // console.log(stats.filter((x) => moment.unix(x.date).isBefore(endDate))); // } // }, [stats]); const calculateTotalScorePerSession = () => { const groupedBySession = groupBySession(stats); const sessionAverage = Object.keys(groupedBySession).map((x: string) => { const session = groupedBySession[x]; const moduleStats = groupByModule(session); const moduleScores = Object.keys(moduleStats).map((y) => { const correct = moduleStats[y].reduce((accumulator, current) => accumulator + current.score.correct, 0); const total = moduleStats[y].reduce((accumulator, current) => accumulator + current.score.total, 0); return { module: y, score: calculateBandScore(correct, total, y as Module, user?.focus || "academic"), }; }); return moduleScores.reduce((acc, curr) => acc + curr.score, 0) / 4; }); return sessionAverage; }; const calculateAverageTimePerModule = () => { const groupedBySession = groupBySession(stats.filter((x) => !!x.timeSpent)); const sessionAverage = Object.keys(groupedBySession).map((x: string) => { const session = groupedBySession[x]; const timeSpent = session[0].timeSpent!; return Math.floor(timeSpent / session.length / 60); }); return sessionAverage; }; const calculateModularScorePerSession = (module: Module) => { const groupedBySession = groupBySession(stats); const sessionAverage = Object.keys(groupedBySession).map((x: string) => { const session = groupedBySession[x]; const moduleStats = groupByModule(session); if (!Object.keys(moduleStats).includes(module)) return null; const correct = moduleStats[module].reduce((acc, curr) => acc + curr.score.correct, 0); const total = moduleStats[module].reduce((acc, curr) => acc + curr.score.total, 0); return calculateBandScore(correct, total, module, user?.focus || "academic"); }); return sessionAverage; }; return ( <> Stats | EnCoach {user && ( , value: Object.keys(groupBySession(userStats)).length, label: "Exams", }, { icon: , value: userStats.length, label: "Exercises", }, { icon: , value: `${stats.length > 0 ? averageScore(userStats) : 0}%`, label: "Average Score", }, ]} />
<> {(user.type === "developer" || user.type === "admin") && ( groups.flatMap((y) => y.participants).includes(x.id)) .map((x) => ({value: x.id, label: `${x.name} - ${x.email}`}))} defaultValue={{value: user.id, label: `${user.name} - ${user.email}`}} onChange={(value) => setStatsUserId(value?.value)} styles={{ option: (styles, state) => ({ ...styles, backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white", color: state.isFocused ? "black" : styles.color, }), }} /> )} {/* !moment(date).isSameOrBefore(moment(startDate))} onChange={([initialDate, finalDate]) => { setStartDate(initialDate); setEndDate(finalDate); }} /> */}
{stats.length > 0 && (
{/* Exams per module */}
Exams per Module
{MODULE_ARRAY.map((module) => (
{totalExamsByModule(stats, module)} of{" "} {Object.keys(groupBySession(stats)).length} {capitalize(module)}
))}
{/* Module Score */}
Module Score Bands
{MODULE_ARRAY.map((module) => (
{user.levels[module]} of{" "} {user.desiredLevels[module]} {capitalize(module)}
))}
{/* Total Score Band per Session */}
Total Score Band per Session index), datasets: [ { type: "line", label: "Total", fill: false, borderColor: "#6A5FB1", backgroundColor: "#7872BF", borderWidth: 2, spanGaps: true, data: calculateTotalScorePerSession(), }, ], }} />
{/* Module Score Band per Session */}
Module Score Band per Session index), datasets: [ ...MODULE_ARRAY.map((module, index) => ({ type: "line" as const, label: capitalize(module), borderColor: COLORS[index], backgroundColor: COLORS[index], borderWidth: 2, data: calculateModularScorePerSession(module), })), ], }} />
{/* Average Time per Module */}
Average Time per Module (in Minutes) !!s.timeSpent))).map((_, index) => index), datasets: [ { type: "line", label: "Average (in minutes)", fill: false, borderColor: "#6A5FB1", backgroundColor: "#7872BF", borderWidth: 2, spanGaps: true, data: calculateAverageTimePerModule(), }, ], }} />
)}
{stats.length === 0 && (
No stats to display...
)}
)} ); }