Merge pull request #153 from ets-cfuhrman-pfe/fuhrmanator/issue78
Some checks are pending
CI/CD Pipeline for Backend / build_and_push_backend (push) Waiting to run
CI/CD Pipeline for Nginx Router / build_and_push_nginx (push) Waiting to run
CI/CD Pipeline for Frontend / build_and_push_frontend (push) Waiting to run
Tests / tests (client) (push) Waiting to run
Tests / tests (server) (push) Waiting to run

Nom du dossier pour chaque quiz devrait être affiché lorsque "tous les dossiers" sont affichés
This commit is contained in:
Christopher (Cris) Fuhrman 2025-01-10 22:38:07 -05:00 committed by GitHub
commit 839ee79912
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 183 additions and 144 deletions

View file

@ -2678,9 +2678,9 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.2.2", "version": "0.2.4",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
"integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
@ -5695,9 +5695,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -9126,9 +9126,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "5.0.8", "version": "5.0.9",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
"integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -9511,9 +9511,9 @@
} }
}, },
"node_modules/postcss/node_modules/nanoid": { "node_modules/postcss/node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {

View file

@ -2,6 +2,7 @@
export interface QuizType { export interface QuizType {
_id: string; _id: string;
folderId: string; folderId: string;
folderName: string;
userId: string; userId: string;
title: string; title: string;
content: string[]; content: string[];

View file

@ -9,6 +9,7 @@ describe('isQuizValid function', () => {
const validQuiz: QuizType = { const validQuiz: QuizType = {
_id: '1', _id: '1',
folderId: 'test', folderId: 'test',
folderName: 'test',
userId: 'user', userId: 'user',
created_at: new Date('2021-10-01'), created_at: new Date('2021-10-01'),
updated_at: new Date('2021-10-02'), updated_at: new Date('2021-10-02'),
@ -24,6 +25,7 @@ describe('isQuizValid function', () => {
const invalidQuiz: QuizType = { const invalidQuiz: QuizType = {
_id: '2', _id: '2',
folderId: 'test', folderId: 'test',
folderName: 'test',
userId: 'user', userId: 'user',
title: '', title: '',
created_at: new Date('2021-10-01'), created_at: new Date('2021-10-01'),
@ -39,6 +41,7 @@ describe('isQuizValid function', () => {
const invalidQuiz: QuizType = { const invalidQuiz: QuizType = {
_id: '2', _id: '2',
folderId: 'test', folderId: 'test',
folderName: 'test',
userId: 'user', userId: 'user',
title: 'sample', title: 'sample',
created_at: new Date('2021-10-01'), created_at: new Date('2021-10-01'),

View file

@ -31,8 +31,8 @@ Object.defineProperty(window, 'localStorage', {
// NOTE: this suite seems to be designed around local storage of quizzes (older version, before a database) // NOTE: this suite seems to be designed around local storage of quizzes (older version, before a database)
describe.skip('QuizService', () => { describe.skip('QuizService', () => {
const mockQuizzes: QuizType[] = [ const mockQuizzes: QuizType[] = [
{ folderId: 'test', userId: 'user', _id: 'quiz1', title: 'Quiz One', content: ['Q1', 'Q2'], created_at: new Date('2024-09-15'), updated_at: new Date('2024-09-15') }, { folderId: 'test', folderName: 'test', userId: 'user', _id: 'quiz1', title: 'Quiz One', content: ['Q1', 'Q2'], created_at: new Date('2024-09-15'), updated_at: new Date('2024-09-15') },
{ folderId: 'test', userId: 'user', _id: 'quiz2', title: 'Quiz Two', content: ['Q3', 'Q4'], created_at: new Date('2024-09-15'), updated_at: new Date('2024-09-15') }, { folderId: 'test', folderName: 'test', userId: 'user', _id: 'quiz2', title: 'Quiz Two', content: ['Q3', 'Q4'], created_at: new Date('2024-09-15'), updated_at: new Date('2024-09-15') },
]; ];
beforeEach(() => { beforeEach(() => {

View file

@ -18,8 +18,11 @@ import {
IconButton, IconButton,
InputAdornment, InputAdornment,
Button, Button,
Card,
Tooltip, Tooltip,
NativeSelect NativeSelect,
CardContent,
styled,
} from '@mui/material'; } from '@mui/material';
import { import {
Search, Search,
@ -34,13 +37,43 @@ import {
// DriveFileMove // DriveFileMove
} from '@mui/icons-material'; } from '@mui/icons-material';
// Create a custom-styled Card component
const CustomCard = styled(Card)({
overflow: 'visible', // Override the overflow property
position: 'relative',
margin: '40px 0 20px 0', // Add top margin to make space for the tab
borderRadius: '8px',
paddingTop: '20px', // Ensure content inside the card doesn't overlap with the tab
});
const Dashboard: React.FC = () => { const Dashboard: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [quizzes, setQuizzes] = useState<QuizType[]>([]); const [quizzes, setQuizzes] = useState<QuizType[]>([]);
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [showImportModal, setShowImportModal] = useState<boolean>(false); const [showImportModal, setShowImportModal] = useState<boolean>(false);
const [folders, setFolders] = useState<FolderType[]>([]); const [folders, setFolders] = useState<FolderType[]>([]);
const [selectedFolder, setSelectedFolder] = useState<string>(''); // Selected folder const [selectedFolderId, setSelectedFolderId] = useState<string>(''); // Selected folder
// Filter quizzes based on search term
// const filteredQuizzes = quizzes.filter(quiz =>
// quiz.title.toLowerCase().includes(searchTerm.toLowerCase())
// );
const filteredQuizzes = useMemo(() => {
return quizzes.filter(
(quiz) =>
quiz && quiz.title && quiz.title.toLowerCase().includes(searchTerm.toLowerCase())
);
}, [quizzes, searchTerm]);
// Group quizzes by folder
const quizzesByFolder = filteredQuizzes.reduce((acc, quiz) => {
if (!acc[quiz.folderName]) {
acc[quiz.folderName] = [];
}
acc[quiz.folderName].push(quiz);
return acc;
}, {} as Record<string, QuizType[]>);
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
@ -59,33 +92,14 @@ const Dashboard: React.FC = () => {
fetchData(); fetchData();
}, []); }, []);
const handleSelectFolder = (event: React.ChangeEvent<HTMLSelectElement>) => { const handleSelectFolder = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedFolder(event.target.value); setSelectedFolderId(event.target.value);
}; };
useEffect(() => { useEffect(() => {
const fetchQuizzesForFolder = async () => { const fetchQuizzesForFolder = async () => {
if (selectedFolder == '') { if (selectedFolderId == '') {
const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load
console.log("show all quizes") console.log("show all quizes")
var quizzes: QuizType[] = []; var quizzes: QuizType[] = [];
@ -93,6 +107,8 @@ const Dashboard: React.FC = () => {
for (const folder of folders as FolderType[]) { for (const folder of folders as FolderType[]) {
const folderQuizzes = await ApiService.getFolderContent(folder._id); const folderQuizzes = await ApiService.getFolderContent(folder._id);
console.log("folder: ", folder.title, " quiz: ", folderQuizzes); console.log("folder: ", folder.title, " quiz: ", folderQuizzes);
// add the folder.title to the QuizType if the folderQuizzes is an array
addFolderTitleToQuizzes(folderQuizzes, folder.title);
quizzes = quizzes.concat(folderQuizzes as QuizType[]) quizzes = quizzes.concat(folderQuizzes as QuizType[])
} }
@ -100,17 +116,19 @@ const Dashboard: React.FC = () => {
} }
else { else {
console.log("show some quizzes") console.log("show some quizzes")
const folderQuizzes = await ApiService.getFolderContent(selectedFolder); const folderQuizzes = await ApiService.getFolderContent(selectedFolderId);
console.log("folderQuizzes: ", folderQuizzes); console.log("folderQuizzes: ", folderQuizzes);
// get the folder title from its id
const folderTitle = folders.find((folder) => folder._id === selectedFolderId)?.title || '';
addFolderTitleToQuizzes(folderQuizzes, folderTitle);
setQuizzes(folderQuizzes as QuizType[]); setQuizzes(folderQuizzes as QuizType[]);
} }
}; };
fetchQuizzesForFolder(); fetchQuizzesForFolder();
}, [selectedFolder]); }, [selectedFolderId]);
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => { const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
@ -135,7 +153,7 @@ const Dashboard: React.FC = () => {
const handleDuplicateQuiz = async (quiz: QuizType) => { const handleDuplicateQuiz = async (quiz: QuizType) => {
try { try {
await ApiService.duplicateQuiz(quiz._id); await ApiService.duplicateQuiz(quiz._id);
if (selectedFolder == '') { if (selectedFolderId == '') {
const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load
console.log("show all quizes") console.log("show all quizes")
var quizzes: QuizType[] = []; var quizzes: QuizType[] = [];
@ -143,14 +161,16 @@ const Dashboard: React.FC = () => {
for (const folder of folders as FolderType[]) { for (const folder of folders as FolderType[]) {
const folderQuizzes = await ApiService.getFolderContent(folder._id); const folderQuizzes = await ApiService.getFolderContent(folder._id);
console.log("folder: ", folder.title, " quiz: ", folderQuizzes); console.log("folder: ", folder.title, " quiz: ", folderQuizzes);
quizzes = quizzes.concat(folderQuizzes as QuizType[]) addFolderTitleToQuizzes(folderQuizzes, folder.title);
quizzes = quizzes.concat(folderQuizzes as QuizType[]);
} }
setQuizzes(quizzes as QuizType[]); setQuizzes(quizzes as QuizType[]);
} }
else { else {
console.log("show some quizzes") console.log("show some quizzes")
const folderQuizzes = await ApiService.getFolderContent(selectedFolder); const folderQuizzes = await ApiService.getFolderContent(selectedFolderId);
addFolderTitleToQuizzes(folderQuizzes, selectedFolderId);
setQuizzes(folderQuizzes as QuizType[]); setQuizzes(folderQuizzes as QuizType[]);
} }
@ -159,13 +179,6 @@ const Dashboard: React.FC = () => {
} }
}; };
const filteredQuizzes = useMemo(() => {
return quizzes.filter(
(quiz) =>
quiz && quiz.title && quiz.title.toLowerCase().includes(searchTerm.toLowerCase())
);
}, [quizzes, searchTerm]);
const handleOnImport = () => { const handleOnImport = () => {
setShowImportModal(true); setShowImportModal(true);
@ -191,30 +204,6 @@ const Dashboard: React.FC = () => {
return true; return true;
}; };
// const handleMoveQuiz = async (quiz: QuizType, newFolderId: string) => {
// try {
// await ApiService.moveQuiz(quiz._id, newFolderId);
// if (selectedFolder == '') {
// const folders = await ApiService.getUserFolders();
// var quizzes: QuizType[] = [];
// for (const folder of folders as FolderType[]) {
// const folderQuizzes = await ApiService.getFolderContent(folder._id);
// quizzes = quizzes.concat(folderQuizzes as QuizType[])
// }
// setQuizzes(quizzes as QuizType[]);
// }
// else {
// const folderQuizzes = await ApiService.getFolderContent(selectedFolder);
// setQuizzes(folderQuizzes as QuizType[]);
// }
// } catch (error) {
// console.error('Error moving quiz:', error);
// }
// };
const downloadTxtFile = async (quiz: QuizType) => { const downloadTxtFile = async (quiz: QuizType) => {
try { try {
@ -264,7 +253,7 @@ const Dashboard: React.FC = () => {
const userFolders = await ApiService.getUserFolders(); const userFolders = await ApiService.getUserFolders();
setFolders(userFolders as FolderType[]); setFolders(userFolders as FolderType[]);
const newlyCreatedFolder = userFolders[userFolders.length - 1] as FolderType; const newlyCreatedFolder = userFolders[userFolders.length - 1] as FolderType;
setSelectedFolder(newlyCreatedFolder._id); setSelectedFolderId(newlyCreatedFolder._id);
} }
} catch (error) { } catch (error) {
@ -274,17 +263,16 @@ const Dashboard: React.FC = () => {
const handleDeleteFolder = async () => { const handleDeleteFolder = async () => {
try { try {
const confirmed = window.confirm('Voulez-vous vraiment supprimer ce dossier?'); const confirmed = window.confirm('Voulez-vous vraiment supprimer ce dossier?');
if (confirmed) { if (confirmed) {
await ApiService.deleteFolder(selectedFolder); await ApiService.deleteFolder(selectedFolderId);
const userFolders = await ApiService.getUserFolders(); const userFolders = await ApiService.getUserFolders();
setFolders(userFolders as FolderType[]); setFolders(userFolders as FolderType[]);
} }
const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load const folders = await ApiService.getUserFolders(); // HACK force user folders to load on first load
console.log("show all quizes") console.log("show all quizzes")
var quizzes: QuizType[] = []; var quizzes: QuizType[] = [];
for (const folder of folders as FolderType[]) { for (const folder of folders as FolderType[]) {
@ -294,19 +282,20 @@ const Dashboard: React.FC = () => {
} }
setQuizzes(quizzes as QuizType[]); setQuizzes(quizzes as QuizType[]);
setSelectedFolder(''); setSelectedFolderId('');
} catch (error) { } catch (error) {
console.error('Error deleting folder:', error); console.error('Error deleting folder:', error);
} }
}; };
const handleRenameFolder = async () => { const handleRenameFolder = async () => {
try { try {
// folderId: string GET THIS FROM CURRENT FOLDER // folderId: string GET THIS FROM CURRENT FOLDER
// currentTitle: string GET THIS FROM CURRENT FOLDER // currentTitle: string GET THIS FROM CURRENT FOLDER
const newTitle = prompt('Entrée le nouveau nom du fichier', "Nouveau nom de dossier"); const newTitle = prompt('Entrée le nouveau nom du fichier', "Nouveau nom de dossier");
if (newTitle) { if (newTitle) {
await ApiService.renameFolder(selectedFolder, newTitle); await ApiService.renameFolder(selectedFolderId, newTitle);
const userFolders = await ApiService.getUserFolders(); const userFolders = await ApiService.getUserFolders();
setFolders(userFolders as FolderType[]); setFolders(userFolders as FolderType[]);
@ -315,15 +304,16 @@ const Dashboard: React.FC = () => {
console.error('Error renaming folder:', error); console.error('Error renaming folder:', error);
} }
}; };
const handleDuplicateFolder = async () => { const handleDuplicateFolder = async () => {
try { try {
// folderId: string GET THIS FROM CURRENT FOLDER // folderId: string GET THIS FROM CURRENT FOLDER
await ApiService.duplicateFolder(selectedFolder); await ApiService.duplicateFolder(selectedFolderId);
// TODO set the selected folder to be the duplicated folder // TODO set the selected folder to be the duplicated folder
const userFolders = await ApiService.getUserFolders(); const userFolders = await ApiService.getUserFolders();
setFolders(userFolders as FolderType[]); setFolders(userFolders as FolderType[]);
const newlyCreatedFolder = userFolders[userFolders.length - 1] as FolderType; const newlyCreatedFolder = userFolders[userFolders.length - 1] as FolderType;
setSelectedFolder(newlyCreatedFolder._id); setSelectedFolderId(newlyCreatedFolder._id);
} catch (error) { } catch (error) {
console.error('Error duplicating folder:', error); console.error('Error duplicating folder:', error);
} }
@ -393,7 +383,7 @@ const Dashboard: React.FC = () => {
<NativeSelect <NativeSelect
id="select-folder" id="select-folder"
color="primary" color="primary"
value={selectedFolder} value={selectedFolderId}
onChange={handleSelectFolder} onChange={handleSelectFolder}
> >
<option value=""> Tous les dossiers... </option> <option value=""> Tous les dossiers... </option>
@ -416,7 +406,7 @@ const Dashboard: React.FC = () => {
<IconButton <IconButton
color="primary" color="primary"
onClick={handleRenameFolder} onClick={handleRenameFolder}
disabled={selectedFolder == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> <Edit /> </IconButton> > <Edit /> </IconButton>
</Tooltip> </Tooltip>
@ -424,7 +414,7 @@ const Dashboard: React.FC = () => {
<IconButton <IconButton
color="primary" color="primary"
onClick={handleDuplicateFolder} onClick={handleDuplicateFolder}
disabled={selectedFolder == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> <FolderCopy /> </IconButton> > <FolderCopy /> </IconButton>
</Tooltip> </Tooltip>
@ -433,7 +423,7 @@ const Dashboard: React.FC = () => {
aria-label="delete" aria-label="delete"
color="primary" color="primary"
onClick={handleDeleteFolder} onClick={handleDeleteFolder}
disabled={selectedFolder == ''} // cannot action on all disabled={selectedFolderId == ''} // cannot action on all
> <DeleteOutline /> </IconButton> > <DeleteOutline /> </IconButton>
</Tooltip> </Tooltip>
</div> </div>
@ -461,74 +451,72 @@ const Dashboard: React.FC = () => {
</div> </div>
<div className='list'> <div className='list'>
{Object.keys(quizzesByFolder).map(folderName => (
<CustomCard key={folderName} className='folder-card'>
<div className='folder-tab'>{folderName}</div>
<CardContent>
{quizzesByFolder[folderName].map((quiz: QuizType) => (
<div className='quiz' key={quiz._id}>
<div className='title'>
<Tooltip title="Lancer quiz" placement="top">
<Button
variant="outlined"
onClick={() => handleLancerQuiz(quiz)}
disabled={!validateQuiz(quiz.content)}
>
{`${quiz.title} (${quiz.content.length} question${quiz.content.length > 1 ? 's' : ''})`}
</Button>
</Tooltip>
</div>
{filteredQuizzes.map((quiz: QuizType) => ( <div className='actions'>
<div className='quiz'> <Tooltip title="Télécharger quiz" placement="top">
<div className='title'> <IconButton
<Tooltip title="Lancer quiz" placement="top"> color="primary"
<Button onClick={() => downloadTxtFile(quiz)}
variant="outlined" > <FileDownload /> </IconButton>
onClick={() => handleLancerQuiz(quiz)} </Tooltip>
disabled={!validateQuiz(quiz.content)}
>
{quiz.title}
</Button>
</Tooltip>
</div>
<div className='actions'> <Tooltip title="Modifier quiz" placement="top">
<Tooltip title="Télécharger quiz" placement="top"> <IconButton
<IconButton color="primary"
color="primary" onClick={() => handleEditQuiz(quiz)}
onClick={() => downloadTxtFile(quiz)} > <Edit /> </IconButton>
> <FileDownload /> </IconButton> </Tooltip>
</Tooltip>
<Tooltip title="Modifier quiz" placement="top"> <Tooltip title="Dupliquer quiz" placement="top">
<IconButton <IconButton
color="primary" color="primary"
onClick={() => handleEditQuiz(quiz)} onClick={() => handleDuplicateQuiz(quiz)}
> <Edit /> </IconButton> > <ContentCopy /> </IconButton>
</Tooltip> </Tooltip>
{/* <Tooltip title="Bouger quiz" placement="top"> <Tooltip title="Supprimer quiz" placement="top">
<IconButton <IconButton
color="primary" aria-label="delete"
onClick={() => handleMoveQuiz(quiz)} color="primary"
> <DriveFileMove /> </IconButton> onClick={() => handleRemoveQuiz(quiz)}
</Tooltip> */} > <DeleteOutline /> </IconButton>
</Tooltip>
<Tooltip title="Dupliquer quiz" placement="top"> <Tooltip title="Partager quiz" placement="top">
<IconButton <IconButton
color="primary" color="primary"
onClick={() => handleDuplicateQuiz(quiz)} onClick={() => handleShareQuiz(quiz)}
> <ContentCopy /> </IconButton> > <Share /> </IconButton>
</Tooltip> </Tooltip>
</div>
<Tooltip title="Supprimer quiz" placement="top"> </div>
<IconButton ))}
aria-label="delete" </CardContent>
color="primary" </CustomCard>
onClick={() => handleRemoveQuiz(quiz)}
> <DeleteOutline /> </IconButton>
</Tooltip>
<Tooltip title="Partager quiz" placement="top">
<IconButton
color="primary"
onClick={() => handleShareQuiz(quiz)}
> <Share /> </IconButton>
</Tooltip>
</div>
</div>
))} ))}
</div> </div>
<ImportModal <ImportModal
open={showImportModal} open={showImportModal}
handleOnClose={() => setShowImportModal(false)} handleOnClose={() => setShowImportModal(false)}
handleOnImport={handleOnImport} handleOnImport={handleOnImport}
selectedFolder={selectedFolder} selectedFolder={selectedFolderId}
/> />
</div> </div>
@ -536,3 +524,11 @@ const Dashboard: React.FC = () => {
}; };
export default Dashboard; export default Dashboard;
function addFolderTitleToQuizzes(folderQuizzes: string | QuizType[], folderName: string) {
if (Array.isArray(folderQuizzes))
folderQuizzes.forEach((quiz) => {
quiz.folderName = folderName;
console.log(`quiz: ${quiz.title} folder: ${quiz.folderName}`);
});
}

View file

@ -77,4 +77,43 @@ div:has(> #select-folder) {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.dashboard .list .quiz .actions {
flex-shrink: 0;
display: flex;
flex-direction: row;
align-items: center;
}
.folder-card {
position: relative;
/* margin: 40px 0 20px 0; /* Add top margin to make space for the tab */
border-radius: 8px;
color: #f9f9f9;
--outline-color: #e1e1e1;
border: 2px solid var(--outline-color);
}
.folder-tab {
position: absolute;
top: -33px;
left: 9px;
padding: 5px 10px;
border-radius: 8px 8px 0 0;
font-weight: bold;
white-space: nowrap; /* Prevent text from wrapping */
display: inline-block; /* Ensure the tab width is based on content */
border: 2px solid var(--outline-color);
border-bottom-style: none;
background-color: white; /* Optional: background color to match the card */
color: #3f51b5; /* Text color to match the outline */
}
/* .folder-card:nth-child(odd) {
background-color: #f9f9f9;
}
.folder-card:nth-child(even) {
background-color: #e0e0e0;
} */