// === SYSTÈME DE NAVIGATION === const AppNavigation = { currentPage: 'home', navigationHistory: ['home'], gamesConfig: null, contentScanner: new ContentScanner(), scannedContent: null, init() { this.loadGamesConfig(); this.initContentScanner(); this.setupEventListeners(); this.handleInitialRoute(); }, async loadGamesConfig() { // Utilisation directe de la config par défaut (pas de fetch) console.log('📁 Utilisation de la configuration par défaut'); this.gamesConfig = this.getDefaultConfig(); }, async initContentScanner() { try { console.log('🔍 Initialisation du scanner de contenu...'); this.scannedContent = await this.contentScanner.scanAllContent(); console.log(`✅ ${this.scannedContent.found.length} modules de contenu détectés automatiquement`); } catch (error) { console.error('Erreur scan contenu:', error); } }, getDefaultConfig() { return { games: { 'whack-a-mole': { enabled: true, name: 'Whack-a-Mole', icon: '🔨', description: 'Tape sur les bonnes réponses !' }, 'whack-a-mole-hard': { enabled: true, name: 'Whack-a-Mole Hard', icon: '💥', description: '3 moles at once, 5x3 grid, harder!' }, 'memory-match': { enabled: true, name: 'Memory Match', icon: '🧠', description: 'Find matching English-French pairs!' }, 'quiz-game': { enabled: true, name: 'Quiz Game', icon: '❓', description: 'Answer vocabulary questions!' }, 'temp-games': { enabled: true, name: 'Jeux Temporaires', icon: '🎯', description: 'Mini-jeux en développement' }, 'fill-the-blank': { enabled: true, name: 'Fill the Blank', icon: '📝', description: 'Complète les phrases en remplissant les blancs !' }, 'text-reader': { enabled: true, name: 'Text Reader', icon: '📖', description: 'Read texts sentence by sentence' }, 'adventure-reader': { enabled: true, name: 'Adventure Reader', icon: '⚔️', description: 'Zelda-style adventure with vocabulary!' } }, content: { 'sbs-level-8': { enabled: true, name: 'SBS Level 8', icon: '📚', description: 'Vocabulaire manuel SBS' }, 'animals': { enabled: false, name: 'Animals', icon: '🐱', description: 'Vocabulaire des animaux' }, 'colors': { enabled: false, name: 'Colors & Numbers', icon: '🌈', description: 'Couleurs et nombres' } } }; }, setupEventListeners() { // Navigation par URL window.addEventListener('popstate', () => { this.handleInitialRoute(); }); // Raccourcis clavier document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { this.goBack(); } }); // Scroll pour masquer/afficher la breadcrumb this.setupScrollBehavior(); }, handleInitialRoute() { const params = Utils.getUrlParams(); if (params.page === 'play' && params.game && params.content) { this.showGamePage(params.game, params.content); } else if (params.page === 'levels' && params.game) { this.showLevelsPage(params.game); } else if (params.page === 'games') { this.showGamesPage(); } else { this.showHomePage(); } }, setupScrollBehavior() { let lastScrollY = window.scrollY; let breadcrumb = null; const handleScroll = () => { if (!breadcrumb) { breadcrumb = document.querySelector('.breadcrumb'); if (!breadcrumb) return; } const currentScrollY = window.scrollY; // Si on scroll vers le bas et qu'on a scrollé plus de 50px if (currentScrollY > lastScrollY && currentScrollY > 50) { breadcrumb.classList.add('hidden'); breadcrumb.classList.remove('visible'); } // Si on scroll vers le haut ou qu'on est près du top else if (currentScrollY < lastScrollY || currentScrollY <= 50) { breadcrumb.classList.remove('hidden'); breadcrumb.classList.add('visible'); } lastScrollY = currentScrollY; }; // Throttle scroll event pour les performances let ticking = false; window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(() => { handleScroll(); ticking = false; }); ticking = true; } }); }, // Navigation vers une page navigateTo(page, game = null, content = null) { const params = { page }; if (game) params.game = game; if (content) params.content = content; Utils.setUrlParams(params); // Mise à jour historique if (this.currentPage !== page) { this.navigationHistory.push(page); } this.currentPage = page; // Affichage de la page appropriée switch(page) { case 'games': this.showGamesPage(); break; case 'levels': this.showLevelsPage(game); break; case 'play': this.showGamePage(game, content); break; default: this.showHomePage(); } this.updateBreadcrumb(); }, // Retour en arrière goBack() { if (this.navigationHistory.length > 1) { this.navigationHistory.pop(); // Retirer la page actuelle const previousPage = this.navigationHistory[this.navigationHistory.length - 1]; const params = Utils.getUrlParams(); if (previousPage === 'levels') { this.navigateTo('levels', params.game); } else if (previousPage === 'games') { this.navigateTo('games'); } else { this.navigateTo('home'); } } }, // Affichage page d'accueil showHomePage() { this.hideAllPages(); document.getElementById('home-page').classList.add('active'); this.currentPage = 'home'; }, // Affichage page sélection jeux showGamesPage() { this.hideAllPages(); document.getElementById('games-page').classList.add('active'); this.renderGamesGrid(); this.currentPage = 'games'; }, // Affichage page sélection niveaux showLevelsPage(gameType) { this.hideAllPages(); document.getElementById('levels-page').classList.add('active'); this.renderLevelsGrid(gameType); this.currentPage = 'levels'; // Mise à jour de la description const gameInfo = this.gamesConfig?.games[gameType]; if (gameInfo) { document.getElementById('level-description').textContent = `Sélectionne le contenu pour jouer à ${gameInfo.name}`; } }, // Affichage page de jeu async showGamePage(gameType, contentType) { this.hideAllPages(); document.getElementById('game-page').classList.add('active'); this.currentPage = 'play'; Utils.showLoading(); try { await GameLoader.loadGame(gameType, contentType); } catch (error) { console.error('Erreur chargement jeu:', error); Utils.showToast('Erreur lors du chargement du jeu', 'error'); this.goBack(); } finally { Utils.hideLoading(); } }, // Masquer toutes les pages hideAllPages() { document.querySelectorAll('.page').forEach(page => { page.classList.remove('active'); }); }, // Rendu grille des jeux renderGamesGrid() { const grid = document.getElementById('games-grid'); grid.innerHTML = ''; if (!this.gamesConfig) return; Object.entries(this.gamesConfig.games).forEach(([key, game]) => { if (game.enabled) { const card = this.createGameCard(key, game); grid.appendChild(card); } }); }, // Création d'une carte de jeu createGameCard(gameKey, gameInfo) { const card = document.createElement('div'); card.className = 'game-card'; card.innerHTML = `
${gameInfo.icon}
${gameInfo.name}
${gameInfo.description}
`; card.addEventListener('click', () => { Utils.animateElement(card, 'pulse'); this.navigateTo('levels', gameKey); }); return card; }, // Rendu grille des niveaux async renderLevelsGrid(gameType) { const grid = document.getElementById('levels-grid'); grid.innerHTML = '
🔍 Recherche du contenu disponible...
'; try { // Obtenir tout le contenu disponible automatiquement const availableContent = await this.contentScanner.getAvailableContent(); if (availableContent.length === 0) { grid.innerHTML = '
Aucun contenu trouvé
'; return; } // Effacer le loading grid.innerHTML = ''; // Filtrer par compatibilité avec le jeu si possible const compatibleContent = await this.contentScanner.getContentByGame(gameType); const contentToShow = compatibleContent.length > 0 ? compatibleContent : availableContent; console.log(`📋 Affichage de ${contentToShow.length} modules pour ${gameType}`); // Créer les cartes pour chaque contenu trouvé contentToShow.forEach(content => { const card = this.createLevelCard(content.id, content, gameType); grid.appendChild(card); }); // Ajouter info de compatibilité si filtré if (compatibleContent.length > 0 && compatibleContent.length < availableContent.length) { const infoDiv = document.createElement('div'); infoDiv.className = 'content-info'; infoDiv.innerHTML = `

Affichage des contenus les plus compatibles avec ${gameType}

`; grid.appendChild(infoDiv); } } catch (error) { console.error('Erreur rendu levels:', error); grid.innerHTML = '
❌ Erreur lors du chargement du contenu
'; } }, // Méthode pour afficher tout le contenu async showAllContent(gameType) { const grid = document.getElementById('levels-grid'); grid.innerHTML = ''; const availableContent = await this.contentScanner.getAvailableContent(); availableContent.forEach(content => { const card = this.createLevelCard(content.id, content, gameType); grid.appendChild(card); }); }, // Création d'une carte de niveau createLevelCard(contentKey, contentInfo, gameType) { const card = document.createElement('div'); card.className = 'level-card'; // Calculer les statistiques à afficher const stats = []; if (contentInfo.stats) { if (contentInfo.stats.vocabularyCount > 0) { stats.push(`📚 ${contentInfo.stats.vocabularyCount} mots`); } if (contentInfo.stats.sentenceCount > 0) { stats.push(`💬 ${contentInfo.stats.sentenceCount} phrases`); } if (contentInfo.stats.dialogueCount > 0) { stats.push(`🎭 ${contentInfo.stats.dialogueCount} dialogues`); } } // Indicateur de compatibilité const compatibility = contentInfo.gameCompatibility?.[gameType]; const compatScore = compatibility?.score || 0; const compatClass = compatScore > 70 ? 'high-compat' : compatScore > 40 ? 'medium-compat' : 'low-compat'; card.innerHTML = `
${contentInfo.icon}
${compatibility ? `
${compatScore > 70 ? '🟢' : compatScore > 40 ? '🟡' : '🟠'}
` : ''}
${contentInfo.name}
${contentInfo.description}
${contentInfo.difficulty} ${contentInfo.metadata.totalItems} éléments ~${contentInfo.metadata.estimatedTime}min
${stats.length > 0 ? `
${stats.join(' • ')}
` : ''} `; card.addEventListener('click', () => { Utils.animateElement(card, 'pulse'); this.navigateTo('play', gameType, contentKey); }); return card; }, // Mise à jour du breadcrumb updateBreadcrumb() { const breadcrumb = document.getElementById('breadcrumb'); breadcrumb.innerHTML = ''; const params = Utils.getUrlParams(); // Accueil const homeItem = this.createBreadcrumbItem('🏠 Accueil', 'home', this.currentPage === 'home'); breadcrumb.appendChild(homeItem); // Jeux if (['games', 'levels', 'play'].includes(this.currentPage)) { const gamesItem = this.createBreadcrumbItem('🎮 Jeux', 'games', this.currentPage === 'games'); breadcrumb.appendChild(gamesItem); } // Niveaux if (['levels', 'play'].includes(this.currentPage) && params.game) { const gameInfo = this.gamesConfig?.games[params.game]; const levelText = gameInfo ? `${gameInfo.icon} ${gameInfo.name}` : 'Niveaux'; const levelsItem = this.createBreadcrumbItem(levelText, 'levels', this.currentPage === 'levels'); breadcrumb.appendChild(levelsItem); } // Jeu en cours if (this.currentPage === 'play' && params.content) { const contentInfo = this.gamesConfig?.content[params.content]; const playText = contentInfo ? `🎯 ${contentInfo.name}` : 'Jeu'; const playItem = this.createBreadcrumbItem(playText, 'play', true); breadcrumb.appendChild(playItem); } }, // Création d'un élément breadcrumb createBreadcrumbItem(text, page, isActive) { const item = document.createElement('button'); item.className = `breadcrumb-item ${isActive ? 'active' : ''}`; item.textContent = text; item.dataset.page = page; if (!isActive) { item.addEventListener('click', () => { const params = Utils.getUrlParams(); if (page === 'home') { this.navigateTo('home'); } else if (page === 'games') { this.navigateTo('games'); } else if (page === 'levels') { this.navigateTo('levels', params.game); } }); } return item; } }; // Fonctions globales pour l'HTML window.navigateTo = (page, game, content) => AppNavigation.navigateTo(page, game, content); window.goBack = () => AppNavigation.goBack(); // Export window.AppNavigation = AppNavigation;