Updated Writing and Speaking to have a tab system for the evaluation vs the "perfect answer"

This commit is contained in:
Tiago Ribeiro
2023-12-06 14:48:54 +00:00
parent 523149327b
commit 72083439af
5 changed files with 200 additions and 60 deletions

View File

@@ -25,19 +25,19 @@ export default function Writing({
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
useEffect(() => {
const listener = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
e.preventDefault();
}
};
// useEffect(() => {
// const listener = (e: KeyboardEvent) => {
// if ((e.ctrlKey || e.metaKey) && e.key === "v") {
// e.preventDefault();
// }
// };
document.addEventListener("keydown", listener);
// document.addEventListener("keydown", listener);
return () => {
document.removeEventListener("keydown", listener);
};
}, []);
// return () => {
// document.removeEventListener("keydown", listener);
// };
// }, []);
useEffect(() => {
if (hasExamEnded) onNext({exercise: id, solutions: [{id, solution: inputText}], score: {correct: 1, total: 1, missing: 0}, type});
@@ -93,22 +93,8 @@ export default function Writing({
)}
<div className="flex flex-col h-full w-full gap-9 mb-20">
<div className="flex flex-col w-full gap-7 bg-mti-gray-smoke rounded-xl py-8 pb-12 px-16">
<span>
{prefix.split("\\n").map((line, index) => (
<React.Fragment key={index}>
{line}
<br />
</React.Fragment>
))}
</span>
<span className="font-semibold">
{prompt.split("\\n").map((line, index) => (
<Fragment key={index}>
<p>{line}</p>
<br />
</Fragment>
))}
</span>
<span className="whitespace-pre-wrap">{prefix}</span>
<span className="font-semibold whitespace-pre-wrap">{prompt}</span>
{attachment && (
<img
onClick={() => setIsModalOpen(true)}
@@ -120,14 +106,7 @@ export default function Writing({
</div>
<div className="w-full h-full flex flex-col gap-4">
<span>
{suffix.split("\\n").map((line, index) => (
<React.Fragment key={index}>
{line}
<br />
</React.Fragment>
))}
</span>
<span className="whitespace-pre-wrap">{suffix}</span>
<textarea
onContextMenu={(e) => e.preventDefault()}
className="w-full h-full min-h-[300px] cursor-text px-7 py-8 input border-2 border-mti-gray-platinum bg-white rounded-3xl"

View File

@@ -6,6 +6,8 @@ import Button from "../Low/Button";
import dynamic from "next/dynamic";
import axios from "axios";
import {speakingReverseMarking} from "@/utils/score";
import {Tab} from "@headlessui/react";
import clsx from "clsx";
const Waveform = dynamic(() => import("../Waveform"), {ssr: false});
@@ -47,7 +49,7 @@ export default function InteractiveSpeaking({
</div>
<div className="flex flex-col gap-4">
<span className="font-bold">You should talk about the following things:</span>
<div className="grid grid-cols-3 gap-6 text-center">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 text-center">
{prompts.map((x, index) => (
<div className="italic flex flex-col gap-2 text-sm" key={index}>
<video key={index} controls className="">
@@ -61,11 +63,11 @@ export default function InteractiveSpeaking({
</div>
<div className="w-full h-full flex flex-col gap-8">
<div className="flex items-center gap-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{solutionsURL.map((x, index) => (
<div
key={index}
className="w-full min-w-[460px] p-4 px-8 bg-transparent border-2 border-mti-gray-platinum rounded-2xl flex-col gap-8 items-center">
className="w-full p-4 px-8 bg-transparent border-2 border-mti-gray-platinum rounded-2xl flex-col gap-8 items-center">
<div className="flex gap-8 items-center justify-center py-8">
<Waveform audio={x} waveColor="#FCDDEC" progressColor="#EF5DA8" />
</div>
@@ -73,7 +75,7 @@ export default function InteractiveSpeaking({
))}
</div>
{userSolutions && userSolutions.length > 0 && (
{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
<div className="flex flex-col gap-4 w-full">
<div className="flex gap-4 px-1">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => (
@@ -82,9 +84,81 @@ export default function InteractiveSpeaking({
</div>
))}
</div>
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-mti-gray-smoke rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
{userSolutions[0].evaluation &&
Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).length === 3 ? (
<Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Evaluation
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer (Prompt 1)
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer (Prompt 2)
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer (Prompt 3)
</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_1!.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_2!.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_3!.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
</Tab.Panels>
</Tab.Group>
) : (
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-ielts-speaking/10 rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
)}
</div>
)}
</div>

View File

@@ -6,6 +6,8 @@ import Button from "../Low/Button";
import dynamic from "next/dynamic";
import axios from "axios";
import {speakingReverseMarking} from "@/utils/score";
import {Tab} from "@headlessui/react";
import clsx from "clsx";
const Waveform = dynamic(() => import("../Waveform"), {ssr: false});
@@ -69,7 +71,7 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
{solutionURL && <Waveform audio={solutionURL} waveColor="#FCDDEC" progressColor="#EF5DA8" />}
</div>
</div>
{userSolutions && userSolutions.length > 0 && (
{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
<div className="flex flex-col gap-4 w-full">
<div className="flex gap-4 px-1">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => (
@@ -78,9 +80,48 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
</div>
))}
</div>
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-mti-gray-smoke rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
{userSolutions[0].evaluation && userSolutions[0].evaluation.perfect_answer ? (
<Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Evaluation
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer
</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
</Tab.Panels>
</Tab.Group>
) : (
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-ielts-speaking/10 rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
)}
</div>
)}
</div>

View File

@@ -1,15 +1,11 @@
/* eslint-disable @next/next/no-img-element */
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";
import {Fragment, useState} from "react";
import Button from "../Low/Button";
import {Dialog, Transition} from "@headlessui/react";
import {Dialog, Tab, Transition} from "@headlessui/react";
import {writingReverseMarking} from "@/utils/score";
import clsx from "clsx";
export default function Writing({id, type, prompt, attachment, userSolutions, onNext, onBack}: WritingExercise & CommonProps) {
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -79,7 +75,7 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
/>
</div>
)}
{userSolutions && userSolutions.length > 0 && (
{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
<div className="flex flex-col gap-4 w-full">
<div className="flex gap-4 px-1">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => (
@@ -88,9 +84,48 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
</div>
))}
</div>
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-mti-gray-smoke rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
{userSolutions[0].evaluation && userSolutions[0].evaluation.perfect_answer ? (
<Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-writing/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
Evaluation
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
Recommended Answer
</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
</Tab.Panels>
</Tab.Group>
) : (
<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-ielts-writing/10 rounded-3xl">
{userSolutions[0].evaluation!.comment}
</div>
)}
</div>
)}
</div>