ENCOA-120: Prevented flicker when leaving page
This commit is contained in:
@@ -45,8 +45,8 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowModal(!!selectedUser && page === "");
|
setShowModal(!!selectedUser && router.asPath === "/#");
|
||||||
}, [selectedUser, page]);
|
}, [selectedUser, router.asPath]);
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
useEffect(reload, [page]);
|
useEffect(reload, [page]);
|
||||||
@@ -87,7 +87,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -116,7 +116,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -138,7 +138,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -157,7 +157,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -179,7 +179,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -201,7 +201,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -223,7 +223,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -245,7 +245,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -262,7 +262,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -281,28 +281,28 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
Icon={BsPersonFill}
|
Icon={BsPersonFill}
|
||||||
label="Students"
|
label="Students"
|
||||||
value={users.filter((x) => x.type === "student").length}
|
value={users.filter((x) => x.type === "student").length}
|
||||||
onClick={() => setPage("students")}
|
onClick={() => router.push("/#students")}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsPencilSquare}
|
Icon={BsPencilSquare}
|
||||||
label="Teachers"
|
label="Teachers"
|
||||||
value={users.filter((x) => x.type === "teacher").length}
|
value={users.filter((x) => x.type === "teacher").length}
|
||||||
onClick={() => setPage("teachers")}
|
onClick={() => router.push("/#teachers")}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsBank}
|
Icon={BsBank}
|
||||||
label="Corporate"
|
label="Corporate"
|
||||||
value={users.filter((x) => x.type === "corporate").length}
|
value={users.filter((x) => x.type === "corporate").length}
|
||||||
onClick={() => setPage("corporate")}
|
onClick={() => router.push("/#corporate")}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsBriefcaseFill}
|
Icon={BsBriefcaseFill}
|
||||||
label="Country Managers"
|
label="Country Managers"
|
||||||
value={users.filter((x) => x.type === "agent").length}
|
value={users.filter((x) => x.type === "agent").length}
|
||||||
onClick={() => setPage("agents")}
|
onClick={() => router.push("/#agents")}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
@@ -312,7 +312,7 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("inactiveStudents")}
|
onClick={() => router.push("/#inactiveStudents")}
|
||||||
Icon={BsPersonFill}
|
Icon={BsPersonFill}
|
||||||
label="Inactive Students"
|
label="Inactive Students"
|
||||||
value={
|
value={
|
||||||
@@ -322,14 +322,14 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
color="rose"
|
color="rose"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("inactiveCountryManagers")}
|
onClick={() => router.push("/#inactiveCountryManagers")}
|
||||||
Icon={BsBriefcaseFill}
|
Icon={BsBriefcaseFill}
|
||||||
label="Inactive Country Managers"
|
label="Inactive Country Managers"
|
||||||
value={users.filter(inactiveCountryManagerFilter).length}
|
value={users.filter(inactiveCountryManagerFilter).length}
|
||||||
color="rose"
|
color="rose"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("inactiveCorporate")}
|
onClick={() => router.push("/#inactiveCorporate")}
|
||||||
Icon={BsBank}
|
Icon={BsBank}
|
||||||
label="Inactive Corporate"
|
label="Inactive Corporate"
|
||||||
value={
|
value={
|
||||||
@@ -338,9 +338,15 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
}
|
}
|
||||||
color="rose"
|
color="rose"
|
||||||
/>
|
/>
|
||||||
<IconCard onClick={() => setPage("paymentdone")} Icon={BsCurrencyDollar} label="Payment Done" value={done.length} color="purple" />
|
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("paymentpending")}
|
onClick={() => router.push("/#paymentdone")}
|
||||||
|
Icon={BsCurrencyDollar}
|
||||||
|
label="Payment Done"
|
||||||
|
value={done.length}
|
||||||
|
color="purple"
|
||||||
|
/>
|
||||||
|
<IconCard
|
||||||
|
onClick={() => router.push("/#paymentpending")}
|
||||||
Icon={BsCurrencyDollar}
|
Icon={BsCurrencyDollar}
|
||||||
label="Pending Payment"
|
label="Pending Payment"
|
||||||
value={pending.length}
|
value={pending.length}
|
||||||
@@ -352,7 +358,12 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
label="Content Management System (CMS)"
|
label="Content Management System (CMS)"
|
||||||
color="green"
|
color="green"
|
||||||
/>
|
/>
|
||||||
<IconCard onClick={() => setPage("corporatestudentslevels")} Icon={BsPersonFill} label="Corporate Students Levels" color="purple" />
|
<IconCard
|
||||||
|
onClick={() => router.push("/#corporatestudentslevels")}
|
||||||
|
Icon={BsPersonFill}
|
||||||
|
label="Corporate Students Levels"
|
||||||
|
color="purple"
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 w-full justify-between">
|
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 w-full justify-between">
|
||||||
@@ -598,17 +609,17 @@ export default function AdminDashboard({user}: Props) {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
{page === "students" && <StudentsList />}
|
{router.asPath === "/#students" && <StudentsList />}
|
||||||
{page === "teachers" && <TeachersList />}
|
{router.asPath === "/#teachers" && <TeachersList />}
|
||||||
{page === "corporate" && <CorporateList />}
|
{router.asPath === "/#corporate" && <CorporateList />}
|
||||||
{page === "agents" && <AgentsList />}
|
{router.asPath === "/#agents" && <AgentsList />}
|
||||||
{page === "inactiveStudents" && <InactiveStudentsList />}
|
{router.asPath === "/#inactiveStudents" && <InactiveStudentsList />}
|
||||||
{page === "inactiveCorporate" && <InactiveCorporateList />}
|
{router.asPath === "/#inactiveCorporate" && <InactiveCorporateList />}
|
||||||
{page === "inactiveCountryManagers" && <InactiveCountryManagerList />}
|
{router.asPath === "/#inactiveCountryManagers" && <InactiveCountryManagerList />}
|
||||||
{page === "paymentdone" && <CorporatePaidStatusList paid={true} />}
|
{router.asPath === "/#paymentdone" && <CorporatePaidStatusList paid={true} />}
|
||||||
{page === "paymentpending" && <CorporatePaidStatusList paid={false} />}
|
{router.asPath === "/#paymentpending" && <CorporatePaidStatusList paid={false} />}
|
||||||
{page === "corporatestudentslevels" && <CorporateStudentsLevelsHelper />}
|
{router.asPath === "/#corporatestudentslevels" && <CorporateStudentsLevelsHelper />}
|
||||||
{page === "" && <DefaultDashboard />}
|
{router.asPath === "/" && <DefaultDashboard />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import List from "@/components/List";
|
|||||||
import {getUserCompanyName} from "@/resources/user";
|
import {getUserCompanyName} from "@/resources/user";
|
||||||
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
||||||
import useUserBalance from "@/hooks/useUserBalance";
|
import useUserBalance from "@/hooks/useUserBalance";
|
||||||
|
import AssignmentsPage from "./views/AssignmentsPage";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: CorporateUser;
|
user: CorporateUser;
|
||||||
@@ -156,15 +157,11 @@ const StudentPerformanceList = ({items, stats, users}: {items: StudentPerformanc
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
||||||
const [page, setPage] = useState("");
|
|
||||||
const [selectedUser, setSelectedUser] = useState<User>();
|
const [selectedUser, setSelectedUser] = useState<User>();
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [selectedAssignment, setSelectedAssignment] = useState<Assignment>();
|
|
||||||
const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
|
|
||||||
|
|
||||||
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
||||||
const {users, reload, isLoading} = useUsers();
|
const {users, reload, isLoading} = useUsers();
|
||||||
const {codes} = useCodes(user.id);
|
|
||||||
const {groups} = useGroups({admin: user.id});
|
const {groups} = useGroups({admin: user.id});
|
||||||
const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({corporate: user.id});
|
const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({corporate: user.id});
|
||||||
const {balance} = useUserBalance();
|
const {balance} = useUserBalance();
|
||||||
@@ -190,8 +187,8 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowModal(!!selectedUser && page === "");
|
setShowModal(!!selectedUser && router.asPath === "/#");
|
||||||
}, [selectedUser, page]);
|
}, [selectedUser, router.asPath]);
|
||||||
|
|
||||||
const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id);
|
const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id);
|
||||||
const teacherFilter = (user: User) => user.type === "teacher" && groups.flatMap((g) => g.participants).includes(user.id);
|
const teacherFilter = (user: User) => user.type === "teacher" && groups.flatMap((g) => g.participants).includes(user.id);
|
||||||
@@ -227,7 +224,7 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -256,7 +253,7 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -275,7 +272,7 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -288,111 +285,6 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AssignmentsPage = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AssignmentView
|
|
||||||
isOpen={!!selectedAssignment && !isCreatingAssignment}
|
|
||||||
onClose={() => {
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
/>
|
|
||||||
<AssignmentCreator
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
groups={assignmentsGroups}
|
|
||||||
users={assignmentsUsers}
|
|
||||||
isCreating={isCreatingAssignment}
|
|
||||||
cancelCreation={() => {
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="w-full flex justify-between items-center">
|
|
||||||
<div
|
|
||||||
onClick={() => setPage("")}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<BsArrowLeft className="text-xl" />
|
|
||||||
<span>Back</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={reloadAssignments}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<span>Reload</span>
|
|
||||||
<BsArrowRepeat className={clsx("text-xl", isAssignmentsLoading && "animate-spin")} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Active Assignments ({assignments.filter(activeAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(activeAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard {...a} users={users} onClick={() => setSelectedAssignment(a)} key={a.id} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Planned Assignments ({assignments.filter(futureAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
<div
|
|
||||||
onClick={() => setIsCreatingAssignment(true)}
|
|
||||||
className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300">
|
|
||||||
<BsPlus className="text-6xl" />
|
|
||||||
<span className="text-lg">New Assignment</span>
|
|
||||||
</div>
|
|
||||||
{assignments.filter(futureAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedAssignment(a);
|
|
||||||
setIsCreatingAssignment(true);
|
|
||||||
}}
|
|
||||||
key={a.id}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Past Assignments ({assignments.filter(pastAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(pastAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowArchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Archived Assignments ({assignments.filter(archivedAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(archivedAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowUnarchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const StudentPerformancePage = () => {
|
const StudentPerformancePage = () => {
|
||||||
const students = users
|
const students = users
|
||||||
.filter((x) => x.type === "student" && groups.flatMap((g) => g.participants).includes(x.id))
|
.filter((x) => x.type === "student" && groups.flatMap((g) => g.participants).includes(x.id))
|
||||||
@@ -406,7 +298,7 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="w-full flex justify-between items-center">
|
<div className="w-full flex justify-between items-center">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -457,14 +349,14 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
)}
|
)}
|
||||||
<section className="grid grid-cols-5 -md:grid-cols-2 gap-4 text-center">
|
<section className="grid grid-cols-5 -md:grid-cols-2 gap-4 text-center">
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("students")}
|
onClick={() => router.push("/#students")}
|
||||||
Icon={BsPersonFill}
|
Icon={BsPersonFill}
|
||||||
label="Students"
|
label="Students"
|
||||||
value={users.filter(studentFilter).length}
|
value={users.filter(studentFilter).length}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("teachers")}
|
onClick={() => router.push("/#teachers")}
|
||||||
Icon={BsPencilSquare}
|
Icon={BsPencilSquare}
|
||||||
label="Teachers"
|
label="Teachers"
|
||||||
value={users.filter(teacherFilter).length}
|
value={users.filter(teacherFilter).length}
|
||||||
@@ -482,7 +374,7 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
value={averageLevelCalculator(stats.filter((s) => groups.flatMap((g) => g.participants).includes(s.user))).toFixed(1)}
|
value={averageLevelCalculator(stats.filter((s) => groups.flatMap((g) => g.participants).includes(s.user))).toFixed(1)}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard onClick={() => setPage("groups")} Icon={BsPeople} label="Groups" value={groups.length} color="purple" />
|
<IconCard onClick={() => router.push("/#groups")} Icon={BsPeople} label="Groups" value={groups.length} color="purple" />
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsPersonCheck}
|
Icon={BsPersonCheck}
|
||||||
label="User Balance"
|
label="User Balance"
|
||||||
@@ -500,11 +392,11 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
label="Student Performance"
|
label="Student Performance"
|
||||||
value={users.filter(studentFilter).length}
|
value={users.filter(studentFilter).length}
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => setPage("studentsPerformance")}
|
onClick={() => router.push("/#studentsPerformance")}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
disabled={isAssignmentsLoading}
|
disabled={isAssignmentsLoading}
|
||||||
onClick={() => setPage("assignments")}
|
onClick={() => router.push("/#assignments")}
|
||||||
className="bg-white col-span-2 rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
className="bg-white col-span-2 rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
||||||
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
||||||
<span className="flex flex-col gap-1 items-center text-xl">
|
<span className="flex flex-col gap-1 items-center text-xl">
|
||||||
@@ -626,12 +518,21 @@ export default function CorporateDashboard({user, linkedCorporate}: Props) {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
{page === "students" && <StudentsList />}
|
{router.asPath === "/#students" && <StudentsList />}
|
||||||
{page === "teachers" && <TeachersList />}
|
{router.asPath === "/#teachers" && <TeachersList />}
|
||||||
{page === "groups" && <GroupsList />}
|
{router.asPath === "/#groups" && <GroupsList />}
|
||||||
{page === "assignments" && <AssignmentsPage />}
|
{router.asPath === "/#assignments" && (
|
||||||
{page === "studentsPerformance" && <StudentPerformancePage />}
|
<AssignmentsPage
|
||||||
{page === "" && <DefaultDashboard />}
|
assignments={assignments}
|
||||||
|
groups={assignmentsGroups}
|
||||||
|
users={assignmentsUsers}
|
||||||
|
reloadAssignments={reloadAssignments}
|
||||||
|
isLoading={isAssignmentsLoading}
|
||||||
|
onBack={() => router.push("/")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{router.asPath === "/#studentsPerformance" && <StudentPerformancePage />}
|
||||||
|
{router.asPath === "/" && <DefaultDashboard />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover";
|
|||||||
import MasterStatistical from "./MasterStatistical";
|
import MasterStatistical from "./MasterStatistical";
|
||||||
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
||||||
import useUserBalance from "@/hooks/useUserBalance";
|
import useUserBalance from "@/hooks/useUserBalance";
|
||||||
|
import AssignmentsPage from "./views/AssignmentsPage";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: MasterCorporateUser;
|
user: MasterCorporateUser;
|
||||||
@@ -298,8 +299,6 @@ export default function MasterCorporateDashboard({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 [showModal, setShowModal] = useState(false);
|
||||||
const [selectedAssignment, setSelectedAssignment] = useState<Assignment>();
|
|
||||||
const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
|
|
||||||
const [corporateAssignments, setCorporateAssignments] = useState<(Assignment & {corporate?: CorporateUser})[]>([]);
|
const [corporateAssignments, setCorporateAssignments] = useState<(Assignment & {corporate?: CorporateUser})[]>([]);
|
||||||
|
|
||||||
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
||||||
@@ -336,8 +335,8 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowModal(!!selectedUser && page === "");
|
setShowModal(!!selectedUser && router.asPath === "/");
|
||||||
}, [selectedUser, page]);
|
}, [selectedUser, router.asPath]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCorporateAssignments(
|
setCorporateAssignments(
|
||||||
@@ -377,7 +376,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -400,7 +399,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -423,7 +422,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -440,7 +439,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -466,7 +465,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="w-full flex justify-between items-center">
|
<div className="w-full flex justify-between items-center">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -483,129 +482,6 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AssignmentsPage = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AssignmentView
|
|
||||||
isOpen={!!selectedAssignment && !isCreatingAssignment}
|
|
||||||
onClose={() => {
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
/>
|
|
||||||
<AssignmentCreator
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
groups={assignmentsGroups}
|
|
||||||
users={assignmentsUsers}
|
|
||||||
isCreating={isCreatingAssignment}
|
|
||||||
cancelCreation={() => {
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="w-full flex justify-between items-center">
|
|
||||||
<div
|
|
||||||
onClick={() => setPage("")}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<BsArrowLeft className="text-xl" />
|
|
||||||
<span>Back</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={reloadAssignments}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<span>Reload</span>
|
|
||||||
<BsArrowRepeat className={clsx("text-xl", isAssignmentsLoading && "animate-spin")} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<span className="text-lg font-bold">Active Assignments Status</span>
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
<span>
|
|
||||||
<b>Total:</b> {assignments.filter(activeAssignmentFilter).reduce((acc, curr) => acc + curr.results.length, 0)}/
|
|
||||||
{assignments.filter(activeAssignmentFilter).reduce((acc, curr) => curr.exams.length + acc, 0)}
|
|
||||||
</span>
|
|
||||||
{Object.keys(groupBy(corporateAssignments, (x) => x.corporate?.id)).map((x) => (
|
|
||||||
<div key={x}>
|
|
||||||
<span className="font-semibold">{getUserCompanyName(users.find((u) => u.id === x)!, users, groups)}: </span>
|
|
||||||
<span>
|
|
||||||
{groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.results.length + acc, 0)}/
|
|
||||||
{groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.exams.length + acc, 0)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Active Assignments ({assignments.filter(activeAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(activeAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard {...a} users={users} onClick={() => setSelectedAssignment(a)} key={a.id} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Planned Assignments ({assignments.filter(futureAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
<div
|
|
||||||
onClick={() => setIsCreatingAssignment(true)}
|
|
||||||
className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300">
|
|
||||||
<BsPlus className="text-6xl" />
|
|
||||||
<span className="text-lg">New Assignment</span>
|
|
||||||
</div>
|
|
||||||
{assignments.filter(futureAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedAssignment(a);
|
|
||||||
setIsCreatingAssignment(true);
|
|
||||||
}}
|
|
||||||
key={a.id}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Past Assignments ({assignments.filter(pastAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(pastAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowArchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Archived Assignments ({assignments.filter(archivedAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(archivedAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowUnarchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const masterCorporateUsers = useMemo(
|
const masterCorporateUsers = useMemo(
|
||||||
() =>
|
() =>
|
||||||
masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
|
masterCorporateUserGroups.reduce((accm: CorporateUser[], id) => {
|
||||||
@@ -621,7 +497,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -637,14 +513,14 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
<>
|
<>
|
||||||
<section className="flex flex-wrap gap-2 items-center -lg:justify-center lg:justify-between text-center">
|
<section className="flex flex-wrap gap-2 items-center -lg:justify-center lg:justify-between text-center">
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("students")}
|
onClick={() => router.push("/#students")}
|
||||||
Icon={BsPersonFill}
|
Icon={BsPersonFill}
|
||||||
label="Students"
|
label="Students"
|
||||||
value={users.filter(studentFilter).length}
|
value={users.filter(studentFilter).length}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("teachers")}
|
onClick={() => router.push("/#teachers")}
|
||||||
Icon={BsPencilSquare}
|
Icon={BsPencilSquare}
|
||||||
label="Teachers"
|
label="Teachers"
|
||||||
value={users.filter(teacherFilter).length}
|
value={users.filter(teacherFilter).length}
|
||||||
@@ -665,7 +541,7 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
).toFixed(1)}
|
).toFixed(1)}
|
||||||
color="purple"
|
color="purple"
|
||||||
/>
|
/>
|
||||||
<IconCard onClick={() => setPage("groups")} Icon={BsPeople} label="Groups" value={groups.length} color="purple" />
|
<IconCard onClick={() => router.push("/#groups")} Icon={BsPeople} label="Groups" value={groups.length} color="purple" />
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsPersonCheck}
|
Icon={BsPersonCheck}
|
||||||
label="User Balance"
|
label="User Balance"
|
||||||
@@ -683,25 +559,25 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
label="Corporate"
|
label="Corporate"
|
||||||
value={masterCorporateUserGroups.length}
|
value={masterCorporateUserGroups.length}
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => setPage("corporate")}
|
onClick={() => router.push("/#corporate")}
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsPersonFillGear}
|
Icon={BsPersonFillGear}
|
||||||
label="Student Performance"
|
label="Student Performance"
|
||||||
value={users.filter(studentFilter).length}
|
value={users.filter(studentFilter).length}
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => setPage("studentsPerformance")}
|
onClick={() => router.push("/#studentsPerformance")}
|
||||||
/>
|
/>
|
||||||
<IconCard
|
<IconCard
|
||||||
Icon={BsDatabase}
|
Icon={BsDatabase}
|
||||||
label="Master Statistical"
|
label="Master Statistical"
|
||||||
// value={masterCorporateUserGroups.length}
|
// value={masterCorporateUserGroups.length}
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => setPage("statistical")}
|
onClick={() => router.push("/#statistical")}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
disabled={isAssignmentsLoading}
|
disabled={isAssignmentsLoading}
|
||||||
onClick={() => setPage("assignments")}
|
onClick={() => router.push("/#assignments")}
|
||||||
className="bg-white col-span-2 rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
className="bg-white col-span-2 rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
||||||
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
||||||
<span className="flex flex-col gap-1 items-center text-xl">
|
<span className="flex flex-col gap-1 items-center text-xl">
|
||||||
@@ -828,14 +704,24 @@ export default function MasterCorporateDashboard({user}: Props) {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
{page === "students" && <StudentsList />}
|
{router.asPath === "/#students" && <StudentsList />}
|
||||||
{page === "teachers" && <TeachersList />}
|
{router.asPath === "/#teachers" && <TeachersList />}
|
||||||
{page === "groups" && <GroupsList />}
|
{router.asPath === "/#groups" && <GroupsList />}
|
||||||
{page === "corporate" && <CorporateList />}
|
{router.asPath === "/#corporate" && <CorporateList />}
|
||||||
{page === "assignments" && <AssignmentsPage />}
|
{router.asPath === "/#assignments" && (
|
||||||
{page === "studentsPerformance" && <StudentPerformancePage />}
|
<AssignmentsPage
|
||||||
{page === "statistical" && <MasterStatisticalPage />}
|
assignments={assignments}
|
||||||
{page === "" && <DefaultDashboard />}
|
corporateAssignments={corporateAssignments}
|
||||||
|
groups={assignmentsGroups}
|
||||||
|
users={assignmentsUsers}
|
||||||
|
reloadAssignments={reloadAssignments}
|
||||||
|
isLoading={isAssignmentsLoading}
|
||||||
|
onBack={() => router.push("/")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{router.asPath === "/#studentsPerformance" && <StudentPerformancePage />}
|
||||||
|
{router.asPath === "/#statistical" && <MasterStatisticalPage />}
|
||||||
|
{router.asPath === "/" && <DefaultDashboard />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ import {getUserCorporate} from "@/utils/groups";
|
|||||||
import {checkAccess} from "@/utils/permissions";
|
import {checkAccess} from "@/utils/permissions";
|
||||||
import usePermissions from "@/hooks/usePermissions";
|
import usePermissions from "@/hooks/usePermissions";
|
||||||
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
import {futureAssignmentFilter, pastAssignmentFilter, archivedAssignmentFilter, activeAssignmentFilter} from "@/utils/assignments";
|
||||||
|
import AssignmentsPage from "./views/AssignmentsPage";
|
||||||
|
import {useRouter} from "next/router";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: User;
|
user: User;
|
||||||
@@ -56,11 +58,8 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
||||||
const [page, setPage] = useState("");
|
|
||||||
const [selectedUser, setSelectedUser] = useState<User>();
|
const [selectedUser, setSelectedUser] = useState<User>();
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [selectedAssignment, setSelectedAssignment] = useState<Assignment>();
|
|
||||||
const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
|
|
||||||
|
|
||||||
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
const {data: stats} = useFilterRecordsByUser<Stat[]>();
|
||||||
const {users, reload} = useUsers();
|
const {users, reload} = useUsers();
|
||||||
@@ -68,6 +67,8 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
const {permissions} = usePermissions(user.id);
|
const {permissions} = usePermissions(user.id);
|
||||||
const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assigner: user.id});
|
const {assignments, isLoading: isAssignmentsLoading, reload: reloadAssignments} = useAssignments({assigner: user.id});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]);
|
const assignmentsGroups = useMemo(() => groups.filter((x) => x.admin === user.id || x.participants.includes(user.id)), [groups, user.id]);
|
||||||
|
|
||||||
const assignmentsUsers = useMemo(
|
const assignmentsUsers = useMemo(
|
||||||
@@ -86,8 +87,8 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowModal(!!selectedUser && page === "");
|
setShowModal(!!selectedUser && router.asPath === "/#");
|
||||||
}, [selectedUser, page]);
|
}, [selectedUser, router.asPath]);
|
||||||
|
|
||||||
const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id);
|
const studentFilter = (user: User) => user.type === "student" && groups.flatMap((g) => g.participants).includes(user.id);
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
renderHeader={(total) => (
|
renderHeader={(total) => (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -141,7 +142,7 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("")}
|
onClick={() => router.push("/")}
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
<BsArrowLeft className="text-xl" />
|
<BsArrowLeft className="text-xl" />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -179,111 +180,6 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
return calculateAverageLevel(levels);
|
return calculateAverageLevel(levels);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AssignmentsPage = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AssignmentView
|
|
||||||
isOpen={!!selectedAssignment && !isCreatingAssignment}
|
|
||||||
onClose={() => {
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
/>
|
|
||||||
<AssignmentCreator
|
|
||||||
assignment={selectedAssignment}
|
|
||||||
groups={assignmentsGroups}
|
|
||||||
users={assignmentsUsers}
|
|
||||||
isCreating={isCreatingAssignment}
|
|
||||||
cancelCreation={() => {
|
|
||||||
setIsCreatingAssignment(false);
|
|
||||||
setSelectedAssignment(undefined);
|
|
||||||
reloadAssignments();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="w-full flex justify-between items-center">
|
|
||||||
<div
|
|
||||||
onClick={() => setPage("")}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<BsArrowLeft className="text-xl" />
|
|
||||||
<span>Back</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={reloadAssignments}
|
|
||||||
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
|
||||||
<span>Reload</span>
|
|
||||||
<BsArrowRepeat className={clsx("text-xl", isAssignmentsLoading && "animate-spin")} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Active Assignments ({assignments.filter(activeAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(activeAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard {...a} users={users} onClick={() => setSelectedAssignment(a)} key={a.id} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Planned Assignments ({assignments.filter(futureAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
<div
|
|
||||||
onClick={() => setIsCreatingAssignment(true)}
|
|
||||||
className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300">
|
|
||||||
<BsPlus className="text-6xl" />
|
|
||||||
<span className="text-lg">New Assignment</span>
|
|
||||||
</div>
|
|
||||||
{assignments.filter(futureAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedAssignment(a);
|
|
||||||
setIsCreatingAssignment(true);
|
|
||||||
}}
|
|
||||||
key={a.id}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Past Assignments ({assignments.filter(pastAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(pastAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowArchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section className="flex flex-col gap-4">
|
|
||||||
<h2 className="text-2xl font-semibold">Archived Assignments ({assignments.filter(archivedAssignmentFilter).length})</h2>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{assignments.filter(archivedAssignmentFilter).map((a) => (
|
|
||||||
<AssignmentCard
|
|
||||||
{...a}
|
|
||||||
users={users}
|
|
||||||
onClick={() => setSelectedAssignment(a)}
|
|
||||||
key={a.id}
|
|
||||||
allowDownload
|
|
||||||
reload={reloadAssignments}
|
|
||||||
allowUnarchive
|
|
||||||
allowExcelDownload
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DefaultDashboard = () => (
|
const DefaultDashboard = () => (
|
||||||
<>
|
<>
|
||||||
{linkedCorporate && (
|
{linkedCorporate && (
|
||||||
@@ -297,7 +193,7 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
!!linkedCorporate && "mt-12 xl:mt-6",
|
!!linkedCorporate && "mt-12 xl:mt-6",
|
||||||
)}>
|
)}>
|
||||||
<IconCard
|
<IconCard
|
||||||
onClick={() => setPage("students")}
|
onClick={() => router.push("/#students")}
|
||||||
Icon={BsPersonFill}
|
Icon={BsPersonFill}
|
||||||
label="Students"
|
label="Students"
|
||||||
value={users.filter(studentFilter).length}
|
value={users.filter(studentFilter).length}
|
||||||
@@ -321,11 +217,11 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
label="Groups"
|
label="Groups"
|
||||||
value={groups.filter((x) => x.admin === user.id).length}
|
value={groups.filter((x) => x.admin === user.id).length}
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => setPage("groups")}
|
onClick={() => router.push("/#groups")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
onClick={() => setPage("assignments")}
|
onClick={() => router.push("/#assignments")}
|
||||||
className="bg-white rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
className="bg-white rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300">
|
||||||
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
<BsEnvelopePaper className="text-6xl text-mti-purple-light" />
|
||||||
<span className="flex flex-col gap-1 items-center text-xl">
|
<span className="flex flex-col gap-1 items-center text-xl">
|
||||||
@@ -389,19 +285,28 @@ export default function TeacherDashboard({user, linkedCorporate}: Props) {
|
|||||||
if (shouldReload) reload();
|
if (shouldReload) reload();
|
||||||
}}
|
}}
|
||||||
onViewStudents={
|
onViewStudents={
|
||||||
selectedUser.type === "corporate" || selectedUser.type === "teacher" ? () => setPage("students") : undefined
|
selectedUser.type === "corporate" || selectedUser.type === "teacher" ? () => router.push("/#students") : undefined
|
||||||
}
|
}
|
||||||
onViewTeachers={selectedUser.type === "corporate" ? () => setPage("teachers") : undefined}
|
onViewTeachers={selectedUser.type === "corporate" ? () => router.push("/#teachers") : undefined}
|
||||||
user={selectedUser}
|
user={selectedUser}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
{page === "students" && <StudentsList />}
|
{router.asPath === "/#students" && <StudentsList />}
|
||||||
{page === "groups" && <GroupsList />}
|
{router.asPath === "/#groups" && <GroupsList />}
|
||||||
{page === "assignments" && <AssignmentsPage />}
|
{router.asPath === "/#assignments" && (
|
||||||
{page === "" && <DefaultDashboard />}
|
<AssignmentsPage
|
||||||
|
assignments={assignments}
|
||||||
|
groups={assignmentsGroups}
|
||||||
|
users={assignmentsUsers}
|
||||||
|
reloadAssignments={reloadAssignments}
|
||||||
|
isLoading={isAssignmentsLoading}
|
||||||
|
onBack={() => router.push("/")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{router.asPath === "/" && <DefaultDashboard />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
147
src/dashboards/views/AssignmentsPage.tsx
Normal file
147
src/dashboards/views/AssignmentsPage.tsx
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import {Assignment} from "@/interfaces/results";
|
||||||
|
import {CorporateUser, Group, User} from "@/interfaces/user";
|
||||||
|
import {getUserCompanyName} from "@/resources/user";
|
||||||
|
import {activeAssignmentFilter, archivedAssignmentFilter, futureAssignmentFilter, pastAssignmentFilter} from "@/utils/assignments";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import {groupBy} from "lodash";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {BsArrowLeft, BsArrowRepeat, BsPlus} from "react-icons/bs";
|
||||||
|
import AssignmentCard from "../AssignmentCard";
|
||||||
|
import AssignmentCreator from "../AssignmentCreator";
|
||||||
|
import AssignmentView from "../AssignmentView";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
assignments: Assignment[];
|
||||||
|
corporateAssignments?: ({corporate?: CorporateUser} & Assignment)[];
|
||||||
|
groups: Group[];
|
||||||
|
users: User[];
|
||||||
|
isLoading: boolean;
|
||||||
|
onBack: () => void;
|
||||||
|
reloadAssignments: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AssignmentsPage({assignments, corporateAssignments, groups, users, isLoading, onBack, reloadAssignments}: Props) {
|
||||||
|
const [selectedAssignment, setSelectedAssignment] = useState<Assignment>();
|
||||||
|
const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AssignmentView
|
||||||
|
isOpen={!!selectedAssignment && !isCreatingAssignment}
|
||||||
|
onClose={() => {
|
||||||
|
setSelectedAssignment(undefined);
|
||||||
|
setIsCreatingAssignment(false);
|
||||||
|
reloadAssignments();
|
||||||
|
}}
|
||||||
|
assignment={selectedAssignment}
|
||||||
|
/>
|
||||||
|
<AssignmentCreator
|
||||||
|
assignment={selectedAssignment}
|
||||||
|
groups={groups}
|
||||||
|
users={users}
|
||||||
|
isCreating={isCreatingAssignment}
|
||||||
|
cancelCreation={() => {
|
||||||
|
setIsCreatingAssignment(false);
|
||||||
|
setSelectedAssignment(undefined);
|
||||||
|
reloadAssignments();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="w-full flex justify-between items-center">
|
||||||
|
<div
|
||||||
|
onClick={onBack}
|
||||||
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
|
<BsArrowLeft className="text-xl" />
|
||||||
|
<span>Back</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={reloadAssignments}
|
||||||
|
className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300">
|
||||||
|
<span>Reload</span>
|
||||||
|
<BsArrowRepeat className={clsx("text-xl", isLoading && "animate-spin")} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<span className="text-lg font-bold">Active Assignments Status</span>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<span>
|
||||||
|
<b>Total:</b> {assignments.filter(activeAssignmentFilter).reduce((acc, curr) => acc + curr.results.length, 0)}/
|
||||||
|
{assignments.filter(activeAssignmentFilter).reduce((acc, curr) => curr.exams.length + acc, 0)}
|
||||||
|
</span>
|
||||||
|
{Object.keys(groupBy(corporateAssignments, (x) => x.corporate?.id)).map((x) => (
|
||||||
|
<div key={x}>
|
||||||
|
<span className="font-semibold">{getUserCompanyName(users.find((u) => u.id === x)!, users, groups)}: </span>
|
||||||
|
<span>
|
||||||
|
{groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.results.length + acc, 0)}/
|
||||||
|
{groupBy(corporateAssignments, (x) => x.corporate?.id)[x].reduce((acc, curr) => curr.exams.length + acc, 0)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<section className="flex flex-col gap-4">
|
||||||
|
<h2 className="text-2xl font-semibold">Active Assignments ({assignments.filter(activeAssignmentFilter).length})</h2>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{assignments.filter(activeAssignmentFilter).map((a) => (
|
||||||
|
<AssignmentCard {...a} users={users} onClick={() => setSelectedAssignment(a)} key={a.id} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="flex flex-col gap-4">
|
||||||
|
<h2 className="text-2xl font-semibold">Planned Assignments ({assignments.filter(futureAssignmentFilter).length})</h2>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<div
|
||||||
|
onClick={() => setIsCreatingAssignment(true)}
|
||||||
|
className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300">
|
||||||
|
<BsPlus className="text-6xl" />
|
||||||
|
<span className="text-lg">New Assignment</span>
|
||||||
|
</div>
|
||||||
|
{assignments.filter(futureAssignmentFilter).map((a) => (
|
||||||
|
<AssignmentCard
|
||||||
|
{...a}
|
||||||
|
users={users}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedAssignment(a);
|
||||||
|
setIsCreatingAssignment(true);
|
||||||
|
}}
|
||||||
|
key={a.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="flex flex-col gap-4">
|
||||||
|
<h2 className="text-2xl font-semibold">Past Assignments ({assignments.filter(pastAssignmentFilter).length})</h2>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{assignments.filter(pastAssignmentFilter).map((a) => (
|
||||||
|
<AssignmentCard
|
||||||
|
{...a}
|
||||||
|
users={users}
|
||||||
|
onClick={() => setSelectedAssignment(a)}
|
||||||
|
key={a.id}
|
||||||
|
allowDownload
|
||||||
|
reload={reloadAssignments}
|
||||||
|
allowArchive
|
||||||
|
allowExcelDownload
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="flex flex-col gap-4">
|
||||||
|
<h2 className="text-2xl font-semibold">Archived Assignments ({assignments.filter(archivedAssignmentFilter).length})</h2>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{assignments.filter(archivedAssignmentFilter).map((a) => (
|
||||||
|
<AssignmentCard
|
||||||
|
{...a}
|
||||||
|
users={users}
|
||||||
|
onClick={() => setSelectedAssignment(a)}
|
||||||
|
key={a.id}
|
||||||
|
allowDownload
|
||||||
|
reload={reloadAssignments}
|
||||||
|
allowUnarchive
|
||||||
|
allowExcelDownload
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ export function getUserCompanyName(user: User, users: User[], groups: Group[]) {
|
|||||||
if (isCorporateUser(user)) return user.corporateInformation?.companyInformation?.name || user.name;
|
if (isCorporateUser(user)) return user.corporateInformation?.companyInformation?.name || user.name;
|
||||||
if (isAgentUser(user)) return user.agentInformation?.companyName || user.name;
|
if (isAgentUser(user)) return user.agentInformation?.companyName || user.name;
|
||||||
|
|
||||||
const belongingGroups = groups.filter((x) => x.participants.includes(user.id));
|
const belongingGroups = groups.filter((x) => x.participants.includes(user?.id));
|
||||||
const belongingGroupsAdmins = belongingGroups.map((x) => users.find((u) => u.id === x.admin)).filter((x) => !!x && isCorporateUser(x));
|
const belongingGroupsAdmins = belongingGroups.map((x) => users.find((u) => u.id === x.admin)).filter((x) => !!x && isCorporateUser(x));
|
||||||
|
|
||||||
if (belongingGroupsAdmins.length === 0) return "";
|
if (belongingGroupsAdmins.length === 0) return "";
|
||||||
|
|||||||
Reference in New Issue
Block a user