// 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);
});
}