diff --git a/config/database.js b/config/database.js index 50274a2..0253423 100644 --- a/config/database.js +++ b/config/database.js @@ -81,7 +81,7 @@ function initDatabase() { logger.info('✓ Tables de base de données créées avec succès'); - // Migration: Ajouter image_filename si elle n'existe pas + // Migrations automatiques db.all("PRAGMA table_info(notes)", (err, columns) => { if (err) { logger.error('Erreur lors de la vérification de la structure de la table notes:', err); @@ -89,6 +89,7 @@ function initDatabase() { } const hasImageFilename = columns.some(col => col.name === 'image_filename'); + const hasArchived = columns.some(col => col.name === 'archived'); if (!hasImageFilename) { logger.info('Migration: Ajout de la colonne image_filename...'); @@ -100,6 +101,17 @@ function initDatabase() { } }); } + + if (!hasArchived) { + logger.info('Migration: Ajout de la colonne archived...'); + db.run('ALTER TABLE notes ADD COLUMN archived BOOLEAN DEFAULT 0', (err) => { + if (err) { + logger.error('Erreur lors de l\'ajout de la colonne archived:', err); + } else { + logger.info('✓ Colonne archived ajoutée avec succès'); + } + }); + } }); // Créer l'utilisateur admin par défaut si la table est vide diff --git a/routes/notes.routes.js b/routes/notes.routes.js index f5ad74f..c20b5c9 100644 --- a/routes/notes.routes.js +++ b/routes/notes.routes.js @@ -39,20 +39,35 @@ const upload = multer({ router.use(authenticateToken); /** - * GET /api/notes + * GET /api/notes?archived=true/false * Liste toutes les notes de l'utilisateur */ router.get('/', async (req, res) => { try { + const showArchived = req.query.archived === 'true'; + const archivedFilter = showArchived ? 1 : 0; + const notes = await getAll(` SELECT - n.id, n.title, n.content, n.image_filename, + n.id, n.title, n.content, n.image_filename, n.archived, n.created_at, n.updated_at, - (SELECT COUNT(*) FROM note_todos WHERE note_id = n.id) as todos_count + (SELECT COUNT(*) FROM note_todos WHERE note_id = n.id) as todos_count, + (SELECT COUNT(*) FROM note_todos WHERE note_id = n.id AND completed = 1) as todos_completed FROM notes n - WHERE n.user_id = ? + WHERE n.user_id = ? AND n.archived = ? ORDER BY n.updated_at DESC - `, [req.user.id]); + `, [req.user.id, archivedFilter]); + + // Charger les todos pour chaque note + for (const note of notes) { + const todos = await getAll(` + SELECT id, text, completed, position + FROM note_todos + WHERE note_id = ? + ORDER BY position ASC, id ASC + `, [note.id]); + note.todos = todos || []; + } res.json(notes || []); } catch (error) { @@ -179,6 +194,33 @@ router.put('/:id', } ); +/** + * PUT /api/notes/:id/archive + * Archiver ou désarchiver une note + */ +router.put('/:id/archive', async (req, res) => { + try { + const { archived } = req.body; + + // Vérifier que la note appartient à l'utilisateur + const note = await getOne('SELECT id FROM notes WHERE id = ? AND user_id = ?', [req.params.id, req.user.id]); + if (!note) { + return res.status(404).json({ error: 'Note non trouvée' }); + } + + await runQuery( + 'UPDATE notes SET archived = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', + [archived ? 1 : 0, req.params.id] + ); + + logger.info(`Note ${archived ? 'archivée' : 'désarchivée'}: ${req.params.id}`); + res.json({ message: `Note ${archived ? 'archivée' : 'désarchivée'} avec succès`, archived }); + } catch (error) { + logger.error('Erreur lors de l\'archivage de la note:', error); + res.status(500).json({ error: 'Erreur serveur' }); + } +}); + /** * DELETE /api/notes/:id * Supprimer une note