From 1aa4f0ddfd83369636dcae46c405f3236e75c7c6 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Tue, 10 Oct 2023 21:17:46 +0100 Subject: [PATCH] Updated a bit more of the way the codes work --- src/components/Diagnostic.tsx | 12 +++--------- src/interfaces/user.ts | 1 + src/pages/api/code.ts | 2 +- src/pages/api/register.ts | 14 ++++++++------ src/pages/exam.tsx | 27 +++++---------------------- src/pages/exercises.tsx | 27 +++++---------------------- src/pages/index.tsx | 29 +++++++++++++++++++++++++++++ src/pages/register.tsx | 2 +- src/utils/exams.ts | 20 ++++++++++++++++++++ 9 files changed, 73 insertions(+), 61 deletions(-) diff --git a/src/components/Diagnostic.tsx b/src/components/Diagnostic.tsx index 20be4856..16077b70 100644 --- a/src/components/Diagnostic.tsx +++ b/src/components/Diagnostic.tsx @@ -3,7 +3,8 @@ import {BAND_SCORES} from "@/constants/ielts"; import {Module} from "@/interfaces"; import {User} from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; -import {getExamById} from "@/utils/exams"; +import {getExam, getExamById} from "@/utils/exams"; +import {MODULE_ARRAY} from "@/utils/moduleUtils"; import {writingMarking} from "@/utils/score"; import {Menu} from "@headlessui/react"; import axios from "axios"; @@ -20,13 +21,6 @@ interface Props { onFinish: () => void; } -const DIAGNOSTIC_EXAMS = [ - ["reading", "CurQtQoxWmHaJHeN0JW2"], - ["listening", "Y6cMao8kUcVnPQOo6teV"], - ["writing", "B1J90R4Lmdn2dwjdHEwj"], - ["speaking", "QVFm4pdcziJQZN2iUTDo"], -]; - export default function Diagnostic({onFinish}: Props) { const [focus, setFocus] = useState<"academic" | "general">(); const [levels, setLevels] = useState({reading: -1, listening: -1, writing: -1, speaking: -1}); @@ -43,7 +37,7 @@ export default function Diagnostic({onFinish}: Props) { }; const selectExam = () => { - const examPromises = DIAGNOSTIC_EXAMS.map((exam) => getExamById(exam[0] as Module, exam[1])); + const examPromises = MODULE_ARRAY.map((module) => getExam(module, true)); Promise.all(examPromises).then((exams) => { if (exams.every((x) => !!x)) { diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index 16a6f22b..c97f125e 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -14,6 +14,7 @@ export interface User { bio: string; isVerified: boolean; demographicInformation?: DemographicInformation; + subscriptionExpirationDate?: null | Date; isDisabled?: boolean; } diff --git a/src/pages/api/code.ts b/src/pages/api/code.ts index 3eea2e4d..df569480 100644 --- a/src/pages/api/code.ts +++ b/src/pages/api/code.ts @@ -29,7 +29,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { const codePromises = codes.map(async (code, index) => { const codeRef = doc(db, "codes", code); - await setDoc(codeRef, {type, code}); + await setDoc(codeRef, {type, code, creator: req.session.user!.id}); if (emails && emails.length > index) { const transport = prepareMailer(); diff --git a/src/pages/api/register.ts b/src/pages/api/register.ts index 71fb07cd..e4cf53f8 100644 --- a/src/pages/api/register.ts +++ b/src/pages/api/register.ts @@ -1,9 +1,9 @@ import {NextApiRequest, NextApiResponse} from "next"; -import {createUserWithEmailAndPassword, getAuth, sendPasswordResetEmail} from "firebase/auth"; +import {createUserWithEmailAndPassword, getAuth} from "firebase/auth"; import {app} from "@/firebase"; import {sessionOptions} from "@/lib/session"; import {withIronSessionApiRoute} from "iron-session/next"; -import {getFirestore, getDoc, doc, setDoc, deleteDoc} from "firebase/firestore"; +import {getFirestore, doc, setDoc, query, collection, where, getDocs} from "firebase/firestore"; import {DemographicInformation, Type} from "@/interfaces/user"; const auth = getAuth(app); @@ -28,13 +28,15 @@ const DEFAULT_LEVELS = { async function login(req: NextApiRequest, res: NextApiResponse) { const {email, password, code} = req.body as {email: string; password: string; code: string; demographicInformation: DemographicInformation}; - const codeRef = await getDoc(doc(db, "codes", code)); - if (!codeRef.exists()) { + 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) { res.status(400).json({error: "Invalid Code!"}); return; } - const codeData = codeRef.data() as {code: string; type: Type}; + const codeData = codeDocs[0].data() as {code: string; type: Type}; createUserWithEmailAndPassword(auth, email, password) .then(async (userCredentials) => { @@ -52,7 +54,7 @@ async function login(req: NextApiRequest, res: NextApiResponse) { }; await setDoc(doc(db, "users", userId), user); - await deleteDoc(codeRef.ref); + await setDoc(codeDocs[0].ref, {userId: userId}, {merge: true}); req.session.user = {...user, id: userId}; await req.session.save(); diff --git a/src/pages/exam.tsx b/src/pages/exam.tsx index d69507bd..6b2ea0ec 100644 --- a/src/pages/exam.tsx +++ b/src/pages/exam.tsx @@ -33,6 +33,7 @@ import {speakingReverseMarking, writingReverseMarking} from "@/utils/score"; import AbandonPopup from "@/components/AbandonPopup"; import {evaluateSpeakingAnswer, evaluateWritingAnswer} from "@/utils/evaluation"; import {useRouter} from "next/router"; +import {getExam} from "@/utils/exams"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -85,10 +86,13 @@ export default function Page() { useEffect(() => { (async () => { if (selectedModules.length > 0 && exams.length === 0) { - const examPromises = selectedModules.map(getExam); + const examPromises = selectedModules.map((module) => getExam(module, avoidRepeated)); Promise.all(examPromises).then((values) => { if (values.every((x) => !!x)) { setExams(values.map((x) => x!)); + } else { + toast.error("Something went wrong, please try again"); + setTimeout(router.reload, 500); } }); } @@ -115,27 +119,6 @@ export default function Page() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedModules, moduleIndex, hasBeenUploaded]); - const getExam = async (module: Module): Promise => { - const examRequest = await axios(`/api/exam/${module}?avoidRepeated=${avoidRepeated}`); - if (examRequest.status !== 200) { - toast.error("Something went wrong!"); - return undefined; - } - - const newExam = examRequest.data; - - switch (module) { - case "reading": - return newExam.shift() as ReadingExam; - case "listening": - return newExam.shift() as ListeningExam; - case "writing": - return newExam.shift() as WritingExam; - case "speaking": - return newExam.shift() as SpeakingExam; - } - }; - const updateExamWithUserSolutions = (exam: Exam): Exam => { if (exam.module === "reading" || exam.module === "listening") { const parts = exam.parts.map((p) => diff --git a/src/pages/exercises.tsx b/src/pages/exercises.tsx index e1a813ac..622cdb82 100644 --- a/src/pages/exercises.tsx +++ b/src/pages/exercises.tsx @@ -36,6 +36,7 @@ import {speakingReverseMarking, writingReverseMarking} from "@/utils/score"; import AbandonPopup from "@/components/AbandonPopup"; import {evaluateSpeakingAnswer, evaluateWritingAnswer} from "@/utils/evaluation"; import {useRouter} from "next/router"; +import {getExam} from "@/utils/exams"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -89,10 +90,13 @@ export default function Page() { useEffect(() => { (async () => { if (selectedModules.length > 0 && exams.length === 0) { - const examPromises = selectedModules.map(getExam); + const examPromises = selectedModules.map((module) => getExam(module, avoidRepeated)); Promise.all(examPromises).then((values) => { if (values.every((x) => !!x)) { setExams(values.map((x) => x!)); + } else { + toast.error("Something went wrong, please try again"); + setTimeout(router.reload, 500); } }); } @@ -119,27 +123,6 @@ export default function Page() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedModules, moduleIndex, hasBeenUploaded]); - const getExam = async (module: Module): Promise => { - const examRequest = await axios(`/api/exam/${module}?avoidRepeated=${avoidRepeated}`); - if (examRequest.status !== 200) { - toast.error("Something went wrong!"); - return undefined; - } - - const newExam = examRequest.data; - - switch (module) { - case "reading": - return newExam.shift() as ReadingExam; - case "listening": - return newExam.shift() as ListeningExam; - case "writing": - return newExam.shift() as WritingExam; - case "speaking": - return newExam.shift() as SpeakingExam; - } - }; - const updateExamWithUserSolutions = (exam: Exam): Exam => { if (exam.module === "reading" || exam.module === "listening") { const parts = exam.parts.map((p) => diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 952791cc..4e250168 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -18,6 +18,7 @@ import Layout from "@/components/High/Layout"; import {calculateAverageLevel} from "@/utils/score"; import axios from "axios"; import DemographicInformationInput from "@/components/DemographicInformationInput"; +import moment from "moment"; export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; @@ -51,6 +52,34 @@ export default function Home() { } }, [user]); + const checkIfUserExpired = () => { + const expirationDate = user!.subscriptionExpirationDate; + + if (expirationDate === null || expirationDate === undefined) return false; + if (moment(expirationDate).isAfter(moment(new Date()))) return false; + + return true; + }; + + if (user && (user.isDisabled || checkIfUserExpired())) { + return ( + <> + + EnCoach | Muscat Training Institute + + + + + +
+
+ + ); + } + if (user && showDemographicInput) { return ( <> diff --git a/src/pages/register.tsx b/src/pages/register.tsx index 2995add0..c0b2182c 100644 --- a/src/pages/register.tsx +++ b/src/pages/register.tsx @@ -18,7 +18,7 @@ export const getServerSideProps = (context: any) => { const {code} = context.query; return { - props: {code}, + props: {code: code || null}, }; }; diff --git a/src/utils/exams.ts b/src/utils/exams.ts index 0dda9342..cfd522d1 100644 --- a/src/utils/exams.ts +++ b/src/utils/exams.ts @@ -12,6 +12,26 @@ import { } from "@/interfaces/exam"; import axios from "axios"; +export const getExam = async (module: Module, avoidRepeated: boolean): Promise => { + const examRequest = await axios(`/api/exam/${module}?avoidRepeated=${avoidRepeated}`); + if (examRequest.status !== 200) { + return undefined; + } + + const newExam = examRequest.data; + + switch (module) { + case "reading": + return newExam.shift() as ReadingExam; + case "listening": + return newExam.shift() as ListeningExam; + case "writing": + return newExam.shift() as WritingExam; + case "speaking": + return newExam.shift() as SpeakingExam; + } +}; + export const getExamById = async (module: Module, id: string): Promise => { const examRequest = await axios(`/api/exam/${module}/${id}`); if (examRequest.status !== 200) {