Files
encoach_frontend/src/pages/dashboard/developer.tsx

206 lines
6.0 KiB
TypeScript

/* eslint-disable @next/next/no-img-element */
import UserDisplayList from "@/components/UserDisplayList";
import IconCard from "@/components/IconCard";
import { EntityWithRoles } from "@/interfaces/entity";
import { Stat, Type, User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import { filterBy, mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import { countEntitiesAssignments } from "@/utils/assignments.be";
import { getEntities } from "@/utils/entities.be";
import { countGroups } from "@/utils/groups.be";
import { checkAccess } from "@/utils/permissions";
import { groupByExam } from "@/utils/stats";
import { countUsersByTypes, getUsers } from "@/utils/users.be";
import { withIronSessionSsr } from "iron-session/next";
import Head from "next/head";
import { useRouter } from "next/router";
import {
BsBank,
BsEnvelopePaper,
BsPencilSquare,
BsPeople,
BsPeopleFill,
BsPersonFill,
BsPersonFillGear,
} from "react-icons/bs";
import { ToastContainer } from "react-toastify";
interface Props {
user: User;
students: User[];
latestStudents: User[];
latestTeachers: User[];
entities: EntityWithRoles[];
usersCount: { [key in Type]: number };
assignmentsCount: number;
stats: Stat[];
groupsCount: number;
}
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
const user = await requestUser(req, res);
if (!user || !user.isVerified) return redirect("/login");
if (!checkAccess(user, ["admin", "developer"])) return redirect("/");
const [
students,
latestStudents,
latestTeachers,
usersCount,
entities,
groupsCount,
] = await Promise.all([
getUsers(
{ type: "student" },
10,
{ averageLevel: -1 },
{ _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
),
getUsers(
{ type: "student" },
10,
{ registrationDate: -1 },
{ _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
),
getUsers(
{ type: "teacher" },
10,
{ registrationDate: -1 },
{ _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
),
countUsersByTypes(["student", "teacher", "corporate", "mastercorporate"]),
getEntities(undefined, { _id: 0, id: 1, label: 1 }),
countGroups(),
]);
const assignmentsCount = await countEntitiesAssignments(
mapBy(entities, "id"),
{ archived: { $ne: true } }
);
return {
props: serialize({
user,
students,
latestStudents,
latestTeachers,
usersCount,
entities,
assignmentsCount,
groupsCount,
}),
};
}, sessionOptions);
export default function Dashboard({
user,
students = [],
latestStudents,
latestTeachers,
usersCount,
entities,
assignmentsCount,
stats = [],
groupsCount,
}: Props) {
const router = useRouter();
return (
<>
<Head>
<title>EnCoach</title>
<meta
name="description"
content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<ToastContainer />
<>
<section className="grid grid-cols-5 place-items-center -md:grid-cols-2 gap-4 text-center">
<IconCard
onClick={() => router.push("/users?type=student")}
Icon={BsPersonFill}
label="Students"
value={usersCount.student}
color="purple"
/>
<IconCard
onClick={() => router.push("/users?type=teacher")}
Icon={BsPencilSquare}
label="Teachers"
value={usersCount.teacher}
color="purple"
/>
<IconCard
Icon={BsBank}
onClick={() => router.push("/users?type=corporate")}
label="Corporates"
value={usersCount.corporate}
color="purple"
/>
<IconCard
Icon={BsBank}
onClick={() => router.push("/users?type=mastercorporate")}
label="Master Corporates"
value={usersCount.mastercorporate}
color="purple"
/>
<IconCard
Icon={BsPeople}
onClick={() => router.push("/classrooms")}
label="Classrooms"
value={groupsCount}
color="purple"
/>
<IconCard
Icon={BsPeopleFill}
onClick={() => router.push("/entities")}
label="Entities"
value={entities.length}
color="purple"
/>
<IconCard
Icon={BsPersonFillGear}
onClick={() => router.push("/statistical")}
label="Entity Statistics"
value={entities.length}
color="purple"
/>
<IconCard
Icon={BsPersonFillGear}
onClick={() => router.push("/users/performance")}
label="Student Performance"
value={usersCount.student}
color="purple"
/>
<IconCard
Icon={BsEnvelopePaper}
onClick={() => router.push("/assignments")}
label="Assignments"
value={assignmentsCount}
color="purple"
/>
</section>
<section className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full justify-between">
<UserDisplayList users={latestStudents} title="Latest Students" />
<UserDisplayList users={latestTeachers} title="Latest Teachers" />
<UserDisplayList users={students} title="Highest level students" />
<UserDisplayList
users={students.sort(
(a, b) =>
Object.keys(groupByExam(filterBy(stats, "user", b.id))).length -
Object.keys(groupByExam(filterBy(stats, "user", a.id))).length
)}
title="Highest exam count students"
/>
</section>
</>
</>
);
}