Gestion des index améliorée

This commit is contained in:
JubaAzul 2025-04-24 16:08:41 -04:00
parent 6d714d1d77
commit 7dcbe55776
6 changed files with 160 additions and 27 deletions

View file

@ -15,7 +15,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
const question = questions[Number(index)].question as MultipleChoiceQuestion; const question = questions[Number(index)].question as MultipleChoiceQuestion;
const [actualAnswer, setActualAnswer] = useState<AnswerType>(() => { const [actualAnswer, setActualAnswer] = useState<AnswerType>(() => {
if (answer && answer.length > 0) { if (answer && answer === undefined) {
return answer; return answer;
} }
return []; return [];
@ -28,7 +28,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
useEffect(() => { useEffect(() => {
console.log('MultipleChoiceQuestionDisplay: passedAnswer', JSON.stringify(answer)); console.log('MultipleChoiceQuestionDisplay: passedAnswer', JSON.stringify(answer));
if (answer !== undefined) { if (answer.length !== undefined) {
setActualAnswer(answer); setActualAnswer(answer);
} else { } else {
setActualAnswer([]); setActualAnswer([]);
@ -120,7 +120,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
onClick={() => onClick={() =>
actualAnswer.length > 0 && submitAnswer && submitAnswer(actualAnswer) actualAnswer.length > 0 && submitAnswer && submitAnswer(actualAnswer)
} }
disabled={answer.length === 0} disabled={actualAnswer.length === 0}
> >
Répondre Répondre
</Button> </Button>

View file

@ -0,0 +1,133 @@
// MultipleChoiceQuestionDisplay.tsx
import React, { useEffect, useState } from 'react';
import '../questionStyle.css';
import { Button } from '@mui/material';
import { FormattedTextTemplate } from '../../GiftTemplate/templates/TextTypeTemplate';
import { MultipleChoiceQuestion } from 'gift-pegjs';
import { AnswerType } from 'src/pages/Student/JoinRoom/JoinRoom';
interface Props {
question: MultipleChoiceQuestion;
handleOnSubmitAnswer?: (answer: AnswerType) => void;
showAnswer?: boolean;
passedAnswer?: AnswerType;
}
const MultipleChoiceQuestionDisplay: React.FC<Props> = (props) => {
const { question, showAnswer, handleOnSubmitAnswer, passedAnswer } = props;
console.log('MultipleChoiceQuestionDisplay: passedAnswer', JSON.stringify(passedAnswer));
const [answer, setAnswer] = useState<AnswerType>(() => {
if (passedAnswer && passedAnswer.length > 0) {
return passedAnswer;
}
return [];
});
let disableButton = false;
if (handleOnSubmitAnswer === undefined) {
disableButton = true;
}
useEffect(() => {
console.log('MultipleChoiceQuestionDisplay: passedAnswer', JSON.stringify(passedAnswer));
if (passedAnswer !== undefined) {
setAnswer(passedAnswer);
} else {
setAnswer([]);
}
}, [passedAnswer, question.id]);
const handleOnClickAnswer = (choice: string) => {
setAnswer((prevAnswer) => {
console.log(`handleOnClickAnswer -- setAnswer(): prevAnswer: ${prevAnswer}, choice: ${choice}`);
const correctAnswersCount = question.choices.filter((c) => c.isCorrect).length;
if (correctAnswersCount === 1) {
// If only one correct answer, replace the current selection
return prevAnswer.includes(choice) ? [] : [choice];
} else {
// Allow multiple selections if there are multiple correct answers
if (prevAnswer.includes(choice)) {
// Remove the choice if it's already selected
return prevAnswer.filter((selected) => selected !== choice);
} else {
// Add the choice if it's not already selected
return [...prevAnswer, choice];
}
}
});
};
const alpha = Array.from(Array(26)).map((_e, i) => i + 65);
const alphabet = alpha.map((x) => String.fromCharCode(x));
return (
<div className="question-container">
<div className="question content">
<div dangerouslySetInnerHTML={{ __html: FormattedTextTemplate(question.formattedStem) }} />
</div>
<div className="choices-wrapper mb-1">
{question.choices.map((choice, i) => {
console.log(`answer: ${answer}, choice: ${choice.formattedText.text}`);
const selected = answer.includes(choice.formattedText.text) ? 'selected' : '';
return (
<div key={choice.formattedText.text + i} className="choice-container">
<Button
variant="text"
className="button-wrapper"
disabled={disableButton}
onClick={() => !showAnswer && handleOnClickAnswer(choice.formattedText.text)}
>
{showAnswer ? (
<div>{choice.isCorrect ? '✅' : '❌'}</div>
) : (
''
)}
<div className={`circle ${selected}`}>{alphabet[i]}</div>
<div className={`answer-text ${selected}`}>
<div
dangerouslySetInnerHTML={{
__html: FormattedTextTemplate(choice.formattedText),
}}
/>
</div>
{choice.formattedFeedback && showAnswer && (
<div className="feedback-container mb-1 mt-1/2">
<div
dangerouslySetInnerHTML={{
__html: FormattedTextTemplate(choice.formattedFeedback),
}}
/>
</div>
)}
</Button>
</div>
);
})}
</div>
{question.formattedGlobalFeedback && showAnswer && (
<div className="global-feedback mb-2">
<div
dangerouslySetInnerHTML={{
__html: FormattedTextTemplate(question.formattedGlobalFeedback),
}}
/>
</div>
)}
{!showAnswer && handleOnSubmitAnswer && (
<Button
variant="contained"
onClick={() =>
answer.length > 0 && handleOnSubmitAnswer && handleOnSubmitAnswer(answer)
}
disabled={answer.length === 0}
>
Répondre
</Button>
)}
</div>
);
};
export default MultipleChoiceQuestionDisplay;

View file

@ -1,30 +1,31 @@
// StudentModeQuiz.tsx // StudentModeQuiz.tsx
import React, { useEffect, useState } from 'react'; import React, { useEffect } from 'react';
import QuestionDisplay from '../QuestionsDisplay/QuestionDisplay'; import QuestionDisplay from '../QuestionsDisplay/QuestionDisplay';
import '../../pages/Student/JoinRoom/joinRoom.css'; import '../../pages/Student/JoinRoom/joinRoom.css';
import { QuestionType } from '../../Types/QuestionType';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import DisconnectButton from 'src/components/DisconnectButton/DisconnectButton'; import DisconnectButton from 'src/components/DisconnectButton/DisconnectButton';
import { useQuizContext } from 'src/pages/Student/JoinRoom/QuizContext'; import { useQuizContext } from 'src/pages/Student/JoinRoom/QuizContext';
const StudentModeQuiz: React.FC = () => { const StudentModeQuiz: React.FC = () => {
const { questions, answers, setIsQuestionSent, disconnectWebSocket, setShowAnswer } = useQuizContext(); // Access setShowAnswer from context const { questions, answers, setIsQuestionSent, disconnectWebSocket, setShowAnswer, index, updateIndex } = useQuizContext(); // Access setShowAnswer from context
const [questionInfos, setQuestion] = useState<QuestionType>(questions[0]);
const previousQuestion = () => { const previousQuestion = () => {
setQuestion(questions[Number(questionInfos.question?.id) - 2]); updateIndex(Number(index) - 1);
}; };
useEffect(() => { useEffect(() => {
const savedAnswer = answers[Number(questionInfos.question.id) - 1]?.answer; let savedAnswer = undefined;
console.log(`StudentModeQuiz: useEffect: index: ${index}`);
if (answers.length === 0) {
savedAnswer = answers[Number(index) - 1]?.answer;}
console.log(`StudentModeQuiz: useEffect: savedAnswer: ${savedAnswer}`); console.log(`StudentModeQuiz: useEffect: savedAnswer: ${savedAnswer}`);
setIsQuestionSent(savedAnswer !== undefined); setIsQuestionSent(savedAnswer !== undefined);
setShowAnswer(savedAnswer !== undefined); // Update showAnswer in context setShowAnswer(savedAnswer !== undefined); // Update showAnswer in context
}, [questionInfos.question, answers, setShowAnswer]); }, [index, answers, setShowAnswer]);
const nextQuestion = () => { const nextQuestion = () => {
setQuestion(questions[Number(questionInfos.question?.id)]); updateIndex(Number(index)+1);
}; };
return ( return (
@ -36,7 +37,7 @@ const StudentModeQuiz: React.FC = () => {
/> />
</div> </div>
<div> <div>
<b>Question {questionInfos.question.id}/{questions.length}</b> <b>Question {Number(index) +1}/{questions.length}</b>
</div> </div>
<div className="overflow-auto"> <div className="overflow-auto">
<div className="question-component-container"> <div className="question-component-container">
@ -47,7 +48,7 @@ const StudentModeQuiz: React.FC = () => {
variant="outlined" variant="outlined"
onClick={previousQuestion} onClick={previousQuestion}
fullWidth fullWidth
disabled={Number(questionInfos.question.id) <= 1} disabled={Number(index) +1 <= 1}
> >
Question précédente Question précédente
</Button> </Button>
@ -57,7 +58,7 @@ const StudentModeQuiz: React.FC = () => {
variant="outlined" variant="outlined"
onClick={nextQuestion} onClick={nextQuestion}
fullWidth fullWidth
disabled={Number(questionInfos.question.id) >= questions.length} disabled={Number(index) >= questions.length -1}
> >
Question suivante Question suivante
</Button> </Button>

View file

@ -80,7 +80,7 @@ const JoinRoom: React.FC = () => {
console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions); console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions);
setQuizMode('teacher'); setQuizMode('teacher');
setIsWaitingForTeacher(true); setIsWaitingForTeacher(true);
updateIndex(null); updateIndex(0);
setQuestions(questions); setQuestions(questions);
// wait for next-question // wait for next-question
}); });
@ -92,6 +92,7 @@ const JoinRoom: React.FC = () => {
setQuestions([]); // clear out from last time (in case quiz is repeated) setQuestions([]); // clear out from last time (in case quiz is repeated)
setQuestions(questions); setQuestions(questions);
updateIndex(0); updateIndex(0);
console.log('on(launch-student-mode): setQuestions:', index);
}); });
socket.on('end-quiz', () => { socket.on('end-quiz', () => {
disconnect(); disconnect();

View file

@ -32,9 +32,10 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
const [disconnectWebSocket, setDisconnectWebSocket] = useState<() => void>(() => () => {}); const [disconnectWebSocket, setDisconnectWebSocket] = useState<() => void>(() => () => {});
const updateIndex = (questionId: number | null) => { const updateIndex = (questionId?: number | null) => {
const questionIndex = questions.findIndex((q) => q.question.id === String(questionId));
setIndex(questionIndex >= 0 ? questionIndex : null); setIndex(questionId ?? null);
}; };
// Function to handle answer submission // Function to handle answer submission
@ -42,9 +43,7 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
if (!idQuestion) { if (!idQuestion) {
setAnswer(answer); setAnswer(answer);
setIsQuestionSent(true); setIsQuestionSent(true);
console.log('index',index);
} else { } else {
console.info(`QuizProvider: submitAnswer: answer: ${answer}, idQuestion: ${idQuestion}`);
const answerData: AnswerSubmissionToBackendType = { const answerData: AnswerSubmissionToBackendType = {
roomName: roomName, roomName: roomName,
answer: answer, answer: answer,
@ -59,7 +58,6 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
return newAnswers; // Return the new array return newAnswers; // Return the new array
}); });
console.log(`QuizProvider: submitAnswer: answers: ${JSON.stringify(answers)}`);
// Submit the answer to the WebSocket service // Submit the answer to the WebSocket service
webSocketService.submitAnswer(answerData); webSocketService.submitAnswer(answerData);

View file

@ -255,10 +255,10 @@ const ManageRoom: React.FC = () => {
const nextQuestion = () => { const nextQuestion = () => {
if (!questions || !index || !quiz?.content) return; if (!questions || !index || !quiz?.content) return;
const nextQuestionIndex = index; const nextQuestionIndex = index +1;
if (nextQuestionIndex === undefined || nextQuestionIndex > questions.length - 1) return; if (nextQuestionIndex === undefined || nextQuestionIndex > questions.length - 1) return;
console.log('nextQuestionIndex:', questions);
updateIndex(nextQuestionIndex); updateIndex(nextQuestionIndex);
webSocketService.nextQuestion({roomName: formattedRoomName, webSocketService.nextQuestion({roomName: formattedRoomName,
questions: questions, questions: questions,
@ -410,7 +410,7 @@ const ManageRoom: React.FC = () => {
<div className="title center-h-align mb-2">{quiz?.title}</div> <div className="title center-h-align mb-2">{quiz?.title}</div>
{index && ( {index && (
<strong className="number of questions"> <strong className="number of questions">
Question {index+1}/ Question {index +1}/
{questions?.length} {questions?.length}
</strong> </strong>
)} )}
@ -451,7 +451,7 @@ const ManageRoom: React.FC = () => {
<Button <Button
onClick={previousQuestion} onClick={previousQuestion}
variant="contained" variant="contained"
disabled={index !== null && index <= 1} disabled={index !== null && index <= 0}
> >
Question précédente Question précédente
</Button> </Button>
@ -462,7 +462,7 @@ const ManageRoom: React.FC = () => {
variant="contained" variant="contained"
disabled={ disabled={
index !== null && index !== null &&
index >= questions.length index >= questions.length -1
} }
> >
Prochaine question Prochaine question