- Adapted more of the design to be more responsive;
- Revamped some of the UserSolutions; - Transformed the homepage chart to use actual dynamic values; - Created an endpoint for the stats;
This commit is contained in:
@@ -70,7 +70,7 @@ function WordsPopout({words, isOpen, onCancel, onAnswer}: WordsPopoutProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export default function FillBlanks({id, allowRepetition, prompt, solutions, text, words, onNext, onBack}: FillBlanksExercise & CommonProps) {
|
||||
export default function FillBlanks({id, allowRepetition, type, prompt, solutions, text, words, onNext, onBack}: FillBlanksExercise & CommonProps) {
|
||||
const [userSolutions, setUserSolutions] = useState<{id: string; solution: string}[]>([]);
|
||||
const [currentBlankId, setCurrentBlankId] = useState<string>();
|
||||
|
||||
@@ -128,7 +128,7 @@ export default function FillBlanks({id, allowRepetition, prompt, solutions, text
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="self-end flex flex-col items-center md:items-start md:flex-row gap-8">
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row 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} />
|
||||
@@ -137,7 +137,7 @@ export default function FillBlanks({id, allowRepetition, prompt, solutions, text
|
||||
</button>
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
onClick={() => onNext({id, solutions: userSolutions, score: calculateScore()})}>
|
||||
onClick={() => onNext({exercise: id, solutions: userSolutions, score: calculateScore(), type})}>
|
||||
Next
|
||||
<div className="absolute right-4">
|
||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||
|
||||
@@ -3,11 +3,11 @@ import {MatchSentencesExercise} from "@/interfaces/exam";
|
||||
import {mdiArrowLeft, mdiArrowRight} from "@mdi/js";
|
||||
import Icon from "@mdi/react";
|
||||
import clsx from "clsx";
|
||||
import {useState} from "react";
|
||||
import {Fragment, useState} from "react";
|
||||
import LineTo from "react-lineto";
|
||||
import {CommonProps} from ".";
|
||||
|
||||
export default function MatchSentences({id, options, prompt, sentences, onNext, onBack}: MatchSentencesExercise & CommonProps) {
|
||||
export default function MatchSentences({id, options, type, prompt, sentences, onNext, onBack}: MatchSentencesExercise & CommonProps) {
|
||||
const [selectedQuestion, setSelectedQuestion] = useState<string>();
|
||||
const [userSolutions, setUserSolutions] = useState<{question: string; option: string}[]>([]);
|
||||
|
||||
@@ -31,7 +31,14 @@ export default function MatchSentences({id, options, prompt, sentences, onNext,
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center gap-8">
|
||||
<span className="text-lg font-medium text-center px-48">{prompt}</span>
|
||||
<span className="text-base md:text-lg font-medium text-center px-2 md:px-4 lg:px-48">
|
||||
{prompt.split("\\n").map((line, index) => (
|
||||
<Fragment key={index}>
|
||||
{line}
|
||||
<br />
|
||||
</Fragment>
|
||||
))}
|
||||
</span>
|
||||
<div className="grid grid-cols-2 gap-16 place-items-center">
|
||||
<div className="flex flex-col gap-1">
|
||||
{sentences.map(({sentence, id, color}) => (
|
||||
@@ -85,7 +92,7 @@ export default function MatchSentences({id, options, prompt, sentences, onNext,
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="self-end flex gap-8">
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row 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} />
|
||||
@@ -94,7 +101,7 @@ export default function MatchSentences({id, options, prompt, sentences, onNext,
|
||||
</button>
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
onClick={() => onNext({id, solutions: userSolutions, score: calculateScore()})}>
|
||||
onClick={() => onNext({exercise: id, solutions: userSolutions, score: calculateScore(), type})}>
|
||||
Next
|
||||
<div className="absolute right-4">
|
||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||
|
||||
@@ -83,7 +83,7 @@ function Question({
|
||||
);
|
||||
}
|
||||
|
||||
export default function MultipleChoice({id, prompt, questions, onNext, onBack}: MultipleChoiceExercise & CommonProps) {
|
||||
export default function MultipleChoice({id, prompt, type, questions, onNext, onBack}: MultipleChoiceExercise & CommonProps) {
|
||||
const [userSolutions, setUserSolutions] = useState<{question: string; option: string}[]>([]);
|
||||
const [questionIndex, setQuestionIndex] = useState(0);
|
||||
|
||||
@@ -101,7 +101,7 @@ export default function MultipleChoice({id, prompt, questions, onNext, onBack}:
|
||||
|
||||
const next = () => {
|
||||
if (questionIndex === questions.length - 1) {
|
||||
onNext({id, solutions: userSolutions, score: calculateScore()});
|
||||
onNext({exercise: id, solutions: userSolutions, score: calculateScore(), type});
|
||||
} else {
|
||||
setQuestionIndex((prev) => prev + 1);
|
||||
}
|
||||
@@ -127,7 +127,8 @@ export default function MultipleChoice({id, prompt, questions, onNext, onBack}:
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="self-end flex gap-8">
|
||||
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row gap-8">
|
||||
<button className={clsx("btn btn-wide gap-4 relative text-white", errorButtonStyle)} onClick={back}>
|
||||
<div className="absolute left-4">
|
||||
<Icon path={mdiArrowLeft} color="white" size={1} />
|
||||
|
||||
@@ -7,7 +7,7 @@ import {CommonProps} from ".";
|
||||
import {Fragment, useEffect, useState} from "react";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export default function Speaking({id, title, text, prompts, onNext, onBack}: SpeakingExercise & CommonProps) {
|
||||
export default function Speaking({id, title, text, type, prompts, onNext, onBack}: SpeakingExercise & CommonProps) {
|
||||
return (
|
||||
<div className="flex flex-col h-full w-2/3 items-center justify-center gap-8">
|
||||
<div className="flex flex-col max-w-2xl gap-4">
|
||||
@@ -32,7 +32,7 @@ export default function Speaking({id, title, text, prompts, onNext, onBack}: Spe
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="self-end flex gap-8">
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row 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} />
|
||||
@@ -41,7 +41,7 @@ export default function Speaking({id, title, text, prompts, onNext, onBack}: Spe
|
||||
</button>
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
onClick={() => onNext({id, solutions: [], score: {correct: 0, total: 0}})}>
|
||||
onClick={() => onNext({exercise: id, solutions: [], score: {correct: 0, total: 0}, type})}>
|
||||
Next
|
||||
<div className="absolute right-4">
|
||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||
|
||||
@@ -42,7 +42,7 @@ function Blank({
|
||||
);
|
||||
}
|
||||
|
||||
export default function WriteBlanks({id, prompt, maxWords, solutions, text, onNext, onBack}: WriteBlanksExercise & CommonProps) {
|
||||
export default function WriteBlanks({id, prompt, type, maxWords, solutions, text, onNext, onBack}: WriteBlanksExercise & CommonProps) {
|
||||
const [userSolutions, setUserSolutions] = useState<{id: string; solution: string}[]>([]);
|
||||
|
||||
const calculateScore = () => {
|
||||
@@ -88,7 +88,7 @@ export default function WriteBlanks({id, prompt, maxWords, solutions, text, onNe
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="self-end flex gap-8">
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row 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} />
|
||||
@@ -97,7 +97,7 @@ export default function WriteBlanks({id, prompt, maxWords, solutions, text, onNe
|
||||
</button>
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
onClick={() => onNext({id, solutions: userSolutions, score: calculateScore()})}>
|
||||
onClick={() => onNext({exercise: id, solutions: userSolutions, score: calculateScore(), type})}>
|
||||
Next
|
||||
<div className="absolute right-4">
|
||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||
|
||||
@@ -7,7 +7,7 @@ import {CommonProps} from ".";
|
||||
import {Fragment, useEffect, useState} from "react";
|
||||
import {toast} from "react-toastify";
|
||||
|
||||
export default function Writing({id, prompt, info, wordCounter, onNext, onBack}: WritingExercise & CommonProps) {
|
||||
export default function Writing({id, prompt, info, type, wordCounter, onNext, onBack}: WritingExercise & CommonProps) {
|
||||
const [inputText, setInputText] = useState("");
|
||||
const [isSubmitEnabled, setIsSubmitEnabled] = useState(false);
|
||||
|
||||
@@ -49,7 +49,7 @@ export default function Writing({id, prompt, info, wordCounter, onNext, onBack}:
|
||||
placeholder="Write your text here..."
|
||||
/>
|
||||
|
||||
<div className="self-end flex gap-8">
|
||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row 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} />
|
||||
@@ -61,7 +61,7 @@ export default function Writing({id, prompt, info, wordCounter, onNext, onBack}:
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
disabled={!isSubmitEnabled}
|
||||
onClick={() => onNext({id, solutions: [inputText], score: {correct: 1, total: 1}})}>
|
||||
onClick={() => onNext({exercise: id, solutions: [inputText], score: {correct: 1, total: 1}, type})}>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@ export default function Writing({id, prompt, info, wordCounter, onNext, onBack}:
|
||||
<button
|
||||
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
|
||||
disabled={!isSubmitEnabled}
|
||||
onClick={() => onNext({id, solutions: [inputText], score: {correct: 1, total: 1}})}>
|
||||
onClick={() => onNext({exercise: id, solutions: [inputText], score: {correct: 1, total: 1}, type})}>
|
||||
Next
|
||||
<div className="absolute right-4">
|
||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||
|
||||
Reference in New Issue
Block a user