Added the ability to view how many students and teachers an admin has

This commit is contained in:
Tiago Ribeiro
2023-10-27 00:28:29 +01:00
parent bdb0ffde95
commit c0269fca45
3 changed files with 108 additions and 17 deletions

View File

@@ -24,7 +24,12 @@ const expirationDateColor = (date: Date) => {
if (today.add(7, "days").isAfter(momentDate)) return "!bg-mti-orange-ultralight border-mti-orange-light"; if (today.add(7, "days").isAfter(momentDate)) return "!bg-mti-orange-ultralight border-mti-orange-light";
}; };
const UserCard = ({onClose, ...user}: User & {onClose: (reload?: boolean) => void}) => { const UserCard = ({
onClose,
onViewStudents,
onViewTeachers,
...user
}: User & {onClose: (reload?: boolean) => void; onViewStudents?: () => void; onViewTeachers?: () => void}) => {
const [expiryDate, setExpiryDate] = useState<Date | null | undefined>(user.subscriptionExpirationDate); const [expiryDate, setExpiryDate] = useState<Date | null | undefined>(user.subscriptionExpirationDate);
const {stats} = useStats(user.id); const {stats} = useStats(user.id);
@@ -215,13 +220,27 @@ const UserCard = ({onClose, ...user}: User & {onClose: (reload?: boolean) => voi
</div> </div>
</section> </section>
<div className="flex gap-4 justify-end mt-4 w-full"> <div className="flex gap-4 justify-between mt-4 w-full">
<Button className="w-full max-w-[200px]" variant="outline" onClick={onClose}> <div className="self-start flex gap-4 justify-start items-center w-full">
Close {onViewStudents && (
</Button> <Button className="w-full max-w-[200px]" variant="outline" color="rose" onClick={onViewStudents}>
<Button onClick={updateUser} className="w-full max-w-[200px]"> View Students
Update </Button>
</Button> )}
{onViewTeachers && (
<Button className="w-full max-w-[200px]" variant="outline" color="rose" onClick={onViewTeachers}>
View Teachers
</Button>
)}
</div>
<div className="self-end flex gap-4 w-full justify-end">
<Button className="w-full max-w-[200px]" variant="outline" onClick={onClose}>
Close
</Button>
<Button onClick={updateUser} className="w-full max-w-[200px]">
Update
</Button>
</div>
</div> </div>
</> </>
); );

View File

@@ -6,9 +6,10 @@ import {User} from "@/interfaces/user";
import UserList from "@/pages/(admin)/Lists/UserList"; import UserList from "@/pages/(admin)/Lists/UserList";
import {dateSorter} from "@/utils"; import {dateSorter} from "@/utils";
import moment from "moment"; import moment from "moment";
import {useState} from "react"; import {useEffect, useState} from "react";
import {BsArrowLeft, BsGlobeCentralSouthAsia, BsPerson, BsPersonFill, BsPersonFillGear, BsPersonGear, BsPersonLinesFill} from "react-icons/bs"; import {BsArrowLeft, BsGlobeCentralSouthAsia, BsPerson, BsPersonFill, BsPersonFillGear, BsPersonGear, BsPersonLinesFill} from "react-icons/bs";
import UserCard from "@/components/UserCard"; import UserCard from "@/components/UserCard";
import useGroups from "@/hooks/useGroups";
interface Props { interface Props {
user: User; user: User;
@@ -17,9 +18,15 @@ interface Props {
export default function OwnerDashboard({user}: Props) { export default function OwnerDashboard({user}: Props) {
const [page, setPage] = useState(""); const [page, setPage] = useState("");
const [selectedUser, setSelectedUser] = useState<User>(); const [selectedUser, setSelectedUser] = useState<User>();
const [showModal, setShowModal] = useState(false);
const {stats} = useStats(user.id); const {stats} = useStats(user.id);
const {users, reload} = useUsers(); const {users, reload} = useUsers();
const {groups} = useGroups();
useEffect(() => {
setShowModal(!!selectedUser && page === "");
}, [selectedUser, page]);
const UserDisplay = (displayUser: User) => ( const UserDisplay = (displayUser: User) => (
<div <div
@@ -42,10 +49,36 @@ export default function OwnerDashboard({user}: Props) {
<BsArrowLeft className="text-xl" /> <BsArrowLeft className="text-xl" />
<span>Back</span> <span>Back</span>
</div> </div>
<h2 className="text-2xl font-semibold">Students</h2> <h2 className="text-2xl font-semibold">
Students (
{
users.filter(
(x) =>
x.type === "student" &&
(!!selectedUser
? groups
.filter((g) => g.admin === selectedUser.id)
.flatMap((g) => g.participants)
.includes(x.id) || false
: true),
).length
}
)
</h2>
</div> </div>
<UserList user={user} filter={(x) => x.type === "student"} /> <UserList
user={user}
filter={(x) =>
x.type === "student" &&
(!!selectedUser
? groups
.filter((g) => g.admin === selectedUser.id)
.flatMap((g) => g.participants)
.includes(x.id) || false
: true)
}
/>
</> </>
); );
@@ -58,10 +91,36 @@ export default function OwnerDashboard({user}: Props) {
<BsArrowLeft className="text-xl" /> <BsArrowLeft className="text-xl" />
<span>Back</span> <span>Back</span>
</div> </div>
<h2 className="text-2xl font-semibold">Teachers</h2> <h2 className="text-2xl font-semibold">
Teachers (
{
users.filter(
(x) =>
x.type === "teacher" &&
(!!selectedUser
? groups
.filter((g) => g.admin === selectedUser.id)
.flatMap((g) => g.participants)
.includes(x.id) || false
: true),
).length
}
)
</h2>
</div> </div>
<UserList user={user} filter={(x) => x.type === "teacher"} /> <UserList
user={user}
filter={(x) =>
x.type === "teacher" &&
(!!selectedUser
? groups
.filter((g) => g.admin === selectedUser.id)
.flatMap((g) => g.participants)
.includes(x.id) || false
: true)
}
/>
</> </>
); );
@@ -74,7 +133,7 @@ export default function OwnerDashboard({user}: Props) {
<BsArrowLeft className="text-xl" /> <BsArrowLeft className="text-xl" />
<span>Back</span> <span>Back</span>
</div> </div>
<h2 className="text-2xl font-semibold">Corporate</h2> <h2 className="text-2xl font-semibold">Corporate ({users.filter((x) => x.type === "admin").length})</h2>
</div> </div>
<UserList user={user} filter={(x) => x.type === "admin"} /> <UserList user={user} filter={(x) => x.type === "admin"} />
@@ -90,7 +149,10 @@ export default function OwnerDashboard({user}: Props) {
<BsArrowLeft className="text-xl" /> <BsArrowLeft className="text-xl" />
<span>Back</span> <span>Back</span>
</div> </div>
<h2 className="text-2xl font-semibold">Inactive Students</h2> <h2 className="text-2xl font-semibold">
Inactive Students (
{users.filter((x) => x.type === "student" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))).length})
</h2>
</div> </div>
<UserList user={user} filter={(x) => x.type === "student" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))} /> <UserList user={user} filter={(x) => x.type === "student" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))} />
@@ -106,7 +168,10 @@ export default function OwnerDashboard({user}: Props) {
<BsArrowLeft className="text-xl" /> <BsArrowLeft className="text-xl" />
<span>Back</span> <span>Back</span>
</div> </div>
<h2 className="text-2xl font-semibold">Inactive Corporate</h2> <h2 className="text-2xl font-semibold">
Inactive Corporate (
{users.filter((x) => x.type === "admin" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))).length})
</h2>
</div> </div>
<UserList user={user} filter={(x) => x.type === "admin" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))} /> <UserList user={user} filter={(x) => x.type === "admin" && (x.isDisabled || moment().isAfter(x.subscriptionExpirationDate))} />
@@ -260,7 +325,7 @@ export default function OwnerDashboard({user}: Props) {
return ( return (
<> <>
<Modal isOpen={!!selectedUser} onClose={() => setSelectedUser(undefined)}> <Modal isOpen={showModal} onClose={() => setSelectedUser(undefined)}>
<> <>
{selectedUser && ( {selectedUser && (
<div className="w-full flex flex-col gap-8"> <div className="w-full flex flex-col gap-8">
@@ -269,6 +334,10 @@ export default function OwnerDashboard({user}: Props) {
setSelectedUser(undefined); setSelectedUser(undefined);
if (shouldReload) reload(); if (shouldReload) reload();
}} }}
onViewStudents={
selectedUser.type === "admin" || selectedUser.type === "teacher" ? () => setPage("students") : undefined
}
onViewTeachers={selectedUser.type === "admin" ? () => setPage("teachers") : undefined}
{...selectedUser} {...selectedUser}
/> />
</div> </div>

View File

@@ -14,11 +14,14 @@ export interface User {
bio: string; bio: string;
isVerified: boolean; isVerified: boolean;
demographicInformation?: DemographicInformation; demographicInformation?: DemographicInformation;
companyInformation?: CompanyInformation;
subscriptionExpirationDate?: null | Date; subscriptionExpirationDate?: null | Date;
isDisabled?: boolean; isDisabled?: boolean;
registrationDate?: Date; registrationDate?: Date;
} }
export interface CompanyInformation {}
export interface DemographicInformation { export interface DemographicInformation {
country: string; country: string;
phone: string; phone: string;