EvalueTonSavoir/client/src/pages/Student/JoinRoom/JoinRoom.tsx

240 lines
9.1 KiB
TypeScript
Raw Normal View History

2024-03-29 20:08:34 -04:00
import React, { useEffect, useState } from 'react';
import { Socket } from 'socket.io-client';
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';
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
import ApiService from '../../../services/ApiService'
export type AnswerType = string | number | boolean;
2024-03-29 20:08:34 -04:00
const JoinRoom: React.FC = () => {
const [roomName, setRoomName] = useState('');
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[]>([]);
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();
};
}, []);
useEffect(() => {
// init the answers array, one for each question
setAnswers(Array(questions.length).fill({} as AnswerSubmissionToBackendType));
console.log(`JoinRoom: useEffect: questions: ${JSON.stringify(questions)}`);
}, [questions]);
2024-03-29 20:08:34 -04:00
const handleCreateSocket = () => {
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
socket.on('join-success', (roomJoinedName) => {
2024-03-29 20:08:34 -04:00
setIsWaitingForTeacher(true);
setIsConnecting(false);
console.log(`on(join-success): Successfully joined the room ${roomJoinedName}`);
2024-03-29 20:08:34 -04:00
});
socket.on('next-question', (question: QuestionType) => {
console.log('JoinRoom: on(next-question): Received next-question:', question);
2024-03-29 20:08:34 -04:00
setQuizMode('teacher');
setIsWaitingForTeacher(false);
setQuestion(question);
});
socket.on('launch-teacher-mode', (questions: QuestionType[]) => {
console.log('on(launch-teacher-mode): Received launch-teacher-mode:', questions);
setQuizMode('teacher');
setIsWaitingForTeacher(true);
setQuestions(questions);
// wait for next-question
});
2024-03-29 20:08:34 -04:00
socket.on('launch-student-mode', (questions: QuestionType[]) => {
console.log('on(launch-student-mode): Received launch-student-mode:', questions);
2024-03-29 20:08:34 -04:00
setQuizMode('student');
setIsWaitingForTeacher(false);
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 = () => {
// 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);
}
};
const handleOnSubmitAnswer = (answer: AnswerType, idQuestion: number) => {
console.info(`JoinRoom: handleOnSubmitAnswer: answer: ${answer}, idQuestion: ${idQuestion}`);
const answerData: AnswerSubmissionToBackendType = {
roomName: roomName,
answer: answer,
username: username,
idQuestion: idQuestion
};
// 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)}`);
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}
answers={answers}
2024-03-29 20:08:34 -04:00
submitAnswer={handleOnSubmitAnswer}
disconnectWebSocket={disconnect}
/>
);
case 'teacher':
return (
question && (
<TeacherModeQuiz
questionInfos={question}
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"
value={roomName}
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
label="Nom d'utilisateur"
2024-03-29 20:08:34 -04:00
variant="outlined"
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;