mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Correction
This commit is contained in:
parent
29924a6786
commit
fd9f04d116
6 changed files with 164 additions and 113 deletions
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue