diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 1f43a5c8..e546a2dc 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -53,7 +53,7 @@ export default function Navbar({user, path, navDisabled = false, focusMode = fal
{showExpirationDate() && ( setCompanyName(e)} - placeholder="Institution name" - label="Institution name" + placeholder="Corporate name" + label="Corporate name" defaultValue={companyName} required /> @@ -134,7 +134,7 @@ export default function RegisterCorporate({isLoading, setIsLoading, mutateUser, type="number" name="companyUsers" onChange={(e) => setCompanyUsers(parseInt(e))} - label="Amount of users" + label="Number of users" defaultValue={companyUsers} required /> diff --git a/src/pages/(register)/RegisterIndividual.tsx b/src/pages/(register)/RegisterIndividual.tsx index 727c3c33..9fbd7bf4 100644 --- a/src/pages/(register)/RegisterIndividual.tsx +++ b/src/pages/(register)/RegisterIndividual.tsx @@ -1,4 +1,5 @@ import Button from "@/components/Low/Button"; +import Checkbox from "@/components/Low/Checkbox"; import Input from "@/components/Low/Input"; import {User} from "@/interfaces/user"; import {sendEmailVerification} from "@/utils/email"; @@ -21,6 +22,7 @@ export default function RegisterIndividual({queryCode, isLoading, setIsLoading, const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [code, setCode] = useState(queryCode || ""); + const [hasCode, setHasCode] = useState(!!queryCode); const onSuccess = () => toast.success("An e-mail has been sent, please make sure to check your spam folder!"); @@ -88,12 +90,27 @@ export default function RegisterIndividual({queryCode, isLoading, setIsLoading, defaultValue={confirmPassword} required /> - setCode(e)} placeholder="Enter your registration code" defaultValue={code} required /> + + {/** TODO: Add a checkbox to disable code */} +
+ + I have a code + + {hasCode && ( + setCode(e)} + placeholder="Enter your registration code (optional)" + defaultValue={code} + /> + )} +
diff --git a/src/pages/(status)/PaymentDue.tsx b/src/pages/(status)/PaymentDue.tsx index 685a81ae..7e518e10 100644 --- a/src/pages/(status)/PaymentDue.tsx +++ b/src/pages/(status)/PaymentDue.tsx @@ -19,7 +19,7 @@ import {Divider} from "primereact/divider"; import Input from "@/components/Low/Input"; import Button from "@/components/Low/Button"; -export default function PaymentDue({user, reload}: {user: User; reload: () => void}) { +export default function PaymentDue({user, hasExpired, reload}: {user: User; hasExpired?: boolean; reload: () => void}) { const [isLoading, setIsLoading] = useState(false); const {packages} = usePackages(); @@ -48,9 +48,9 @@ export default function PaymentDue({user, reload}: {user: User; reload: () => vo
)} {user ? ( - +
- You do not have time credits for your account type! + {hasExpired && You do not have time credits for your account type!} {isIndividual() && (
diff --git a/src/pages/api/register.ts b/src/pages/api/register.ts index f5b0348f..e1607d3d 100644 --- a/src/pages/api/register.ts +++ b/src/pages/api/register.ts @@ -6,6 +6,7 @@ import {withIronSessionApiRoute} from "iron-session/next"; import {getFirestore, doc, setDoc, query, collection, where, getDocs} from "firebase/firestore"; import {CorporateInformation, DemographicInformation, Type} from "@/interfaces/user"; import {addUserToGroupOnCreation} from "@/utils/registration"; +import moment from "moment"; const auth = getAuth(app); const db = getFirestore(app); @@ -45,12 +46,12 @@ async function registerIndividual(req: NextApiRequest, res: NextApiResponse) { const codeQuery = query(collection(db, "codes"), where("code", "==", code)); const codeDocs = (await getDocs(codeQuery)).docs.filter((x) => !Object.keys(x.data()).includes("userId")); - if (codeDocs.length === 0) { + if (code && code.length > 0 && codeDocs.length === 0) { res.status(400).json({error: "Invalid Code!"}); return; } - const codeData = codeDocs[0].data() as {code: string; type: Type; creator?: string; expiryDate: Date | null}; + const codeData = codeDocs.length > 0 ? (codeDocs[0].data() as {code: string; type: Type; creator?: string; expiryDate: Date | null}) : undefined; createUserWithEmailAndPassword(auth, email, password) .then(async (userCredentials) => { @@ -62,17 +63,20 @@ async function registerIndividual(req: NextApiRequest, res: NextApiResponse) { desiredLevels: DEFAULT_DESIRED_LEVELS, levels: DEFAULT_LEVELS, bio: "", - isFirstLogin: codeData.type === "student", + isFirstLogin: codeData ? codeData.type === "student" : true, focus: "academic", - type: codeData.type, - subscriptionExpirationDate: codeData.expiryDate, + type: codeData ? codeData.type : "student", + subscriptionExpirationDate: codeData ? codeData.expiryDate : moment().subtract(1, "days").toISOString(), registrationDate: new Date(), status: code ? "active" : "paymentDue", }; await setDoc(doc(db, "users", userId), user); - await setDoc(codeDocs[0].ref, {userId: userId}, {merge: true}); - if (codeData.creator) await addUserToGroupOnCreation(userId, codeData.type, codeData.creator); + + if (codeDocs.length > 0 && codeData) { + await setDoc(codeDocs[0].ref, {userId: userId}, {merge: true}); + if (codeData.creator) await addUserToGroupOnCreation(userId, codeData.type, codeData.creator); + } req.session.user = {...user, id: userId}; await req.session.save(); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index e249d187..db14347e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -92,7 +92,7 @@ export default function Home() {
)} - {(user.status === "paymentDue" || checkIfUserExpired()) && } + {(user.status === "paymentDue" || checkIfUserExpired()) && } ); } diff --git a/src/pages/payment.tsx b/src/pages/payment.tsx new file mode 100644 index 00000000..a0a6945a --- /dev/null +++ b/src/pages/payment.tsx @@ -0,0 +1,70 @@ +/* eslint-disable @next/next/no-img-element */ +import Head from "next/head"; +import Navbar from "@/components/Navbar"; +import {BsFileEarmarkText, BsPencil, BsStar, BsBook, BsHeadphones, BsPen, BsMegaphone} from "react-icons/bs"; +import {withIronSessionSsr} from "iron-session/next"; +import {sessionOptions} from "@/lib/session"; +import {useEffect, useState} from "react"; +import useStats from "@/hooks/useStats"; +import {averageScore, groupBySession, totalExams} from "@/utils/stats"; +import useUser from "@/hooks/useUser"; +import Sidebar from "@/components/Sidebar"; +import Diagnostic from "@/components/Diagnostic"; +import {ToastContainer} from "react-toastify"; +import {capitalize} from "lodash"; +import {Module} from "@/interfaces"; +import ProgressBar from "@/components/Low/ProgressBar"; +import Layout from "@/components/High/Layout"; +import {calculateAverageLevel} from "@/utils/score"; +import axios from "axios"; +import DemographicInformationInput from "@/components/DemographicInformationInput"; +import moment from "moment"; +import Link from "next/link"; +import {MODULE_ARRAY} from "@/utils/moduleUtils"; +import ProfileSummary from "@/components/ProfileSummary"; +import StudentDashboard from "@/dashboards/Student"; +import AdminDashboard from "@/dashboards/Admin"; +import CorporateDashboard from "@/dashboards/Corporate"; +import TeacherDashboard from "@/dashboards/Teacher"; +import AgentDashboard from "@/dashboards/Agent"; +import PaymentDue from "./(status)/PaymentDue"; +import {useRouter} from "next/router"; + +export const getServerSideProps = withIronSessionSsr(({req, res}) => { + const user = req.session.user; + + if (!user || !user.isVerified) { + res.setHeader("location", "/login"); + res.statusCode = 302; + res.end(); + return { + props: { + user: null, + }, + }; + } + + return { + props: {user: req.session.user}, + }; +}, sessionOptions); + +export default function Home() { + const {user, mutateUser} = useUser({redirectTo: "/login"}); + const router = useRouter(); + + return ( + <> + + EnCoach + + + + + {user && } + + ); +} diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index abf372c6..44386fab 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -296,9 +296,9 @@ export default function Home() {
- + -
+