document.addEventListener('DOMContentLoaded', function() { let currentChapterId = null; const storyId = document.querySelector('input[name="id"]')?.value; // Fonction de notification function showNotification(message, type = 'success') { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; document.body.appendChild(notification); // Animation d'entrée setTimeout(() => { notification.style.opacity = '1'; notification.style.transform = 'translateY(0)'; }, 10); // Auto-suppression après 3 secondes setTimeout(() => { notification.style.opacity = '0'; notification.style.transform = 'translateY(-100%)'; setTimeout(() => notification.remove(), 300); }, 3000); } // Création de l'icône SVG pour le séparateur const icons = { divider: ` ` }; // Ajout de l'icône à Quill const Block = Quill.import('blots/block'); const icons_list = Quill.import('ui/icons'); icons_list['divider'] = icons.divider; // Définition du format pour le séparateur class DividerBlot extends Block { static create() { const node = super.create(); node.className = 'chapter-divider'; return node; } } DividerBlot.blotName = 'divider'; DividerBlot.tagName = 'hr'; Quill.register(DividerBlot); // Configuration et initialisation de Quill const quill = new Quill('#editor', { theme: 'snow', modules: { toolbar: { container: [ [{ 'header': [1, 2, 3, false] }], ['bold', 'italic', 'underline', 'strike'], [{ 'color': [] }, { 'background': [] }], [{ 'font': [] }], [{ 'align': [] }], ['blockquote', 'code-block'], [{ 'list': 'ordered'}, { 'list': 'bullet' }], [{ 'script': 'sub'}, { 'script': 'super' }], [{ 'indent': '-1'}, { 'indent': '+1' }], [{ 'direction': 'rtl' }], ['link', 'image', 'video'], ['divider'], ['clean'] ], handlers: { image: function() { const input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', 'image/*'); input.click(); input.onchange = async () => { const file = input.files[0]; if (file) { const formData = new FormData(); formData.append('image', file); formData.append('storyId', storyId); try { const response = await fetch('api/upload-image.php', { method: 'POST', body: formData }); if (!response.ok) throw new Error('Upload failed'); const result = await response.json(); if (result.success) { const range = quill.getSelection(true); quill.insertEmbed(range.index, 'image', result.url); quill.setSelection(range.index + 1); } else { showNotification(result.error || 'Erreur lors de l\'upload', 'error'); } } catch (error) { console.error('Error:', error); showNotification('Erreur lors de l\'upload de l\'image', 'error'); } } }; } } }, keyboard: { bindings: { tab: false, 'indent backwards': false } } }, placeholder: 'Commencez à écrire votre chapitre ici...' }); // Gestion des chapitres const modal = document.getElementById('chapterEditor'); const addChapterBtn = document.getElementById('addChapter'); const saveChapterBtn = document.getElementById('saveChapter'); const cancelEditBtn = document.getElementById('cancelEdit'); const chapterTitleInput = document.getElementById('chapterTitle'); const chaptersList = document.getElementById('chaptersList'); // Configuration de Sortable pour la réorganisation des chapitres if (chaptersList) { new Sortable(chaptersList, { animation: 150, handle: '.chapter-number', ghostClass: 'sortable-ghost', onEnd: async function(evt) { const chapters = Array.from(chaptersList.children).map((item, index) => ({ id: item.dataset.id, position: index })); try { const response = await fetch('api/reorder-chapters.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ storyId: storyId, chapters: chapters }) }); if (!response.ok) { throw new Error('Erreur lors de la réorganisation'); } chapters.forEach((chapter, index) => { const element = document.querySelector(`[data-id="${chapter.id}"] .chapter-number`); if (element) { element.textContent = index + 1; } }); } catch (error) { console.error('Erreur:', error); showNotification('Erreur lors de la réorganisation des chapitres', 'error'); } } }); } // Gestionnaires d'événements pour l'édition des chapitres if (addChapterBtn) { addChapterBtn.addEventListener('click', () => { currentChapterId = null; chapterTitleInput.value = ''; quill.setContents([]); modal.style.display = 'block'; }); } if (cancelEditBtn) { cancelEditBtn.addEventListener('click', () => { if (hasUnsavedChanges()) { if (!confirm('Des modifications non sauvegardées seront perdues. Voulez-vous vraiment fermer ?')) { return; } } modal.style.display = 'none'; }); } // Gestion des clics sur la liste des chapitres if (chaptersList) { chaptersList.addEventListener('click', async (e) => { const target = e.target; if (target.matches('.edit-chapter')) { const chapterItem = target.closest('.chapter-item'); currentChapterId = chapterItem.dataset.id; try { const response = await fetch(`api/get-chapter.php?storyId=${storyId}&chapterId=${currentChapterId}`); if (!response.ok) { throw new Error('Erreur réseau'); } const chapter = await response.json(); // Mise à jour du titre chapterTitleInput.value = chapter.title || ''; // Gestion du contenu if (chapter.html) { quill.root.innerHTML = chapter.html; } else if (chapter.content) { try { const content = typeof chapter.content === 'string' ? JSON.parse(chapter.content) : chapter.content; quill.setContents(content); } catch (contentError) { console.error('Erreur de parsing du contenu:', contentError); quill.setText(chapter.content || ''); } } else { quill.setContents([]); } modal.style.display = 'block'; } catch (error) { console.error('Erreur détaillée:', error); showNotification('Erreur lors du chargement du chapitre', 'error'); } } // Gestion de la suppression if (target.matches('.delete-chapter')) { const chapterItem = target.closest('.chapter-item'); const chapterId = chapterItem.dataset.id; const chapterTitle = chapterItem.querySelector('.chapter-title').textContent; if (confirm(`Voulez-vous vraiment supprimer le chapitre "${chapterTitle}" ? Cette action est irréversible.`)) { try { const response = await fetch('api/delete-chapter.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ storyId: storyId, chapterId: chapterId }) }); if (!response.ok) { throw new Error('Erreur réseau'); } const result = await response.json(); if (result.success) { // Animation de suppression chapterItem.style.opacity = '0'; chapterItem.style.transform = 'translateX(-100%)'; setTimeout(() => { chapterItem.remove(); showNotification('Chapitre supprimé avec succès'); }, 300); } else { throw new Error(result.error || 'Erreur lors de la suppression'); } } catch (error) { console.error('Erreur:', error); showNotification(error.message, 'error'); } } } }); } // Sauvegarde d'un chapitre if (saveChapterBtn) { saveChapterBtn.addEventListener('click', async () => { const title = chapterTitleInput.value.trim(); if (!title) { showNotification('Le titre est requis', 'error'); return; } try { const response = await fetch('api/save-chapter.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ storyId: storyId, chapterId: currentChapterId, title: title, content: JSON.stringify(quill.getContents()) }) }); if (response.ok) { showNotification('Chapitre sauvegardé avec succès'); setTimeout(() => location.reload(), 500); } else { throw new Error('Erreur lors de la sauvegarde'); } } catch (error) { console.error('Erreur:', error); showNotification('Erreur lors de la sauvegarde du chapitre', 'error'); } }); } function hasUnsavedChanges() { if (!currentChapterId) { return chapterTitleInput.value !== '' || quill.getLength() > 1; } return true; } });