// Variables globales pour les données let monsters = []; let quests = []; let announcements = []; // Éléments DOM const monsterListEl = document.getElementById('monsterList'); const modalMonsterNameEl = document.getElementById('modalMonsterName'); const questListEl = document.getElementById('questList'); const addQuestBtn = document.getElementById('addQuestBtn'); const addQuestForm = document.getElementById('addQuestForm'); const crownFilterEls = document.querySelectorAll('input[name="crownFilter"]'); const announcementAreaEl = document.getElementById('announcementArea'); const confirmDeleteBtn = document.getElementById('confirmDeleteBtn'); const monsterSearchEl = document.getElementById('monsterSearch'); const clearSearchBtn = document.getElementById('clearSearchBtn'); // Variables globales let currentMonsterId = null; let currentQuestToDelete = null; // Modales Bootstrap const questListModal = new bootstrap.Modal(document.getElementById('questListModal')); const addQuestModal = new bootstrap.Modal(document.getElementById('addQuestModal')); const deleteQuestModal = new bootstrap.Modal(document.getElementById('deleteQuestModal')); // Initialisation document.addEventListener('DOMContentLoaded', () => { loadData(); renderMonsterList(); initMonsterSearchSelect(); displayAnnouncements(); // Événements addQuestBtn.addEventListener('click', () => { resetMonsterSearchSelect(); addQuestModal.show(); }); addQuestForm.addEventListener('submit', handleAddQuest); crownFilterEls.forEach(radio => { radio.addEventListener('change', filterQuests); }); confirmDeleteBtn.addEventListener('click', handleDeleteQuest); // Événements pour la recherche monsterSearchEl.addEventListener('input', searchMonsters); clearSearchBtn.addEventListener('click', clearSearch); }); // Fonctions de chargement et sauvegarde des données function loadData() { // Vérifier si les données de jeu sont disponibles depuis data.js if (window.gameData) { // Copier les monstres depuis gameData monsters = [...window.gameData.monsters]; // Charger les quêtes depuis localStorage ou utiliser les données par défaut const storedQuests = localStorage.getItem('mhw_quests'); quests = storedQuests ? JSON.parse(storedQuests) : [...window.gameData.initialQuests]; // Charger les annonces depuis localStorage ou utiliser les données par défaut const storedAnnouncements = localStorage.getItem('mhw_announcements'); announcements = storedAnnouncements ? JSON.parse(storedAnnouncements) : [...window.gameData.initialAnnouncements]; } else { console.error("Erreur: données de jeu non disponibles. Assurez-vous que data.js est chargé avant main.js"); monsterListEl.innerHTML = `
Erreur de chargement des données. Veuillez rafraîchir la page.
`; } } function saveData() { localStorage.setItem('mhw_quests', JSON.stringify(quests)); localStorage.setItem('mhw_announcements', JSON.stringify(announcements)); console.log('Données sauvegardées'); } // Affichage des annonces function displayAnnouncements() { const activeAnnouncements = announcements.filter(a => a.active); if (activeAnnouncements.length > 0) { announcementAreaEl.innerHTML = activeAnnouncements.map(a => `

${a.text}

`).join(''); announcementAreaEl.classList.remove('d-none'); } else { announcementAreaEl.classList.add('d-none'); } } // Rendu de la liste des monstres function renderMonsterList(filteredMonsters = null) { const monstersToRender = filteredMonsters || monsters; if (monstersToRender.length === 0) { monsterListEl.innerHTML = `

Aucun monstre disponible pour le moment.

`; return; } monsterListEl.innerHTML = monstersToRender.map(monster => { const smallCrownCount = quests.filter(q => q.monsterId === monster.id && q.crownType === 'small').length; const largeCrownCount = quests.filter(q => q.monsterId === monster.id && q.crownType === 'large').length; return `
${monster.name}
${monster.name}
👑 ${smallCrownCount} 👑 ${largeCrownCount}
`; }).join(''); // Ajouter les écouteurs d'événements après avoir rendu la liste document.querySelectorAll('.monster-card').forEach(card => { card.addEventListener('click', () => { const monsterId = parseInt(card.dataset.monsterId); showQuestsForMonster(monsterId); }); }); } // Recherche de monstres sur la page principale function searchMonsters() { const searchTerm = monsterSearchEl.value.trim().toLowerCase(); if (searchTerm === '') { // Si la recherche est vide, afficher tous les monstres renderMonsterList(); return; } // Filtrer les monstres qui correspondent à la recherche const filteredMonsters = monsters.filter(monster => monster.name.toLowerCase().includes(searchTerm) ); // Afficher un message si aucun monstre ne correspond if (filteredMonsters.length === 0) { monsterListEl.innerHTML = `

Aucun monstre ne correspond à votre recherche "${monsterSearchEl.value}".

`; return; } renderMonsterList(filteredMonsters); } // Effacer la recherche function clearSearch() { monsterSearchEl.value = ''; renderMonsterList(); } // Afficher les quêtes pour un monstre spécifique function showQuestsForMonster(monsterId) { currentMonsterId = monsterId; const monster = monsters.find(m => m.id === monsterId); if (!monster) return; modalMonsterNameEl.textContent = monster.name; // Réinitialiser le filtre document.getElementById('filterAll').checked = true; // Afficher toutes les quêtes pour ce monstre renderQuestList(monsterId); // Afficher la modale questListModal.show(); } // Rendu de la liste des quêtes function renderQuestList(monsterId, filter = 'all') { let monsterQuests = quests.filter(q => q.monsterId === monsterId); if (filter !== 'all') { monsterQuests = monsterQuests.filter(q => q.crownType === filter); } if (monsterQuests.length === 0) { questListEl.innerHTML = `

Aucune quête disponible pour ce monstre avec ce filtre.

`; return; } questListEl.innerHTML = monsterQuests.map(quest => { const monster = monsters.find(m => m.id === quest.monsterId); const crownClass = quest.crownType === 'small' ? 'small-crown' : 'large-crown'; const crownText = quest.crownType === 'small' ? 'Petite couronne' : 'Grande couronne'; const questDate = new Date(quest.date); const daysDiff = Math.floor((new Date() - questDate) / (1000 * 60 * 60 * 24)); const freshness = daysDiff <= 1 ? 'Aujourd\'hui' : daysDiff <= 2 ? 'Hier' : `Il y a ${daysDiff} jours`; return `
👑 ${crownText} pour ${monster.name}

Proposée par: ${quest.playerName} (ID: ${quest.playerId})

Ajoutée: ${freshness}

`; }).join(''); // Ajouter les écouteurs d'événements pour les boutons de suppression document.querySelectorAll('.quest-delete-btn').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const questId = parseInt(btn.dataset.questId); showDeleteConfirmation(questId); }); }); } // Filtrer les quêtes function filterQuests() { const filterValue = document.querySelector('input[name="crownFilter"]:checked').value; renderQuestList(currentMonsterId, filterValue); } // Afficher la confirmation de suppression function showDeleteConfirmation(questId) { currentQuestToDelete = questId; deleteQuestModal.show(); } // Gérer la suppression d'une quête function handleDeleteQuest() { if (currentQuestToDelete === null) return; // Trouver l'index de la quête à supprimer const questIndex = quests.findIndex(q => q.id === currentQuestToDelete); if (questIndex === -1) return; // Mémoriser le monsterId pour mettre à jour l'affichage const monsterId = quests[questIndex].monsterId; // Supprimer la quête quests.splice(questIndex, 1); // Sauvegarder les données saveData(); // Mettre à jour l'affichage renderMonsterList(); // Si la modale des quêtes est ouverte, mettre à jour son contenu if (currentMonsterId === monsterId) { renderQuestList(currentMonsterId); } // Fermer la modale de confirmation deleteQuestModal.hide(); // Réinitialiser currentQuestToDelete = null; } // Initialiser le sélecteur de monstre avec recherche function initMonsterSearchSelect() { const searchInput = document.getElementById('monsterSearchSelect'); const searchResults = document.getElementById('monsterSearchResults'); const hiddenInput = document.getElementById('selectedMonsterId'); if (!searchInput || !searchResults || !hiddenInput) return; // Événement pour l'input de recherche searchInput.addEventListener('input', function() { const searchTerm = this.value.trim().toLowerCase(); // Filtrer les monstres qui correspondent à la recherche const filteredMonsters = monsters.filter(monster => monster.name.toLowerCase().includes(searchTerm) ); // Afficher les résultats renderSearchResults(filteredMonsters, searchResults); // Montrer les résultats si l'input a du contenu if (searchTerm.length > 0) { searchResults.classList.remove('d-none'); } else if (!hiddenInput.value) { // Cacher seulement si aucun monstre n'est déjà sélectionné searchResults.classList.add('d-none'); } }); // Événement pour le focus sur l'input searchInput.addEventListener('focus', function() { const searchTerm = this.value.trim().toLowerCase(); // Si l'input a du contenu ou si un monstre est déjà sélectionné, montrer les résultats if (searchTerm.length > 0 || hiddenInput.value) { // Filtrer les monstres qui correspondent à la recherche const filteredMonsters = searchTerm.length > 0 ? monsters.filter(monster => monster.name.toLowerCase().includes(searchTerm)) : monsters; // Afficher les résultats renderSearchResults(filteredMonsters, searchResults); searchResults.classList.remove('d-none'); } }); // Fermer les résultats lors d'un clic à l'extérieur document.addEventListener('click', function(e) { if (!searchInput?.contains(e.target) && !searchResults?.contains(e.target)) { searchResults?.classList.add('d-none'); } }); // Navigation avec les flèches du clavier searchInput.addEventListener('keydown', function(e) { if (searchResults.classList.contains('d-none')) return; const items = searchResults.querySelectorAll('.monster-search-item'); const activeItem = searchResults.querySelector('.monster-search-item.active'); switch(e.key) { case 'ArrowDown': e.preventDefault(); if (!activeItem) { items[0]?.classList.add('active'); ensureVisible(items[0], searchResults); } else { const nextItem = activeItem.nextElementSibling; if (nextItem) { activeItem.classList.remove('active'); nextItem.classList.add('active'); ensureVisible(nextItem, searchResults); } } break; case 'ArrowUp': e.preventDefault(); if (activeItem) { const prevItem = activeItem.previousElementSibling; if (prevItem) { activeItem.classList.remove('active'); prevItem.classList.add('active'); ensureVisible(prevItem, searchResults); } } break; case 'Enter': e.preventDefault(); if (activeItem) { const monsterId = activeItem.dataset.monsterId; selectMonster(monsterId, searchInput, hiddenInput, searchResults); } break; case 'Escape': e.preventDefault(); searchResults.classList.add('d-none'); break; } }); } // S'assurer que l'élément actif est visible dans la liste déroulante function ensureVisible(element, container) { if (!element || !container) return; const containerRect = container.getBoundingClientRect(); const elementRect = element.getBoundingClientRect(); if (elementRect.bottom > containerRect.bottom) { container.scrollTop += elementRect.bottom - containerRect.bottom; } else if (elementRect.top < containerRect.top) { container.scrollTop -= containerRect.top - elementRect.top; } } // Afficher les résultats de recherche pour le sélecteur de monstre function renderSearchResults(results, container) { if (!container) return; if (results.length === 0) { container.innerHTML = '
Aucun monstre trouvé
'; return; } container.innerHTML = results.map(monster => `
${monster.name}
` ).join(''); // Ajouter les écouteurs d'événements pour les éléments de la liste container.querySelectorAll('.monster-search-item').forEach(item => { item.addEventListener('click', function() { const monsterId = this.dataset.monsterId; const searchInput = document.getElementById('monsterSearchSelect'); const hiddenInput = document.getElementById('selectedMonsterId'); const searchResults = document.getElementById('monsterSearchResults'); selectMonster(monsterId, searchInput, hiddenInput, searchResults); }); }); } // Sélectionner un monstre dans le sélecteur function selectMonster(monsterId, searchInput, hiddenInput, searchResults) { const monster = monsters.find(m => m.id == monsterId); if (monster) { searchInput.value = monster.name; hiddenInput.value = monster.id; searchInput.classList.add('selected-monster'); searchResults.classList.add('d-none'); } } // Réinitialiser le sélecteur de monstre function resetMonsterSearchSelect() { const searchInput = document.getElementById('monsterSearchSelect'); const hiddenInput = document.getElementById('selectedMonsterId'); const searchResults = document.getElementById('monsterSearchResults'); if (searchInput) { searchInput.value = ''; searchInput.classList.remove('selected-monster'); } if (hiddenInput) { hiddenInput.value = ''; } if (searchResults) { searchResults.classList.add('d-none'); } } // Gérer l'ajout d'une quête function handleAddQuest(e) { e.preventDefault(); const monsterId = parseInt(document.getElementById('selectedMonsterId')?.value); const crownType = document.querySelector('input[name="crownType"]:checked')?.value; const playerName = document.getElementById('playerName')?.value.trim(); const playerId = document.getElementById('playerId')?.value.trim(); if (!monsterId || !crownType || !playerName || !playerId) { alert('Veuillez remplir tous les champs requis'); return; } // Générer un ID unique pour la nouvelle quête const newQuestId = quests.length > 0 ? Math.max(...quests.map(q => q.id)) + 1 : 1; // Créer la nouvelle quête const newQuest = { id: newQuestId, monsterId, crownType, playerName, playerId, date: new Date().toISOString() }; // Ajouter la quête à la liste quests.push(newQuest); // Sauvegarder les données saveData(); // Mettre à jour l'affichage renderMonsterList(); // Réinitialiser le formulaire et fermer la modale addQuestForm.reset(); resetMonsterSearchSelect(); addQuestModal.hide(); // Si la modale des quêtes est ouverte, mettre à jour son contenu if (currentMonsterId === monsterId) { renderQuestList(currentMonsterId); } } // Nettoyer les quêtes de plus de 7 jours (à appeler depuis l'admin) function cleanOldQuests() { const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const oldQuestsCount = quests.filter(q => new Date(q.date) < sevenDaysAgo).length; quests = quests.filter(q => new Date(q.date) >= sevenDaysAgo); saveData(); renderMonsterList(); return oldQuestsCount; }