mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
Merge pull request #123 from R0m1k3/claude/fix-notes-sync-issue-01AMeEdrKQErsM7bvhKkqEEF
Claude/fix notes sync issue 01 a me edr kq ers m7bvh kkq eef
This commit is contained in:
4 files changed
+129
-43
No files matched your search
Generated
+1
-20
@@ -138,7 +138,6 @@
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -3682,7 +3681,6 @@
|
||||
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -3693,7 +3691,6 @@
|
||||
"integrity": "sha512-k5dJVszUiNr1DSe8Cs+knKR6IrqhqdhpUwzqhkS8ecQTSf3THNtbfIp/umqHMpX2bv+9dkx3fwDv/86LcSfvSg==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -3704,7 +3701,6 @@
|
||||
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
@@ -3761,7 +3757,6 @@
|
||||
"integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.46.4",
|
||||
"@typescript-eslint/types": "8.46.4",
|
||||
@@ -4047,7 +4042,6 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -4482,7 +4476,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.25",
|
||||
"caniuse-lite": "^1.0.30001754",
|
||||
@@ -5335,8 +5328,7 @@
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
|
||||
"integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/embla-carousel-react": {
|
||||
"version": "8.6.0",
|
||||
@@ -5537,7 +5529,6 @@
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -6992,7 +6983,6 @@
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
||||
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
@@ -8226,7 +8216,6 @@
|
||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
|
||||
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"pg-connection-string": "^2.9.1",
|
||||
"pg-pool": "^3.10.1",
|
||||
@@ -8366,7 +8355,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -8757,7 +8745,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -8798,7 +8785,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
||||
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
@@ -9851,7 +9837,6 @@
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz",
|
||||
"integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"arg": "^5.0.2",
|
||||
@@ -10056,7 +10041,6 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -10185,7 +10169,6 @@
|
||||
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -10433,7 +10416,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
|
||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
@@ -10525,7 +10507,6 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
|
||||
+23
-9
@@ -1414,9 +1414,14 @@ const Index = () => {
|
||||
<Checkbox
|
||||
checked={todo.completed}
|
||||
onCheckedChange={async () => {
|
||||
const updatedTodos = [...(openNote.todos || [])];
|
||||
updatedTodos[index] = { ...todo, completed: !todo.completed };
|
||||
await handleUpdateNote({ todos: updatedTodos });
|
||||
if (!todo.id) return;
|
||||
const success = await NotesService.toggleTodo(todo.id, !todo.completed);
|
||||
if (success) {
|
||||
const updatedTodos = [...(openNote.todos || [])];
|
||||
updatedTodos[index] = { ...todo, completed: !todo.completed };
|
||||
setOpenNote({ ...openNote, todos: updatedTodos });
|
||||
setNotes(prev => prev.map(note => note.id === openNote.id ? { ...note, todos: updatedTodos } : note));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className={todo.completed ? "line-through text-muted-foreground flex-1 text-sm" : "flex-1 text-sm"}>
|
||||
@@ -1427,9 +1432,14 @@ const Index = () => {
|
||||
size="icon"
|
||||
className="h-6 w-6"
|
||||
onClick={async () => {
|
||||
const updatedTodos = [...(openNote.todos || [])];
|
||||
updatedTodos.splice(index, 1);
|
||||
await handleUpdateNote({ todos: updatedTodos });
|
||||
if (!todo.id) return;
|
||||
const success = await NotesService.deleteTodo(todo.id);
|
||||
if (success) {
|
||||
const updatedTodos = openNote.todos.filter((_, i) => i !== index);
|
||||
setOpenNote({ ...openNote, todos: updatedTodos });
|
||||
setNotes(prev => prev.map(note => note.id === openNote.id ? { ...note, todos: updatedTodos } : note));
|
||||
showSuccess("Tâche supprimée");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
@@ -2215,9 +2225,13 @@ const Index = () => {
|
||||
label="Tâche"
|
||||
placeholder="Entrez la tâche..."
|
||||
onConfirm={async (text) => {
|
||||
if (openNote) {
|
||||
const updatedTodos = [...(openNote.todos || []), { text, completed: false }];
|
||||
await handleUpdateNote({ todos: updatedTodos });
|
||||
if (openNote?.id) {
|
||||
const newTodo = await NotesService.addTodo(openNote.id, text);
|
||||
if (newTodo) {
|
||||
const updatedTodos = [...(openNote.todos || []), newTodo];
|
||||
setOpenNote({ ...openNote, todos: updatedTodos });
|
||||
setNotes(prev => prev.map(note => note.id === openNote.id ? { ...note, todos: updatedTodos } : note));
|
||||
}
|
||||
}
|
||||
}}
|
||||
confirmText="Ajouter"
|
||||
|
||||
@@ -80,28 +80,40 @@ export default function NoteDetailPage() {
|
||||
};
|
||||
|
||||
const handleAddTodo = async () => {
|
||||
if (!note || !todoText.trim()) return;
|
||||
const newTodo = { text: todoText, completed: false };
|
||||
const updatedTodos = [...(note.todos || []), newTodo];
|
||||
await updateNote({ todos: updatedTodos });
|
||||
setTodoText("");
|
||||
setAddTodoModal(false);
|
||||
showSuccess("Tâche ajoutée");
|
||||
if (!note?.id || !todoText.trim()) return;
|
||||
const newTodo = await NotesService.addTodo(note.id, todoText.trim());
|
||||
if (newTodo) {
|
||||
const updatedTodos = [...(note.todos || []), newTodo];
|
||||
setNote({ ...note, todos: updatedTodos });
|
||||
setTodoText("");
|
||||
setAddTodoModal(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleTodo = async (index: number) => {
|
||||
if (!note?.todos) return;
|
||||
const updatedTodos = [...note.todos];
|
||||
updatedTodos[index] = { ...updatedTodos[index], completed: !updatedTodos[index].completed };
|
||||
await updateNote({ todos: updatedTodos });
|
||||
const todo = note.todos[index];
|
||||
if (!todo.id) return;
|
||||
|
||||
const success = await NotesService.toggleTodo(todo.id, !todo.completed);
|
||||
if (success) {
|
||||
const updatedTodos = [...note.todos];
|
||||
updatedTodos[index] = { ...updatedTodos[index], completed: !updatedTodos[index].completed };
|
||||
setNote({ ...note, todos: updatedTodos });
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteTodo = async (index: number) => {
|
||||
if (!note?.todos) return;
|
||||
const updatedTodos = [...note.todos];
|
||||
updatedTodos.splice(index, 1);
|
||||
await updateNote({ todos: updatedTodos });
|
||||
showSuccess("Tâche supprimée");
|
||||
const todo = note.todos[index];
|
||||
if (!todo.id) return;
|
||||
|
||||
const success = await NotesService.deleteTodo(todo.id);
|
||||
if (success) {
|
||||
const updatedTodos = note.todos.filter((_, i) => i !== index);
|
||||
setNote({ ...note, todos: updatedTodos });
|
||||
showSuccess("Tâche supprimée");
|
||||
}
|
||||
};
|
||||
|
||||
const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
@@ -219,6 +219,85 @@ class NotesService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Todo management methods
|
||||
async addTodo(noteId: number, text: string): Promise<Todo | null> {
|
||||
try {
|
||||
const response = await fetch(`/api/notes/${noteId}/todos`, {
|
||||
method: "POST",
|
||||
headers: AuthService.getHeaders(),
|
||||
body: JSON.stringify({ text })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Erreur lors de l'ajout de la tâche");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
showSuccess("Tâche ajoutée");
|
||||
return result.todo || result;
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : "Erreur serveur");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async updateTodo(todoId: number, updates: Partial<Todo>): Promise<Todo | null> {
|
||||
try {
|
||||
const response = await fetch(`/api/notes/todos/${todoId}`, {
|
||||
method: "PUT",
|
||||
headers: AuthService.getHeaders(),
|
||||
body: JSON.stringify(updates)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Erreur lors de la mise à jour de la tâche");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result.todo || result;
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : "Erreur serveur");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async toggleTodo(todoId: number, completed: boolean): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch(`/api/notes/todos/${todoId}`, {
|
||||
method: "PUT",
|
||||
headers: AuthService.getHeaders(),
|
||||
body: JSON.stringify({ completed })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Erreur lors de la mise à jour de la tâche");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : "Erreur serveur");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteTodo(todoId: number): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch(`/api/notes/todos/${todoId}`, {
|
||||
method: "DELETE",
|
||||
headers: AuthService.getHeaders()
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Erreur lors de la suppression de la tâche");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : "Erreur serveur");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotesService();
|
||||
Reference in new issue
Block a user