Fix: Synchronisation des dates de modification et tags après sauvegarde

Problème :
- Après modification d'une note, il fallait rafraîchir la page pour voir updated_at
- Après ajout d'un tag, il fallait rafraîchir la page pour le voir dans la note

Solution backend :
1. routes/notes.routes.js - PUT /api/notes/:id :
   - Récupération de la note mise à jour après UPDATE
   - Retour de { message, note } au lieu de juste { message }
   - La note retournée contient la vraie updated_at générée par PostgreSQL

Solution frontend :
1. NotesService.ts - updateNote() :
   - Changement du type de retour de Promise<boolean> vers Promise<Note | null>
   - Récupération et retour de la note mise à jour depuis la réponse du serveur
   - Merge de la note locale (todos, images) avec les données du serveur (updated_at)

2. Index.tsx - handleNoteChange et handleContentChange :
   - Utilisation de la note retournée par updateNote() au lieu de l'état local
   - Mise à jour de openNote et notes avec les données du serveur

3. Index.tsx - Synchronisation des tags :
   - loadNoteTags : Mise à jour de openNote.tags après chargement
   - confirmAddTag : Mise à jour de openNote.tags après ajout
   - handleDeleteTag : Mise à jour de openNote.tags après suppression
   - Conversion du format { id, tag } vers { id, name } pour cohérence

Résultat :
- Les dates de modification s'affichent immédiatement après sauvegarde
- Les tags ajoutés apparaissent immédiatement dans l'interface
- Plus besoin de rafraîchir la page manuellement
This commit is contained in:
Claude committed 2025-11-17 07:45:43 +00:00
1 parent 76b91788b7
commit eed5696596
3 files changed
+67 -15

No files matched your search

+13 -1
View File
@@ -238,7 +238,19 @@ router.put('/:id',
await runQuery(`UPDATE notes SET ${updates.join(', ')} WHERE id = $${paramCount}`, params);
}
res.json({ message: 'Note modifiée avec succès' });
// Récupérer la note mise à jour avec sa nouvelle updated_at
const updatedNote = await getOne(`
SELECT id, title, content, image_filename, archived, priority, created_at, updated_at
FROM notes
WHERE id = $1
`, [req.params.id]);
logger.info(`[UPDATE NOTE] Note mise à jour - ID: ${req.params.id}, updated_at: ${updatedNote.updated_at}`);
res.json({
message: 'Note modifiée avec succès',
note: updatedNote
});
} catch (error) {
logger.error('Erreur lors de la modification de la note:', error);
res.status(500).json({ error: 'Erreur serveur' });
+38 -7
View File
@@ -423,6 +423,14 @@ const Index = () => {
try {
const tags = await TagsService.getTags(noteId);
setNoteTags(tags || []);
// Synchroniser avec openNote.tags (convertir de 'tag' vers 'name')
if (openNote && openNote.id === noteId) {
setOpenNote({
...openNote,
tags: (tags || []).map(t => ({ id: t.id, name: t.tag }))
});
}
} catch (error) {
console.error("Erreur lors du chargement des tags:", error);
setNoteTags([]);
@@ -458,8 +466,12 @@ const Index = () => {
setNotes(prev => prev.map(note => note.id === updatedNote.id ? updatedNote : note));
try {
const success = await NotesService.updateNote(updatedNote);
if (!success) {
const savedNote = await NotesService.updateNote(updatedNote);
if (savedNote) {
// Mettre à jour avec les données du serveur (updated_at, etc.)
setOpenNote(savedNote);
setNotes(prev => prev.map(note => note.id === savedNote.id ? savedNote : note));
} else {
showError("Erreur lors de la sauvegarde");
}
} catch (error) {
@@ -482,9 +494,12 @@ const Index = () => {
saveTimerRef.current = setTimeout(async () => {
try {
await NotesService.updateNote(updatedNote);
// Update notes list silently after save
setNotes(prev => prev.map(note => note.id === updatedNote.id ? updatedNote : note));
const savedNote = await NotesService.updateNote(updatedNote);
if (savedNote) {
// Mettre à jour avec les données du serveur (updated_at, etc.)
setOpenNote(savedNote);
setNotes(prev => prev.map(note => note.id === savedNote.id ? savedNote : note));
}
} catch (error) {
showError("Erreur lors de la sauvegarde automatique");
}
@@ -701,7 +716,15 @@ const Index = () => {
try {
const newTag = await TagsService.addTag(openNote.id, tagText);
if (newTag) {
setNoteTags([...noteTags, newTag]);
const updatedNoteTags = [...noteTags, newTag];
setNoteTags(updatedNoteTags);
// Synchroniser avec openNote.tags (convertir de 'tag' vers 'name')
setOpenNote({
...openNote,
tags: updatedNoteTags.map(t => ({ id: t.id, name: t.tag }))
});
showSuccess("Tag ajouté");
}
} catch (error) {
@@ -715,7 +738,15 @@ const Index = () => {
try {
const success = await TagsService.deleteTag(openNote.id, tagId);
if (success) {
setNoteTags(noteTags.filter(t => t.id !== tagId));
const updatedNoteTags = noteTags.filter(t => t.id !== tagId);
setNoteTags(updatedNoteTags);
// Synchroniser avec openNote.tags (convertir de 'tag' vers 'name')
setOpenNote({
...openNote,
tags: updatedNoteTags.map(t => ({ id: t.id, name: t.tag }))
});
showSuccess("Tag supprimé");
}
} catch (error) {
+16 -7
View File
@@ -85,9 +85,9 @@ class NotesService {
}
}
async updateNote(note: Note): Promise<boolean> {
if (!note.id) return false;
async updateNote(note: Note): Promise<Note | null> {
if (!note.id) return null;
try {
const response = await fetch(`/api/notes/${note.id}`, {
method: "PUT",
@@ -98,15 +98,24 @@ class NotesService {
images: note.images || []
})
});
if (!response.ok) {
throw new Error("Erreur lors de la mise à jour de la note");
}
return true;
const result = await response.json();
// Le backend retourne { message, note } avec la note mise à jour incluant updated_at
if (result.note) {
return {
...note, // Garder les todos et images de l'état local
...result.note // Écraser avec les données du serveur (updated_at, etc.)
};
}
return note; // Fallback si le backend ne retourne pas la note
} catch (error) {
showError(error instanceof Error ? error.message : "Erreur serveur");
return false;
return null;
}
}