diff --git a/src/dashboards/MasterStatistical.tsx b/src/dashboards/MasterStatistical.tsx index 944b0972..d693ef0d 100644 --- a/src/dashboards/MasterStatistical.tsx +++ b/src/dashboards/MasterStatistical.tsx @@ -18,6 +18,7 @@ import Checkbox from "@/components/Low/Checkbox"; import { useListSearch } from "@/hooks/useListSearch"; import axios from "axios"; import { toast } from "react-toastify"; +import Button from "@/components/Low/Button"; interface Props { corporateUsers: User[]; users: User[]; @@ -207,10 +208,11 @@ const MasterStatistical = (props: Props) => { }), ]; - const { rows: filteredRows, renderSearch, text: searchText } = useListSearch( - searchFilters, - tableResults - ); + const { + rows: filteredRows, + renderSearch, + text: searchText, + } = useListSearch(searchFilters, tableResults); const table = useReactTable({ data: filteredRows, @@ -240,7 +242,6 @@ const MasterStatistical = (props: Props) => { ); }; - const triggerDownload = async () => { try { setDownloading(true); @@ -267,28 +268,9 @@ const MasterStatistical = (props: Props) => { } }; - const renderIcon = () => { - if (downloading) { - return ( - - ); - } - - return ( - { - e.stopPropagation(); - triggerDownload(); - }} - /> - ); - }; - const consolidateResults = getStudentsConsolidateScore(); return ( <> - {renderIcon()}
{ />
{renderSearch()} +
+ +
diff --git a/src/pages/api/assignments/statistical/excel.ts b/src/pages/api/assignments/statistical/excel.ts index 54c8153e..ce4ebac0 100644 --- a/src/pages/api/assignments/statistical/excel.ts +++ b/src/pages/api/assignments/statistical/excel.ts @@ -11,7 +11,11 @@ import { getSpecificUsers } from "@/utils/users.be"; import { checkAccess } from "@/utils/permissions"; import { getAssignmentsForCorporates } from "@/utils/assignments.be"; import { search } from "@/utils/search"; - +import { getGradingSystem } from "@/utils/grading.be"; +import { Exam } from "@/interfaces/exam"; +import { User } from "@/interfaces/user"; +import { calculateBandScore, getGradingLabel } from "@/utils/score"; +import { Module } from "@/interfaces"; const db = getFirestore(app); export default withIronSessionApiRoute(handler, sessionOptions); @@ -25,6 +29,7 @@ interface TableData { date: moment.Moment; assignment: string; corporateId: string; + level: string; } async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -59,7 +64,42 @@ async function post(req: NextApiRequest, res: NextApiResponse) { const assignmentUsers = [ ...new Set(assignments.flatMap((a) => a.assignees)), ]; + const assigners = [...new Set(assignments.map((a) => a.assigner))]; const users = await getSpecificUsers(assignmentUsers); + const assignerUsers = await getSpecificUsers(assigners); + + const assignerUsersGradingSystems = await Promise.all( + assignerUsers.map(async (user: User) => { + const data = await getGradingSystem(user); + // in this context I need to override as I'll have to match to the assigner + return { ...data, user: user.id }; + }) + ); + + const getGradingSystemHelper = ( + exams: {id: string; module: Module; assignee: string}[], + assigner: string, + user: User, + correct: number, + total: number + ) => { + if (exams.some((e) => e.module === "level")) { + const gradingSystem = assignerUsersGradingSystems.find( + (gs) => gs.user === assigner + ); + if (gradingSystem) { + const bandScore = calculateBandScore( + correct, + total, + "level", + user.focus + ); + return getGradingLabel(bandScore, gradingSystem?.steps || []); + } + } + + return "N/A"; + }; const tableResults = assignments.reduce( (accmA: TableData[], a: AssignmentWithCorporateId) => { @@ -67,14 +107,25 @@ async function post(req: NextApiRequest, res: NextApiResponse) { const userStats = a.results.find((r) => r.user === assignee)?.stats || []; const userData = users.find((u) => u.id === assignee); - const corporate = users.find((u) => u.id === a.assigner)?.name || ""; + const corporateUser = users.find((u) => u.id === a.assigner); + const correct = userStats.reduce((n, e) => n + e.score.correct, 0); + const total = userStats.reduce((n, e) => n + e.score.total, 0); + const level = getGradingSystemHelper( + a.exams, + a.assigner, + userData!, + correct, + total + ); + console.log("Level", level); const commonData = { user: userData?.name || "", email: userData?.email || "", userId: assignee, corporateId: a.corporateId, - corporate, + corporate: corporateUser?.name || "", assignment: a.name, + level, }; if (userStats.length === 0) { return { @@ -87,7 +138,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) { return { ...commonData, - correct: userStats.reduce((n, e) => n + e.score.correct, 0), + correct, submitted: true, date: moment.max(userStats.map((e) => moment(e.date))), }; @@ -129,11 +180,17 @@ async function post(req: NextApiRequest, res: NextApiResponse) { }, { label: "Date", - value: (entry: TableData) => entry.date?.format("YYYY/MM/DD") || '', + value: (entry: TableData) => entry.date?.format("YYYY/MM/DD") || "", }, + { + label: "Level", + value: (entry: TableData) => entry.level, + } ]; - const filteredSearch = searchText ? search(searchText, searchFilters, tableResults) : tableResults; + const filteredSearch = searchText + ? search(searchText, searchFilters, tableResults) + : tableResults; worksheet.addRow(headers.map((h) => h.label)); (filteredSearch as TableData[]).forEach((entry) => { diff --git a/src/pages/api/grading/index.ts b/src/pages/api/grading/index.ts index 6beb7e24..bc829e00 100644 --- a/src/pages/api/grading/index.ts +++ b/src/pages/api/grading/index.ts @@ -15,6 +15,7 @@ import {Grading} from "@/interfaces"; import {getGroupsForUser} from "@/utils/groups.be"; import {uniq} from "lodash"; import {getUser} from "@/utils/users.be"; +import { getGradingSystem } from "@/utils/grading.be"; const db = getFirestore(app); @@ -31,19 +32,8 @@ async function get(req: NextApiRequest, res: NextApiResponse) { return; } - const snapshot = await getDoc(doc(db, "grading", req.session.user.id)); - if (snapshot.exists()) return res.status(200).json(snapshot.data()); - - if (req.session.user.type !== "teacher" && req.session.user.type !== "student") - return res.status(200).json({steps: CEFR_STEPS, user: req.session.user.id}); - - const corporate = await getUserCorporate(req.session.user.id); - if (!corporate) return res.status(200).json(CEFR_STEPS); - - const corporateSnapshot = await getDoc(doc(db, "grading", corporate.id)); - if (corporateSnapshot.exists()) return res.status(200).json(snapshot.data()); - - return res.status(200).json({steps: CEFR_STEPS, user: req.session.user.id}); + const gradingSystem = await getGradingSystem(req.session.user); + return res.status(200).json(gradingSystem); } async function post(req: NextApiRequest, res: NextApiResponse) { diff --git a/src/utils/grading.be.ts b/src/utils/grading.be.ts new file mode 100644 index 00000000..d934f839 --- /dev/null +++ b/src/utils/grading.be.ts @@ -0,0 +1,23 @@ +import { app } from "@/firebase"; +import { getFirestore, doc, getDoc } from "firebase/firestore"; +import { CEFR_STEPS } from "@/resources/grading"; +import { getUserCorporate } from "@/utils/groups.be"; +import { User } from "@/interfaces/user"; +import { Grading } from "@/interfaces"; +const db = getFirestore(app); + +export const getGradingSystem = async (user: User): Promise => { + const snapshot = await getDoc(doc(db, "grading", user.id)); + if (snapshot.exists()) return snapshot.data() as Grading; + + if (user.type !== "teacher" && user.type !== "student") + return { steps: CEFR_STEPS, user: user.id }; + + const corporate = await getUserCorporate(user.id); + if (!corporate) return { steps: CEFR_STEPS, user: user.id }; + + const corporateSnapshot = await getDoc(doc(db, "grading", corporate.id)); + if (corporateSnapshot.exists()) return corporateSnapshot.data() as Grading; + + return { steps: CEFR_STEPS, user: user.id }; +};