Updated the design of the WriteBlanks exercise
This commit is contained in:
@@ -35,7 +35,7 @@ function Blank({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
className={clsx("input border rounded-xl px-2 py-1 bg-white text-blue-400 border-blue-400 my-2")}
|
className="py-2 px-3 rounded-2xl w-48 bg-white focus:outline-none my-2"
|
||||||
placeholder={id}
|
placeholder={id}
|
||||||
onChange={(e) => setUserInput(e.target.value)}
|
onChange={(e) => setUserInput(e.target.value)}
|
||||||
onBlur={() => setUserSolution(userInput)}
|
onBlur={() => setUserSolution(userInput)}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import {WriteBlanksExercise} from "@/interfaces/exam";
|
|||||||
import {mdiArrowLeft, mdiArrowRight} from "@mdi/js";
|
import {mdiArrowLeft, mdiArrowRight} from "@mdi/js";
|
||||||
import Icon from "@mdi/react";
|
import Icon from "@mdi/react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import {useEffect, useState} from "react";
|
import {Fragment, useEffect, useState} from "react";
|
||||||
import reactStringReplace from "react-string-replace";
|
import reactStringReplace from "react-string-replace";
|
||||||
import {CommonProps} from ".";
|
import {CommonProps} from ".";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
import Button from "../Low/Button";
|
||||||
|
|
||||||
function Blank({
|
function Blank({
|
||||||
id,
|
id,
|
||||||
@@ -17,7 +18,7 @@ function Blank({
|
|||||||
setUserSolution,
|
setUserSolution,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
solutions?: string[];
|
solutions: string[];
|
||||||
userSolution?: string;
|
userSolution?: string;
|
||||||
maxWords: number;
|
maxWords: number;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@@ -34,22 +35,35 @@ function Blank({
|
|||||||
}
|
}
|
||||||
}, [maxWords, userInput, setUserSolution]);
|
}, [maxWords, userInput, setUserSolution]);
|
||||||
|
|
||||||
|
const isUserSolutionCorrect = () => userSolution && solutions.map((x) => x.trim().toLowerCase()).includes(userSolution.trim().toLowerCase());
|
||||||
|
|
||||||
const getSolutionStyling = () => {
|
const getSolutionStyling = () => {
|
||||||
if (solutions && userSolution) {
|
if (!userSolution) {
|
||||||
if (solutions.map((x) => x.trim().toLowerCase()).includes(userSolution.trim().toLowerCase())) return "text-green-500 border-green-500";
|
return "bg-mti-blue-ultralight text-mti-blue-light";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "text-red-500 border-red-500";
|
return "bg-mti-green-ultralight text-mti-green-light";
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<span className="inline-flex gap-2">
|
||||||
|
{userSolution && !isUserSolutionCorrect() && (
|
||||||
<input
|
<input
|
||||||
className={clsx("input border rounded-xl px-2 py-1 bg-white my-2", !solutions && "text-blue-400 border-blue-400", getSolutionStyling())}
|
className="py-2 px-3 rounded-2xl w-48 focus:outline-none my-2 bg-mti-orange-ultralight text-mti-orange-light"
|
||||||
|
placeholder={id}
|
||||||
|
onChange={(e) => setUserInput(e.target.value)}
|
||||||
|
value={userSolution}
|
||||||
|
contentEditable={disabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<input
|
||||||
|
className={clsx("py-2 px-3 rounded-2xl w-48 focus:outline-none my-2", getSolutionStyling())}
|
||||||
placeholder={id}
|
placeholder={id}
|
||||||
onChange={(e) => setUserInput(e.target.value)}
|
onChange={(e) => setUserInput(e.target.value)}
|
||||||
value={!solutions ? userInput : solutions.join(" / ")}
|
value={!solutions ? userInput : solutions.join(" / ")}
|
||||||
contentEditable={disabled}
|
contentEditable={disabled}
|
||||||
/>
|
/>
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +79,7 @@ export default function WriteBlanksSolutions({
|
|||||||
}: WriteBlanksExercise & CommonProps) {
|
}: WriteBlanksExercise & CommonProps) {
|
||||||
const renderLines = (line: string) => {
|
const renderLines = (line: string) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span className="text-base leading-5">
|
||||||
{reactStringReplace(line, /({{\d+}})/g, (match) => {
|
{reactStringReplace(line, /({{\d+}})/g, (match) => {
|
||||||
const id = match.replaceAll(/[\{\}]/g, "");
|
const id = match.replaceAll(/[\{\}]/g, "");
|
||||||
const userSolution = userSolutions.find((x) => x.id === id);
|
const userSolution = userSolutions.find((x) => x.id === id);
|
||||||
@@ -79,31 +93,33 @@ export default function WriteBlanksSolutions({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col gap-4 mt-4 h-full mb-20">
|
||||||
<span className="text-lg font-medium text-center px-48">{prompt}</span>
|
<span className="text-sm w-full leading-6">
|
||||||
<span>
|
{prompt.split("\\n").map((line, index) => (
|
||||||
{text.split("\\n").map((line) => (
|
<Fragment key={index}>
|
||||||
<>
|
{line}
|
||||||
|
<br />
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
<span className="bg-mti-gray-smoke rounded-xl px-5 py-6">
|
||||||
|
{text.split("\\n").map((line, index) => (
|
||||||
|
<p key={index}>
|
||||||
{renderLines(line)}
|
{renderLines(line)}
|
||||||
<br />
|
<br />
|
||||||
</>
|
</p>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="self-end flex flex-col-reverse items-center w-full md:justify-between md:items-start md:flex-row gap-8">
|
<div className="self-end flex justify-between w-full gap-8 absolute bottom-8 left-0 px-8">
|
||||||
<button className={clsx("btn btn-wide gap-4 relative text-white", errorButtonStyle)} onClick={onBack}>
|
<Button color="green" variant="outline" onClick={() => onBack()} className="max-w-[200px] w-full">
|
||||||
<div className="absolute left-4">
|
|
||||||
<Icon path={mdiArrowLeft} color="white" size={1} />
|
|
||||||
</div>
|
|
||||||
Back
|
Back
|
||||||
</button>
|
</Button>
|
||||||
<button className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)} onClick={onNext}>
|
|
||||||
|
<Button color="green" onClick={() => onNext()} className="max-w-[200px] self-end w-full">
|
||||||
Next
|
Next
|
||||||
<div className="absolute right-4">
|
</Button>
|
||||||
<Icon path={mdiArrowRight} color="white" size={1} />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user