diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index f36e1bd..a1fb65b 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -13,7 +13,7 @@ import { RichTextEditor } from "@/components/RichTextEditor"; import { MadeWithDyad } from "@/components/made-with-dyad"; import { PlusCircle, Search, User, LogOut, Settings, ChevronDown, Plus, Archive, Trash2, - Image, CheckSquare, FileText, Rss, ExternalLink, RefreshCw, Key, Zap, Paperclip, X, Edit + Image as ImageIcon, CheckSquare, FileText, Rss, ExternalLink, RefreshCw, Key, Zap, Paperclip, X, Edit } from "lucide-react"; import AuthService from "@/services/AuthService"; import AdminService from "@/services/AdminService"; @@ -35,8 +35,7 @@ const Index = () => { const [showAdmin, setShowAdmin] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const [notes, setNotes] = useState([]); - const [currentNote, setCurrentNote] = useState(null); - const [showNoteDialog, setShowNoteDialog] = useState(false); + const [openNote, setOpenNote] = useState(null); const [users, setUsers] = useState([]); const [todos, setTodos] = useState([]); const [rssFeeds, setRssFeeds] = useState([]); @@ -144,8 +143,7 @@ const Index = () => { const newNote = await NotesService.createNote("Nouvelle note"); if (newNote) { setNotes([newNote, ...notes]); - setCurrentNote(newNote); - setShowNoteDialog(true); + setOpenNote(newNote); } } catch (error) { showError("Erreur lors de la création de la note"); @@ -153,26 +151,29 @@ const Index = () => { }; const handleOpenNote = (note: Note) => { - setCurrentNote(note); - setShowNoteDialog(true); + setOpenNote(note); + }; + + const handleCloseNote = () => { + setOpenNote(null); }; const handleUpdateNote = async (updatedFields: Partial) => { - if (!currentNote) return; + if (!openNote) return; try { const updatedNote = { - ...currentNote, + ...openNote, ...updatedFields, - todos: currentNote.todos || [], - images: currentNote.images || [], - files: currentNote.files || [] + todos: openNote.todos || [], + images: openNote.images || [], + files: openNote.files || [] }; const success = await NotesService.updateNote(updatedNote); if (success) { - setCurrentNote(updatedNote); + setOpenNote(updatedNote); setNotes(notes.map(note => note.id === updatedNote.id ? updatedNote : note)); } } catch (error) { @@ -181,17 +182,16 @@ const Index = () => { }; const handleDeleteNote = async () => { - if (!currentNote?.id) return; + if (!openNote?.id) return; if (window.confirm("Êtes-vous sûr de vouloir supprimer cette note ?")) { try { - const success = await NotesService.deleteNote(currentNote.id); + const success = await NotesService.deleteNote(openNote.id); if (success) { - const updatedNotes = notes.filter(note => note.id !== currentNote.id); + const updatedNotes = notes.filter(note => note.id !== openNote.id); setNotes(updatedNotes); - setShowNoteDialog(false); - setCurrentNote(null); + setOpenNote(null); showSuccess("Note supprimée"); } } catch (error) { @@ -327,12 +327,12 @@ const Index = () => { }; const handleFileUpload = async (e: React.ChangeEvent) => { - if (e.target.files && e.target.files[0] && currentNote?.id) { + if (e.target.files && e.target.files[0] && openNote?.id) { const formData = new FormData(); formData.append('file', e.target.files[0]); try { - const response = await fetch(`/api/notes/${currentNote.id}/files`, { + const response = await fetch(`/api/notes/${openNote.id}/files`, { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` @@ -342,7 +342,7 @@ const Index = () => { if (response.ok) { const file = await response.json(); - const updatedFiles = [...(currentNote.files || []), file]; + const updatedFiles = [...(openNote.files || []), file]; handleUpdateNote({ files: updatedFiles }); showSuccess("Fichier ajouté"); } @@ -416,8 +416,348 @@ const Index = () => { {/* Main Content */}
- {/* Todos & RSS Boxes - Large side by side */} -
+ {/* Two Column Layout: Notes Left | Boxes Right */} +
+ {/* Left Column: Notes or Open Note */} +
+ {!openNote ? ( + <> + {/* Notes Grid Header */} +
+
+

Mes Notes

+
+ + +
+
+ +
+ + setSearchQuery(e.target.value)} + /> +
+
+ + {/* Notes Grid - 2 columns */} +
+ {filteredNotes.length > 0 ? ( + filteredNotes.map(note => ( + handleOpenNote(note)} + > + +

+ {note.title || "Sans titre"} +

+

+ {note.content ? note.content.replace(/<[^>]*>/g, '') : "Note vide"} +

+
+ {note.todos && note.todos.length > 0 && ( + + + {note.todos.length} + + )} + {note.images && note.images.length > 0 && ( + + + {note.images.length} + + )} + {note.files && note.files.length > 0 && ( + + + {note.files.length} + + )} +
+
+
+ )) + ) : ( +
+ +

+ {searchQuery ? "Aucune note trouvée" : "Aucune note"} +

+ {!searchQuery && ( + + )} +
+ )} +
+ + ) : ( + /* Open Note Editor */ +
+
+ + +
+ + +
+
+ + handleUpdateNote({ title: e.target.value })} + /> + + + + Contenu + + Tâches + {openNote.todos && openNote.todos.length > 0 && ( + {openNote.todos.length} + )} + + + Images + {openNote.images && openNote.images.length > 0 && ( + {openNote.images.length} + )} + + + Fichiers + {openNote.files && openNote.files.length > 0 && ( + {openNote.files.length} + )} + + + + + handleUpdateNote({ content })} + /> + + + + + +
+ {openNote.todos && openNote.todos.length > 0 ? ( + openNote.todos.map((todo, index) => ( +
+ { + const updatedTodos = [...(openNote.todos || [])]; + updatedTodos[index] = { ...todo, completed: !todo.completed }; + await handleUpdateNote({ todos: updatedTodos }); + }} + /> + + {todo.text} + + +
+ )) + ) : ( +

Aucune tâche

+ )} +
+
+ + +
+ { + if (e.target.files && e.target.files[0] && openNote.id) { + try { + const image = await NotesService.uploadImage(openNote.id, e.target.files[0]); + if (image) { + const updatedImages = [...(openNote.images || []), image]; + await handleUpdateNote({ images: updatedImages }); + } + } catch (error) { + showError("Erreur lors de l'upload de l'image"); + } + } + }} + className="cursor-pointer" + /> +
+ +
+ {openNote.images && openNote.images.length > 0 ? ( + openNote.images.map((image, index) => ( +
+ {image.original_name} + +
+ )) + ) : ( +

Aucune image

+ )} +
+
+ + +
+ +
+ +
+ {openNote.files && openNote.files.length > 0 ? ( + openNote.files.map((file: any, index: number) => ( +
+ +
+

{file.original_name || file.filename}

+ {file.size && ( +

+ {(file.size / 1024).toFixed(2)} KB +

+ )} +
+
+ + +
+
+ )) + ) : ( +

Aucun fichier

+ )} +
+
+
+
+ )} +
+ + {/* Right Column: Todos & RSS Boxes stacked */} +
{/* Todos Box */} @@ -559,375 +899,10 @@ const Index = () => {
- - {/* Notes Section */} -
-
-
-

Mes Notes

-
- - -
-
- -
- - setSearchQuery(e.target.value)} - /> -
-
- - {/* Notes Grid */} -
- {filteredNotes.length > 0 ? ( - filteredNotes.map(note => ( - handleOpenNote(note)} - > - -

- {note.title || "Sans titre"} -

-

- {note.content ? note.content.replace(/<[^>]*>/g, '') : "Note vide"} -

-
- {note.todos && note.todos.length > 0 && ( - - - {note.todos.length} - - )} - {note.images && note.images.length > 0 && ( - - - {note.images.length} - - )} - {note.files && note.files.length > 0 && ( - - - {note.files.length} - - )} -
-
-
- )) - ) : ( -
- -

- {searchQuery ? "Aucune note trouvée" : "Aucune note"} -

- {!searchQuery && ( - - )} -
- )} -
-
+
- {/* Note Editor Dialog - Full Screen */} - - - -
- handleUpdateNote({ title: e.target.value })} - /> - -
- - -
-
-
- - {currentNote && ( - - - Contenu - - Tâches - {currentNote.todos && currentNote.todos.length > 0 && ( - {currentNote.todos.length} - )} - - - Images - {currentNote.images && currentNote.images.length > 0 && ( - {currentNote.images.length} - )} - - - Fichiers - {currentNote.files && currentNote.files.length > 0 && ( - {currentNote.files.length} - )} - - - - - handleUpdateNote({ content })} - placeholder="Commencez à écrire votre note..." - /> - - - - - - - -
- {currentNote.todos && currentNote.todos.length > 0 ? ( - currentNote.todos.map((todo, index) => ( -
- { - const updatedTodos = [...(currentNote.todos || [])]; - updatedTodos[index].completed = !updatedTodos[index].completed; - handleUpdateNote({ todos: updatedTodos }); - }} - /> - - {todo.text} - - -
- )) - ) : ( -

Aucune tâche dans cette note

- )} -
-
-
-
- - - - - - -
- {currentNote.images && currentNote.images.length > 0 ? ( - currentNote.images.map((image, index) => ( -
- {`Image - -
- )) - ) : ( -

Aucune image

- )} -
-
-
-
- - - - - - -
- {currentNote.files && currentNote.files.length > 0 ? ( - currentNote.files.map((file: any, index: number) => ( -
-
- - {file.filename || file.original_name} - - {file.size ? `${(file.size / 1024).toFixed(1)} KB` : ''} - -
-
- - -
-
- )) - ) : ( -

Aucun fichier attaché

- )} -
-
-
-
-
- )} -
-
- + {/* Admin Modal */} {/* Admin Modal */} diff --git a/src/services/NotesService.ts b/src/services/NotesService.ts index cbfa60e..a301ecb 100644 --- a/src/services/NotesService.ts +++ b/src/services/NotesService.ts @@ -11,6 +11,7 @@ interface Todo { interface Image { id?: number; filename: string; + original_name?: string; } interface NoteFile {