Compare commits

..

4 Commits

Author SHA1 Message Date
Tiago Ribeiro
2bfb94d01b Merged in develop (pull request #162)
Implemented limit 5 sessions per User
2025-03-05 08:22:28 +00:00
Tiago Ribeiro
a78e6eb64f Merged in develop (pull request #160)
Develop
2025-03-04 23:24:59 +00:00
Tiago Ribeiro
d78654a30f Merged in develop (pull request #158)
Develop
2025-03-04 10:02:57 +00:00
Tiago Ribeiro
53d6b0dd51 Merged in develop (pull request #153)
Prod Update - 12/02/2025
2025-02-12 09:13:08 +00:00
3 changed files with 26 additions and 184 deletions

View File

@@ -12,10 +12,6 @@ import {
BsCurrencyDollar, BsCurrencyDollar,
BsClipboardData, BsClipboardData,
BsPeople, BsPeople,
BsChevronDown,
BsChevronUp,
BsChatText,
BsCardText,
} from "react-icons/bs"; } from "react-icons/bs";
import { GoWorkflow } from "react-icons/go"; import { GoWorkflow } from "react-icons/go";
import { CiDumbbell } from "react-icons/ci"; import { CiDumbbell } from "react-icons/ci";
@@ -35,7 +31,7 @@ import {
useAllowedEntities, useAllowedEntities,
useAllowedEntitiesSomePermissions, useAllowedEntitiesSomePermissions,
} from "@/hooks/useEntityPermissions"; } from "@/hooks/useEntityPermissions";
import { useMemo, useState } from "react"; import { useMemo } from "react";
import { PermissionType } from "../interfaces/permissions"; import { PermissionType } from "../interfaces/permissions";
interface Props { interface Props {
@@ -56,7 +52,6 @@ interface NavProps {
disabled?: boolean; disabled?: boolean;
isMinimized?: boolean; isMinimized?: boolean;
badge?: number; badge?: number;
children?: React.ReactNode;
} }
const Nav = ({ const Nav = ({
@@ -67,71 +62,34 @@ const Nav = ({
disabled = false, disabled = false,
isMinimized = false, isMinimized = false,
badge, badge,
children,
}: NavProps) => { }: NavProps) => {
const [open, setOpen] = useState(false);
return ( return (
<div <Link
href={!disabled ? keyPath : ""}
className={clsx( className={clsx(
"flex flex-col gap-2 transition-all duration-300 ease-in-out", "flex items-center gap-4 rounded-full p-4 text-gray-500 hover:text-white",
open && !isMinimized && "bg-white rounded-xl" "transition-all duration-300 ease-in-out relative",
disabled
? "hover:bg-mti-gray-dim cursor-not-allowed"
: "hover:bg-mti-purple-light cursor-pointer",
path.startsWith(keyPath) && "bg-mti-purple-light text-white",
isMinimized ? "w-fit" : "w-full min-w-[200px] px-8 2xl:min-w-[220px]"
)} )}
> >
<Link <Icon size={24} />
href={!disabled ? keyPath : ""} {!isMinimized && <span className="text-lg font-semibold">{label}</span>}
className={clsx( {!!badge && badge > 0 && (
"flex items-center gap-4 rounded-full p-4 text-gray-500 hover:text-white", <div
"transition-all duration-300 ease-in-out relative", className={clsx(
disabled "bg-mti-purple-light h-5 w-5 text-xs rounded-full flex items-center justify-center text-white",
? "hover:bg-mti-gray-dim cursor-not-allowed" "transition ease-in-out duration-300",
: "hover:bg-mti-purple-light cursor-pointer", isMinimized && "absolute right-0 top-0"
path.startsWith(keyPath) && "bg-mti-purple-light text-white", )}
isMinimized ? "w-fit" : "w-full min-w-[200px] px-8 2xl:min-w-[220px]" >
)} {badge}
> </div>
<Icon size={24} /> )}
{!isMinimized && <span className="text-lg font-semibold">{label}</span>} </Link>
{!!badge && badge > 0 && (
<div
className={clsx(
"bg-mti-purple-light h-5 w-5 text-xs rounded-full flex items-center justify-center text-white",
"transition ease-in-out duration-300",
isMinimized && "absolute right-0 top-0"
)}
>
{badge}
</div>
)}
{children && (
<button
className="flex items-center gap-4 rounded-full p-4 absolute right-0"
onClick={(e) => {
setOpen((prev) => !prev);
e.preventDefault();
}}
>
{open ? (
<BsChevronUp
size={24}
className={clsx(
isMinimized && "hidden",
"transition ease-in-out duration-300"
)}
/>
) : (
<BsChevronDown
size={24}
className={clsx(
isMinimized && "hidden",
"transition ease-in-out duration-300"
)}
/>
)}
</button>
)}
</Link>
{open || isMinimized ? children : null}
</div>
); );
}; };
@@ -367,24 +325,7 @@ export default function Sidebar({
path={path} path={path}
keyPath="/training" keyPath="/training"
isMinimized={isMinimized} isMinimized={isMinimized}
> />
<Nav
disabled={disableNavigation}
Icon={BsChatText}
label="Vocabulary"
path={path}
keyPath="/training/vocabulary"
isMinimized={isMinimized}
/>
<Nav
disabled={disableNavigation}
Icon={BsCardText}
label="Grammar"
path={path}
keyPath="/training/grammar"
isMinimized={isMinimized}
/>
</Nav>
)} )}
{sidebarPermissions["viewPaymentRecords"] && ( {sidebarPermissions["viewPaymentRecords"] && (
<Nav <Nav
@@ -483,24 +424,7 @@ export default function Sidebar({
path={path} path={path}
keyPath="/training" keyPath="/training"
isMinimized isMinimized
> />
<Nav
disabled={disableNavigation}
Icon={BsChatText}
label="Vocabulary"
path={path}
keyPath="/training/vocabulary"
isMinimized
/>
<Nav
disabled={disableNavigation}
Icon={BsCardText}
label="Grammar"
path={path}
keyPath="/training/grammar"
isMinimized
/>
</Nav>
)} )}
{sidebarPermissions["viewPaymentRecords"] && ( {sidebarPermissions["viewPaymentRecords"] && (
<Nav <Nav

View File

@@ -1,41 +0,0 @@
/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import { withIronSessionSsr } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { User } from "@/interfaces/user";
import { ToastContainer } from "react-toastify";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import { redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
const user = await requestUser(req, res);
if (!user) return redirect("/login");
if (shouldRedirectHome(user)) return redirect("/");
return {
props: serialize({ user }),
};
}, sessionOptions);
const Grammar: React.FC<{
user: User;
}> = ({ user }) => {
return (
<>
<Head>
<title>Training | 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 />
</>
);
};
export default Grammar;

View File

@@ -1,41 +0,0 @@
/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import { withIronSessionSsr } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { User } from "@/interfaces/user";
import { ToastContainer } from "react-toastify";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import { redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
const user = await requestUser(req, res);
if (!user) return redirect("/login");
if (shouldRedirectHome(user)) return redirect("/");
return {
props: serialize({ user }),
};
}, sessionOptions);
const Vocabulary: React.FC<{
user: User;
}> = ({ user }) => {
return (
<>
<Head>
<title>Training | 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 />
</>
);
};
export default Vocabulary;