From 0eddded56086690f84e53b2b3136fa47a156d96d Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 13 Jun 2024 18:17:07 +0100 Subject: [PATCH] Updated part of the speaking accordingly --- src/components/Exercises/Speaking.tsx | 36 ++++++++++++------- src/components/Modal.tsx | 10 ++++-- .../Solutions/InteractiveSpeaking.tsx | 21 ++++++++--- src/components/Solutions/Speaking.tsx | 21 ++++++++--- src/components/Solutions/Writing.tsx | 21 ++++++++--- src/interfaces/exam.ts | 3 +- 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/components/Exercises/Speaking.tsx b/src/components/Exercises/Speaking.tsx index 17219cdb..11786660 100644 --- a/src/components/Exercises/Speaking.tsx +++ b/src/components/Exercises/Speaking.tsx @@ -7,18 +7,20 @@ import Button from "../Low/Button"; import useExamStore from "@/stores/examStore"; import {downloadBlob} from "@/utils/evaluation"; import axios from "axios"; +import Modal from "../Modal"; const Waveform = dynamic(() => import("../Waveform"), {ssr: false}); const ReactMediaRecorder = dynamic(() => import("react-media-recorder").then((mod) => mod.ReactMediaRecorder), { ssr: false, }); -export default function Speaking({id, title, text, video_url, type, prompts, userSolutions, onNext, onBack}: SpeakingExercise & CommonProps) { +export default function Speaking({id, title, text, video_url, type, prompts, suffix, userSolutions, onNext, onBack}: SpeakingExercise & CommonProps) { const [recordingDuration, setRecordingDuration] = useState(0); const [isRecording, setIsRecording] = useState(false); const [mediaBlob, setMediaBlob] = useState(); const [audioURL, setAudioURL] = useState(); const [isLoading, setIsLoading] = useState(false); + const [isPromptsModalOpen, setIsPromptsModalOpen] = useState(false); const hasExamEnded = useExamStore((state) => state.hasExamEnded); @@ -93,9 +95,26 @@ export default function Speaking({id, title, text, video_url, type, prompts, use return (
+ setIsPromptsModalOpen(false)}> +
+
+ {prompts.map((x, index) => ( +
  • + {x} +
  • + ))} +
    + {!!suffix && {suffix}} +
    +
    - {title} +
    + {title} + {prompts.length > 0 && ( + You should talk for at least 30 seconds for your answer to be valid. + )} +
    {!video_url && ( {text.split("\\n").map((line, index) => ( @@ -107,7 +126,7 @@ export default function Speaking({id, title, text, video_url, type, prompts, use )}
    -
    +
    {video_url && (
    )} {prompts && prompts.length > 0 && ( -
    - You should talk about the following things: -
    - {prompts.map((x, index) => ( -
  • - {x} -
  • - ))} -
    +
    +
    )}
    diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index 673de4ab..0bd0e46e 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -1,14 +1,16 @@ import {Dialog, Transition} from "@headlessui/react"; +import clsx from "clsx"; import {Fragment, ReactElement} from "react"; interface Props { isOpen: boolean; onClose: () => void; title?: string; + className?: string; children?: ReactElement; } -export default function Modal({isOpen, title, onClose, children}: Props) { +export default function Modal({isOpen, title, className, onClose, children}: Props) { return ( @@ -33,7 +35,11 @@ export default function Modal({isOpen, title, onClose, children}: Props) { leave="ease-in duration-200" leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95"> - + {title && ( {title} diff --git a/src/components/Solutions/InteractiveSpeaking.tsx b/src/components/Solutions/InteractiveSpeaking.tsx index 598cc5c3..6c3c6290 100644 --- a/src/components/Solutions/InteractiveSpeaking.tsx +++ b/src/components/Solutions/InteractiveSpeaking.tsx @@ -132,11 +132,22 @@ export default function InteractiveSpeaking({ {userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
    - {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => ( -
    - {key}: Level {userSolutions[0].evaluation!.task_response[key]} -
    - ))} + {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { + const taskResponse = userSolutions[0].evaluation!.task_response[key]; + const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade; + + return ( +
    + {key}: Level {grade} +
    + ); + })}
    {userSolutions[0].evaluation && Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).length === 3 ? ( diff --git a/src/components/Solutions/Speaking.tsx b/src/components/Solutions/Speaking.tsx index 17248e5f..7ec7fc08 100644 --- a/src/components/Solutions/Speaking.tsx +++ b/src/components/Solutions/Speaking.tsx @@ -126,11 +126,22 @@ export default function Speaking({id, type, title, video_url, text, prompts, use {userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
    - {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => ( -
    - {key}: Level {userSolutions[0].evaluation!.task_response[key]} -
    - ))} + {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { + const taskResponse = userSolutions[0].evaluation!.task_response[key]; + const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade; + + return ( +
    + {key}: Level {grade} +
    + ); + })}
    {userSolutions[0].evaluation && (userSolutions[0].evaluation.perfect_answer || userSolutions[0].evaluation.perfect_answer_1) ? ( diff --git a/src/components/Solutions/Writing.tsx b/src/components/Solutions/Writing.tsx index 303a4242..038cb19e 100644 --- a/src/components/Solutions/Writing.tsx +++ b/src/components/Solutions/Writing.tsx @@ -117,11 +117,22 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on {userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
    - {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => ( -
    - {key}: Level {userSolutions[0].evaluation!.task_response[key]} -
    - ))} + {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { + const taskResponse = userSolutions[0].evaluation!.task_response[key]; + const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade; + + return ( +
    + {key}: Level {grade} +
    + ); + })}
    {userSolutions[0].evaluation && userSolutions[0].evaluation.perfect_answer ? ( diff --git a/src/interfaces/exam.ts b/src/interfaces/exam.ts index 15c6df20..9b4b255a 100644 --- a/src/interfaces/exam.ts +++ b/src/interfaces/exam.ts @@ -111,7 +111,7 @@ export type Exercise = export interface Evaluation { comment: string; overall: number; - task_response: {[key: string]: number}; + task_response: {[key: string]: number | {grade: number; comment: string}}; misspelled_pairs?: {correction: string | null; misspelled: string}[]; } @@ -163,6 +163,7 @@ export interface SpeakingExercise { title: string; text: string; prompts: string[]; + suffix?: string; video_url: string; userSolutions: { id: string;