diff --git a/client/src/components/GIFTCheatSheet/GiftCheatSheet.tsx b/client/src/components/GIFTCheatSheet/GiftCheatSheet.tsx index 036f2d0..0d22eae 100644 --- a/client/src/components/GIFTCheatSheet/GiftCheatSheet.tsx +++ b/client/src/components/GIFTCheatSheet/GiftCheatSheet.tsx @@ -1,6 +1,7 @@ // GiftCheatSheet.tsx import React, { useState } from 'react'; import './giftCheatSheet.css'; +import FileCopyIcon from '@mui/icons-material/FileCopy'; const GiftCheatSheet: React.FC = () => { const [copySuccess, setCopySuccess] = useState(false); @@ -19,7 +20,7 @@ const GiftCheatSheet: React.FC = () => { console.error('Erreur lors de la copie dans le presse-papiers : ', error); }); }; - + const QuestionVraiFaux = "::Exemple de question vrai/faux:: \n 2+2 \\= 4 ? {T} //Utilisez les valeurs {T}, {F}, {TRUE} et {FALSE}."; const QuestionChoixMul = "::Ville capitale du Canada:: \nQuelle ville est la capitale du Canada? {\n~ Toronto\n~ Montréal\n= Ottawa #Rétroaction spécifique.\n} // Commentaire non visible (au besoin)"; @@ -42,7 +43,10 @@ const GiftCheatSheet: React.FC = () => { - +
@@ -54,7 +58,10 @@ const GiftCheatSheet: React.FC = () => { } - +

3. Questions à choix multiple avec plusieurs réponses

@@ -65,7 +72,10 @@ const GiftCheatSheet: React.FC = () => { } - +
@@ -75,7 +85,10 @@ const GiftCheatSheet: React.FC = () => { {QuestionCourte} - +
@@ -87,7 +100,10 @@ const GiftCheatSheet: React.FC = () => { } - +
@@ -185,7 +201,7 @@ const GiftCheatSheet: React.FC = () => { Attention: l'ancienne fonctionnalité avec les balises {''} n'est plus supportée.

-
+

10. Informations supplémentaires

@@ -199,6 +215,6 @@ const GiftCheatSheet: React.FC = () => {

); -}; +}; export default GiftCheatSheet; diff --git a/client/src/components/Header/Header.tsx b/client/src/components/Header/Header.tsx index 016d23e..71f0a79 100644 --- a/client/src/components/Header/Header.tsx +++ b/client/src/components/Header/Header.tsx @@ -2,6 +2,7 @@ import { Link, useNavigate } from 'react-router-dom'; import * as React from 'react'; import './header.css'; import { Button } from '@mui/material'; +import ExitToAppIcon from '@mui/icons-material/ExitToApp'; interface HeaderProps { isLoggedIn: boolean; @@ -28,8 +29,9 @@ const Header: React.FC = ({ isLoggedIn, handleLogout }) => { handleLogout(); navigate('/'); }} + startIcon={} > - Logout + Déconnexion )} diff --git a/client/src/components/QuestionsDisplay/TrueFalseQuestionDisplay/TrueFalseQuestionDisplay.tsx b/client/src/components/QuestionsDisplay/TrueFalseQuestionDisplay/TrueFalseQuestionDisplay.tsx index 717cdbe..7decbab 100644 --- a/client/src/components/QuestionsDisplay/TrueFalseQuestionDisplay/TrueFalseQuestionDisplay.tsx +++ b/client/src/components/QuestionsDisplay/TrueFalseQuestionDisplay/TrueFalseQuestionDisplay.tsx @@ -59,7 +59,6 @@ const TrueFalseQuestionDisplay: React.FC = (props) => { disabled={disableButton} > {showAnswer ? (
{(question.isTrue ? '✅' : '❌')}
) : ``} -
V
Vrai
{showAnswer && answer && question.trueFormattedFeedback && ( @@ -76,7 +75,6 @@ const TrueFalseQuestionDisplay: React.FC = (props) => { > {showAnswer ? (
{(!question.isTrue ? '✅' : '❌')}
) : ``} -
F
Faux
{showAnswer && !answer && question.falseFormattedFeedback && ( diff --git a/client/src/components/StudentWaitPage/StudentWaitPage.tsx b/client/src/components/StudentWaitPage/StudentWaitPage.tsx index c5de4f2..52f8958 100644 --- a/client/src/components/StudentWaitPage/StudentWaitPage.tsx +++ b/client/src/components/StudentWaitPage/StudentWaitPage.tsx @@ -21,16 +21,15 @@ const StudentWaitPage: React.FC = ({ students, launchQuiz, setQuizMode }) return (
-
+
+ Lancer +
diff --git a/client/src/components/TeacherModeQuiz/TeacherModeQuiz.tsx b/client/src/components/TeacherModeQuiz/TeacherModeQuiz.tsx index 8925c09..ca67aba 100644 --- a/client/src/components/TeacherModeQuiz/TeacherModeQuiz.tsx +++ b/client/src/components/TeacherModeQuiz/TeacherModeQuiz.tsx @@ -116,7 +116,7 @@ const TeacherModeQuiz: React.FC = ({ diff --git a/client/src/pages/AuthManager/providers/SimpleLogin/Login.tsx b/client/src/pages/AuthManager/providers/SimpleLogin/Login.tsx index ecc9a1c..e0d4988 100644 --- a/client/src/pages/AuthManager/providers/SimpleLogin/Login.tsx +++ b/client/src/pages/AuthManager/providers/SimpleLogin/Login.tsx @@ -44,7 +44,6 @@ const SimpleLogin: React.FC = () => { variant="outlined" value={email} onChange={(e) => setEmail(e.target.value)} - placeholder="Nom d'utilisateur" sx={{ marginBottom: '1rem' }} fullWidth /> @@ -55,7 +54,6 @@ const SimpleLogin: React.FC = () => { type="password" value={password} onChange={(e) => setPassword(e.target.value)} - placeholder="Nom de la salle" sx={{ marginBottom: '1rem' }} fullWidth /> diff --git a/client/src/pages/Teacher/Dashboard/Dashboard.tsx b/client/src/pages/Teacher/Dashboard/Dashboard.tsx index cdae619..9d84bbb 100644 --- a/client/src/pages/Teacher/Dashboard/Dashboard.tsx +++ b/client/src/pages/Teacher/Dashboard/Dashboard.tsx @@ -105,7 +105,7 @@ const Dashboard: React.FC = () => { fetchData(); }, []); - + useEffect(() => { if (rooms.length > 0 && !selectedRoom) { selectRoom(rooms[rooms.length - 1]); @@ -121,41 +121,41 @@ const Dashboard: React.FC = () => { } }; - // Créer une salle - const createRoom = async (title: string) => { - // Créer la salle et récupérer l'objet complet - const newRoom = await ApiService.createRoom(title); - - // Mettre à jour la liste des salles - const updatedRooms = await ApiService.getUserRooms(); - setRooms(updatedRooms as RoomType[]); - - // Sélectionner la nouvelle salle avec son ID - selectRoomByName(newRoom); // Utiliser l'ID de l'objet retourné - }; + // Créer une salle + const createRoom = async (title: string) => { + // Créer la salle et récupérer l'objet complet + const newRoom = await ApiService.createRoom(title); + + // Mettre à jour la liste des salles + const updatedRooms = await ApiService.getUserRooms(); + setRooms(updatedRooms as RoomType[]); + + // Sélectionner la nouvelle salle avec son ID + selectRoomByName(newRoom); // Utiliser l'ID de l'objet retourné + }; - // Sélectionner une salle - const selectRoomByName = (roomId: string) => { + // Sélectionner une salle + const selectRoomByName = (roomId: string) => { const room = rooms.find(r => r._id === roomId); - selectRoom(room); - localStorage.setItem('selectedRoomId', roomId); - }; + selectRoom(room); + localStorage.setItem('selectedRoomId', roomId); + }; - const handleCreateRoom = async () => { - if (newRoomTitle.trim()) { - try { + const handleCreateRoom = async () => { + if (newRoomTitle.trim()) { + try { await createRoom(newRoomTitle); const userRooms = await ApiService.getUserRooms(); setRooms(userRooms as RoomType[]); - setOpenAddRoomDialog(false); - setNewRoomTitle(''); - } catch (error) { + setOpenAddRoomDialog(false); + setNewRoomTitle(''); + } catch (error) { setErrorMessage(error instanceof Error ? error.message : "Erreur inconnue"); - setShowErrorDialog(true); - } - } - }; + setShowErrorDialog(true); + } + } + }; const handleSelectFolder = (event: React.ChangeEvent) => { setSelectedFolderId(event.target.value); @@ -398,7 +398,7 @@ const Dashboard: React.FC = () => { } else { const randomSixDigit = Math.floor(100000 + Math.random() * 900000); navigate(`/teacher/manage-room/${quiz._id}/${randomSixDigit}`); - } + } }; const handleShareQuiz = async (quiz: QuizType) => { @@ -425,30 +425,63 @@ const Dashboard: React.FC = () => { return (
-
Tableau de bord
+ {/* Conteneur pour le titre et le sélecteur de salle */} +
+ {/* Titre tableau de bord */} +
+ Tableau de bord +
-
- - handleSelectRoom(e)} + id="room-select" + style={{ + padding: '8px 12px', + fontSize: '14px', + borderRadius: '8px', + border: '1px solid #ccc', + backgroundColor: '#fff', + maxWidth: '200px', + cursor: 'pointer', + fontWeight: '500' + }} + > + - ))} - - - + {rooms.map((room) => ( + + ))} + + +
- {selectedRoom && ( -
-

Salle sélectionnée: {selectedRoom.title}

-
- )} - + {/* Dialog pour créer une salle */} setOpenAddRoomDialog(false)}> Créer une nouvelle salle @@ -463,6 +496,8 @@ const Dashboard: React.FC = () => { + + {/* Dialog d'erreur */} setShowErrorDialog(false)}> Erreur @@ -473,193 +508,238 @@ const Dashboard: React.FC = () => { -
- - - - - - ) - }} - /> +
+
+ + + + + + ) + }} + sx={{ + '& .MuiOutlinedInput-root': { + borderRadius: '8px', + '& fieldset': { + borderColor: '#e0e0e0' + }, + '&:hover fieldset': { + borderColor: '#5271FF' + } + } + }} + /> +
+ +
+ + + +
-
-
+ {/* Conteneur principal avec les actions et la liste des quiz */} +
+ {/* Barre d'outils pour le sélecteur de dossier et les actions */} +
+ {/* Sélecteur de dossier */} - - - {folders.map((folder: FolderType) => ( + + {folders.map((folder) => ( ))} + + {/* Actions dossiers */} +
+ + + + + + + + + + + + + + + + + + + + +
-
- - - {' '} - {' '} - - - - -
- + {Object.keys(quizzesByFolder).map((folderName) => ( + - {' '} - {' '} - -
-
- - -
- - {' '} - {' '} - -
-
- - -
- - {' '} - {' '} - -
-
-
-
- -
- - - -
-
- {Object.keys(quizzesByFolder).map((folderName) => ( - -
{folderName}
- - {quizzesByFolder[folderName].map((quiz: QuizType) => ( -
-
- -
+
+ {folderName} +
+ + {quizzesByFolder[folderName].map((quiz) => ( +
+
+ -
- + +
+ +
+ + downloadTxtFile(quiz)} + > + + + + + + handleEditQuiz(quiz)} + > + + + + + + handleDuplicateQuiz(quiz)} + > + + + + + + handleRemoveQuiz(quiz)} + > + + + + + + handleShareQuiz(quiz)} + > + + + +
- -
- - downloadTxtFile(quiz)} - > - {' '} - {' '} - - - - - handleEditQuiz(quiz)} - > - {' '} - {' '} - - - - - handleDuplicateQuiz(quiz)} - > - {' '} - {' '} - - - - - handleRemoveQuiz(quiz)} - > - {' '} - {' '} - - - - - handleShareQuiz(quiz)} - > - {' '} - {' '} - - -
-
- ))} - - - ))} + ))} + + + ))} +
+ + {/* Modal d'importation */} setShowImportModal(false)} diff --git a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx index 89f822a..12eafcd 100644 --- a/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx +++ b/client/src/pages/Teacher/EditorQuiz/EditorQuiz.tsx @@ -17,6 +17,7 @@ import ReturnButton from 'src/components/ReturnButton/ReturnButton'; import ApiService from '../../../services/ApiService'; import { escapeForGIFT } from '../../../utils/giftUtils'; import { Upload } from '@mui/icons-material'; +import SaveIcon from '@mui/icons-material/Save'; interface EditQuizParams { id: string; @@ -244,6 +245,7 @@ const QuizForm: React.FC = () => { diff --git a/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx b/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx index 8c3d699..67d403b 100644 --- a/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx +++ b/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx @@ -35,19 +35,19 @@ const ManageRoom: React.FC = () => { const [formattedRoomName, setFormattedRoomName] = useState(""); const [newlyConnectedUser, setNewlyConnectedUser] = useState(null); - // Handle the newly connected user in useEffect, because it needs state info + // Handle the newly connected user in useEffect, because it needs state info // not available in the socket.on() callback useEffect(() => { if (newlyConnectedUser) { console.log(`Handling newly connected user: ${newlyConnectedUser.name}`); setStudents((prevStudents) => [...prevStudents, newlyConnectedUser]); - + // only send nextQuestion if the quiz has started if (!quizStarted) { console.log(`!quizStarted: returning.... `); return; } - + if (quizMode === 'teacher') { webSocketService.nextQuestion({ roomName: formattedRoomName, @@ -60,7 +60,7 @@ const ManageRoom: React.FC = () => { } else { console.error('Invalid quiz mode:', quizMode); } - + // Reset the newly connected user state setNewlyConnectedUser(null); } @@ -91,7 +91,7 @@ const ManageRoom: React.FC = () => { return () => { disconnectWebSocket(); }; - }, [roomName, navigate]); + }, [roomName, navigate]); useEffect(() => { if (quizId) { @@ -138,8 +138,8 @@ const ManageRoom: React.FC = () => { setFormattedRoomName(roomNameUpper); console.log(`Creating WebSocket room named ${roomNameUpper}`); - /** - * ATTENTION: Lire les variables d'état dans + /** + * ATTENTION: Lire les variables d'état dans * les .on() n'est pas une bonne pratique. * Les valeurs sont celles au moment de la création * de la fonction et non au moment de l'exécution. @@ -254,8 +254,8 @@ const ManageRoom: React.FC = () => { setCurrentQuestion(quizQuestions[nextQuestionIndex]); webSocketService.nextQuestion({roomName: formattedRoomName, - questions: quizQuestions, - questionIndex: nextQuestionIndex, + questions: quizQuestions, + questionIndex: nextQuestionIndex, isLaunch: false}); }; @@ -382,15 +382,19 @@ const ManageRoom: React.FC = () => { width: '100%' }} > - {( + {
{students.length}/60
- )} + }
diff --git a/client/src/pages/Teacher/ManageRoom/manageRoom.css b/client/src/pages/Teacher/ManageRoom/manageRoom.css index ad870a9..ece7043 100644 --- a/client/src/pages/Teacher/ManageRoom/manageRoom.css +++ b/client/src/pages/Teacher/ManageRoom/manageRoom.css @@ -1,26 +1,33 @@ - .room .roomHeader { width: 100%; display: flex; - flex-direction: row; - justify-content: space-between; - align-content: stretch + flex-direction: column; + align-items: flex-start; + position: relative; } -.room .roomHeader .returnButton { - flex-basis: 10%; - display: flex; - justify-content: center; +.room .roomHeader .returnButton { + position: absolute; + top: 10px; + left: 0; + z-index: 10; } .room .roomHeader .centerTitle { flex-basis: auto; - display: flex; flex-direction: column; - justify-content: flex-end; - align-items: flex-end; + justify-content: flex-start; + align-items: flex-start; + margin-top: 40px; +} +.room .roomHeader .headerContent { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 60px; } .room .roomHeader .dumb { @@ -31,155 +38,11 @@ width: 100%; height: 70vh; display: flex; - overflow: auto; justify-content: center; - /* align-items: center; */ } - - - - - -/* .create-room-container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; +.room h1 { + text-align: center; + margin-top: 50px; } - -.manage-room-container { - display: flex; - flex-direction: column; - align-items: center; - height: 100%; - width: 100%; -} - -.quiz-setup-container { - display: flex; - flex-direction: column; - width: 100%; - margin-top: 2rem; -} - -.quiz-mode-selection { - display: flex; - flex-grow: 0; - flex-direction: column; - justify-content: center; - align-items: center; - margin-top: 10px; - height: 15vh; -} - -.users-container { - display: flex; - flex-direction: column; - align-items: center; - flex-grow: 1; - gap: 2vh; -} - -.launch-quiz-btn { - width: 20vw; - height: 11vh; - margin-top: 2vh; - box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); -} - -.mode-choice { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - width: 20vw; - margin-top: 2vh; -} - -.user { - background-color: #e7dad1; - padding: 10px 20px; - border: 1px solid black; - border-radius: 10px; - box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); -} - -.bottom-btn { - display: flex; - width: 100%; - justify-content: flex-end; - margin-top: 2vh; -} - -.room-container { - position: relative; - width: 100%; - max-width: 60vw; -} - -@media only screen and (max-device-width: 768px) { - .room-container { - max-width: 100%; - } -} - -.room-wrapper { - display: flex; - width: 100%; - height: 100%; - justify-content: center; -} - -.room-name-wrapper { - display: flex; - flex-direction: column; - align-items: end; -} -.user-item { - width: 100%; -} - -.flex-column-wrapper { - display: flex; - flex-direction: column; - height: 85vh; - overflow: auto; -} - -.preview-and-result-container { - display: flex; - flex-direction: column; - gap: 2rem; -} - -.nextQuestionButton { - align-self: flex-end; - margin-bottom: 5rem !important; -} - -.top-container { - display: flex; - justify-content: space-between; - align-items: center; -} - -@media only screen and (max-device-height: 4000px) { - .flex-column-wrapper { - height: 60vh; - } -} - -@media only screen and (max-device-height: 1079px) { - .flex-column-wrapper { - height: 50vh; - } -} - -@media only screen and (max-device-height: 741px) { - .flex-column-wrapper { - height: 40vh; - } -} */ diff --git a/client/src/pages/Teacher/Share/Share.tsx b/client/src/pages/Teacher/Share/Share.tsx index 0dc4fe7..1c2650d 100644 --- a/client/src/pages/Teacher/Share/Share.tsx +++ b/client/src/pages/Teacher/Share/Share.tsx @@ -10,6 +10,7 @@ import { Button, NativeSelect } from '@mui/material'; import ReturnButton from 'src/components/ReturnButton/ReturnButton'; import ApiService from '../../../services/ApiService'; +import SaveIcon from '@mui/icons-material/Save'; const Share: React.FC = () => { console.log('Component rendered'); @@ -119,6 +120,7 @@ const Share: React.FC = () => {