QuizToPDF modal and basic function done

This commit is contained in:
Philippe 2025-02-04 15:09:38 -05:00
parent cb069bebeb
commit 19130d8f44
5 changed files with 386 additions and 182 deletions

View file

@ -1,2 +1,3 @@
VITE_BACKEND_URL=http://localhost:4400 VITE_BACKEND_URL=http://localhost:4400
VITE_BACKEND_SOCKET_URL=http://localhost:4400 VITE_BACKEND_SOCKET_URL=http://localhost:4400
VITE_AZURE_BACKEND_URL=http://localhost:4400

383
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
"esbuild": "^0.23.1", "esbuild": "^0.23.1",
"gift-pegjs": "^2.0.0-beta.1", "gift-pegjs": "^2.0.0-beta.1",
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"jspdf": "^2.5.2",
"katex": "^0.16.11", "katex": "^0.16.11",
"marked": "^14.1.2", "marked": "^14.1.2",
"nanoid": "^5.0.2", "nanoid": "^5.0.2",

View file

@ -0,0 +1,121 @@
import React, { useState } from 'react';
import { Dialog, DialogTitle, DialogActions, Button, Tooltip, IconButton } from '@mui/material';
import { FileDownload } from '@mui/icons-material';
import { QuizType } from '../../Types/QuizType';
import ApiService from '../../services/ApiService';
import jsPDF from 'jspdf';
interface DownloadQuizModalProps {
quiz: QuizType;
}
const DownloadQuizModal: React.FC<DownloadQuizModalProps> = ({ quiz }) => {
const [open, setOpen] = useState(false);
const handleOpenModal = () => setOpen(true);
const handleCloseModal = () => setOpen(false);
const handleDownload = async (format: 'txt' | 'pdf-with-answers' | 'pdf-without-answers') => {
switch (format) {
case 'txt':
await downloadTxtFile(quiz);
break;
case 'pdf-with-answers':
await downloadPdfFile(quiz, true);
break;
case 'pdf-without-answers':
await downloadPdfFile(quiz, false);
break;
}
handleCloseModal();
};
const downloadTxtFile = async (quiz: QuizType) => {
try {
const selectedQuiz = await ApiService.getQuiz(quiz._id) as QuizType;
if (!selectedQuiz) throw new Error('Quiz not found');
let quizContent = "";
selectedQuiz.content.forEach((question) => {
const formattedQuestion = question.trim();
if (formattedQuestion !== '') quizContent += formattedQuestion + '\n\n';
});
const blob = new Blob([quizContent], { type: 'text/plain' });
const a = document.createElement('a');
a.download = `${selectedQuiz.title}.gift`;
a.href = window.URL.createObjectURL(blob);
a.click();
} catch (error) {
console.error('Error exporting quiz:', error);
}
};
const downloadPdfFile = async (quiz: QuizType, withAnswers: boolean) => {
try {
const selectedQuiz = await ApiService.getQuiz(quiz._id) as QuizType;
if (!selectedQuiz) throw new Error('Quiz not found');
const doc = new jsPDF();
doc.setFont("helvetica", "bold");
doc.setFontSize(25);
doc.text(selectedQuiz.title, 10, 15);
let yPosition = 40;
doc.setFont("helvetica", "normal");
doc.setFontSize(16);
selectedQuiz.content.forEach((question, index) => {
let formattedQuestion = question.trim();
if (!withAnswers) {
formattedQuestion = formattedQuestion.replace(/::.*?::/g, '')
.replace(/\/\/.*$/gm, '')
.replace(/#[^\n]*/g, '')
.replace(/=/g, '')
.replace(/~/g, '')
.replace(/\{(.*?)\}/g, '{$1}');
}
const wrappedText = doc.splitTextToSize(`${index + 1}. ${formattedQuestion}`, 180);
doc.text(wrappedText, 10, yPosition);
yPosition += wrappedText.length * 10;
});
const filename = withAnswers
? `${selectedQuiz.title}_avec_reponses.pdf`
: `${selectedQuiz.title}_sans_reponses.pdf`;
doc.save(filename);
} catch (error) {
console.error('Error exporting quiz as PDF:', error);
}
};
return (
<>
<Tooltip title="Télécharger quiz" placement="top">
<IconButton color="primary" onClick={handleOpenModal}>
<FileDownload />
</IconButton>
</Tooltip>
<Dialog open={open} onClose={handleCloseModal} fullWidth maxWidth="xs">
<DialogTitle sx={{ textAlign: "center" }}>Choisissez un format de téléchargement</DialogTitle>
<DialogActions sx={{ display: "flex", justifyContent: "center", gap: 2 }}>
<Button onClick={() => handleDownload('txt')}>GIFT</Button>
<Button onClick={() => handleDownload('pdf-with-answers')}> PDF avec réponses</Button>
<Button onClick={() => handleDownload('pdf-without-answers')}>PDF sans réponses</Button>
</DialogActions>
</Dialog>
</>
);
};
export default DownloadQuizModal;

View file

@ -27,7 +27,6 @@ import {
import { import {
Search, Search,
DeleteOutline, DeleteOutline,
FileDownload,
Add, Add,
Upload, Upload,
FolderCopy, FolderCopy,
@ -36,6 +35,7 @@ import {
Share, Share,
// DriveFileMove // DriveFileMove
} from '@mui/icons-material'; } from '@mui/icons-material';
import DownloadQuizModal from 'src/components/DownloadQuizModal/DownloadQuizModal';
// Create a custom-styled Card component // Create a custom-styled Card component
const CustomCard = styled(Card)({ const CustomCard = styled(Card)({
@ -205,47 +205,6 @@ const Dashboard: React.FC = () => {
return true; return true;
}; };
const downloadTxtFile = async (quiz: QuizType) => {
try {
const selectedQuiz = await ApiService.getQuiz(quiz._id) as QuizType;
//quizzes.find((quiz) => quiz._id === quiz._id);
if (!selectedQuiz) {
throw new Error('Selected quiz not found');
}
//const { title, content } = selectedQuiz;
let quizContent = "";
const title = selectedQuiz.title;
console.log(selectedQuiz.content);
selectedQuiz.content.forEach((question, qIndex) => {
const formattedQuestion = question.trim();
// console.log(formattedQuestion);
if (formattedQuestion !== '') {
quizContent += formattedQuestion + '\n';
if (qIndex !== selectedQuiz.content.length - 1) {
quizContent += '\n';
}
}
});
if (!validateQuiz(selectedQuiz.content)) {
window.alert('Attention! Ce quiz contient des questions invalides selon le format GIFT.');
}
const blob = new Blob([quizContent], { type: 'text/plain' });
const a = document.createElement('a');
const filename = title;
a.download = `${filename}.gift`;
a.href = window.URL.createObjectURL(blob);
a.click();
} catch (error) {
console.error('Error exporting selected quiz:', error);
}
};
const handleCreateFolder = async () => { const handleCreateFolder = async () => {
try { try {
const folderTitle = prompt('Titre du dossier'); const folderTitle = prompt('Titre du dossier');
@ -299,7 +258,7 @@ const Dashboard: React.FC = () => {
const renamedFolderId = selectedFolderId; const renamedFolderId = selectedFolderId;
const result = await ApiService.renameFolder(selectedFolderId, newTitle); const result = await ApiService.renameFolder(selectedFolderId, newTitle);
if (result !== true ) { if (result !== true) {
window.alert(`Une erreur est survenue: ${result}`); window.alert(`Une erreur est survenue: ${result}`);
return; return;
} }
@ -481,12 +440,9 @@ const Dashboard: React.FC = () => {
</div> </div>
<div className='actions'> <div className='actions'>
<Tooltip title="Télécharger quiz" placement="top"> <div className="dashboard">
<IconButton <DownloadQuizModal quiz={quiz} />
color="primary" </div>
onClick={() => downloadTxtFile(quiz)}
> <FileDownload /> </IconButton>
</Tooltip>
<Tooltip title="Modifier quiz" placement="top"> <Tooltip title="Modifier quiz" placement="top">
<IconButton <IconButton