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..db9b99e 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 (
-
+
}
- fullWidth
- sx={{ fontWeight: 600, fontSize: 20 }}
+ sx={{ fontWeight: 600, fontSize: 20, width: 'auto' }}
>
- Lancer
-
+ 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..8003525 100644
--- a/client/src/pages/Teacher/Dashboard/Dashboard.tsx
+++ b/client/src/pages/Teacher/Dashboard/Dashboard.tsx
@@ -66,6 +66,7 @@ const Dashboard: React.FC = () => {
const [selectedRoom, selectRoom] = useState(); // menu
const [errorMessage, setErrorMessage] = useState('');
const [showErrorDialog, setShowErrorDialog] = useState(false);
+ const [isSearchVisible, setIsSearchVisible] = useState(false);
// Filter quizzes based on search term
// const filteredQuizzes = quizzes.filter(quiz =>
@@ -105,7 +106,7 @@ const Dashboard: React.FC = () => {
fetchData();
}, []);
-
+
useEffect(() => {
if (rooms.length > 0 && !selectedRoom) {
selectRoom(rooms[rooms.length - 1]);
@@ -120,42 +121,45 @@ const Dashboard: React.FC = () => {
selectRoomByName(event.target.value);
}
};
+ const toggleSearchVisibility = () => {
+ setIsSearchVisible(!isSearchVisible); // Alterne entre afficher et cacher la barre de recherche
+ };
- // 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 +402,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 +429,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
+
-
-
-
- {selectedRoom && (
-
-
Salle sélectionnée: {selectedRoom.title}
-
- )}
-
+ {/* Dialog pour créer une salle */}
+
+ {/* Dialog d'erreur */}
-
-
-
-
-
-
- )
- }}
- />
-
-
-
-
-
- Tous les dossiers...
-
- {folders.map((folder: FolderType) => (
-
- {' '}
- {folder.title}{' '}
-
- ))}
-
+
+ {/* Barre de recherche avec un bouton d'icône qui s'affiche ou se cache */}
+
+ {!isSearchVisible ? (
+
+
+
+ ) : (
+ // Barre de recherche visible
+
+
+
+
+
+ )
+ }}
+ />
+ )}
-
-
-
- {' '}
- {' '}
-
-
-
-
-
-
- {' '}
- {' '}
-
-
-
-
-
-
-
- {' '}
- {' '}
-
-
-
-
-
-
-
- {' '}
- {' '}
-
-
-
-
-
-
-
}
onClick={handleCreateQuiz}
+ sx={{ borderRadius: '8px' }}
>
- Ajouter un nouveau quiz
+ Nouveau quiz
-
- {Object.keys(quizzesByFolder).map((folderName) => (
-
- {folderName}
-
- {quizzesByFolder[folderName].map((quiz: QuizType) => (
-
-
-
-
+
+ {/* 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 */}
+
+ Tous les dossiers...
+ {folders.map((folder) => (
+
+ {folder.title}
+
+ ))}
+
+
+ {/* Actions dossiers */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Liste des quiz organisés par dossier */}
+
+ {Object.keys(quizzesByFolder).map((folderName) => (
+
+
+ {folderName}
+
+
+ {quizzesByFolder[folderName].map((quiz) => (
+
+
+
-
-
+
+
+
+
+
+ downloadTxtFile(quiz)}
+ >
+
+
+
+
+
+ handleEditQuiz(quiz)}
+ >
+
+
+
+
+
+ handleDuplicateQuiz(quiz)}
+ >
+
+
+
+
+ handleShareQuiz(quiz)}
+ >
+
+
+
+
+ handleRemoveQuiz(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 = () => {