From 207328dadecc7557deac289287648818d4e947d3 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Mon, 17 Apr 2023 13:03:48 +0100 Subject: [PATCH] Updated the writing exam to work based on exercises instead of just a single one --- package.json | 1 + src/components/Exercises/Writing.tsx | 83 +++++++++++ src/components/Exercises/index.tsx | 13 +- src/exams/Listening.tsx | 4 +- src/exams/Reading.tsx | 4 +- src/exams/Writing.tsx | 95 ++++++------ src/interfaces/exam.ts | 18 ++- src/utils/string.ts | 9 ++ yarn.lock | 206 +++++++++++++++++++++++++-- 9 files changed, 359 insertions(+), 74 deletions(-) create mode 100644 src/components/Exercises/Writing.tsx create mode 100644 src/utils/string.ts diff --git a/package.json b/package.json index cf8fff68..1c5b0e76 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-dom": "18.2.0", "react-firebase-hooks": "^5.1.1", "react-lineto": "^3.3.0", + "react-media-recorder": "^1.6.6", "react-player": "^2.12.0", "react-string-replace": "^1.1.0", "react-toastify": "^9.1.2", diff --git a/src/components/Exercises/Writing.tsx b/src/components/Exercises/Writing.tsx new file mode 100644 index 00000000..ff2fc813 --- /dev/null +++ b/src/components/Exercises/Writing.tsx @@ -0,0 +1,83 @@ +import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles"; +import {WritingExercise} from "@/interfaces/exam"; +import {mdiArrowLeft, mdiArrowRight} from "@mdi/js"; +import Icon from "@mdi/react"; +import clsx from "clsx"; +import {CommonProps} from "."; +import {Fragment, useEffect, useState} from "react"; +import {toast} from "react-toastify"; + +export default function WriteBlanks({id, prompt, info, wordCounter, onNext, onBack}: WritingExercise & CommonProps) { + const [inputText, setInputText] = useState(""); + const [isSubmitEnabled, setIsSubmitEnabled] = useState(false); + + useEffect(() => { + const words = inputText.split(" ").filter((x) => x !== ""); + + if (wordCounter.type === "min") { + setIsSubmitEnabled(wordCounter.limit <= words.length); + } else { + setIsSubmitEnabled(true); + if (wordCounter.limit < words.length) { + toast.warning(`You have reached your word limit of ${wordCounter.limit} words!`, {toastId: "word-limit"}); + setInputText(words.slice(0, words.length - 1).join(" ")); + } + } + }, [inputText, wordCounter]); + + return ( +
+
+ {info} + + {prompt.split("\\n").map((line, index) => ( + + {line} +
+
+ ))} +
+ + You should write {wordCounter.type === "min" ? "at least" : "at most"} {wordCounter.limit} words. + +
+ +