Created the first exercise of the listening demo

This commit is contained in:
Tiago Ribeiro
2023-03-24 18:09:05 +00:00
parent 3d74bf9bf1
commit 2b38f9df9b
8 changed files with 473 additions and 84 deletions

View File

@@ -1,9 +1,12 @@
import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles";
import {FillBlanksExercise} from "@/interfaces/exam";
import {Dialog, Transition} from "@headlessui/react";
import { mdiArrowLeft, mdiArrowRight } from "@mdi/js";
import Icon from "@mdi/react";
import clsx from "clsx";
import {Fragment, useState} from "react";
import reactStringReplace from "react-string-replace";
import { CommonProps } from ".";
interface WordsPopoutProps {
words: {word: string; isDisabled: boolean}[];
@@ -12,6 +15,8 @@ interface WordsPopoutProps {
onAnswer: (answer: string) => void;
}
type UserSolution = {id: string; solution: string};
function WordsPopout({words, isOpen, onCancel, onAnswer}: WordsPopoutProps) {
return (
<Transition appear show={isOpen} as={Fragment}>
@@ -67,7 +72,7 @@ function WordsPopout({words, isOpen, onCancel, onAnswer}: WordsPopoutProps) {
);
}
export default function FillBlanks({allowRepetition, prompt, solutions, text, words}: FillBlanksExercise) {
export default function FillBlanks({allowRepetition, prompt, solutions, text, words, onNext, onBack}: FillBlanksExercise & CommonProps) {
const [userSolutions, setUserSolutions] = useState<{id: string; solution: string}[]>([]);
const [currentBlankId, setCurrentBlankId] = useState<string>();
@@ -89,6 +94,7 @@ export default function FillBlanks({allowRepetition, prompt, solutions, text, wo
};
return (
<>
<div className="flex flex-col">
<WordsPopout
words={words.map((word) => ({word, isDisabled: allowRepetition ? false : userSolutions.map((x) => x.solution).includes(word)}))}
@@ -109,5 +115,77 @@ export default function FillBlanks({allowRepetition, prompt, solutions, text, wo
))}
</span>
</div>
<div className="self-end flex gap-8">
<button className={clsx("btn btn-wide gap-4 relative text-white", errorButtonStyle)} onClick={onBack}>
<div className="absolute left-4">
<Icon path={mdiArrowLeft} color="white" size={1} />
</div>
Back
</button>
<button className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)} onClick={onNext}>
Next
<div className="absolute right-4">
<Icon path={mdiArrowRight} color="white" size={1} />
</div>
</button>
</div>
</>
);
}
export function FillBlanksSolutions({
allowRepetition,
prompt,
solutions,
text,
words,
userSolutions,
}: FillBlanksExercise & {userSolutions: UserSolution[]}) {
const renderLines = (line: string) => {
return (
<span>
{reactStringReplace(line, /({{\d}})/g, (match) => {
const id = match.replaceAll(/[\{\}]/g, "");
const userSolution = userSolutions.find((x) => x.id === id);
const solution = solutions.find((x) => x.id === id)!;
if (!userSolution) {
return (
<>
<button className={clsx("border-2 rounded-xl px-4 text-gray-500 border-gray-500")}>{solution.solution}</button>
</>
);
}
if (userSolution.solution === solution.solution) {
return <button className={clsx("border-2 rounded-xl px-4 text-green-500 border-green-500")}>{solution.solution}</button>;
}
if (userSolution.solution !== solution.solution) {
return (
<>
<button className={clsx("border-2 rounded-xl px-4 text-red-500 border-red-500 mr-1")}>{userSolution.solution}</button>
<button className={clsx("border-2 rounded-xl px-4 text-gray-500 border-gray-500")}>{solution.solution}</button>
</>
);
}
})}
</span>
);
};
return (
<div className="flex flex-col">
<span className="text-lg font-medium text-center px-48">{prompt}</span>
<span>
{text.split("\n").map((line) => (
<>
{renderLines(line)}
<br />
</>
))}
</span>
</div>
);
}