Correction

This commit is contained in:
NouhailaAater 2025-02-21 20:15:32 -05:00
parent 29924a6786
commit fd9f04d116
6 changed files with 164 additions and 113 deletions

View file

@ -10,22 +10,28 @@ interface Props {
students: StudentType[]; students: StudentType[];
launchQuiz: () => void; launchQuiz: () => void;
setQuizMode: (mode: 'student' | 'teacher') => void; setQuizMode: (mode: 'student' | 'teacher') => void;
setIsRoomSelectionVisible: (visible: boolean) => void;
} }
const StudentWaitPage: React.FC<Props> = ({ students, launchQuiz, setQuizMode }) => { const StudentWaitPage: React.FC<Props> = ({ students, launchQuiz, setQuizMode, setIsRoomSelectionVisible }) => {
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false); const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
const handleLaunchClick = () => {
setIsDialogOpen(true);
setIsRoomSelectionVisible(false);
};
return ( return (
<div className="wait"> <div className="wait">
<div className='button'> <div className='button'>
<Button <Button
variant="contained" variant="contained"
onClick={() => setIsDialogOpen(true)} onClick={handleLaunchClick}
startIcon={<PlayArrow />} startIcon={<PlayArrow />}
fullWidth fullWidth
sx={{ fontWeight: 600, fontSize: 20 }} sx={{ fontWeight: 600, fontSize: 20 }}
> >
Lancer Lancer
</Button> </Button>
</div> </div>

View file

@ -60,6 +60,8 @@ const JoinRoom: React.FC = () => {
console.log('Failed to join the room.'); console.log('Failed to join the room.');
setConnectionError(`Erreur de connexion : ${message}`); setConnectionError(`Erreur de connexion : ${message}`);
setIsConnecting(false); setIsConnecting(false);
setRoomName(''); // Réinitialise le nom de la salle
setUsername(''); // Réinitialise le nom d'utilisateur
}); });
socket.on('connect_error', (error) => { socket.on('connect_error', (error) => {
switch (error.message) { switch (error.message) {
@ -96,6 +98,8 @@ const JoinRoom: React.FC = () => {
} }
if (username && roomName) { if (username && roomName) {
console.log(`Tentative de rejoindre : ${roomName}, utilisateur : ${username}`);
webSocketService.joinRoom(roomName, username); webSocketService.joinRoom(roomName, username);
} }
}; };
@ -160,12 +164,12 @@ const JoinRoom: React.FC = () => {
error={connectionError}> error={connectionError}>
<TextField <TextField
type="number" type="text"
label="Numéro de la salle" label="Nom de la salle"
variant="outlined" variant="outlined"
value={roomName} value={roomName}
onChange={(e) => setRoomName(e.target.value)} onChange={(e) => setRoomName(e.target.value)}
placeholder="Numéro de la salle" placeholder="Nom de la salle"
sx={{ marginBottom: '1rem' }} sx={{ marginBottom: '1rem' }}
fullWidth fullWidth
/> />

View file

@ -43,34 +43,35 @@ const ManageRoom: React.FC = () => {
const [selectedRoomId, setSelectedRoomId] = useState<string>(''); const [selectedRoomId, setSelectedRoomId] = useState<string>('');
const [openDialog, setOpenDialog] = useState(false); const [openDialog, setOpenDialog] = useState(false);
const [newRoomTitle, setNewRoomTitle] = useState(''); const [newRoomTitle, setNewRoomTitle] = useState('');
const [isRoomSelectionVisible, setIsRoomSelectionVisible] = useState(true);
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
if (!ApiService.isLoggedIn()) { if (!ApiService.isLoggedIn()) {
navigate('/teacher/login'); navigate('/teacher/login');
return; return;
} else {
const userRooms = await ApiService.getUserRooms();
setRooms(userRooms as RoomType[]);
} }
const userRooms = await ApiService.getUserRooms();
setRooms(userRooms as RoomType[]);
}; };
fetchData(); fetchData();
}, []); }, []);
const handleSelectRoom = (event: React.ChangeEvent<HTMLSelectElement>) => { const handleSelectRoom = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedRoomId(event.target.value); const roomId = event.target.value;
setSelectedRoomId(roomId);
const selectedRoom = rooms.find((room) => room._id === roomId);
setRoomName(selectedRoom?.title || '');
}; };
useEffect(() => { useEffect(() => {
if (selectedRoomId && rooms.length > 0) { if (rooms.length > 0 && !selectedRoomId) {
const selectedRoom = rooms.find((room) => room._id === selectedRoomId); setSelectedRoomId(rooms[0]._id);
setRoomName(selectedRoom ? selectedRoom.title : '');
} else {
setRoomName('');
} }
}, [selectedRoomId, rooms]); }, [rooms]);
const handleDialogClose = () => { const handleDialogClose = () => {
setOpenDialog(false); setOpenDialog(false);
@ -81,16 +82,21 @@ const ManageRoom: React.FC = () => {
}; };
const handleSubmitRoom = async () => { const handleSubmitRoom = async () => {
try { try {
if (newRoomTitle) { if (newRoomTitle.trim()) {
await ApiService.createRoom(newRoomTitle); const createdRoom = await ApiService.createRoom(newRoomTitle);
const userRooms = await ApiService.getUserRooms();
setRooms(userRooms as RoomType[]); const updatedRooms = await ApiService.getUserRooms();
const newlyCreatedRoom = userRooms[userRooms.length - 1] as RoomType; setRooms(updatedRooms as RoomType[]);
setSelectedRoomId(newlyCreatedRoom._id);
if (createdRoom && createdRoom) {
setSelectedRoomId(createdRoom);
setRoomName(createdRoom);
}
setOpenDialog(false); setOpenDialog(false);
setNewRoomTitle('');
} }
} catch (error) { } catch (error) {
console.error('Error creating Room:', error); console.error('Error creating Room::', error);
} }
}; };
@ -131,6 +137,25 @@ const ManageRoom: React.FC = () => {
} }
}, [quizId]); }, [quizId]);
useEffect(() => {
if (rooms.length > 0 && !selectedRoomId) {
setSelectedRoomId(rooms[0].title);
}
}, [rooms]);
useEffect(() => {
if (!newRoomTitle && !selectedRoomId) {
setConnectingError('Aucun nom de salle sélectionné ou créé.');
}
}, [newRoomTitle, selectedRoomId]);
useEffect(() => {
if (selectedRoomId && selectedRoomId.trim() !== '') {
console.log(`Sélection d'une nouvelle salle: ${selectedRoomId}`);
createWebSocketRoom();
}
}, [selectedRoomId]);
const disconnectWebSocket = () => { const disconnectWebSocket = () => {
if (socket) { if (socket) {
webSocketService.endQuiz(roomName); webSocketService.endQuiz(roomName);
@ -146,42 +171,34 @@ const ManageRoom: React.FC = () => {
const createWebSocketRoom = () => { const createWebSocketRoom = () => {
console.log('Creating WebSocket room...'); console.log('Creating WebSocket room...');
setConnectingError(''); setConnectingError('');
const targetRoom = rooms.find((room) => room._id === selectedRoomId) || rooms[0];
if (!targetRoom) {
setConnectingError('Aucune salle disponible');
return;
}
console.log('Création WebSocket pour:', targetRoom.title);
const socket = webSocketService.connect(ENV_VARIABLES.VITE_BACKEND_SOCKET_URL); const socket = webSocketService.connect(ENV_VARIABLES.VITE_BACKEND_SOCKET_URL);
socket.on('connect', () => { socket.on('connect', () => {
webSocketService.createRoom(selectedRoomId); webSocketService.createRoom(targetRoom.title);
console.error('socket.on(connect:)'); setRoomName(targetRoom.title);
}); });
socket.on('connect_error', (error) => { socket.on('connect_error', (error) => {
setConnectingError('Erreur lors de la connexion... Veuillez réessayer'); setConnectingError('Erreur lors de la connexion... Veuillez réessayer');
console.error('ManageRoom: WebSocket connection error:', error); console.error('ManageRoom: WebSocket connection error:', error);
}); });
socket.on('create-success', (roomName: string) => { socket.on('create-success', (roomName: string) => {
console.log('create-success', roomName);
setRoomName(roomName); setRoomName(roomName);
console.error('create-success', roomName);
}); });
socket.on('create-failure', () => { socket.on('create-failure', () => {
console.log('Error creating room.'); console.log('Error creating room.');
}); });
socket.on('user-joined', (student: StudentType) => {
console.log(`Student joined: name = ${student.name}, id = ${student.id}`);
setStudents((prevStudents) => [...prevStudents, student]);
if (quizMode === 'teacher') {
webSocketService.nextQuestion(roomName, currentQuestion);
} else if (quizMode === 'student') {
webSocketService.launchStudentModeQuiz(roomName, quizQuestions);
}
});
socket.on('join-failure', (message) => {
setConnectingError(message);
setSocket(null);
});
socket.on('user-disconnected', (userId: string) => {
console.log(`Student left: id = ${userId}`);
setStudents((prevUsers) => prevUsers.filter((user) => user.id !== userId));
});
setSocket(socket); setSocket(socket);
}; };
@ -477,64 +494,69 @@ const ManageRoom: React.FC = () => {
<div className="dumb"></div> <div className="dumb"></div>
</div> </div>
<div className="room"> {isRoomSelectionVisible && (
<div className="select"> <div className="roomSelection">
<NativeSelect <div className="select">
id="select-room" <NativeSelect
color="primary" id="select-room"
value={selectedRoomId} color="primary"
onChange={handleSelectRoom} value={selectedRoomId}
> onChange={handleSelectRoom}
<option value=""> Sélectionner une salle </option> >
{rooms.map((room: RoomType) => ( <option value=""> Sélectionner une salle </option>
<option value={room._id} key={room._id}> {rooms.map((room: RoomType) => (
{' '} <option value={room._id} key={room._id}>
{room.title}{' '} {' '}
</option> {room.title}
))} </option>
</NativeSelect> ))}
</div> </NativeSelect>
</div>
<div className="actions" style={{ display: 'flex', justifyContent: 'flex-end' }}> <div
<Button className="actions"
variant="contained" style={{ display: 'flex', justifyContent: 'flex-end' }}
color="primary"
onClick={handleCreateRoom}
style={{
width: 'auto',
marginLeft: '30px',
height: '40px',
padding: '0 20px'
}}
> >
Ajouter une nouvelle salle <Button
</Button> variant="contained"
</div> color="primary"
onClick={handleCreateRoom}
style={{
width: 'auto',
marginLeft: '30px',
height: '40px',
padding: '0 20px'
}}
>
Ajouter une nouvelle salle
</Button>
</div>
{/* Dialog pour créer une salle */} {/* Dialog pour créer une salle */}
<Dialog open={openDialog} onClose={handleDialogClose} maxWidth="sm" fullWidth> <Dialog open={openDialog} onClose={handleDialogClose} maxWidth="sm" fullWidth>
<DialogTitle>Créer une nouvelle salle</DialogTitle> <DialogTitle>Créer une nouvelle salle</DialogTitle>
<DialogContent> <DialogContent>
<TextField <TextField
autoFocus autoFocus
margin="dense" margin="dense"
label="Titre de la salle" label="Titre de la salle"
type="text" type="text"
fullWidth fullWidth
value={newRoomTitle} value={newRoomTitle}
onChange={(e) => setNewRoomTitle(e.target.value)} onChange={(e) => setNewRoomTitle(e.target.value)}
/> />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={handleDialogClose} color="secondary"> <Button onClick={handleDialogClose} color="secondary">
Annuler Annuler
</Button> </Button>
<Button onClick={handleSubmitRoom} color="primary"> <Button onClick={handleSubmitRoom} color="primary">
Créer Créer
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
</div> </div>
)}
{/* the following breaks the css (if 'room' classes are nested) */} {/* the following breaks the css (if 'room' classes are nested) */}
<div className=""> <div className="">
@ -612,6 +634,7 @@ const ManageRoom: React.FC = () => {
students={students} students={students}
launchQuiz={launchQuiz} launchQuiz={launchQuiz}
setQuizMode={setQuizMode} setQuizMode={setQuizMode}
setIsRoomSelectionVisible={setIsRoomSelectionVisible}
/> />
)} )}
</div> </div>

View file

@ -391,7 +391,7 @@ class ApiService {
if (result.status !== 200) { if (result.status !== 200) {
throw new Error(`L'obtention des salles utilisateur a échoué. Status: ${result.status}`); throw new Error(`L'obtention des salles utilisateur a échoué. Status: ${result.status}`);
} }
return result.data.data.map((room: RoomType) => ({ _id: room._id, title: room.title })); return result.data.data.map((room: RoomType) => ({ _id: room._id, title: room.title }));
} catch (error) { } catch (error) {

View file

@ -1,4 +1,3 @@
// WebSocketService.tsx
import { io, Socket } from 'socket.io-client'; import { io, Socket } from 'socket.io-client';
// Must (manually) sync these types to server/socket/socket.js // Must (manually) sync these types to server/socket/socket.js
@ -48,8 +47,7 @@ class WebSocketService {
createRoom(roomName: string) { createRoom(roomName: string) {
if (this.socket) { if (this.socket) {
const nameToSend = roomName; this.socket.emit('create-room', roomName);
this.socket.emit('create-room', nameToSend);
} }
} }

View file

@ -24,29 +24,51 @@ const setupWebsocket = (io) => {
); );
socket.on("create-room", (sentRoomName) => { socket.on("create-room", (sentRoomName) => {
console.log(`Demande de création de salle avec le nom : ${sentRoomName}`);
if (sentRoomName) { if (sentRoomName) {
const roomName = sentRoomName.toUpperCase(); const roomName = sentRoomName.toUpperCase();
if (!io.sockets.adapter.rooms.get(roomName)) { if (!io.sockets.adapter.rooms.get(roomName)) {
socket.join(roomName); socket.join(roomName);
socket.emit("create-success", roomName); socket.emit("create-success", roomName);
console.log(`Salle créée avec succès : ${roomName}`);
} else { } else {
socket.emit("create-failure"); socket.emit("create-failure", `La salle ${roomName} existe déjà.`);
console.log(`Échec de création : ${roomName} existe déjà`);
} }
} else { } else {
const roomName = generateRoomName(); const roomName = generateRoomName();
console.log(`Génération d'une salle aléatoire : ${roomName}`);
if (!io.sockets.adapter.rooms.get(roomName)) { if (!io.sockets.adapter.rooms.get(roomName)) {
socket.join(roomName); socket.join(roomName);
socket.emit("create-success", roomName); socket.emit("create-success", roomName);
console.log(`Salle créée avec succès : ${roomName}`);
} else { } else {
socket.emit("create-failure"); socket.emit(
"create-failure",
"Échec de création de la salle aléatoire"
);
console.log(`Échec de création de la salle aléatoire`);
} }
} }
console.log(
"Salles existantes après la tentative de création : ",
Array.from(io.sockets.adapter.rooms.keys())
);
}); });
socket.on("join-room", ({ enteredRoomName, username }) => { socket.on("join-room", ({ enteredRoomName, username }) => {
if (io.sockets.adapter.rooms.has(enteredRoomName)) { const roomToCheck = enteredRoomName.toUpperCase();
const clientsInRoom = console.log(
io.sockets.adapter.rooms.get(enteredRoomName).size; `Requête de connexion : salle="${roomToCheck}", utilisateur="${username}"`
);
console.log(
"Salles existantes :",
Array.from(io.sockets.adapter.rooms.keys())
);
if (io.sockets.adapter.rooms.has(roomToCheck)) {
const clientsInRoom = io.sockets.adapter.rooms.get(roomToCheck).size;
if (clientsInRoom <= MAX_USERS_PER_ROOM) { if (clientsInRoom <= MAX_USERS_PER_ROOM) {
const newStudent = { const newStudent = {
@ -54,10 +76,8 @@ const setupWebsocket = (io) => {
name: username, name: username,
answers: [], answers: [],
}; };
socket.join(enteredRoomName); socket.join(roomToCheck);
socket socket.to(roomToCheck).emit("user-joined", newStudent);
.to(enteredRoomName)
.emit("user-joined", newStudent);
socket.emit("join-success"); socket.emit("join-success");
} else { } else {
socket.emit("join-failure", "La salle est remplie"); socket.emit("join-failure", "La salle est remplie");