mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Gestion des index améliorée
This commit is contained in:
parent
6d714d1d77
commit
7dcbe55776
6 changed files with 160 additions and 27 deletions
|
|
@ -15,7 +15,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
|
|||
const question = questions[Number(index)].question as MultipleChoiceQuestion;
|
||||
|
||||
const [actualAnswer, setActualAnswer] = useState<AnswerType>(() => {
|
||||
if (answer && answer.length > 0) {
|
||||
if (answer && answer === undefined) {
|
||||
return answer;
|
||||
}
|
||||
return [];
|
||||
|
|
@ -28,7 +28,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
|
|||
|
||||
useEffect(() => {
|
||||
console.log('MultipleChoiceQuestionDisplay: passedAnswer', JSON.stringify(answer));
|
||||
if (answer !== undefined) {
|
||||
if (answer.length !== undefined) {
|
||||
setActualAnswer(answer);
|
||||
} else {
|
||||
setActualAnswer([]);
|
||||
|
|
@ -120,7 +120,7 @@ const MultipleChoiceQuestionDisplay: React.FC = () => {
|
|||
onClick={() =>
|
||||
actualAnswer.length > 0 && submitAnswer && submitAnswer(actualAnswer)
|
||||
}
|
||||
disabled={answer.length === 0}
|
||||
disabled={actualAnswer.length === 0}
|
||||
>
|
||||
Répondre
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1,30 +1,31 @@
|
|||
// StudentModeQuiz.tsx
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import QuestionDisplay from '../QuestionsDisplay/QuestionDisplay';
|
||||
import '../../pages/Student/JoinRoom/joinRoom.css';
|
||||
import { QuestionType } from '../../Types/QuestionType';
|
||||
import { Button } from '@mui/material';
|
||||
import DisconnectButton from 'src/components/DisconnectButton/DisconnectButton';
|
||||
import { useQuizContext } from 'src/pages/Student/JoinRoom/QuizContext';
|
||||
|
||||
const StudentModeQuiz: React.FC = () => {
|
||||
const { questions, answers, setIsQuestionSent, disconnectWebSocket, setShowAnswer } = useQuizContext(); // Access setShowAnswer from context
|
||||
|
||||
const [questionInfos, setQuestion] = useState<QuestionType>(questions[0]);
|
||||
const { questions, answers, setIsQuestionSent, disconnectWebSocket, setShowAnswer, index, updateIndex } = useQuizContext(); // Access setShowAnswer from context
|
||||
|
||||
const previousQuestion = () => {
|
||||
setQuestion(questions[Number(questionInfos.question?.id) - 2]);
|
||||
updateIndex(Number(index) - 1);
|
||||
};
|
||||
|
||||
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}`);
|
||||
setIsQuestionSent(savedAnswer !== undefined);
|
||||
setShowAnswer(savedAnswer !== undefined); // Update showAnswer in context
|
||||
}, [questionInfos.question, answers, setShowAnswer]);
|
||||
}, [index, answers, setShowAnswer]);
|
||||
|
||||
const nextQuestion = () => {
|
||||
setQuestion(questions[Number(questionInfos.question?.id)]);
|
||||
updateIndex(Number(index)+1);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -36,7 +37,7 @@ const StudentModeQuiz: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<b>Question {questionInfos.question.id}/{questions.length}</b>
|
||||
<b>Question {Number(index) +1}/{questions.length}</b>
|
||||
</div>
|
||||
<div className="overflow-auto">
|
||||
<div className="question-component-container">
|
||||
|
|
@ -47,7 +48,7 @@ const StudentModeQuiz: React.FC = () => {
|
|||
variant="outlined"
|
||||
onClick={previousQuestion}
|
||||
fullWidth
|
||||
disabled={Number(questionInfos.question.id) <= 1}
|
||||
disabled={Number(index) +1 <= 1}
|
||||
>
|
||||
Question précédente
|
||||
</Button>
|
||||
|
|
@ -57,7 +58,7 @@ const StudentModeQuiz: React.FC = () => {
|
|||
variant="outlined"
|
||||
onClick={nextQuestion}
|
||||
fullWidth
|
||||
disabled={Number(questionInfos.question.id) >= questions.length}
|
||||
disabled={Number(index) >= questions.length -1}
|
||||
>
|
||||
Question suivante
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ const JoinRoom: React.FC = () => {
|
|||
console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions);
|
||||
setQuizMode('teacher');
|
||||
setIsWaitingForTeacher(true);
|
||||
updateIndex(null);
|
||||
updateIndex(0);
|
||||
setQuestions(questions);
|
||||
// wait for next-question
|
||||
});
|
||||
|
|
@ -92,6 +92,7 @@ const JoinRoom: React.FC = () => {
|
|||
setQuestions([]); // clear out from last time (in case quiz is repeated)
|
||||
setQuestions(questions);
|
||||
updateIndex(0);
|
||||
console.log('on(launch-student-mode): setQuestions:', index);
|
||||
});
|
||||
socket.on('end-quiz', () => {
|
||||
disconnect();
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||
const [disconnectWebSocket, setDisconnectWebSocket] = useState<() => void>(() => () => {});
|
||||
|
||||
|
||||
const updateIndex = (questionId: number | null) => {
|
||||
const questionIndex = questions.findIndex((q) => q.question.id === String(questionId));
|
||||
setIndex(questionIndex >= 0 ? questionIndex : null);
|
||||
const updateIndex = (questionId?: number | null) => {
|
||||
|
||||
setIndex(questionId ?? null);
|
||||
|
||||
};
|
||||
|
||||
// Function to handle answer submission
|
||||
|
|
@ -42,9 +43,7 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||
if (!idQuestion) {
|
||||
setAnswer(answer);
|
||||
setIsQuestionSent(true);
|
||||
console.log('index',index);
|
||||
} else {
|
||||
console.info(`QuizProvider: submitAnswer: answer: ${answer}, idQuestion: ${idQuestion}`);
|
||||
const answerData: AnswerSubmissionToBackendType = {
|
||||
roomName: roomName,
|
||||
answer: answer,
|
||||
|
|
@ -59,7 +58,6 @@ export const QuizProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||
return newAnswers; // Return the new array
|
||||
});
|
||||
|
||||
console.log(`QuizProvider: submitAnswer: answers: ${JSON.stringify(answers)}`);
|
||||
|
||||
// Submit the answer to the WebSocket service
|
||||
webSocketService.submitAnswer(answerData);
|
||||
|
|
|
|||
|
|
@ -255,10 +255,10 @@ const ManageRoom: React.FC = () => {
|
|||
const nextQuestion = () => {
|
||||
if (!questions || !index || !quiz?.content) return;
|
||||
|
||||
const nextQuestionIndex = index;
|
||||
const nextQuestionIndex = index +1;
|
||||
|
||||
if (nextQuestionIndex === undefined || nextQuestionIndex > questions.length - 1) return;
|
||||
|
||||
console.log('nextQuestionIndex:', questions);
|
||||
updateIndex(nextQuestionIndex);
|
||||
webSocketService.nextQuestion({roomName: formattedRoomName,
|
||||
questions: questions,
|
||||
|
|
@ -410,7 +410,7 @@ const ManageRoom: React.FC = () => {
|
|||
<div className="title center-h-align mb-2">{quiz?.title}</div>
|
||||
{index && (
|
||||
<strong className="number of questions">
|
||||
Question {index+1}/
|
||||
Question {index +1}/
|
||||
{questions?.length}
|
||||
</strong>
|
||||
)}
|
||||
|
|
@ -451,7 +451,7 @@ const ManageRoom: React.FC = () => {
|
|||
<Button
|
||||
onClick={previousQuestion}
|
||||
variant="contained"
|
||||
disabled={index !== null && index <= 1}
|
||||
disabled={index !== null && index <= 0}
|
||||
>
|
||||
Question précédente
|
||||
</Button>
|
||||
|
|
@ -462,7 +462,7 @@ const ManageRoom: React.FC = () => {
|
|||
variant="contained"
|
||||
disabled={
|
||||
index !== null &&
|
||||
index >= questions.length
|
||||
index >= questions.length -1
|
||||
}
|
||||
>
|
||||
Prochaine question
|
||||
|
|
|
|||
Loading…
Reference in a new issue