ENCOA-270, ENCOA-265, ENCOA-262, ENCOA-258

This commit is contained in:
Tiago Ribeiro
2024-12-11 16:54:37 +00:00
parent eabfcd026b
commit 71ed1013b7
10 changed files with 68 additions and 48 deletions

View File

@@ -55,7 +55,7 @@ export default function Lists({ user, entities = [], permissions }: Props) {
Exam List
</Tab>
)}
{checkAccess(user, ["developer", "admin", "corporate"]) && entitiesViewCodes.length > 0 && (
{checkAccess(user, ["developer", "admin", "corporate", "mastercorporate"]) && entitiesViewCodes.length > 0 && (
<Tab
className={({ selected }) =>
clsx(

View File

@@ -15,9 +15,11 @@ import { ToastContainer } from "react-toastify";
import useDiscounts from "@/hooks/useDiscounts";
import PaymobPayment from "@/components/PaymobPayment";
import moment from "moment";
import { EntityWithRoles } from "@/interfaces/entity";
interface Props {
user: User;
entities: EntityWithRoles[]
hasExpired?: boolean;
reload: () => void;
}

View File

@@ -36,6 +36,7 @@ import {
BsPersonFillGear,
} from "react-icons/bs";
import { ToastContainer } from "react-toastify";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
interface Props {
user: User;
@@ -67,6 +68,8 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
const students = useMemo(() => users.filter((u) => u.type === "student"), [users]);
const teachers = useMemo(() => users.filter((u) => u.type === "teacher"), [users]);
const allowedEntityStatistics = useAllowedEntities(user, entities, 'view_entity_statistics')
const router = useRouter();
const averageLevelCalculator = (studentStats: Stat[]) => {
@@ -94,16 +97,6 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
return calculateAverageLevel(levels);
};
const UserDisplay = (displayUser: User) => (
<div className="flex w-full p-4 gap-4 items-center hover:bg-mti-purple-ultralight cursor-pointer transition ease-in-out duration-300">
<img src={displayUser.profilePicture} alt={displayUser.name} className="rounded-full w-10 h-10" />
<div className="flex flex-col gap-1 items-start">
<span>{displayUser.name}</span>
<span className="text-sm opacity-75">{displayUser.email}</span>
</div>
</div>
);
return (
<>
<Head>
@@ -152,7 +145,14 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
color="purple"
/>
<IconCard Icon={BsClipboard2Data} label="Exams Performed" value={uniqBy(stats, "exam").length} color="purple" />
<IconCard Icon={BsPaperclip} label="Average Level" value={averageLevelCalculator(stats).toFixed(1)} color="purple" />
{allowedEntityStatistics.length > 0 && (
<IconCard Icon={BsPersonFillGear}
onClick={() => router.push("/statistical")}
label="Entity Statistics"
value={allowedEntityStatistics.length}
color="purple"
/>
)}
<IconCard Icon={BsPersonFillGear}
onClick={() => router.push("/users/performance")}
label="Student Performance"

View File

@@ -21,11 +21,12 @@ import { uniqBy } from "lodash";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { BsClipboard2Data, BsEnvelopePaper, BsPaperclip, BsPeople, BsPersonFill } from "react-icons/bs";
import { BsClipboard2Data, BsEnvelopePaper, BsPaperclip, BsPeople, BsPersonFill, BsPersonFillGear } from "react-icons/bs";
import { ToastContainer } from "react-toastify";
import { requestUser } from "@/utils/api";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
import { filterAllowedUsers } from "@/utils/users.be";
import { isAdmin } from "@/utils/users";
interface Props {
user: User;
@@ -44,7 +45,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
return redirect("/")
const entityIDS = mapBy(user.entities, "id") || [];
const entities = await getEntitiesWithRoles(entityIDS);
const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : entityIDS);
const users = await filterAllowedUsers(user, entities)
const assignments = await getEntitiesAssignments(entityIDS);
@@ -58,6 +59,8 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
const students = useMemo(() => users.filter((u) => u.type === "student"), [users]);
const router = useRouter();
const allowedEntityStatistics = useAllowedEntities(user, entities, 'view_entity_statistics')
const averageLevelCalculator = (studentStats: Stat[]) => {
const formattedStats = studentStats
.map((s) => ({
@@ -83,16 +86,6 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
return calculateAverageLevel(levels);
};
const UserDisplay = (displayUser: User) => (
<div className="flex w-full p-4 gap-4 items-center hover:bg-mti-purple-ultralight cursor-pointer transition ease-in-out duration-300">
<img src={displayUser.profilePicture} alt={displayUser.name} className="rounded-full w-10 h-10" />
<div className="flex flex-col gap-1 items-start">
<span>{displayUser.name}</span>
<span className="text-sm opacity-75">{displayUser.email}</span>
</div>
</div>
);
return (
<>
<Head>
@@ -128,7 +121,14 @@ export default function Dashboard({ user, users, entities, assignments, stats, g
color="purple"
/>
<IconCard Icon={BsClipboard2Data} label="Exams Performed" value={uniqBy(stats, "exam").length} color="purple" />
<IconCard Icon={BsPaperclip} label="Average Level" value={averageLevelCalculator(stats).toFixed(1)} color="purple" />
{allowedEntityStatistics.length > 0 && (
<IconCard Icon={BsPersonFillGear}
onClick={() => router.push("/statistical")}
label="Entity Statistics"
value={allowedEntityStatistics.length}
color="purple"
/>
)}
<IconCard
Icon={BsEnvelopePaper}
onClick={() => router.push("/assignments")}

View File

@@ -92,7 +92,8 @@ const ENTITY_MANAGEMENT: PermissionLayout[] = [
{ label: "Edit Role Permissions", key: "edit_role_permissions" },
{ label: "Assign Role to User", key: "assign_to_role" },
{ label: "Delete Entity Role", key: "delete_entity_role" },
{ label: "Download Statistics Report", key: "download_statistics_report" }
{ label: "Download Statistics Report", key: "download_statistics_report" },
{ label: "Edit Grading System", key: "edit_grading_system" }
]
const ASSIGNMENT_MANAGEMENT: PermissionLayout[] = [

View File

@@ -1,24 +1,35 @@
/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import { withIronSessionSsr } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import useUser from "@/hooks/useUser";
import PaymentDue from "./(status)/PaymentDue";
import {useRouter} from "next/router";
import { useRouter } from "next/router";
import { requestUser } from "@/utils/api";
import { redirect } from "@/utils";
import { mapBy, redirect, serialize } from "@/utils";
import { getEntities } from "@/utils/entities.be";
import { isAdmin } from "@/utils/users";
import { EntityWithRoles } from "@/interfaces/entity";
import { User } from "@/interfaces/user";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
const user = await requestUser(req, res)
if (!user) return redirect("/login")
const entityIDs = mapBy(user.entities, 'id')
const entities = await getEntities(isAdmin(user) ? undefined : entityIDs)
return {
props: {user},
props: serialize({ user, entities }),
};
}, sessionOptions);
export default function Home() {
const {user} = useUser({redirectTo: "/login"});
interface Props {
user: User,
entities: EntityWithRoles[]
}
export default function Home({ user, entities }: Props) {
const router = useRouter();
return (
@@ -32,7 +43,7 @@ export default function Home() {
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
{user && <PaymentDue user={user} reload={router.reload} />}
<PaymentDue entities={entities} user={user} reload={router.reload} />
</>
);
}

View File

@@ -70,6 +70,7 @@ export default function Admin({ user, entities, permissions, allUsers, entitiesG
const entitiesAllowCreateUsers = useAllowedEntities(user, entities, 'create_user_batch')
const entitiesAllowCreateCode = useAllowedEntities(user, entities, 'create_code')
const entitiesAllowCreateCodes = useAllowedEntities(user, entities, 'create_code_batch')
const entitiesAllowEditGrading = useAllowedEntities(user, entities, 'edit_grading_system')
return (
<>
@@ -111,7 +112,7 @@ export default function Admin({ user, entities, permissions, allUsers, entitiesG
<CorporateGradingSystem
user={user}
entitiesGrading={entitiesGrading}
entities={entities}
entities={entitiesAllowEditGrading}
mutate={() => router.replace(router.asPath)}
/>
</Modal>
@@ -159,6 +160,7 @@ export default function Admin({ user, entities, permissions, allUsers, entitiesG
color="purple"
className="w-full h-full col-span-2"
onClick={() => setModalOpen("gradingSystem")}
disabled={entitiesAllowEditGrading.length === 0}
/>
)}
</div>