Updated the Exercise count for the Interactive Speaking as well

This commit is contained in:
Tiago Ribeiro
2023-11-21 09:35:54 +00:00
parent d0f89cfe01
commit 51e7c535df
7 changed files with 64 additions and 17 deletions

View File

@@ -11,7 +11,16 @@ const ReactMediaRecorder = dynamic(() => import("react-media-recorder").then((mo
ssr: false, ssr: false,
}); });
export default function InteractiveSpeaking({id, title, text, type, prompts, onNext, onBack}: InteractiveSpeakingExercise & CommonProps) { export default function InteractiveSpeaking({
id,
title,
text,
type,
prompts,
updateIndex,
onNext,
onBack,
}: InteractiveSpeakingExercise & CommonProps) {
const [recordingDuration, setRecordingDuration] = useState(0); const [recordingDuration, setRecordingDuration] = useState(0);
const [isRecording, setIsRecording] = useState(false); const [isRecording, setIsRecording] = useState(false);
const [mediaBlob, setMediaBlob] = useState<string>(); const [mediaBlob, setMediaBlob] = useState<string>();
@@ -20,6 +29,10 @@ export default function InteractiveSpeaking({id, title, text, type, prompts, onN
const hasExamEnded = useExamStore((state) => state.hasExamEnded); const hasExamEnded = useExamStore((state) => state.hasExamEnded);
useEffect(() => {
if (updateIndex) updateIndex(promptIndex);
}, [promptIndex, updateIndex]);
useEffect(() => { useEffect(() => {
if (hasExamEnded) { if (hasExamEnded) {
onNext({ onNext({

View File

@@ -57,6 +57,14 @@ export const renderExercise = (
case "speaking": case "speaking":
return <Speaking key={exercise.id} {...(exercise as SpeakingExercise)} onNext={onNext} onBack={onBack} />; return <Speaking key={exercise.id} {...(exercise as SpeakingExercise)} onNext={onNext} onBack={onBack} />;
case "interactiveSpeaking": case "interactiveSpeaking":
return <InteractiveSpeaking key={exercise.id} {...(exercise as InteractiveSpeakingExercise)} onNext={onNext} onBack={onBack} />; return (
<InteractiveSpeaking
key={exercise.id}
{...(exercise as InteractiveSpeakingExercise)}
updateIndex={updateIndex}
onNext={onNext}
onBack={onBack}
/>
);
} }
}; };

View File

@@ -83,7 +83,7 @@ export default function Level({exam, showSolutions = false, onFinish}: Props) {
<div className="flex flex-col h-full w-full gap-8 items-center"> <div className="flex flex-col h-full w-full gap-8 items-center">
<ModuleTitle <ModuleTitle
minTimer={exam.minTimer} minTimer={exam.minTimer}
exerciseIndex={exerciseIndex + (exerciseIndex === -1 ? 0 : 1) + questionIndex + currentQuestionIndex} exerciseIndex={exerciseIndex + 1 + questionIndex + currentQuestionIndex}
module="level" module="level"
totalExercises={countExercises(exam.exercises)} totalExercises={countExercises(exam.exercises)}
disableTimer={showSolutions} disableTimer={showSolutions}

View File

@@ -20,14 +20,21 @@ interface Props {
} }
export default function Speaking({exam, showSolutions = false, onFinish}: Props) { export default function Speaking({exam, showSolutions = false, onFinish}: Props) {
const [questionIndex, setQuestionIndex] = useState(0);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [exerciseIndex, setExerciseIndex] = useState(0); const [exerciseIndex, setExerciseIndex] = useState(0);
const [userSolutions, setUserSolutions] = useState<UserSolution[]>(exam.exercises.map((x) => defaultUserSolutions(x, exam))); const [userSolutions, setUserSolutions] = useState<UserSolution[]>(exam.exercises.map((x) => defaultUserSolutions(x, exam)));
const [hasExamEnded, setHasExamEnded] = useExamStore((state) => [state.hasExamEnded, state.setHasExamEnded]); const [hasExamEnded, setHasExamEnded] = useExamStore((state) => [state.hasExamEnded, state.setHasExamEnded]);
useEffect(() => {
setCurrentQuestionIndex(0);
}, [questionIndex]);
const nextExercise = (solution?: UserSolution) => { const nextExercise = (solution?: UserSolution) => {
if (solution) { if (solution) {
setUserSolutions((prev) => [...prev.filter((x) => x.exercise !== solution.exercise), solution]); setUserSolutions((prev) => [...prev.filter((x) => x.exercise !== solution.exercise), solution]);
} }
setQuestionIndex((prev) => prev + currentQuestionIndex);
if (exerciseIndex + 1 < exam.exercises.length) { if (exerciseIndex + 1 < exam.exercises.length) {
setExerciseIndex((prev) => prev + 1); setExerciseIndex((prev) => prev + 1);
@@ -71,7 +78,7 @@ export default function Speaking({exam, showSolutions = false, onFinish}: Props)
<ModuleTitle <ModuleTitle
label={convertCamelCaseToReadable(exam.exercises[exerciseIndex].type)} label={convertCamelCaseToReadable(exam.exercises[exerciseIndex].type)}
minTimer={exam.minTimer} minTimer={exam.minTimer}
exerciseIndex={exerciseIndex + 1} exerciseIndex={exerciseIndex + 1 + questionIndex + currentQuestionIndex}
module="speaking" module="speaking"
totalExercises={countExercises(exam.exercises)} totalExercises={countExercises(exam.exercises)}
disableTimer={showSolutions} disableTimer={showSolutions}
@@ -79,11 +86,11 @@ export default function Speaking({exam, showSolutions = false, onFinish}: Props)
{exerciseIndex > -1 && {exerciseIndex > -1 &&
exerciseIndex < exam.exercises.length && exerciseIndex < exam.exercises.length &&
!showSolutions && !showSolutions &&
renderExercise(getExercise(), nextExercise, previousExercise)} renderExercise(getExercise(), nextExercise, previousExercise, setCurrentQuestionIndex)}
{exerciseIndex > -1 && {exerciseIndex > -1 &&
exerciseIndex < exam.exercises.length && exerciseIndex < exam.exercises.length &&
showSolutions && showSolutions &&
renderSolution(exam.exercises[exerciseIndex], nextExercise, previousExercise)} renderSolution(exam.exercises[exerciseIndex], nextExercise, previousExercise, setCurrentQuestionIndex)}
</div> </div>
</> </>
); );

View File

@@ -259,15 +259,6 @@ export default function ExamPage({page}: Props) {
return ( return (
<> <>
<Head>
<title>{capitalize(page).toString()} | EnCoach</title>
<meta
name="description"
content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<ToastContainer /> <ToastContainer />
{user && ( {user && (
<Layout <Layout

View File

@@ -4,6 +4,7 @@ import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session"; import {sessionOptions} from "@/lib/session";
import {shouldRedirectHome} from "@/utils/navigation.disabled"; import {shouldRedirectHome} from "@/utils/navigation.disabled";
import ExamPage from "./(exam)/ExamPage"; import ExamPage from "./(exam)/ExamPage";
import Head from "next/head";
export const getServerSideProps = withIronSessionSsr(({req, res}) => { export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user; const user = req.session.user;
@@ -36,5 +37,18 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
}, sessionOptions); }, sessionOptions);
export default function Page() { export default function Page() {
return <ExamPage page="exams" />; return (
<>
<Head>
<title>Exams | EnCoach</title>
<meta
name="description"
content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<ExamPage page="exams" />
</>
);
} }

View File

@@ -4,6 +4,7 @@ import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session"; import {sessionOptions} from "@/lib/session";
import {shouldRedirectHome} from "@/utils/navigation.disabled"; import {shouldRedirectHome} from "@/utils/navigation.disabled";
import ExamPage from "./(exam)/ExamPage"; import ExamPage from "./(exam)/ExamPage";
import Head from "next/head";
export const getServerSideProps = withIronSessionSsr(({req, res}) => { export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user; const user = req.session.user;
@@ -36,5 +37,18 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
}, sessionOptions); }, sessionOptions);
export default function Page() { export default function Page() {
return <ExamPage page="exercises" />; return (
<>
<Head>
<title>Exercises | EnCoach</title>
<meta
name="description"
content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<ExamPage page="exercises" />
</>
);
} }