From addef7c6740213312234c9b65422da14683f64f0 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 6 Apr 2023 12:02:07 +0100 Subject: [PATCH] Created a simple component for the writing exam --- package.json | 1 + src/demo/writing.json | 11 +++++++ src/exams/Writing.tsx | 67 ++++++++++++++++++++++++++++++++++++++++ src/interfaces/exam.ts | 16 +++++++++- src/pages/_app.tsx | 9 +++--- src/pages/exam/index.tsx | 12 ++++++- yarn.lock | 9 +++++- 7 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 src/demo/writing.json create mode 100644 src/exams/Writing.tsx diff --git a/package.json b/package.json index 6ae3f361..512991e0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-lineto": "^3.3.0", "react-player": "^2.12.0", "react-string-replace": "^1.1.0", + "react-toastify": "^9.1.2", "typescript": "4.9.5", "zustand": "^4.3.6" }, diff --git a/src/demo/writing.json b/src/demo/writing.json new file mode 100644 index 00000000..ad980986 --- /dev/null +++ b/src/demo/writing.json @@ -0,0 +1,11 @@ +{ + "module": "writing", + "text": { + "info": "You should spend about 20 minutes on this task.", + "prompt": "The charts below show the results of a survey of adult education. The first chart shows the reasons why adults decide to study. The pie chart shows how people think the costs of adult education should be shared.\nWrite a report for a university lecturer, describing the information shown below.", + "wordCounter": { + "type": "min", + "limit": 5 + } + } +} \ No newline at end of file diff --git a/src/exams/Writing.tsx b/src/exams/Writing.tsx new file mode 100644 index 00000000..e4631268 --- /dev/null +++ b/src/exams/Writing.tsx @@ -0,0 +1,67 @@ +import {infoButtonStyle} from "@/constants/buttonStyles"; +import {WritingExam} from "@/interfaces/exam"; +import clsx from "clsx"; +import {Fragment, useEffect, useState} from "react"; +import {toast} from "react-toastify"; + +interface Props { + exam: WritingExam; +} + +export default function Writing({exam}: Props) { + const [inputText, setInputText] = useState(""); + const [isSubmitEnabled, setIsSubmitEnabled] = useState(false); + + useEffect(() => { + const words = inputText.split(" ").filter((x) => x !== ""); + const {wordCounter} = exam.text; + 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!`); + setInputText(words.slice(0, words.length - 1).join(" ")); + } + } + }, [inputText, exam]); + + return ( +
+
+ {exam.text.info} + + {exam.text.prompt.split("\n").map((line, index) => ( + + {line} +
+
+ ))} +
+ + You should write {exam.text.wordCounter.type === "min" ? "at least" : "at most"} {exam.text.wordCounter.limit} words. + +
+