// Main application JavaScript for the frontend // Wait for the DOM to be loaded before executing document.addEventListener('DOMContentLoaded', function() { // Initialize theme initTheme(); // Setup interactive elements setupSubjectSelection(); setupCategorySelection(); setupTextSelection(); setupThemeToggle(); // Setup feedback form submission const feedbackForm = document.getElementById('feedback-form'); if (feedbackForm) { feedbackForm.addEventListener('submit', function(e) { const feedbackMessage = document.getElementById('feedback-message'); if (!feedbackMessage.value.trim()) { e.preventDefault(); alert('Veuillez entrer un message avant d\'envoyer votre feedback.'); } }); } }); // 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 subject selection functionality function setupSubjectSelection() { const subjectCards = document.querySelectorAll('.subject-card'); const subjectSelect = document.getElementById('matiere-select'); // Handle subject card clicks subjectCards.forEach(card => { card.addEventListener('click', function() { const matiereId = this.getAttribute('data-matiere-id'); // Update select element if it exists if (subjectSelect) { subjectSelect.value = matiereId; // Trigger change event to load subcategories const event = new Event('change'); subjectSelect.dispatchEvent(event); } else { loadSubCategories(matiereId); } // Highlight the selected card subjectCards.forEach(c => c.classList.remove('active')); this.classList.add('active'); // Show the categories section const categoriesSection = document.getElementById('sous-categories-section'); if (categoriesSection) { categoriesSection.classList.remove('d-none'); categoriesSection.scrollIntoView({ behavior: 'smooth' }); } }); }); // Handle subject select change if (subjectSelect) { subjectSelect.addEventListener('change', function() { const matiereId = this.value; if (matiereId) { loadSubCategories(matiereId); // Show the categories section const categoriesSection = document.getElementById('sous-categories-section'); if (categoriesSection) { categoriesSection.classList.remove('d-none'); } } }); } } // Load subcategories for the selected subject function loadSubCategories(matiereId) { fetch(`/get_sous_categories/${matiereId}`) .then(response => response.json()) .then(data => { // Update subcategories list const sousCategoriesList = document.getElementById('sous-categories-list'); if (sousCategoriesList) { sousCategoriesList.innerHTML = ''; data.forEach(category => { const item = document.createElement('li'); item.className = 'selection-item'; item.setAttribute('data-category-id', category.id); item.textContent = category.nom; // Add click event item.addEventListener('click', function() { const categoryId = this.getAttribute('data-category-id'); loadTextes(categoryId); // Highlight the selected category const items = sousCategoriesList.querySelectorAll('.selection-item'); items.forEach(i => i.classList.remove('active')); this.classList.add('active'); // Show the texts section const textesSection = document.getElementById('textes-section'); if (textesSection) { textesSection.classList.remove('d-none'); } }); sousCategoriesList.appendChild(item); }); // Show the subcategories section if it's hidden const sousCategoriesSection = document.getElementById('sous-categories-section'); if (sousCategoriesSection) { sousCategoriesSection.classList.remove('d-none'); } } }) .catch(error => { console.error('Error loading subcategories:', error); }); } // Setup category selection functionality function setupCategorySelection() { const categorySelect = document.getElementById('sous-categorie-select'); if (categorySelect) { categorySelect.addEventListener('change', function() { const categoryId = this.value; if (categoryId) { loadTextes(categoryId); // Show the texts section const textesSection = document.getElementById('textes-section'); if (textesSection) { textesSection.classList.remove('d-none'); } } }); } } // Load texts for the selected category function loadTextes(categoryId) { fetch(`/get_textes/${categoryId}`) .then(response => response.json()) .then(data => { // Update texts list const textesList = document.getElementById('textes-list'); if (textesList) { textesList.innerHTML = ''; data.forEach(texte => { const item = document.createElement('li'); item.className = 'selection-item'; item.setAttribute('data-texte-id', texte.id); item.textContent = texte.titre; // Add click event item.addEventListener('click', function() { const texteId = this.getAttribute('data-texte-id'); displayTexte(texteId); // Highlight the selected text const items = textesList.querySelectorAll('.selection-item'); items.forEach(i => i.classList.remove('active')); this.classList.add('active'); }); textesList.appendChild(item); }); // Show the texts section const textesSection = document.getElementById('textes-section'); if (textesSection) { textesSection.classList.remove('d-none'); } // Hide the content section since no text is selected yet const contentSection = document.getElementById('content-section'); if (contentSection) { contentSection.classList.add('d-none'); } } }) .catch(error => { console.error('Error loading texts:', error); }); } // Setup text selection functionality function setupTextSelection() { const texteSelect = document.getElementById('texte-select'); if (texteSelect) { texteSelect.addEventListener('change', function() { const texteId = this.value; if (texteId) { displayTexte(texteId); } }); } } // Display the selected texte with content blocks function displayTexte(texteId) { fetch(`/get_texte/${texteId}`) .then(response => response.json()) .then(data => { const contentSection = document.getElementById('content-section'); const contentTitle = document.getElementById('content-title'); const contentBlocks = document.getElementById('content-blocks'); if (contentSection && contentTitle && contentBlocks) { // Update content title contentTitle.textContent = data.titre; // Update content theme color based on matiere color if (data.color_code) { // Apply color to title underline contentTitle.style.borderBottomColor = data.color_code; // Apply color to all block titles const style = document.createElement('style'); style.id = 'dynamic-block-styles'; const existingStyle = document.getElementById('dynamic-block-styles'); if (existingStyle) { existingStyle.remove(); } style.textContent = ` .content-block-title { border-bottom-color: ${data.color_code} !important; } .content-block { border-left: 4px solid ${data.color_code} !important; } `; document.head.appendChild(style); } // Clear existing content contentBlocks.innerHTML = ''; // Create content blocks if (data.blocks && data.blocks.length > 0) { data.blocks.forEach(block => { // Create block container const blockDiv = document.createElement('div'); blockDiv.className = 'content-block fade-in'; // Check if block has an image if (block.image) { blockDiv.classList.add('block-with-image'); blockDiv.classList.add(`image-${block.image_position || 'left'}`); // Create image container const imageDiv = document.createElement('div'); imageDiv.className = 'block-image-container'; // Create image element const imageEl = document.createElement('img'); imageEl.className = 'block-image'; imageEl.src = block.image.src; imageEl.alt = block.image.alt || 'Illustration'; imageDiv.appendChild(imageEl); blockDiv.appendChild(imageDiv); // Create content container const contentDiv = document.createElement('div'); contentDiv.className = 'block-content-container'; // Add block title if present if (block.title) { const titleEl = document.createElement('h3'); titleEl.className = 'content-block-title'; titleEl.textContent = block.title; contentDiv.appendChild(titleEl); } // Add block content const contentEl = document.createElement('div'); contentEl.className = 'content-block-content'; contentEl.innerHTML = block.content.replace(/\n/g, '
'); contentDiv.appendChild(contentEl); blockDiv.appendChild(contentDiv); } else { // No image - simple block // Add block title if present if (block.title) { const titleEl = document.createElement('h3'); titleEl.className = 'content-block-title'; titleEl.textContent = block.title; blockDiv.appendChild(titleEl); } // Add block content const contentEl = document.createElement('div'); contentEl.className = 'content-block-content'; contentEl.innerHTML = block.content.replace(/\n/g, '
'); blockDiv.appendChild(contentEl); } // Add the block to the content area contentBlocks.appendChild(blockDiv); }); } else { // Fallback to regular content if no blocks const blockDiv = document.createElement('div'); blockDiv.className = 'content-block'; blockDiv.innerHTML = data.contenu.replace(/\n/g, '
'); contentBlocks.appendChild(blockDiv); } // Show the content section contentSection.classList.remove('d-none'); contentSection.scrollIntoView({ behavior: 'smooth' }); } }) .catch(error => { console.error('Error loading texte:', error); }); }