/* eslint-disable @next/next/no-img-element */ import Head from "next/head"; import {withIronSessionSsr} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {User} from "@/interfaces/user"; import {ToastContainer} from "react-toastify"; import Layout from "@/components/High/Layout"; import {shouldRedirectHome} from "@/utils/navigation.disabled"; import {useEffect, useState} from "react"; import clsx from "clsx"; import {FaPlus} from "react-icons/fa"; import useRecordStore from "@/stores/recordStore"; import router from "next/router"; import useTrainingContentStore from "@/stores/trainingContentStore"; import axios from "axios"; import {ITrainingContent} from "@/training/TrainingInterfaces"; import moment from "moment"; import {uuidv4} from "@firebase/util"; import TrainingScore from "@/training/TrainingScore"; import ModuleBadge from "@/components/ModuleBadge"; import RecordFilter from "@/components/Medium/RecordFilter"; import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser"; import { mapBy, redirect, serialize } from "@/utils"; import { getEntitiesWithRoles } from "@/utils/entities.be"; import { getAssignmentsByAssignee } from "@/utils/assignments.be"; import { getEntitiesUsers } from "@/utils/users.be"; import { EntityWithRoles } from "@/interfaces/entity"; import { Assignment } from "@/interfaces/results"; import { requestUser } from "@/utils/api"; export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { const user = await requestUser(req, res) if (!user) return redirect("/login") if (shouldRedirectHome(user)) return redirect("/") const entityIDs = mapBy(user.entities, 'id') const entities = await getEntitiesWithRoles(entityIDs) const users = await getEntitiesUsers(entityIDs) return { props: serialize({user, users, entities}), }; }, sessionOptions); const Training: React.FC<{user: User, entities: EntityWithRoles[], users: User[] }> = ({user, entities, users}) => { const [recordUserId, setRecordTraining] = useRecordStore((state) => [state.selectedUser, state.setTraining]); const [filter, setFilter] = useState<"months" | "weeks" | "days" | "assignments">(); const [stats, setTrainingStats] = useTrainingContentStore((state) => [state.stats, state.setStats]); const [isNewContentLoading, setIsNewContentLoading] = useState(stats.length != 0); const [groupedByTrainingContent, setGroupedByTrainingContent] = useState<{[key: string]: ITrainingContent}>(); const {data: trainingContent, isLoading: areRecordsLoading} = useFilterRecordsByUser( recordUserId || user?.id, undefined, "training", ); useEffect(() => { const handleRouteChange = (url: string) => { setTrainingStats([]); }; router.events.on("routeChangeStart", handleRouteChange); return () => { router.events.off("routeChangeStart", handleRouteChange); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [router.events, setTrainingStats]); useEffect(() => { const postStats = async () => { try { const response = await axios.post<{id: string}>(`/api/training`, {userID: user.id, stats: stats}); return response.data.id; } catch (error) { setIsNewContentLoading(false); } }; if (isNewContentLoading) { postStats().then((id) => { setTrainingStats([]); if (id) { router.push(`/training/${id}`); } }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isNewContentLoading]); const handleNewTrainingContent = () => { setRecordTraining(true); router.push("/record"); }; const filterTrainingContentByDate = (trainingContent: {[key: string]: ITrainingContent}) => { if (filter) { const filterDate = moment() .subtract({[filter as string]: 1}) .format("x"); const filteredTrainingContent: {[key: string]: ITrainingContent} = {}; Object.keys(trainingContent).forEach((timestamp) => { if (timestamp >= filterDate) filteredTrainingContent[timestamp] = trainingContent[timestamp]; }); return filteredTrainingContent; } return trainingContent; }; useEffect(() => { if (trainingContent.length > 0) { const grouped = trainingContent.reduce((acc, content) => { acc[content.created_at] = content; return acc; }, {} as {[key: number]: ITrainingContent}); setGroupedByTrainingContent(grouped); } else { setGroupedByTrainingContent(undefined); } }, [trainingContent]); const formatTimestamp = (timestamp: string) => { const date = moment(parseInt(timestamp)); const formatter = "YYYY/MM/DD - HH:mm"; return date.format(formatter); }; const selectTrainingContent = (trainingContent: ITrainingContent) => { router.push(`/training/${trainingContent.id}`); }; const trainingContentContainer = (timestamp: string) => { if (!groupedByTrainingContent) return <>; const trainingContent: ITrainingContent = groupedByTrainingContent[timestamp]; const uniqueModules = [...new Set(trainingContent.exams.map((exam) => exam.module))]; return ( <>
selectTrainingContent(trainingContent)} role="button">
{formatTimestamp(timestamp)}
{uniqueModules.map((module) => ( ))}
); }; return ( <> Training | EnCoach {isNewContentLoading || areRecordsLoading ? (
{isNewContentLoading && ( Assessing your exams, please be patient... )}
) : ( <> {user.type === "student" && ( <>
Generate New Training Material
)}
{trainingContent.length == 0 && (
No training content to display...
)} {!areRecordsLoading && groupedByTrainingContent && Object.keys(groupedByTrainingContent).length > 0 && (
{Object.keys(filterTrainingContentByDate(groupedByTrainingContent)) .sort((a, b) => parseInt(b) - parseInt(a)) .map(trainingContentContainer)}
)} )}
); }; export default Training;