Compare commits

..

No commits in common. "51cebdaba1a55722d825b749f2905b6acb7e1f75" and "36b5c58b9433d31ce498395fa56baa6b9c2fbfb6" have entirely different histories.

View file

@ -38,7 +38,7 @@ import {
Upload, Upload,
FolderCopy, FolderCopy,
ContentCopy, ContentCopy,
Edit Edit,
} from '@mui/icons-material'; } from '@mui/icons-material';
import ShareQuizModal from 'src/components/ShareQuizModal/ShareQuizModal'; import ShareQuizModal from 'src/components/ShareQuizModal/ShareQuizModal';
@ -65,7 +65,6 @@ const Dashboard: React.FC = () => {
const [selectedRoom, selectRoom] = useState<RoomType>(); // menu const [selectedRoom, selectRoom] = useState<RoomType>(); // menu
const [errorMessage, setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
const [showErrorDialog, setShowErrorDialog] = useState(false); const [showErrorDialog, setShowErrorDialog] = useState(false);
const [isSearchVisible, setIsSearchVisible] = useState(false);
// Filter quizzes based on search term // Filter quizzes based on search term
// const filteredQuizzes = quizzes.filter(quiz => // const filteredQuizzes = quizzes.filter(quiz =>
@ -105,7 +104,7 @@ const Dashboard: React.FC = () => {
fetchData(); fetchData();
}, []); }, []);
useEffect(() => { useEffect(() => {
if (rooms.length > 0 && !selectedRoom) { if (rooms.length > 0 && !selectedRoom) {
selectRoom(rooms[rooms.length - 1]); selectRoom(rooms[rooms.length - 1]);
@ -121,44 +120,41 @@ const Dashboard: React.FC = () => {
} }
}; };
const toggleSearchVisibility = () => { // Créer une salle
setIsSearchVisible(!isSearchVisible); 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 // Sélectionner une salle
const updatedRooms = await ApiService.getUserRooms(); const selectRoomByName = (roomId: string) => {
setRooms(updatedRooms as RoomType[]); const room = rooms.find(r => r._id === roomId);
selectRoom(room);
localStorage.setItem('selectedRoomId', roomId);
};
// Sélectionner la nouvelle salle avec son ID const handleCreateRoom = async () => {
selectRoomByName(newRoom); // Utiliser l'ID de l'objet retourné if (newRoomTitle.trim()) {
}; try {
// Sélectionner une salle
const selectRoomByName = (roomId: string) => {
const room = rooms.find((r) => r._id === roomId);
selectRoom(room);
localStorage.setItem('selectedRoomId', roomId);
};
const handleCreateRoom = async () => {
if (newRoomTitle.trim()) {
try {
await createRoom(newRoomTitle); await createRoom(newRoomTitle);
const userRooms = await ApiService.getUserRooms(); const userRooms = await ApiService.getUserRooms();
setRooms(userRooms as RoomType[]); setRooms(userRooms as RoomType[]);
setOpenAddRoomDialog(false); setOpenAddRoomDialog(false);
setNewRoomTitle(''); setNewRoomTitle('');
} catch (error) { } catch (error) {
setErrorMessage(error instanceof Error ? error.message : 'Erreur inconnue'); setErrorMessage(error instanceof Error ? error.message : "Erreur inconnue");
setShowErrorDialog(true); setShowErrorDialog(true);
} }
} }
}; };
const handleSelectFolder = (event: React.ChangeEvent<HTMLSelectElement>) => { const handleSelectFolder = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedFolderId(event.target.value); setSelectedFolderId(event.target.value);
@ -401,68 +397,35 @@ const Dashboard: React.FC = () => {
} else { } else {
const randomSixDigit = Math.floor(100000 + Math.random() * 900000); const randomSixDigit = Math.floor(100000 + Math.random() * 900000);
navigate(`/teacher/manage-room/${quiz._id}/${randomSixDigit}`); navigate(`/teacher/manage-room/${quiz._id}/${randomSixDigit}`);
} }
}; };
return ( return (
<div className="dashboard"> <div className="dashboard">
{/* Conteneur pour le titre et le sélecteur de salle */} <div className="title">Tableau de bord</div>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '20px'
}}
>
{/* Titre tableau de bord */}
<div className="title" style={{ fontSize: '30px', fontWeight: 'bold' }}>
Tableau de bord
</div>
{/* Sélecteur de salle */} <div className="roomSelection">
<div <label htmlFor="select-room">Sélectionner une salle: </label>
className="roomSelection" <select value={selectedRoom?._id || ''} onChange={(e) => handleSelectRoom(e)}>
style={{ display: 'flex', justifyContent: 'flex-end', gap: '15px' }} <option value="" disabled>
> -- Sélectionner une salle --
<select </option>
value={selectedRoom?._id || ''} {rooms.map((room) => (
onChange={(e) => handleSelectRoom(e)} <option key={room._id} value={room._id}>
id="room-select" {room.title}
style={{
padding: '8px 12px',
fontSize: '14px',
borderRadius: '8px',
border: '1px solid #ccc',
backgroundColor: '#fff',
maxWidth: '200px',
cursor: 'pointer',
fontWeight: '500'
}}
>
<option value="" disabled>
Sélectionner une salle
</option> </option>
{rooms.map((room) => ( ))}
<option key={room._id} value={room._id}> <option value="add-room">Ajouter salle</option>
{room.title} </select>
</option>
))}
<option
value="add-room"
style={{
color: 'black',
backgroundColor: '#f0f0f0',
fontWeight: 'bold'
}}
>
Ajouter une salle
</option>
</select>
</div>
</div> </div>
{/* Dialog pour créer une salle */} {selectedRoom && (
<div className="roomTitle">
<h2>Salle sélectionnée: {selectedRoom.title}</h2>
</div>
)}
<Dialog open={openAddRoomDialog} onClose={() => setOpenAddRoomDialog(false)}> <Dialog open={openAddRoomDialog} onClose={() => setOpenAddRoomDialog(false)}>
<DialogTitle>Créer une nouvelle salle</DialogTitle> <DialogTitle>Créer une nouvelle salle</DialogTitle>
<DialogContent> <DialogContent>
@ -487,17 +450,24 @@ const Dashboard: React.FC = () => {
</DialogActions> </DialogActions>
</Dialog> </Dialog>
<div <div className="search-bar">
style={{ <TextField
display: 'flex', onChange={handleSearch}
justifyContent: 'flex-end', value={searchTerm}
alignItems: 'center', placeholder="Rechercher un quiz par son titre"
width: '100%', fullWidth
gap: '20px' InputProps={{
}} endAdornment: (
></div> <InputAdornment position="end">
<IconButton>
<Search />
</IconButton>
</InputAdornment>
)
}}
/>
</div>
{/* Conteneur principal avec les actions et la liste des quiz */}
<div className="folder"> <div className="folder">
<div className="select"> <div className="select">
<NativeSelect <NativeSelect
@ -505,18 +475,13 @@ const Dashboard: React.FC = () => {
color="primary" color="primary"
value={selectedFolderId} value={selectedFolderId}
onChange={handleSelectFolder} onChange={handleSelectFolder}
sx={{
padding: '6px 12px',
maxWidth: '180px',
borderRadius: '8px',
borderColor: '#e0e0e0',
'&:hover': { borderColor: '#5271FF' }
}}
> >
<option value="">Tous les dossiers...</option> <option value=""> Tous les dossiers... </option>
{folders.map((folder) => (
{folders.map((folder: FolderType) => (
<option value={folder._id} key={folder._id}> <option value={folder._id} key={folder._id}>
{folder.title} {' '}
{folder.title}{' '}
</option> </option>
))} ))}
</NativeSelect> </NativeSelect>
@ -532,130 +497,65 @@ const Dashboard: React.FC = () => {
<Tooltip title="Renommer dossier" placement="top"> <Tooltip title="Renommer dossier" placement="top">
<div> <div>
<IconButton <IconButton
color="primary" color="primary"
onClick={handleRenameFolder} onClick={handleRenameFolder}
disabled={selectedFolderId == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> >
{' '} {' '}
<Edit />{' '} <Edit />{' '}
</IconButton> </IconButton>
</div> </div>
</Tooltip> </Tooltip>
<Tooltip title="Dupliquer dossier" placement="top"> <Tooltip title="Dupliquer dossier" placement="top">
<div> <div>
<IconButton <IconButton
color="primary" color="primary"
onClick={handleDuplicateFolder} onClick={handleDuplicateFolder}
disabled={selectedFolderId == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> >
{' '} {' '}
<FolderCopy />{' '} <FolderCopy />{' '}
</IconButton> </IconButton>
</div> </div>
</Tooltip> </Tooltip>
<Tooltip title="Supprimer dossier" placement="top"> <Tooltip title="Supprimer dossier" placement="top">
<div> <div>
<IconButton <IconButton
aria-label="delete" aria-label="delete"
color="primary" color="primary"
onClick={handleDeleteFolder} onClick={handleDeleteFolder}
disabled={selectedFolderId == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> >
{' '} {' '}
<DeleteOutline />{' '} <DeleteOutline />{' '}
</IconButton> </IconButton>
</div> </div>
</Tooltip> </Tooltip>
</div> </div>
</div> </div>
<div <div className="ajouter">
className="search-bar" <Button
style={{ variant="outlined"
display: 'flex', color="primary"
justifyContent: 'space-between', startIcon={<Add />}
alignItems: 'center', onClick={handleCreateQuiz}
gap: '20px', >
width: '100%' Ajouter un nouveau quiz
}} </Button>
>
<div style={{ flex: 1 }}>
{!isSearchVisible ? (
<IconButton
onClick={toggleSearchVisibility}
sx={{
borderRadius: '8px',
border: '1px solid #ccc',
padding: '8px 12px',
backgroundColor: '#fff',
color: '#5271FF'
}}
>
<Search />
</IconButton>
) : (
<TextField
onChange={handleSearch}
value={searchTerm}
placeholder="Rechercher un quiz"
fullWidth
autoFocus
sx={{
borderRadius: '8px',
border: '1px solid #ccc',
padding: '8px 12px',
backgroundColor: '#fff',
fontWeight: 500,
width: '100%',
maxWidth: '1000px'
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={toggleSearchVisibility}
sx={{
borderRadius: '8px',
border: '1px solid #ccc',
backgroundColor: '#fff',
color: '#5271FF'
}}
>
<Search />
</IconButton>
</InputAdornment>
)
}}
/>
)}
</div>
{/* À droite : les boutons */} <Button
<div style={{ display: 'flex', gap: '12px' }}> variant="outlined"
<Button color="primary"
variant="outlined" startIcon={<Upload />}
color="primary" onClick={handleOnImport}
startIcon={<Add />} >
onClick={handleCreateQuiz} Import
sx={{ borderRadius: '8px', minWidth: 'auto', padding: '4px 12px' }} </Button>
>
Nouveau quiz
</Button>
<Button
variant="outlined"
color="primary"
startIcon={<Upload />}
onClick={handleOnImport}
>
Importer
</Button>
</div>
</div> </div>
<div className="list"> <div className="list">
{Object.keys(quizzesByFolder).map((folderName) => ( {Object.keys(quizzesByFolder).map((folderName) => (
<CustomCard key={folderName} className="folder-card"> <CustomCard key={folderName} className="folder-card">
@ -671,9 +571,7 @@ const Dashboard: React.FC = () => {
onClick={() => handleLancerQuiz(quiz)} onClick={() => handleLancerQuiz(quiz)}
disabled={!validateQuiz(quiz.content)} disabled={!validateQuiz(quiz.content)}
> >
{`${quiz.title} (${ {`${quiz.title} (${quiz.content.length} question${
quiz.content.length
} question${
quiz.content.length > 1 ? 's' : '' quiz.content.length > 1 ? 's' : ''
})`} })`}
</Button> </Button>
@ -711,20 +609,21 @@ const Dashboard: React.FC = () => {
<ContentCopy />{' '} <ContentCopy />{' '}
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<div className="quiz-share">
<ShareQuizModal quiz={quiz} />
</div>
<Tooltip title="Supprimer" placement="top"> <Tooltip title="Supprimer" placement="top">
<IconButton <IconButton
aria-label="delete" aria-label="delete"
color="error" color="primary"
onClick={() => handleRemoveQuiz(quiz)} onClick={() => handleRemoveQuiz(quiz)}
> >
{' '} {' '}
<DeleteOutline />{' '} <DeleteOutline />{' '}
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<div className="quiz-share">
<ShareQuizModal quiz={quiz} />
</div>
</div> </div>
</div> </div>
))} ))}