From 95c3f899117cf48a73bc816285b003fec67f1652 Mon Sep 17 00:00:00 2001 From: Joao Ramos Date: Tue, 6 Aug 2024 19:24:43 +0100 Subject: [PATCH] Added title to the exam generate --- src/pages/(generation)/LevelGeneration.tsx | 12 ++++++++- .../(generation)/ListeningGeneration.tsx | 13 ++++++++-- src/pages/(generation)/ReadingGeneration.tsx | 15 ++++++++--- src/pages/(generation)/SpeakingGeneration.tsx | 13 ++++++++-- src/pages/(generation)/WritingGeneration.tsx | 13 ++++++++-- src/pages/api/exam/[module]/index.ts | 25 ++++++++++++++++--- src/pages/generation.tsx | 22 ++++++++++++---- 7 files changed, 94 insertions(+), 19 deletions(-) diff --git a/src/pages/(generation)/LevelGeneration.tsx b/src/pages/(generation)/LevelGeneration.tsx index 3ebf73c0..09b1615a 100644 --- a/src/pages/(generation)/LevelGeneration.tsx +++ b/src/pages/(generation)/LevelGeneration.tsx @@ -230,7 +230,11 @@ const TaskTab = ({section, setSection}: {section: LevelSection; setSection: (sec ); }; -const LevelGeneration = () => { +interface Props { + id: string; +} + +const LevelGeneration = ({ id } : Props) => { const [generatedExam, setGeneratedExam] = useState(); const [isLoading, setIsLoading] = useState(false); const [resultingExam, setResultingExam] = useState(); @@ -420,10 +424,16 @@ const LevelGeneration = () => { return; } + if(!id) { + toast.error("Please insert a title before submitting"); + return; + } + setIsLoading(true); const exam = { ...generatedExam, + id, parts: generatedExam.parts.map((p, i) => ({...p, exercises: parts[i].part!.exercises})), }; diff --git a/src/pages/(generation)/ListeningGeneration.tsx b/src/pages/(generation)/ListeningGeneration.tsx index 85fd1064..5388b183 100644 --- a/src/pages/(generation)/ListeningGeneration.tsx +++ b/src/pages/(generation)/ListeningGeneration.tsx @@ -228,7 +228,11 @@ interface ListeningPart { | string; } -const ListeningGeneration = () => { +interface Props { + id: string; +} + +const ListeningGeneration = ({ id } : Props) => { const [part1, setPart1] = useState(); const [part2, setPart2] = useState(); const [part3, setPart3] = useState(); @@ -258,11 +262,16 @@ const ListeningGeneration = () => { console.log({parts}); if (parts.length === 0) return toast.error("Please generate at least one section!"); + if(!id) { + toast.error("Please insert a title before submitting"); + return; + } + setIsLoading(true); axios .post(`/api/exam/listening/generate/listening`, { - id: generate({minLength: 4, maxLength: 8, min: 3, max: 5, join: " ", formatter: capitalize}), + id, parts, minTimer, difficulty, diff --git a/src/pages/(generation)/ReadingGeneration.tsx b/src/pages/(generation)/ReadingGeneration.tsx index de4a0caf..6bd81dde 100644 --- a/src/pages/(generation)/ReadingGeneration.tsx +++ b/src/pages/(generation)/ReadingGeneration.tsx @@ -258,7 +258,11 @@ const PartTab = ({ ); }; -const ReadingGeneration = () => { +interface Props { + id: string; +} + +const ReadingGeneration = ({ id } : Props) => { const [part1, setPart1] = useState(); const [part2, setPart2] = useState(); const [part3, setPart3] = useState(); @@ -300,13 +304,18 @@ const ReadingGeneration = () => { return; } + if(!id) { + toast.error("Please insert a title before submitting"); + return; + } + setIsLoading(true); const exam: ReadingExam = { parts, isDiagnostic: false, minTimer, module: "reading", - id: generate({minLength: 4, maxLength: 8, min: 3, max: 5, join: " ", formatter: capitalize}), + id, type: "academic", variant: parts.length === 3 ? "full" : "partial", difficulty, @@ -328,7 +337,7 @@ const ReadingGeneration = () => { }) .catch((error) => { console.log(error); - toast.error("Something went wrong while generating, please try again later."); + toast.error(error.response.data.error || "Something went wrong while generating, please try again later."); }) .finally(() => setIsLoading(false)); }; diff --git a/src/pages/(generation)/SpeakingGeneration.tsx b/src/pages/(generation)/SpeakingGeneration.tsx index 7b6b26ea..c4959f6c 100644 --- a/src/pages/(generation)/SpeakingGeneration.tsx +++ b/src/pages/(generation)/SpeakingGeneration.tsx @@ -221,7 +221,11 @@ interface SpeakingPart { avatar?: (typeof AVATARS)[number]; } -const SpeakingGeneration = () => { +interface Props { + id: string; +} + +const SpeakingGeneration = ({ id } : Props) => { const [part1, setPart1] = useState(); const [part2, setPart2] = useState(); const [part3, setPart3] = useState(); @@ -243,6 +247,11 @@ const SpeakingGeneration = () => { const submitExam = () => { if (!part1?.result && !part2?.result && !part3?.result) return toast.error("Please generate at least one task!"); + if(!id) { + toast.error("Please insert a title before submitting"); + return; + } + setIsLoading(true); const genders = [part1?.gender, part2?.gender, part3?.gender].filter((x) => !!x); @@ -256,7 +265,7 @@ const SpeakingGeneration = () => { })); const exam: SpeakingExam = { - id: generate({minLength: 4, maxLength: 8, min: 3, max: 5, join: " ", formatter: capitalize}), + id, isDiagnostic: false, exercises: exercises as (SpeakingExercise | InteractiveSpeakingExercise)[], minTimer, diff --git a/src/pages/(generation)/WritingGeneration.tsx b/src/pages/(generation)/WritingGeneration.tsx index 6555614a..be4e12cd 100644 --- a/src/pages/(generation)/WritingGeneration.tsx +++ b/src/pages/(generation)/WritingGeneration.tsx @@ -75,7 +75,11 @@ const TaskTab = ({task, index, difficulty, setTask}: {task?: string; difficulty: ); }; -const WritingGeneration = () => { +interface Props { + id: string; +} + +const WritingGeneration = ({ id } : Props) => { const [task1, setTask1] = useState(); const [task2, setTask2] = useState(); const [minTimer, setMinTimer] = useState(60); @@ -116,6 +120,11 @@ const WritingGeneration = () => { return; } + if(!id) { + toast.error("Please insert a title before submitting"); + return; + } + const exercise1 = task1 ? ({ id: v4(), @@ -152,7 +161,7 @@ const WritingGeneration = () => { minTimer, module: "writing", exercises: [...(exercise1 ? [exercise1] : []), ...(exercise2 ? [exercise2] : [])], - id: generate({minLength: 4, maxLength: 8, min: 3, max: 5, join: " ", formatter: capitalize}), + id, variant: exercise1 && exercise2 ? "full" : "partial", difficulty, }; diff --git a/src/pages/api/exam/[module]/index.ts b/src/pages/api/exam/[module]/index.ts index e7ff0699..95d1eb9f 100644 --- a/src/pages/api/exam/[module]/index.ts +++ b/src/pages/api/exam/[module]/index.ts @@ -1,7 +1,7 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type {NextApiRequest, NextApiResponse} from "next"; import {app} from "@/firebase"; -import {getFirestore, setDoc, doc} from "firebase/firestore"; +import {getFirestore, setDoc, doc, runTransaction, collection, query, where, getDocs} from "firebase/firestore"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {Exam, InstructorGender, Variant} from "@/interfaces/exam"; @@ -47,8 +47,25 @@ async function POST(req: NextApiRequest, res: NextApiResponse) { } const {module} = req.query as {module: string}; - const exam = {...req.body, module: module}; - await setDoc(doc(db, module, req.body.id), exam); + + try { + const exam = {...req.body, module: module}; + await runTransaction(db, async (transaction) => { - res.status(200).json(exam); + const docRef = doc(db, module, req.body.id); + const docSnap = await transaction.get(docRef); + + if (docSnap.exists()) { + throw new Error('Name already exists'); + } + + + const newDocRef = doc(db, module, req.body.id); + transaction.set(newDocRef, exam); + }); + res.status(200).json(exam); + } catch (error) { + console.error("Transaction failed: ", error); + res.status(500).json({ok: false, error: (error as any).message}); + } } diff --git a/src/pages/generation.tsx b/src/pages/generation.tsx index c2a0de83..2fd4660d 100644 --- a/src/pages/generation.tsx +++ b/src/pages/generation.tsx @@ -57,6 +57,7 @@ export default function Generation() { const { user } = useUser({ redirectTo: "/login" }); + const [title, setTitle] = useState(""); return ( <> @@ -73,6 +74,17 @@ export default function Generation() {

Exam Generation

+ + @@ -117,11 +129,11 @@ export default function Generation() { ))}
- {module === "reading" && } - {module === "listening" && } - {module === "writing" && } - {module === "speaking" && } - {module === "level" && } + {module === "reading" && } + {module === "listening" && } + {module === "writing" && } + {module === "speaking" && } + {module === "level" && }
)}