class NotesService { constructor() { this.currentNote = null; this.notes = []; // DOM Elements this.notesList = document.getElementById('notes-list'); this.noteEditor = document.getElementById('note-editor'); this.noteTitle = document.getElementById('note-title'); this.noteContent = document.getElementById('note-content'); this.todosList = document.getElementById('todos-list'); this.imagesList = document.getElementById('images-list'); this.searchInput = document.getElementById('search-notes'); this.newNoteBtn = document.getElementById('new-note-btn'); this.archiveNoteBtn = document.getElementById('archive-note-btn'); this.deleteNoteBtn = document.getElementById('delete-note-btn'); this.addTodoBtn = document.getElementById('add-todo-btn'); this.imageUpload = document.getElementById('image-upload'); this.setupEventListeners(); } setupEventListeners() { if (this.newNoteBtn) { this.newNoteBtn.addEventListener('click', () => this.createNewNote()); } if (this.archiveNoteBtn) { this.archiveNoteBtn.addEventListener('click', () => this.toggleArchiveNote()); } if (this.deleteNoteBtn) { this.deleteNoteBtn.addEventListener('click', () => this.deleteNote()); } if (this.addTodoBtn) { this.addTodoBtn.addEventListener('click', () => this.addTodo()); } if (this.imageUpload) { this.imageUpload.addEventListener('change', (e) => this.handleImageUpload(e)); } if (this.searchInput) { this.searchInput.addEventListener('input', (e) => this.handleSearch(e)); } // Auto-save on content changes if (this.noteTitle) { this.noteTitle.addEventListener('input', () => this.autoSave()); } if (this.noteContent) { this.noteContent.addEventListener('input', () => this.autoSave()); } } async loadNotes() { if (!window.auth || !window.auth.token) { console.log('Not authenticated, skipping notes loading'); return; } try { const response = await fetch('/api/notes', { headers: window.auth.getHeaders() }); if (!response.ok) { throw new Error(`Failed to load notes: ${response.status}`); } this.notes = await response.json(); this.renderNotesList(); } catch (error) { console.error('Error loading notes:', error); } } renderNotesList(searchTerm = '') { if (!this.notesList) return; this.notesList.innerHTML = ''; if (!this.notes || !this.notes.length) { this.notesList.innerHTML = '
Aucune note
'; return; } const filteredNotes = searchTerm ? this.notes.filter(note => (note.title && note.title.toLowerCase().includes(searchTerm.toLowerCase())) || (note.content && note.content.toLowerCase().includes(searchTerm.toLowerCase())) ) : this.notes; filteredNotes.forEach(note => { if (!note) return; const noteElement = document.createElement('div'); noteElement.className = `note-item ${note.id === (this.currentNote && this.currentNote.id) ? 'active' : ''}`; noteElement.innerHTML = `

${note.title || 'Sans titre'}

${note.content || ''}

`; noteElement.addEventListener('click', () => this.selectNote(note)); this.notesList.appendChild(noteElement); }); } selectNote(note) { if (!note) return; this.currentNote = note; if (this.noteTitle) this.noteTitle.value = note.title || ''; if (this.noteContent) this.noteContent.innerHTML = note.content || ''; this.renderTodos(); this.renderImages(); this.renderNotesList(); // Update active state } renderTodos() { if (!this.todosList || !this.currentNote) return; const todos = this.currentNote.todos || []; this.todosList.innerHTML = ''; todos.forEach((todo, index) => { if (!todo) return; const todoElement = document.createElement('div'); todoElement.className = `todo-item ${todo.completed ? 'completed' : ''}`; todoElement.innerHTML = ` ${todo.text || ''} `; const checkbox = todoElement.querySelector('input'); if (checkbox) { checkbox.addEventListener('change', () => this.toggleTodo(index)); } const deleteBtn = todoElement.querySelector('button'); if (deleteBtn) { deleteBtn.addEventListener('click', () => this.deleteTodo(index)); } this.todosList.appendChild(todoElement); }); } renderImages() { if (!this.imagesList || !this.currentNote) return; const images = this.currentNote.images || []; this.imagesList.innerHTML = ''; images.forEach((image, index) => { if (!image || !image.filename) return; const imageElement = document.createElement('div'); imageElement.className = 'image-thumbnail'; imageElement.innerHTML = ` Note image `; const deleteBtn = imageElement.querySelector('button'); if (deleteBtn) { deleteBtn.addEventListener('click', () => this.deleteImage(image.id)); } this.imagesList.appendChild(imageElement); }); } async createNewNote() { if (!window.auth || !window.auth.getHeaders) return; try { const response = await fetch('/api/notes', { method: 'POST', headers: window.auth.getHeaders(), body: JSON.stringify({ title: 'Nouvelle note', content: '', todos: [] }) }); const newNote = await response.json(); if (newNote) { this.notes.unshift(newNote); this.renderNotesList(); this.selectNote(newNote); } } catch (error) { console.error('Error creating note:', error); } } async autoSave() { if (!this.currentNote || !window.auth || !window.auth.getHeaders) return; clearTimeout(this.saveTimeout); this.saveTimeout = setTimeout(async () => { try { if (!this.noteTitle || !this.noteContent) return; await fetch(`/api/notes/${this.currentNote.id}`, { method: 'PUT', headers: window.auth.getHeaders(), body: JSON.stringify({ title: this.noteTitle.value || '', content: this.noteContent.innerHTML || '', todos: this.currentNote.todos || [] }) }); // Update local note this.currentNote.title = this.noteTitle.value || ''; this.currentNote.content = this.noteContent.innerHTML || ''; this.renderNotesList(); } catch (error) { console.error('Error saving note:', error); } }, 1000); } async toggleArchiveNote() { if (!this.currentNote || !window.auth || !window.auth.getHeaders) return; try { await fetch(`/api/notes/${this.currentNote.id}`, { method: 'PUT', headers: window.auth.getHeaders(), body: JSON.stringify({ ...this.currentNote, archived: !this.currentNote.archived }) }); this.currentNote.archived = !this.currentNote.archived; this.renderNotesList(); } catch (error) { console.error('Error archiving note:', error); } } async deleteNote() { if (!this.currentNote || !window.auth || !window.auth.getHeaders) return; if (!confirm('Êtes-vous sûr de vouloir supprimer cette note ?')) return; try { await fetch(`/api/notes/${this.currentNote.id}`, { method: 'DELETE', headers: window.auth.getHeaders() }); const index = this.notes.findIndex(n => n.id === this.currentNote.id); if (index !== -1) { this.notes.splice(index, 1); } this.currentNote = null; this.renderNotesList(); if (this.noteTitle) this.noteTitle.value = ''; if (this.noteContent) this.noteContent.innerHTML = ''; if (this.todosList) this.todosList.innerHTML = ''; if (this.imagesList) this.imagesList.innerHTML = ''; } catch (error) { console.error('Error deleting note:', error); } } async addTodo() { if (!this.currentNote) return; const text = prompt('Nouveau todo:'); if (!text) return; if (!this.currentNote.todos) { this.currentNote.todos = []; } this.currentNote.todos.push({ text, completed: false }); this.renderTodos(); this.autoSave(); } async toggleTodo(index) { if (!this.currentNote || !this.currentNote.todos) return; if (index < 0 || index >= this.currentNote.todos.length) return; this.currentNote.todos[index].completed = !this.currentNote.todos[index].completed; this.renderTodos(); this.autoSave(); } async deleteTodo(index) { if (!this.currentNote || !this.currentNote.todos) return; if (index < 0 || index >= this.currentNote.todos.length) return; this.currentNote.todos.splice(index, 1); this.renderTodos(); this.autoSave(); } async handleImageUpload(event) { if (!this.currentNote || !event.target || !event.target.files || !event.target.files.length) return; if (!window.auth || !window.auth.getHeaders) return; const formData = new FormData(); formData.append('image', event.target.files[0]); try { const response = await fetch(`/api/notes/${this.currentNote.id}/images`, { method: 'POST', headers: { 'Authorization': window.auth.getHeaders().Authorization }, body: formData }); const image = await response.json(); if (!this.currentNote.images) { this.currentNote.images = []; } this.currentNote.images.push(image); this.renderImages(); } catch (error) { console.error('Error uploading image:', error); } if (event.target) { event.target.value = ''; // Reset input } } async deleteImage(imageId) { if (!this.currentNote || !this.currentNote.images) return; if (!window.auth || !window.auth.getHeaders) return; if (!confirm('Supprimer cette image ?')) return; try { await fetch(`/api/notes/${this.currentNote.id}/images/${imageId}`, { method: 'DELETE', headers: window.auth.getHeaders() }); const index = this.currentNote.images.findIndex(img => img.id === imageId); if (index !== -1) { this.currentNote.images.splice(index, 1); } this.renderImages(); } catch (error) { console.error('Error deleting image:', error); } } handleSearch(event) { if (!event || !event.target) return; this.renderNotesList(event.target.value || ''); } } // Initialize notes service window.notes = new NotesService();