2024-03-29 20:08:34 -04:00
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
|
|
|
|
|
import { Socket } from 'socket.io-client';
|
2025-01-10 15:46:17 -05:00
|
|
|
import { ENV_VARIABLES } from 'src/constants';
|
2024-03-29 20:08:34 -04:00
|
|
|
|
2025-01-16 12:37:07 -05:00
|
|
|
import StudentModeQuiz from 'src/components/StudentModeQuiz/StudentModeQuiz';
|
|
|
|
|
import TeacherModeQuiz from 'src/components/TeacherModeQuiz/TeacherModeQuiz';
|
2024-09-26 00:34:30 -04:00
|
|
|
import webSocketService, { AnswerSubmissionToBackendType } from '../../../services/WebsocketService';
|
2025-01-16 12:37:07 -05:00
|
|
|
import DisconnectButton from 'src/components/DisconnectButton/DisconnectButton';
|
2024-03-29 20:08:34 -04:00
|
|
|
|
|
|
|
|
import './joinRoom.css';
|
|
|
|
|
import { QuestionType } from '../../../Types/QuestionType';
|
|
|
|
|
import { TextField } from '@mui/material';
|
|
|
|
|
import LoadingButton from '@mui/lab/LoadingButton';
|
|
|
|
|
|
2025-01-16 12:37:07 -05:00
|
|
|
import LoginContainer from 'src/components/LoginContainer/LoginContainer'
|
2024-03-29 20:08:34 -04:00
|
|
|
|
2025-02-21 14:48:21 -05:00
|
|
|
import ApiService from '../../../services/ApiService'
|
|
|
|
|
|
2025-03-21 00:25:25 -04:00
|
|
|
export type AnswerType = Array<string | number | boolean>;
|
2025-03-08 01:09:41 -05:00
|
|
|
|
2024-03-29 20:08:34 -04:00
|
|
|
const JoinRoom: React.FC = () => {
|
|
|
|
|
const [roomName, setRoomName] = useState('');
|
2025-02-21 14:48:21 -05:00
|
|
|
const [username, setUsername] = useState(ApiService.getUsername());
|
2024-03-29 20:08:34 -04:00
|
|
|
const [socket, setSocket] = useState<Socket | null>(null);
|
|
|
|
|
const [isWaitingForTeacher, setIsWaitingForTeacher] = useState(false);
|
|
|
|
|
const [question, setQuestion] = useState<QuestionType>();
|
|
|
|
|
const [quizMode, setQuizMode] = useState<string>();
|
|
|
|
|
const [questions, setQuestions] = useState<QuestionType[]>([]);
|
2025-03-08 01:09:41 -05:00
|
|
|
const [answers, setAnswers] = useState<AnswerSubmissionToBackendType[]>([]);
|
2024-03-29 20:08:34 -04:00
|
|
|
const [connectionError, setConnectionError] = useState<string>('');
|
|
|
|
|
const [isConnecting, setIsConnecting] = useState<boolean>(false);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
handleCreateSocket();
|
|
|
|
|
return () => {
|
|
|
|
|
disconnect();
|
|
|
|
|
};
|
|
|
|
|
}, []);
|
|
|
|
|
|
2025-03-08 01:09:41 -05:00
|
|
|
useEffect(() => {
|
|
|
|
|
console.log(`JoinRoom: useEffect: questions: ${JSON.stringify(questions)}`);
|
2025-03-09 00:54:21 -05:00
|
|
|
setAnswers(questions ? Array(questions.length).fill({} as AnswerSubmissionToBackendType) : []);
|
2025-03-08 01:09:41 -05:00
|
|
|
}, [questions]);
|
|
|
|
|
|
|
|
|
|
|
2024-03-29 20:08:34 -04:00
|
|
|
const handleCreateSocket = () => {
|
2025-02-21 14:48:21 -05:00
|
|
|
console.log(`JoinRoom: handleCreateSocket: ${ENV_VARIABLES.VITE_BACKEND_URL}`);
|
|
|
|
|
const socket = webSocketService.connect(ENV_VARIABLES.VITE_BACKEND_URL);
|
2024-04-05 20:10:59 -04:00
|
|
|
|
2025-02-27 15:49:09 -05:00
|
|
|
socket.on('join-success', (roomJoinedName) => {
|
2024-03-29 20:08:34 -04:00
|
|
|
setIsWaitingForTeacher(true);
|
|
|
|
|
setIsConnecting(false);
|
2025-02-27 15:49:09 -05:00
|
|
|
console.log(`on(join-success): Successfully joined the room ${roomJoinedName}`);
|
2024-03-29 20:08:34 -04:00
|
|
|
});
|
|
|
|
|
socket.on('next-question', (question: QuestionType) => {
|
2025-03-08 01:09:41 -05:00
|
|
|
console.log('JoinRoom: on(next-question): Received next-question:', question);
|
2024-03-29 20:08:34 -04:00
|
|
|
setQuizMode('teacher');
|
|
|
|
|
setIsWaitingForTeacher(false);
|
|
|
|
|
setQuestion(question);
|
|
|
|
|
});
|
2025-03-08 01:09:41 -05:00
|
|
|
socket.on('launch-teacher-mode', (questions: QuestionType[]) => {
|
|
|
|
|
console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions);
|
|
|
|
|
setQuizMode('teacher');
|
|
|
|
|
setIsWaitingForTeacher(true);
|
2025-03-09 00:54:21 -05:00
|
|
|
setQuestions([]); // clear out from last time (in case quiz is repeated)
|
2025-03-08 01:09:41 -05:00
|
|
|
setQuestions(questions);
|
|
|
|
|
// wait for next-question
|
|
|
|
|
});
|
2024-03-29 20:08:34 -04:00
|
|
|
socket.on('launch-student-mode', (questions: QuestionType[]) => {
|
2025-02-27 15:49:09 -05:00
|
|
|
console.log('on(launch-student-mode): Received launch-student-mode:', questions);
|
2025-02-23 22:40:46 -05:00
|
|
|
|
2024-03-29 20:08:34 -04:00
|
|
|
setQuizMode('student');
|
|
|
|
|
setIsWaitingForTeacher(false);
|
2025-03-09 00:54:21 -05:00
|
|
|
setQuestions([]); // clear out from last time (in case quiz is repeated)
|
2024-03-29 20:08:34 -04:00
|
|
|
setQuestions(questions);
|
|
|
|
|
setQuestion(questions[0]);
|
|
|
|
|
});
|
|
|
|
|
socket.on('end-quiz', () => {
|
|
|
|
|
disconnect();
|
|
|
|
|
});
|
|
|
|
|
socket.on('join-failure', (message) => {
|
|
|
|
|
console.log('Failed to join the room.');
|
|
|
|
|
setConnectionError(`Erreur de connexion : ${message}`);
|
|
|
|
|
setIsConnecting(false);
|
|
|
|
|
});
|
|
|
|
|
socket.on('connect_error', (error) => {
|
|
|
|
|
switch (error.message) {
|
|
|
|
|
case 'timeout':
|
2024-10-30 17:19:11 -04:00
|
|
|
setConnectionError("JoinRoom: timeout: Le serveur n'est pas disponible");
|
2024-03-29 20:08:34 -04:00
|
|
|
break;
|
|
|
|
|
case 'websocket error':
|
2024-10-30 17:19:11 -04:00
|
|
|
setConnectionError("JoinRoom: websocket error: Le serveur n'est pas disponible");
|
2024-03-29 20:08:34 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
setIsConnecting(false);
|
|
|
|
|
console.log('Connection Error:', error.message);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
setSocket(socket);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const disconnect = () => {
|
2025-03-08 01:09:41 -05:00
|
|
|
// localStorage.clear();
|
2024-03-29 20:08:34 -04:00
|
|
|
webSocketService.disconnect();
|
|
|
|
|
setSocket(null);
|
|
|
|
|
setQuestion(undefined);
|
|
|
|
|
setIsWaitingForTeacher(false);
|
|
|
|
|
setQuizMode('');
|
|
|
|
|
setRoomName('');
|
|
|
|
|
setUsername('');
|
|
|
|
|
setIsConnecting(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleSocket = () => {
|
|
|
|
|
setIsConnecting(true);
|
|
|
|
|
setConnectionError('');
|
|
|
|
|
if (!socket?.connected) {
|
|
|
|
|
handleCreateSocket();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (username && roomName) {
|
2025-02-21 20:15:32 -05:00
|
|
|
console.log(`Tentative de rejoindre : ${roomName}, utilisateur : ${username}`);
|
|
|
|
|
|
2024-03-29 20:08:34 -04:00
|
|
|
webSocketService.joinRoom(roomName, username);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-08 01:09:41 -05:00
|
|
|
const handleOnSubmitAnswer = (answer: AnswerType, idQuestion: number) => {
|
|
|
|
|
console.info(`JoinRoom: handleOnSubmitAnswer: answer: ${answer}, idQuestion: ${idQuestion}`);
|
2024-09-26 00:34:30 -04:00
|
|
|
const answerData: AnswerSubmissionToBackendType = {
|
|
|
|
|
roomName: roomName,
|
|
|
|
|
answer: answer,
|
|
|
|
|
username: username,
|
|
|
|
|
idQuestion: idQuestion
|
|
|
|
|
};
|
2025-03-08 01:09:41 -05:00
|
|
|
// localStorage.setItem(`Answer${idQuestion}`, JSON.stringify(answer));
|
|
|
|
|
setAnswers((prevAnswers) => {
|
|
|
|
|
console.log(`JoinRoom: handleOnSubmitAnswer: prevAnswers: ${JSON.stringify(prevAnswers)}`);
|
|
|
|
|
const newAnswers = [...prevAnswers]; // Create a copy of the previous answers array
|
|
|
|
|
newAnswers[idQuestion - 1] = answerData; // Update the specific answer
|
|
|
|
|
return newAnswers; // Return the new array
|
|
|
|
|
});
|
|
|
|
|
console.log(`JoinRoom: handleOnSubmitAnswer: answers: ${JSON.stringify(answers)}`);
|
2024-09-26 00:34:30 -04:00
|
|
|
webSocketService.submitAnswer(answerData);
|
2024-03-29 20:08:34 -04:00
|
|
|
};
|
|
|
|
|
|
2025-02-27 23:20:17 -05:00
|
|
|
const handleReturnKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
2025-02-27 23:43:58 -05:00
|
|
|
if (e.key === 'Enter' && username && roomName) {
|
2025-02-27 23:20:17 -05:00
|
|
|
handleSocket();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-29 20:08:34 -04:00
|
|
|
if (isWaitingForTeacher) {
|
|
|
|
|
return (
|
|
|
|
|
<div className='room'>
|
|
|
|
|
<div className='roomHeader'>
|
|
|
|
|
|
|
|
|
|
<DisconnectButton
|
|
|
|
|
onReturn={disconnect}
|
|
|
|
|
message={`Êtes-vous sûr de vouloir quitter?`} />
|
|
|
|
|
|
|
|
|
|
<div className='centerTitle'>
|
|
|
|
|
<div className='title'>Salle: {roomName}</div>
|
|
|
|
|
<div className='userCount subtitle'>
|
|
|
|
|
En attente que le professeur lance le questionnaire...
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className='dumb'></div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (quizMode) {
|
|
|
|
|
case 'student':
|
|
|
|
|
return (
|
|
|
|
|
<StudentModeQuiz
|
|
|
|
|
questions={questions}
|
2025-03-08 01:09:41 -05:00
|
|
|
answers={answers}
|
2024-03-29 20:08:34 -04:00
|
|
|
submitAnswer={handleOnSubmitAnswer}
|
|
|
|
|
disconnectWebSocket={disconnect}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
case 'teacher':
|
|
|
|
|
return (
|
|
|
|
|
question && (
|
|
|
|
|
<TeacherModeQuiz
|
|
|
|
|
questionInfos={question}
|
2025-03-08 01:09:41 -05:00
|
|
|
answers={answers}
|
2024-03-29 20:08:34 -04:00
|
|
|
submitAnswer={handleOnSubmitAnswer}
|
|
|
|
|
disconnectWebSocket={disconnect}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
default:
|
|
|
|
|
return (
|
|
|
|
|
<LoginContainer
|
|
|
|
|
title='Rejoindre une salle'
|
|
|
|
|
error={connectionError}>
|
|
|
|
|
|
|
|
|
|
<TextField
|
2025-02-21 20:15:32 -05:00
|
|
|
type="text"
|
|
|
|
|
label="Nom de la salle"
|
2024-03-29 20:08:34 -04:00
|
|
|
variant="outlined"
|
2024-09-24 18:24:04 -04:00
|
|
|
value={roomName}
|
2025-02-27 15:49:09 -05:00
|
|
|
onChange={(e) => setRoomName(e.target.value.toUpperCase())}
|
2025-02-21 20:15:32 -05:00
|
|
|
placeholder="Nom de la salle"
|
2024-03-29 20:08:34 -04:00
|
|
|
sx={{ marginBottom: '1rem' }}
|
2025-02-27 23:20:17 -05:00
|
|
|
fullWidth={true}
|
|
|
|
|
onKeyDown={handleReturnKey}
|
2024-03-29 20:08:34 -04:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
2024-09-24 18:24:04 -04:00
|
|
|
label="Nom d'utilisateur"
|
2024-03-29 20:08:34 -04:00
|
|
|
variant="outlined"
|
2024-09-24 18:24:04 -04:00
|
|
|
value={username}
|
|
|
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
|
|
|
placeholder="Nom d'utilisateur"
|
2024-03-29 20:08:34 -04:00
|
|
|
sx={{ marginBottom: '1rem' }}
|
2025-02-27 23:20:17 -05:00
|
|
|
fullWidth={true}
|
|
|
|
|
onKeyDown={handleReturnKey}
|
2024-03-29 20:08:34 -04:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<LoadingButton
|
|
|
|
|
loading={isConnecting}
|
|
|
|
|
onClick={handleSocket}
|
|
|
|
|
variant="contained"
|
|
|
|
|
sx={{ marginBottom: `${connectionError && '2rem'}` }}
|
|
|
|
|
disabled={!username || !roomName}
|
|
|
|
|
>Rejoindre</LoadingButton>
|
|
|
|
|
|
|
|
|
|
</LoginContainer>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default JoinRoom;
|