Updated Master Statistical
This commit is contained in:
@@ -625,7 +625,8 @@ export default function MasterCorporateDashboard({user}: Props) {
|
||||
<h2 className="text-2xl font-semibold">Master Statistical</h2>
|
||||
</div>
|
||||
<MasterStatistical
|
||||
users={masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
|
||||
users={users}
|
||||
corporateUsers={masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
|
||||
const user = users.find((u) => u.id === id) as CorporateUser;
|
||||
if (user) return [...accm, user];
|
||||
return accm;
|
||||
@@ -694,13 +695,13 @@ export default function MasterCorporateDashboard({user}: Props) {
|
||||
color="purple"
|
||||
onClick={() => setPage("studentsPerformance")}
|
||||
/>
|
||||
{/* <IconCard
|
||||
<IconCard
|
||||
Icon={BsDatabase}
|
||||
label="Master Statistical"
|
||||
// value={masterCorporateUserGroups.length}
|
||||
color="purple"
|
||||
onClick={() => setPage("statistical")}
|
||||
/> */}
|
||||
/>
|
||||
<button
|
||||
disabled={isAssignmentsLoading}
|
||||
onClick={() => setPage("assignments")}
|
||||
|
||||
@@ -1,22 +1,70 @@
|
||||
import React from "react";
|
||||
import {CorporateUser} from "@/interfaces/user";
|
||||
import { CorporateUser, User } from "@/interfaces/user";
|
||||
import { BsBank, BsPersonFill } from "react-icons/bs";
|
||||
import IconCard from "./IconCard";
|
||||
import useAssignmentsCorporates from "@/hooks/useAssignmentCorporates";
|
||||
import ReactDatePicker from "react-datepicker";
|
||||
import moment from "moment";
|
||||
import { groupBySession } from "@/utils/stats";
|
||||
import { Assignment, AssignmentResult } from "@/interfaces/results";
|
||||
|
||||
interface Props {
|
||||
users: CorporateUser[];
|
||||
corporateUsers: CorporateUser[];
|
||||
users: User[];
|
||||
}
|
||||
|
||||
interface TableData {
|
||||
user: string;
|
||||
correct: number;
|
||||
corporate: string;
|
||||
submitted: boolean;
|
||||
date: moment.Moment;
|
||||
assignment: string;
|
||||
}
|
||||
const MasterStatistical = (props: Props) => {
|
||||
const {users} = props;
|
||||
const { users, corporateUsers } = props;
|
||||
|
||||
const usersList = React.useMemo(() => users.map((x) => x.id), [users]);
|
||||
const corporates = React.useMemo(() => corporateUsers.map((x) => x.id), [corporateUsers]);
|
||||
const [startDate, setStartDate] = React.useState<Date | null>(
|
||||
moment("01/01/2023").toDate()
|
||||
);
|
||||
const [endDate, setEndDate] = React.useState<Date | null>(
|
||||
moment().endOf("year").toDate()
|
||||
);
|
||||
|
||||
const {assignments} = useAssignmentsCorporates({corporates: usersList});
|
||||
const { assignments } = useAssignmentsCorporates({
|
||||
corporates,
|
||||
startDate,
|
||||
endDate,
|
||||
});
|
||||
|
||||
|
||||
const x = assignments.reduce((accmA: TableData[], a: Assignment) => {
|
||||
const userResults = a.results.reduce((accmB: TableData[], r: AssignmentResult) => {
|
||||
const userStats = groupBySession(r.stats);
|
||||
const data = Object.keys(userStats).map((key) => ({
|
||||
user: users.find((u) => u.id === r.user)?.name || "",
|
||||
correct: userStats[key].reduce((n, e) => n + e.score.correct, 0),
|
||||
corporate: users.find((u) => u.id === a.assigner)?.name || "",
|
||||
submitted: false,
|
||||
date: moment.max(userStats[key].map((e) => moment(e.date))),
|
||||
assignment: a.name,
|
||||
}));
|
||||
return [...accmB, ...data];
|
||||
}, []);
|
||||
|
||||
return [...accmA, ...userResults];
|
||||
}, []);
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2 items-center text-center">
|
||||
<IconCard Icon={BsBank} label="Consolidate" value={0} color="purple" onClick={() => console.log("clicked")} />
|
||||
{users.map((group) => (
|
||||
<IconCard
|
||||
Icon={BsBank}
|
||||
label="Consolidate"
|
||||
value={0}
|
||||
color="purple"
|
||||
onClick={() => console.log("clicked")}
|
||||
/>
|
||||
{corporateUsers.map((group) => (
|
||||
<IconCard
|
||||
key={group.id}
|
||||
Icon={BsBank}
|
||||
@@ -26,7 +74,33 @@ const MasterStatistical = (props: Props) => {
|
||||
onClick={() => console.log("clicked", group)}
|
||||
/>
|
||||
))}
|
||||
<IconCard onClick={() => console.log("clicked")} Icon={BsPersonFill} label="Consolidate Highest Student" color="purple" />
|
||||
|
||||
<ReactDatePicker
|
||||
dateFormat="dd/MM/yyyy"
|
||||
className="px-4 py-6 w-full text-sm text-center font-normal placeholder:text-mti-gray-cool disabled:bg-mti-gray-platinum/40 disabled:text-mti-gray-dim disabled:cursor-not-allowed rounded-full border border-mti-gray-platinum focus:outline-none"
|
||||
selected={startDate}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
selectsRange
|
||||
showMonthDropdown
|
||||
onChange={([initialDate, finalDate]: [Date, Date]) => {
|
||||
setStartDate(initialDate ?? moment("01/01/2023").toDate());
|
||||
if (finalDate) {
|
||||
// basicly selecting a final day works as if I'm selecting the first
|
||||
// minute of that day. this way it covers the whole day
|
||||
setEndDate(moment(finalDate).endOf("day").toDate());
|
||||
return;
|
||||
}
|
||||
setEndDate(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
<IconCard
|
||||
onClick={() => console.log("clicked")}
|
||||
Icon={BsPersonFill}
|
||||
label="Consolidate Highest Student"
|
||||
color="purple"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Assignment } from "@/interfaces/results";
|
||||
import axios from "axios";
|
||||
import moment from "moment";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function useAssignmentsCorporates({
|
||||
corporates,
|
||||
startDate,
|
||||
endDate,
|
||||
}: {
|
||||
corporates: string[];
|
||||
startDate: Date | null;
|
||||
endDate: Date | null;
|
||||
}) {
|
||||
const [assignments, setAssignments] = useState<Assignment[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -18,9 +23,15 @@ export default function useAssignmentsCorporates({
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
const urlSearchParams = new URLSearchParams({
|
||||
ids: corporates.join(","),
|
||||
...(startDate ? { startDate: startDate.toISOString() } : {}),
|
||||
...(endDate ? { endDate: endDate.toISOString() } : {}),
|
||||
});
|
||||
|
||||
axios
|
||||
.get<Assignment[]>(
|
||||
`/api/assignments/corporate?ids=${corporates.join(",")}`
|
||||
`/api/assignments/corporate?${urlSearchParams.toString()}`
|
||||
)
|
||||
.then(async (response) => {
|
||||
setAssignments(response.data);
|
||||
@@ -28,7 +39,7 @@ export default function useAssignmentsCorporates({
|
||||
.finally(() => setIsLoading(false));
|
||||
};
|
||||
|
||||
useEffect(getData, [corporates]);
|
||||
useEffect(getData, [corporates, startDate, endDate]);
|
||||
|
||||
return { assignments, isLoading, isError, reload: getData };
|
||||
}
|
||||
|
||||
@@ -10,16 +10,18 @@ interface ModuleResult {
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface AssignmentResult {
|
||||
user: string;
|
||||
type: "academic" | "general";
|
||||
stats: Stat[];
|
||||
}
|
||||
|
||||
export interface Assignment {
|
||||
id: string;
|
||||
name: string;
|
||||
assigner: string;
|
||||
assignees: string[];
|
||||
results: {
|
||||
user: string;
|
||||
type: "academic" | "general";
|
||||
stats: Stat[];
|
||||
}[];
|
||||
results: AssignmentResult[];
|
||||
exams: {id: string; module: Module; assignee: string}[];
|
||||
instructorGender?: InstructorGender;
|
||||
startDate: Date;
|
||||
|
||||
@@ -20,13 +20,16 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
async function GET(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { ids } = req.query as { ids: string };
|
||||
const { ids, startDate, endDate } = req.query as { ids: string, startDate?: string, endDate?: string };
|
||||
|
||||
const startDateParsed = startDate ? new Date(startDate) : undefined;
|
||||
const endDateParsed = endDate ? new Date(endDate) : undefined;
|
||||
try {
|
||||
const idsList = ids.split(",");
|
||||
|
||||
const assigners = await Promise.all(idsList.map(getAllAssignersByCorporate));
|
||||
const assignmentList = [...assigners.flat(), ...idsList];
|
||||
const assignments = await getAssignmentsByAssigners(assignmentList);
|
||||
const assignments = await getAssignmentsByAssigners(assignmentList, startDateParsed, endDateParsed);
|
||||
res.status(200).json(assignments);
|
||||
} catch (err: any) {
|
||||
res.status(500).json({ error: err.message });
|
||||
|
||||
@@ -1,19 +1,58 @@
|
||||
import { app } from "@/firebase";
|
||||
import { Assignment } from "@/interfaces/results";
|
||||
import {collection, getDocs, getFirestore, query, where} from "firebase/firestore";
|
||||
import {
|
||||
collection,
|
||||
getDocs,
|
||||
getFirestore,
|
||||
query,
|
||||
where,
|
||||
} from "firebase/firestore";
|
||||
|
||||
const db = getFirestore(app);
|
||||
|
||||
export const getAssignmentsByAssigner = async (id: string) => {
|
||||
const {docs} = await getDocs(query(collection(db, "assignments"), where("assigner", "==", id)));
|
||||
export const getAssignmentsByAssigner = async (
|
||||
id: string,
|
||||
startDate?: Date,
|
||||
endDate?: Date
|
||||
) => {
|
||||
const { docs } = await getDocs(
|
||||
query(
|
||||
collection(db, "assignments"),
|
||||
...[
|
||||
where("assigner", "==", id),
|
||||
...(startDate ? [where("startDate", ">=", startDate.toISOString())] : []),
|
||||
// firebase doesnt accept compound queries so we have to filter on the server
|
||||
// ...endDate ? [where("endDate", "<=", endDate)] : [],
|
||||
]
|
||||
)
|
||||
);
|
||||
if (endDate) {
|
||||
return docs
|
||||
.map((x) => ({ ...(x.data() as Assignment), id: x.id }))
|
||||
.filter((x) => new Date(x.endDate) <= endDate) as Assignment[];
|
||||
}
|
||||
return docs.map((x) => ({ ...x.data(), id: x.id })) as Assignment[];
|
||||
};
|
||||
|
||||
export const getAssignmentsByAssignerBetweenDates = async (id: string, startDate: Date, endDate: Date) => {
|
||||
const {docs} = await getDocs(query(collection(db, "assignments"), where("assigner", "==", id), ));
|
||||
export const getAssignmentsByAssignerBetweenDates = async (
|
||||
id: string,
|
||||
startDate: Date,
|
||||
endDate: Date
|
||||
) => {
|
||||
const { docs } = await getDocs(
|
||||
query(collection(db, "assignments"), where("assigner", "==", id))
|
||||
);
|
||||
return docs.map((x) => ({ ...x.data(), id: x.id })) as Assignment[];
|
||||
};
|
||||
|
||||
export const getAssignmentsByAssigners = async (ids: string[]) => {
|
||||
return (await Promise.all(ids.map(getAssignmentsByAssigner))).flat();
|
||||
export const getAssignmentsByAssigners = async (
|
||||
ids: string[],
|
||||
startDate?: Date,
|
||||
endDate?: Date
|
||||
) => {
|
||||
return (
|
||||
await Promise.all(
|
||||
ids.map((id) => getAssignmentsByAssigner(id, startDate, endDate))
|
||||
)
|
||||
).flat();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user