Fixed a typo in the records
This commit is contained in:
@@ -2,9 +2,9 @@ import React from "react";
|
|||||||
import { BsClock, BsXCircle } from "react-icons/bs";
|
import { BsClock, BsXCircle } from "react-icons/bs";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { Stat, User } from "@/interfaces/user";
|
import { Stat, User } from "@/interfaces/user";
|
||||||
import { Module, Step } from "@/interfaces";
|
import { Grading, Module, Step } from "@/interfaces";
|
||||||
import ai_usage from "@/utils/ai.detection";
|
import ai_usage from "@/utils/ai.detection";
|
||||||
import { calculateBandScore } from "@/utils/score";
|
import { calculateBandScore, getGradingLabel } from "@/utils/score";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { Assignment } from "@/interfaces/results";
|
import { Assignment } from "@/interfaces/results";
|
||||||
import { uuidv4 } from "@firebase/util";
|
import { uuidv4 } from "@firebase/util";
|
||||||
@@ -15,6 +15,7 @@ import { convertToUserSolutions } from "@/utils/stats";
|
|||||||
import { getExamById } from "@/utils/exams";
|
import { getExamById } from "@/utils/exams";
|
||||||
import { Exam, UserSolution } from "@/interfaces/exam";
|
import { Exam, UserSolution } from "@/interfaces/exam";
|
||||||
import ModuleBadge from "../ModuleBadge";
|
import ModuleBadge from "../ModuleBadge";
|
||||||
|
import { findBy } from "@/utils";
|
||||||
|
|
||||||
const formatTimestamp = (timestamp: string | number) => {
|
const formatTimestamp = (timestamp: string | number) => {
|
||||||
const time = typeof timestamp === "string" ? parseInt(timestamp) : timestamp;
|
const time = typeof timestamp === "string" ? parseInt(timestamp) : timestamp;
|
||||||
@@ -70,6 +71,7 @@ const aggregateScoresByModule = (stats: Stat[]): { module: Module; total: number
|
|||||||
interface StatsGridItemProps {
|
interface StatsGridItemProps {
|
||||||
width?: string | undefined;
|
width?: string | undefined;
|
||||||
height?: string | undefined;
|
height?: string | undefined;
|
||||||
|
gradingSystems: Grading[]
|
||||||
examNumber?: number | undefined;
|
examNumber?: number | undefined;
|
||||||
stats: Stat[];
|
stats: Stat[];
|
||||||
timestamp: string | number;
|
timestamp: string | number;
|
||||||
@@ -94,6 +96,7 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
|
|||||||
timestamp,
|
timestamp,
|
||||||
user,
|
user,
|
||||||
assignments,
|
assignments,
|
||||||
|
gradingSystems,
|
||||||
users,
|
users,
|
||||||
training,
|
training,
|
||||||
selectedTrainingExams,
|
selectedTrainingExams,
|
||||||
@@ -191,9 +194,34 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const levelAverage = () =>
|
||||||
|
aggregatedLevels.reduce((accumulator, current) => accumulator + current.level, 0) / aggregatedLevels.length
|
||||||
|
|
||||||
|
const renderLevelScore = () => {
|
||||||
|
const defaultLevelScore = levelAverage().toFixed(1)
|
||||||
|
if (!stats.every(s => s.module === "level")) return defaultLevelScore
|
||||||
|
if (gradingSystems.length === 0) return defaultLevelScore
|
||||||
|
|
||||||
|
const score = {
|
||||||
|
correct: stats.reduce((acc, curr) => acc + curr.score.correct, 0),
|
||||||
|
total: stats.reduce((acc, curr) => acc + curr.score.total, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const level: number = calculateBandScore(score.correct, score.total, "level", user.focus);
|
||||||
|
|
||||||
|
if (!!assignment) {
|
||||||
|
const gradingSystem = findBy(gradingSystems, 'entity', assignment.entity)
|
||||||
|
if (!gradingSystem) return defaultLevelScore
|
||||||
|
|
||||||
|
return getGradingLabel(level, gradingSystem.steps)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getGradingLabel(level, gradingSystems[0].steps)
|
||||||
|
}
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<div className="w-full flex justify-between -md:items-center 2xl:items-center">
|
<div className="w-full flex justify-between">
|
||||||
<div className="flex flex-col md:gap-1 -md:gap-2 2xl:gap-2">
|
<div className="flex flex-col md:gap-1 -md:gap-2 2xl:gap-2">
|
||||||
<span className="font-medium">{formatTimestamp(timestamp)}</span>
|
<span className="font-medium">{formatTimestamp(timestamp)}</span>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -211,12 +239,10 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex flex-row gap-2">
|
<div className="flex flex-row gap-2">
|
||||||
{!!assignment && (assignment.released || assignment.released === undefined) && (
|
{((!!assignment && (assignment.released || assignment.released === undefined)) || !assignment) && (
|
||||||
<span className={textColor}>
|
<span className={textColor}>
|
||||||
Level{" "}
|
Level{' '}
|
||||||
{(
|
{renderLevelScore()}
|
||||||
aggregatedLevels.reduce((accumulator, current) => accumulator + current.level, 0) / aggregatedLevels.length
|
|
||||||
).toFixed(1)}
|
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{shouldRenderPDFIcon() && renderPdfIcon(session, textColor, textColor)}
|
{shouldRenderPDFIcon() && renderPdfIcon(session, textColor, textColor)}
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import { User } from "@/interfaces/user";
|
|||||||
import useExamStore from "@/stores/examStore";
|
import useExamStore from "@/stores/examStore";
|
||||||
import { calculateBandScore, getGradingLabel } from "@/utils/score";
|
import { calculateBandScore, getGradingLabel } from "@/utils/score";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { Fragment, useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
BsArrowCounterclockwise,
|
BsArrowCounterclockwise,
|
||||||
BsBan,
|
BsBan,
|
||||||
@@ -19,10 +18,7 @@ import {
|
|||||||
BsHeadphones,
|
BsHeadphones,
|
||||||
BsMegaphone,
|
BsMegaphone,
|
||||||
BsPen,
|
BsPen,
|
||||||
BsShareFill,
|
|
||||||
} from "react-icons/bs";
|
} from "react-icons/bs";
|
||||||
import { LevelScore } from "@/constants/ielts";
|
|
||||||
import { getLevelScore } from "@/utils/score";
|
|
||||||
import { capitalize } from "lodash";
|
import { capitalize } from "lodash";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import { UserSolution } from "@/interfaces/exam";
|
import { UserSolution } from "@/interfaces/exam";
|
||||||
@@ -68,6 +64,7 @@ export default function Finish({ user, practiceScores, scores, modules, informat
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => setSelectedScore(scores.find((x) => x.module === selectedModule)!), [scores, selectedModule]);
|
useEffect(() => setSelectedScore(scores.find((x) => x.module === selectedModule)!), [scores, selectedModule]);
|
||||||
|
useEffect(() => setSelectedPracticeScore(practiceScores.find((x) => x.module === selectedModule)!), [practiceScores, selectedModule]);
|
||||||
|
|
||||||
const moduleColors: { [key in Module]: { progress: string; inner: string } } = {
|
const moduleColors: { [key in Module]: { progress: string; inner: string } } = {
|
||||||
reading: {
|
reading: {
|
||||||
@@ -284,7 +281,7 @@ export default function Finish({ user, practiceScores, scores, modules, informat
|
|||||||
<div className="bg-mti-green mt-1 h-3 min-h-[0.75rem] w-3 min-w-[0.75rem] rounded-full" />
|
<div className="bg-mti-green mt-1 h-3 min-h-[0.75rem] w-3 min-w-[0.75rem] rounded-full" />
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="text-mti-green">
|
<span className="text-mti-green">
|
||||||
{selectedPracticeScore.correct} / {selectedScore.total}
|
{selectedPracticeScore.correct} / {selectedPracticeScore.total}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-lg whitespace-nowrap">Practice Questions</span>
|
<span className="text-lg whitespace-nowrap">Practice Questions</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { mapBy, redirect, serialize } from "@/utils";
|
|||||||
import { getEntitiesWithRoles } from "@/utils/entities.be";
|
import { getEntitiesWithRoles } from "@/utils/entities.be";
|
||||||
import { checkAccess } from "@/utils/permissions";
|
import { checkAccess } from "@/utils/permissions";
|
||||||
import { getGroups, getGroupsByEntities } from "@/utils/groups.be";
|
import { getGroups, getGroupsByEntities } from "@/utils/groups.be";
|
||||||
import { getGradingSystemByEntity } from "@/utils/grading.be";
|
import { getGradingSystemByEntities, getGradingSystemByEntity } from "@/utils/grading.be";
|
||||||
import { Grading } from "@/interfaces";
|
import { Grading } from "@/interfaces";
|
||||||
import { EntityWithRoles } from "@/interfaces/entity";
|
import { EntityWithRoles } from "@/interfaces/entity";
|
||||||
import CardList from "@/components/High/CardList";
|
import CardList from "@/components/High/CardList";
|
||||||
@@ -44,9 +44,10 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
|||||||
const entities = await getEntitiesWithRoles(checkAccess(user, ["admin", "developer"]) ? undefined : entityIDs)
|
const entities = await getEntitiesWithRoles(checkAccess(user, ["admin", "developer"]) ? undefined : entityIDs)
|
||||||
const users = await (checkAccess(user, ["admin", "developer"]) ? getUsers() : getEntitiesUsers(mapBy(entities, 'id')))
|
const users = await (checkAccess(user, ["admin", "developer"]) ? getUsers() : getEntitiesUsers(mapBy(entities, 'id')))
|
||||||
const assignments = await (checkAccess(user, ["admin", "developer"]) ? getAssignments() : getEntitiesAssignments(mapBy(entities, 'id')))
|
const assignments = await (checkAccess(user, ["admin", "developer"]) ? getAssignments() : getEntitiesAssignments(mapBy(entities, 'id')))
|
||||||
|
const gradingSystems = await getGradingSystemByEntities(mapBy(entities, 'id'))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: serialize({ user, users, assignments, entities }),
|
props: serialize({ user, users, assignments, entities, gradingSystems }),
|
||||||
};
|
};
|
||||||
}, sessionOptions);
|
}, sessionOptions);
|
||||||
|
|
||||||
@@ -57,11 +58,12 @@ interface Props {
|
|||||||
users: User[];
|
users: User[];
|
||||||
assignments: Assignment[];
|
assignments: Assignment[];
|
||||||
entities: EntityWithRoles[]
|
entities: EntityWithRoles[]
|
||||||
|
gradingSystems: Grading[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_TRAINING_EXAMS = 10;
|
const MAX_TRAINING_EXAMS = 10;
|
||||||
|
|
||||||
export default function History({ user, users, assignments, entities }: Props) {
|
export default function History({ user, users, assignments, entities, gradingSystems }: Props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [statsUserId, setStatsUserId, training, setTraining] = useRecordStore((state) => [
|
const [statsUserId, setStatsUserId, training, setTraining] = useRecordStore((state) => [
|
||||||
state.selectedUser,
|
state.selectedUser,
|
||||||
@@ -165,6 +167,7 @@ export default function History({ user, users, assignments, entities }: Props) {
|
|||||||
<StatsGridItem
|
<StatsGridItem
|
||||||
key={uuidv4()}
|
key={uuidv4()}
|
||||||
stats={dateStats}
|
stats={dateStats}
|
||||||
|
gradingSystems={gradingSystems}
|
||||||
timestamp={timestamp}
|
timestamp={timestamp}
|
||||||
user={user}
|
user={user}
|
||||||
assignments={assignments}
|
assignments={assignments}
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ const TrainingContent: React.FC<{user: User}> = ({user}) => {
|
|||||||
{trainingContent.exams.map((exam, examIndex) => (
|
{trainingContent.exams.map((exam, examIndex) => (
|
||||||
<StatsGridItem
|
<StatsGridItem
|
||||||
key={`exam-${examIndex}`}
|
key={`exam-${examIndex}`}
|
||||||
|
gradingSystems={[]}
|
||||||
width="380px"
|
width="380px"
|
||||||
height="150px"
|
height="150px"
|
||||||
examNumber={examIndex + 1}
|
examNumber={examIndex + 1}
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ export const convertToUserSolutions = (stats: Stat[]): UserSolution[] => {
|
|||||||
solutions: stat.solutions,
|
solutions: stat.solutions,
|
||||||
type: stat.type,
|
type: stat.type,
|
||||||
module: stat.module,
|
module: stat.module,
|
||||||
shuffleMaps: stat.shuffleMaps
|
shuffleMaps: stat.shuffleMaps,
|
||||||
|
isPractice: stat.isPractice
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user