// Admin JavaScript for the backend management interface document.addEventListener('DOMContentLoaded', function() { // Initialize theme initTheme(); // Setup dashboard functionality setupDashboardCards(); // Setup admin forms setupMatiereForm(); setupSousCategorieForm(); setupTexteForm(); // Setup content block editor setupContentBlockEditor(); // Setup image management setupImageUploader(); setupImageGallery(); // Setup theme toggle setupThemeToggle(); }); // Initialize theme based on user preference function initTheme() { const userPreference = localStorage.getItem('theme') || 'light'; document.documentElement.setAttribute('data-theme', userPreference); // Update theme icon updateThemeIcon(userPreference); } // Setup theme toggle functionality function setupThemeToggle() { const themeToggle = document.getElementById('theme-toggle'); if (!themeToggle) return; themeToggle.addEventListener('click', function() { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; // Update theme attribute document.documentElement.setAttribute('data-theme', newTheme); // Save preference to localStorage localStorage.setItem('theme', newTheme); // Update icon updateThemeIcon(newTheme); // Send theme preference to server saveThemePreference(newTheme); }); } // Update the theme toggle icon based on current theme function updateThemeIcon(theme) { const themeToggle = document.getElementById('theme-toggle'); if (!themeToggle) return; // Update icon based on theme if (theme === 'dark') { themeToggle.innerHTML = ''; themeToggle.setAttribute('title', 'Activer le mode clair'); } else { themeToggle.innerHTML = ''; themeToggle.setAttribute('title', 'Activer le mode sombre'); } } // Save theme preference to server function saveThemePreference(theme) { const formData = new FormData(); formData.append('theme', theme); fetch('/set_theme', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { console.log('Theme preference saved:', data); }) .catch(error => { console.error('Error saving theme preference:', error); }); } // Setup dashboard cards with hover effects function setupDashboardCards() { const dashboardCards = document.querySelectorAll('.admin-card'); dashboardCards.forEach(card => { card.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-5px)'; this.style.boxShadow = 'var(--hover-shadow)'; this.style.transition = 'transform 0.3s ease, box-shadow 0.3s ease'; }); card.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0)'; this.style.boxShadow = 'var(--shadow)'; }); }); } // Setup matiere form functionality function setupMatiereForm() { // Show edit form when edit button is clicked const editButtons = document.querySelectorAll('.edit-matiere-btn'); editButtons.forEach(button => { button.addEventListener('click', function() { const matiereId = this.getAttribute('data-id'); const matiereName = this.getAttribute('data-name'); const matiereColor = this.getAttribute('data-color'); const editForm = document.getElementById('edit-matiere-form'); if (editForm) { const idInput = editForm.querySelector('input[name="matiere_id"]'); const nameInput = editForm.querySelector('input[name="nom"]'); const colorInput = editForm.querySelector('input[name="color_code"]'); idInput.value = matiereId; nameInput.value = matiereName; colorInput.value = matiereColor; // Show the edit form document.getElementById('add-matiere-section').classList.add('d-none'); document.getElementById('edit-matiere-section').classList.remove('d-none'); // Scroll to edit form editForm.scrollIntoView({ behavior: 'smooth' }); } }); }); // Cancel edit button const cancelEditButton = document.getElementById('cancel-edit-matiere'); if (cancelEditButton) { cancelEditButton.addEventListener('click', function(e) { e.preventDefault(); document.getElementById('add-matiere-section').classList.remove('d-none'); document.getElementById('edit-matiere-section').classList.add('d-none'); }); } // Color picker preview const colorPickers = document.querySelectorAll('input[type="color"]'); colorPickers.forEach(picker => { picker.addEventListener('input', function() { // Find adjacent preview element or create one let preview = this.nextElementSibling; if (!preview || !preview.classList.contains('color-preview')) { preview = document.createElement('span'); preview.className = 'color-preview'; preview.style.display = 'inline-block'; preview.style.width = '24px'; preview.style.height = '24px'; preview.style.borderRadius = '50%'; preview.style.marginLeft = '10px'; this.parentNode.insertBefore(preview, this.nextSibling); } preview.style.backgroundColor = this.value; }); // Trigger once to initialize const event = new Event('input'); picker.dispatchEvent(event); }); } // Setup sous categorie form functionality function setupSousCategorieForm() { // Show edit form when edit button is clicked const editButtons = document.querySelectorAll('.edit-sous-categorie-btn'); editButtons.forEach(button => { button.addEventListener('click', function() { const sousCategorieId = this.getAttribute('data-id'); const sousCategorieName = this.getAttribute('data-name'); const matiereId = this.getAttribute('data-matiere-id'); const editForm = document.getElementById('edit-sous-categorie-form'); if (editForm) { const idInput = editForm.querySelector('input[name="sous_categorie_id"]'); const nameInput = editForm.querySelector('input[name="nom"]'); const matiereSelect = editForm.querySelector('select[name="matiere_id"]'); idInput.value = sousCategorieId; nameInput.value = sousCategorieName; matiereSelect.value = matiereId; // Show the edit form document.getElementById('add-sous-categorie-section').classList.add('d-none'); document.getElementById('edit-sous-categorie-section').classList.remove('d-none'); // Scroll to edit form editForm.scrollIntoView({ behavior: 'smooth' }); } }); }); // Cancel edit button const cancelEditButton = document.getElementById('cancel-edit-sous-categorie'); if (cancelEditButton) { cancelEditButton.addEventListener('click', function(e) { e.preventDefault(); document.getElementById('add-sous-categorie-section').classList.remove('d-none'); document.getElementById('edit-sous-categorie-section').classList.add('d-none'); }); } // Matiere select filter const matiereFilterSelect = document.getElementById('matiere-filter'); if (matiereFilterSelect) { matiereFilterSelect.addEventListener('change', function() { const selectedMatiereId = this.value; const sousCategorieRows = document.querySelectorAll('.sous-categorie-row'); sousCategorieRows.forEach(row => { if (selectedMatiereId === '' || row.getAttribute('data-matiere-id') === selectedMatiereId) { row.style.display = ''; } else { row.style.display = 'none'; } }); }); } } // Setup texte form functionality function setupTexteForm() { // Matiere select change - populate sous-categories const matiereSelect = document.getElementById('matiere-select'); if (matiereSelect) { matiereSelect.addEventListener('change', function() { const matiereId = this.value; const sousCategorieSelect = document.getElementById('sous-categorie-select'); if (matiereId && sousCategorieSelect) { // Clear current options sousCategorieSelect.innerHTML = ''; // Fetch sous-categories for the selected matiere fetch(`/get_sous_categories/${matiereId}`) .then(response => response.json()) .then(data => { data.forEach(sousCategorie => { const option = document.createElement('option'); option.value = sousCategorie.id; option.textContent = sousCategorie.nom; sousCategorieSelect.appendChild(option); }); }) .catch(error => { console.error('Error loading sous-categories:', error); }); } }); } } // Setup content block editor function setupContentBlockEditor() { const blocksContainer = document.getElementById('blocks-container'); const addBlockButton = document.getElementById('add-block-button'); const saveBlocksButton = document.getElementById('save-blocks-button'); if (!blocksContainer) return; // Add new block if (addBlockButton) { addBlockButton.addEventListener('click', function() { addContentBlock(); }); } // Make blocks sortable if (window.Sortable) { new Sortable(blocksContainer, { animation: 150, handle: '.block-handle', ghostClass: 'block-ghost', onEnd: function() { // Update order numbers updateBlockOrder(); } }); } // Save blocks if (saveBlocksButton) { saveBlocksButton.addEventListener('click', function() { saveContentBlocks(); }); } // Add event listeners for existing blocks setupExistingBlockControls(); } // Setup controls for existing blocks function setupExistingBlockControls() { // Setup delete buttons const deleteButtons = document.querySelectorAll('.delete-block-btn'); deleteButtons.forEach(button => { button.addEventListener('click', function() { if (confirm('Êtes-vous sûr de vouloir supprimer ce bloc ?')) { const blockEditor = this.closest('.block-editor'); blockEditor.remove(); updateBlockOrder(); } }); }); // Setup image position selects const positionSelects = document.querySelectorAll('.image-position-select'); positionSelects.forEach(select => { select.addEventListener('change', function() { updateBlockImagePreview(this.closest('.block-editor')); }); }); // Setup image selection buttons const imageSelectButtons = document.querySelectorAll('.select-image-btn'); imageSelectButtons.forEach(button => { button.addEventListener('click', function() { const blockEditor = this.closest('.block-editor'); const galleryModal = document.getElementById('image-gallery-modal'); if (galleryModal) { // Set current block ID as data attribute for the modal galleryModal.setAttribute('data-target-block', blockEditor.getAttribute('data-block-id')); // Show the modal const modal = new bootstrap.Modal(galleryModal); modal.show(); } }); }); // Setup image remove buttons const removeImageButtons = document.querySelectorAll('.remove-image-btn'); removeImageButtons.forEach(button => { button.addEventListener('click', function() { const blockEditor = this.closest('.block-editor'); const imageIdInput = blockEditor.querySelector('.block-image-id'); const imagePreview = blockEditor.querySelector('.image-preview'); if (imageIdInput) { imageIdInput.value = ''; } if (imagePreview) { imagePreview.src = ''; imagePreview.style.display = 'none'; } // Hide remove button this.style.display = 'none'; // Show select button const selectButton = blockEditor.querySelector('.select-image-btn'); if (selectButton) { selectButton.style.display = 'inline-block'; } }); }); } // Add a new content block to the editor function addContentBlock(data = null) { const blocksContainer = document.getElementById('blocks-container'); if (!blocksContainer) return; // Generate a unique ID for the block const blockId = 'block-' + Date.now(); // Create block HTML const blockHtml = `

Bloc #${blocksContainer.children.length + 1}

Preview
`; // Add the block to the container blocksContainer.insertAdjacentHTML('beforeend', blockHtml); // Setup event listeners for the new block const newBlock = blocksContainer.lastElementChild; // Delete button const deleteButton = newBlock.querySelector('.delete-block-btn'); if (deleteButton) { deleteButton.addEventListener('click', function() { if (confirm('Êtes-vous sûr de vouloir supprimer ce bloc ?')) { newBlock.remove(); updateBlockOrder(); } }); } // Image position select const positionSelect = newBlock.querySelector('.image-position-select'); if (positionSelect) { positionSelect.addEventListener('change', function() { updateBlockImagePreview(newBlock); }); } // Image selection button const imageSelectButton = newBlock.querySelector('.select-image-btn'); if (imageSelectButton) { imageSelectButton.addEventListener('click', function() { const galleryModal = document.getElementById('image-gallery-modal'); if (galleryModal) { // Set current block ID as data attribute for the modal galleryModal.setAttribute('data-target-block', blockId); // Show the modal const modal = new bootstrap.Modal(galleryModal); modal.show(); } }); } // Image remove button const removeImageButton = newBlock.querySelector('.remove-image-btn'); if (removeImageButton) { removeImageButton.addEventListener('click', function() { const imageIdInput = newBlock.querySelector('.block-image-id'); const imagePreview = newBlock.querySelector('.image-preview'); if (imageIdInput) { imageIdInput.value = ''; } if (imagePreview) { imagePreview.src = ''; imagePreview.style.display = 'none'; } // Hide remove button removeImageButton.style.display = 'none'; // Show select button if (imageSelectButton) { imageSelectButton.style.display = 'inline-block'; } }); } // Scroll to the new block newBlock.scrollIntoView({ behavior: 'smooth' }); } // Update block order numbers in the UI function updateBlockOrder() { const blocks = document.querySelectorAll('.block-editor'); blocks.forEach((block, index) => { const titleEl = block.querySelector('.block-editor-title'); if (titleEl) { titleEl.textContent = `Bloc #${index + 1}`; } }); } // Update image preview based on position function updateBlockImagePreview(blockEditor) { // This function would apply CSS classes to show how the image position // will look in the frontend const positionSelect = blockEditor.querySelector('.image-position-select'); const imagePreview = blockEditor.querySelector('.image-preview'); if (!positionSelect || !imagePreview || imagePreview.style.display === 'none') { return; } const position = positionSelect.value; // Remove existing position classes imagePreview.classList.remove('position-left', 'position-right', 'position-top'); // Add the selected position class imagePreview.classList.add(`position-${position}`); // Apply some simple styling to demonstrate the position switch (position) { case 'left': imagePreview.style.float = 'left'; imagePreview.style.marginRight = '15px'; imagePreview.style.marginBottom = '10px'; imagePreview.style.width = '30%'; break; case 'right': imagePreview.style.float = 'right'; imagePreview.style.marginLeft = '15px'; imagePreview.style.marginBottom = '10px'; imagePreview.style.width = '30%'; break; case 'top': imagePreview.style.float = 'none'; imagePreview.style.marginRight = '0'; imagePreview.style.marginLeft = '0'; imagePreview.style.marginBottom = '15px'; imagePreview.style.width = '100%'; break; } } // Save content blocks function saveContentBlocks() { const blocksContainer = document.getElementById('blocks-container'); const blocksDataInput = document.getElementById('blocks-data'); if (!blocksContainer || !blocksDataInput) return; const blocks = blocksContainer.querySelectorAll('.block-editor'); const blocksData = []; blocks.forEach((block, index) => { const blockId = block.getAttribute('data-block-id'); const title = block.querySelector('.block-title').value; const content = block.querySelector('.block-content').value; const imageId = block.querySelector('.block-image-id').value; const imagePosition = block.querySelector('.image-position-select').value; blocksData.push({ id: blockId, title: title, content: content, image_id: imageId, image_position: imagePosition, order: index }); }); // Set the blocks data as JSON in the hidden input blocksDataInput.value = JSON.stringify(blocksData); // Submit the form const form = document.getElementById('blocks-form'); if (form) { form.submit(); } } // Setup image uploader function setupImageUploader() { const imageUploadForm = document.getElementById('image-upload-form'); const imageFileInput = document.getElementById('image-file'); const imagePreview = document.getElementById('upload-image-preview'); if (imageFileInput && imagePreview) { imageFileInput.addEventListener('change', function() { if (this.files && this.files[0]) { const reader = new FileReader(); reader.onload = function(e) { imagePreview.src = e.target.result; imagePreview.style.display = 'block'; }; reader.readAsDataURL(this.files[0]); } }); } if (imageUploadForm) { imageUploadForm.addEventListener('submit', function(e) { const fileInput = this.querySelector('#image-file'); if (!fileInput.files || fileInput.files.length === 0) { e.preventDefault(); alert('Veuillez sélectionner une image.'); } }); } } // Setup image gallery function setupImageGallery() { // Handle image selection from gallery const galleryItems = document.querySelectorAll('.gallery-item'); galleryItems.forEach(item => { item.addEventListener('click', function() { const imageId = this.getAttribute('data-image-id'); const imageSrc = this.querySelector('img').src; const galleryModal = document.getElementById('image-gallery-modal'); if (galleryModal) { const targetBlockId = galleryModal.getAttribute('data-target-block'); const blockEditor = document.querySelector(`.block-editor[data-block-id="${targetBlockId}"]`); if (blockEditor) { // Update the image ID input const imageIdInput = blockEditor.querySelector('.block-image-id'); if (imageIdInput) { imageIdInput.value = imageId; } // Update the image preview const imagePreview = blockEditor.querySelector('.image-preview'); if (imagePreview) { imagePreview.src = imageSrc; imagePreview.style.display = 'block'; } // Hide select button and show remove button const selectButton = blockEditor.querySelector('.select-image-btn'); const removeButton = blockEditor.querySelector('.remove-image-btn'); if (selectButton) { selectButton.style.display = 'none'; } if (removeButton) { removeButton.style.display = 'inline-block'; } // Update image preview position updateBlockImagePreview(blockEditor); } // Close the modal const modal = bootstrap.Modal.getInstance(galleryModal); if (modal) { modal.hide(); } } }); }); }