516 lines
19 KiB
JavaScript
Raw Normal View History

2025-03-09 16:15:31 +01:00
// Variables globales
let monsters = [];
let quests = [];
let announcements = [];
// Éléments DOM pour les onglets
const announcementsTab = document.getElementById('announcementsTab');
const monstersTab = document.getElementById('monstersTab');
const maintenanceTab = document.getElementById('maintenanceTab');
const sectionsEls = document.querySelectorAll('.admin-section');
// Éléments DOM pour les annonces
const announcementsListEl = document.getElementById('announcementsList');
const emptyAnnouncementsMessageEl = document.getElementById('emptyAnnouncementsMessage');
const addAnnouncementBtn = document.getElementById('addAnnouncementBtn');
const announcementForm = document.getElementById('announcementForm');
const announcementIdEl = document.getElementById('announcementId');
const announcementTextEl = document.getElementById('announcementText');
const announcementActiveEl = document.getElementById('announcementActive');
const announcementModalTitleEl = document.getElementById('announcementModalTitle');
// Éléments DOM pour les monstres
const monstersListEl = document.getElementById('monstersList');
const emptyMonstersMessageEl = document.getElementById('emptyMonstersMessage');
const addMonsterBtn = document.getElementById('addMonsterBtn');
const monsterForm = document.getElementById('monsterForm');
const monsterIdEl = document.getElementById('monsterId');
const monsterNameEl = document.getElementById('monsterName');
const monsterImageEl = document.getElementById('monsterImage');
const monsterModalTitleEl = document.getElementById('monsterModalTitle');
// Éléments DOM pour la maintenance
const cleanOldQuestsBtn = document.getElementById('cleanOldQuestsBtn');
const cleanResultEl = document.getElementById('cleanResult');
const totalMonstersCountEl = document.getElementById('totalMonstersCount');
const totalQuestsCountEl = document.getElementById('totalQuestsCount');
const smallCrownQuestsCountEl = document.getElementById('smallCrownQuestsCount');
const largeCrownQuestsCountEl = document.getElementById('largeCrownQuestsCount');
// Éléments DOM pour la confirmation de suppression
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
const confirmDeleteMessageEl = document.getElementById('confirmDeleteMessage');
const confirmDeleteTitleEl = document.getElementById('confirmDeleteTitle');
// Modales Bootstrap
const announcementModal = new bootstrap.Modal(document.getElementById('announcementModal'));
const monsterModal = new bootstrap.Modal(document.getElementById('monsterModal'));
const confirmDeleteModal = new bootstrap.Modal(document.getElementById('confirmDeleteModal'));
// Variables pour la suppression
let currentDeletionType = null;
let currentDeletionId = null;
// Vérifier l'authentification et rediriger si nécessaire
function checkAuthentication() {
if (localStorage.getItem('admin_authenticated') !== 'true') {
window.location.href = 'login.html';
return false;
}
return true;
}
// Déconnexion
function logout() {
localStorage.removeItem('admin_authenticated');
window.location.href = 'login.html?logout=true';
}
// Initialisation
document.addEventListener('DOMContentLoaded', () => {
// Vérifier l'authentification
if (!checkAuthentication()) {
return;
}
loadData();
// Événements pour les onglets
announcementsTab.addEventListener('click', (e) => {
e.preventDefault();
showSection('announcementsSection');
});
monstersTab.addEventListener('click', (e) => {
e.preventDefault();
showSection('monstersSection');
});
maintenanceTab.addEventListener('click', (e) => {
e.preventDefault();
showSection('maintenanceSection');
updateStatistics();
});
// Événements pour les annonces
addAnnouncementBtn.addEventListener('click', () => {
resetAnnouncementForm();
announcementModalTitleEl.textContent = 'Ajouter une annonce';
announcementModal.show();
});
announcementForm.addEventListener('submit', handleSaveAnnouncement);
// Événements pour les monstres
addMonsterBtn.addEventListener('click', () => {
resetMonsterForm();
monsterModalTitleEl.textContent = 'Ajouter un monstre';
monsterModal.show();
});
monsterForm.addEventListener('submit', handleSaveMonster);
// Événements pour la maintenance
cleanOldQuestsBtn.addEventListener('click', handleCleanOldQuests);
// Événement pour la confirmation de suppression
confirmDeleteBtn.addEventListener('click', handleConfirmDelete);
// Événement pour la déconnexion
document.getElementById('logoutBtn').addEventListener('click', logout);
});
// Fonctions de chargement et sauvegarde des données
function loadData() {
// Dans une implémentation réelle, ces données seraient chargées depuis des fichiers JSON ou une API
// Pour l'instant, nous utilisons des données temporaires
monsters = [
{ id: 1, name: 'Chatacabra', image: 'img/Chatacabra.jpg' },
{ id: 2, name: 'Quematrice', image: 'img/Quematrice.jpg' },
{ id: 3, name: 'Lala Barina', image: 'img/Lala_Barina.jpg' },
{ id: 4, name: 'Congalala', image: 'img/Congalala.jpg' },
{ id: 5, name: 'Balahara', image: 'img/Balahara.jpg' },
{ id: 6, name: 'Doshaguma', image: 'img/Doshaguma.jpg' },
{ id: 7, name: 'Uth Duna', image: 'img/Uth_Duna.jpg' },
{ id: 8, name: 'Rompopolo', image: 'img/Rompopolo.jpg' },
{ id: 9, name: 'Rey Dau', image: 'img/Rey_Dau.jpg' },
{ id: 10, name: 'Nerscylla', image: 'img/Nerscylla.jpg' },
{ id: 11, name: 'Hirabami', image: 'img/Hirabami.jpg' },
{ id: 12, name: 'Ajarakan', image: 'img/Ajarakan.jpg' },
{ id: 13, name: 'Nu Udra', image: 'img/Nu_Udra.jpg' },
{ id: 14, name: 'Doshaguma Gardien', image: 'img/Doshaguma_Gardien.jpg' },
{ id: 15, name: 'Rathalos Gardien', image: 'img/Rathalos_Gardien.jpg' },
{ id: 16, name: 'Jin Dahaad', image: 'img/Jin_Dahaad.jpg' },
{ id: 17, name: 'Odogaron Désastre Gardien', image: 'img/Odogaron_Desastre_Gardien.jpg' },
{ id: 18, name: 'Xu Wu', image: 'img/Xu_Wu.jpg' },
{ id: 19, name: 'Arkveld Gardien', image: 'img/Arkveld_Gardien.jpg' },
{ id: 20, name: 'Zoh Shia', image: 'img/Zoh_Shia.jpg' },
{ id: 21, name: 'Yian Kut-Ku', image: 'img/Yian_Kut-Ku.jpg' },
{ id: 22, name: 'Gypceros', image: 'img/Gypceros.jpg' },
{ id: 23, name: 'Rathian', image: 'img/Rathian.jpg' },
{ id: 24, name: 'Anjanath Tonnerre Gardien', image: 'img/Anjanath_Tonnerre_Gardien.jpg' },
{ id: 25, name: 'Rathalos', image: 'img/Rathalos.jpg' },
{ id: 26, name: 'Gravios', image: 'img/Gravios.jpg' },
{ id: 27, name: 'Blangonga', image: 'img/Blangonga.jpg' },
{ id: 28, name: 'Gore Malaga', image: 'img/Gore_Malaga.jpg' },
{ id: 29, name: 'Arkveld', image: 'img/Arkveld.jpg' }
];
quests = [
{ id: 1, monsterId: 1, crownType: 'small', playerName: 'Hunter123', playerId: 'MHW-1234', date: new Date().toISOString() },
{ id: 2, monsterId: 1, crownType: 'large', playerName: 'DragonSlayer', playerId: 'MHW-5678', date: new Date().toISOString() },
{ id: 3, monsterId: 2, crownType: 'small', playerName: 'ThunderLord', playerId: 'MHW-9012', date: new Date().toISOString() }
];
announcements = [
{ id: 1, text: "Bienvenue sur le site de partage de quêtes à couronnes pour Monster Hunter Wilds!", active: true },
{ id: 2, text: "De nouveaux monstres ont été ajoutés, consultez la liste!", active: false }
];
// Essayer de charger depuis localStorage s'il y a des données
const storedMonsters = localStorage.getItem('mhw_monsters');
const storedQuests = localStorage.getItem('mhw_quests');
const storedAnnouncements = localStorage.getItem('mhw_announcements');
if (storedMonsters) monsters = JSON.parse(storedMonsters);
if (storedQuests) quests = JSON.parse(storedQuests);
if (storedAnnouncements) announcements = JSON.parse(storedAnnouncements);
renderAnnouncementsList();
renderMonstersList();
}
function saveData() {
// Dans une implémentation réelle, ces données seraient sauvegardées via une API
localStorage.setItem('mhw_monsters', JSON.stringify(monsters));
localStorage.setItem('mhw_quests', JSON.stringify(quests));
localStorage.setItem('mhw_announcements', JSON.stringify(announcements));
console.log('Données sauvegardées');
}
// Fonctions pour la navigation entre les sections
function showSection(sectionId) {
// Désactiver tous les onglets et masquer toutes les sections
document.querySelectorAll('.list-group-item').forEach(tab => {
tab.classList.remove('active');
});
sectionsEls.forEach(section => {
section.classList.add('d-none');
});
// Activer l'onglet sélectionné et afficher sa section
document.getElementById(sectionId).classList.remove('d-none');
if (sectionId === 'announcementsSection') {
announcementsTab.classList.add('active');
} else if (sectionId === 'monstersSection') {
monstersTab.classList.add('active');
} else if (sectionId === 'maintenanceSection') {
maintenanceTab.classList.add('active');
}
}
// ============ ANNONCES ============
// Rendu de la liste des annonces
function renderAnnouncementsList() {
if (announcements.length === 0) {
announcementsListEl.innerHTML = '';
emptyAnnouncementsMessageEl.classList.remove('d-none');
return;
}
emptyAnnouncementsMessageEl.classList.add('d-none');
announcementsListEl.innerHTML = announcements.map(announcement => {
const statusBadge = announcement.active
? '<span class="badge bg-success">Active</span>'
: '<span class="badge bg-secondary">Inactive</span>';
return `
<tr>
<td>${announcement.text}</td>
<td>${statusBadge}</td>
<td>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary edit-announcement-btn" data-id="${announcement.id}">
Éditer
</button>
<button class="btn btn-outline-danger delete-announcement-btn" data-id="${announcement.id}">
Supprimer
</button>
</div>
</td>
</tr>
`;
}).join('');
// Ajouter les écouteurs d'événements pour les boutons
document.querySelectorAll('.edit-announcement-btn').forEach(btn => {
btn.addEventListener('click', () => {
const announcementId = parseInt(btn.dataset.id);
editAnnouncement(announcementId);
});
});
document.querySelectorAll('.delete-announcement-btn').forEach(btn => {
btn.addEventListener('click', () => {
const announcementId = parseInt(btn.dataset.id);
showDeleteConfirmation('announcement', announcementId);
});
});
}
// Réinitialiser le formulaire d'annonce
function resetAnnouncementForm() {
announcementIdEl.value = '';
announcementTextEl.value = '';
announcementActiveEl.checked = true;
}
// Éditer une annonce
function editAnnouncement(announcementId) {
const announcement = announcements.find(a => a.id === announcementId);
if (!announcement) return;
announcementIdEl.value = announcement.id;
announcementTextEl.value = announcement.text;
announcementActiveEl.checked = announcement.active;
announcementModalTitleEl.textContent = 'Modifier l\'annonce';
announcementModal.show();
}
// Gérer la sauvegarde d'une annonce
function handleSaveAnnouncement(e) {
e.preventDefault();
const announcementId = announcementIdEl.value.trim();
const announcementText = announcementTextEl.value.trim();
const announcementActive = announcementActiveEl.checked;
if (!announcementText) {
alert('Veuillez saisir le texte de l\'annonce');
return;
}
if (announcementId) {
// Mode édition
const index = announcements.findIndex(a => a.id === parseInt(announcementId));
if (index !== -1) {
announcements[index].text = announcementText;
announcements[index].active = announcementActive;
}
} else {
// Mode ajout
const newAnnouncementId = announcements.length > 0
? Math.max(...announcements.map(a => a.id)) + 1
: 1;
announcements.push({
id: newAnnouncementId,
text: announcementText,
active: announcementActive
});
}
saveData();
renderAnnouncementsList();
announcementModal.hide();
}
// ============ MONSTRES ============
// Rendu de la liste des monstres
function renderMonstersList() {
if (monsters.length === 0) {
monstersListEl.innerHTML = '';
emptyMonstersMessageEl.classList.remove('d-none');
return;
}
emptyMonstersMessageEl.classList.add('d-none');
monstersListEl.innerHTML = monsters.map(monster => {
const questCount = quests.filter(q => q.monsterId === monster.id).length;
return `
<tr>
<td>
<img src="${monster.image}" alt="${monster.name}" class="img-thumbnail" width="80">
</td>
<td>${monster.name}</td>
<td>${questCount}</td>
<td>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary edit-monster-btn" data-id="${monster.id}">
Éditer
</button>
<button class="btn btn-outline-danger delete-monster-btn" data-id="${monster.id}">
Supprimer
</button>
</div>
</td>
</tr>
`;
}).join('');
// Ajouter les écouteurs d'événements pour les boutons
document.querySelectorAll('.edit-monster-btn').forEach(btn => {
btn.addEventListener('click', () => {
const monsterId = parseInt(btn.dataset.id);
editMonster(monsterId);
});
});
document.querySelectorAll('.delete-monster-btn').forEach(btn => {
btn.addEventListener('click', () => {
const monsterId = parseInt(btn.dataset.id);
showDeleteConfirmation('monster', monsterId);
});
});
}
// Réinitialiser le formulaire de monstre
function resetMonsterForm() {
monsterIdEl.value = '';
monsterNameEl.value = '';
monsterImageEl.value = '';
}
// Éditer un monstre
function editMonster(monsterId) {
const monster = monsters.find(m => m.id === monsterId);
if (!monster) return;
monsterIdEl.value = monster.id;
monsterNameEl.value = monster.name;
// Retirer le préfixe 'img/' pour l'affichage dans le formulaire
let imagePath = monster.image;
if (imagePath.startsWith('img/')) {
imagePath = imagePath.substring(4);
}
monsterImageEl.value = imagePath;
monsterModalTitleEl.textContent = 'Modifier le monstre';
monsterModal.show();
}
// Gérer la sauvegarde d'un monstre
function handleSaveMonster(e) {
e.preventDefault();
const monsterId = monsterIdEl.value.trim();
const monsterName = monsterNameEl.value.trim();
let monsterImage = monsterImageEl.value.trim();
// Ajouter le préfixe 'img/' si ce n'est pas déjà fait
if (!monsterImage.startsWith('img/')) {
monsterImage = 'img/' + monsterImage;
}
if (!monsterName || !monsterImage) {
alert('Veuillez remplir tous les champs');
return;
}
if (monsterId) {
// Mode édition
const index = monsters.findIndex(m => m.id === parseInt(monsterId));
if (index !== -1) {
monsters[index].name = monsterName;
monsters[index].image = monsterImage;
}
} else {
// Mode ajout
const newMonsterId = monsters.length > 0
? Math.max(...monsters.map(m => m.id)) + 1
: 1;
monsters.push({
id: newMonsterId,
name: monsterName,
image: monsterImage
});
}
saveData();
renderMonstersList();
monsterModal.hide();
}
// ============ MAINTENANCE ============
// Mettre à jour les statistiques
function updateStatistics() {
totalMonstersCountEl.textContent = monsters.length;
totalQuestsCountEl.textContent = quests.length;
smallCrownQuestsCountEl.textContent = quests.filter(q => q.crownType === 'small').length;
largeCrownQuestsCountEl.textContent = quests.filter(q => q.crownType === 'large').length;
}
// Nettoyer les quêtes anciennes
function handleCleanOldQuests() {
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();
updateStatistics();
cleanResultEl.innerHTML = `${oldQuestsCount} quête(s) supprimée(s) avec succès.`;
cleanResultEl.classList.remove('d-none');
// Masquer le message après 3 secondes
setTimeout(() => {
cleanResultEl.classList.add('d-none');
}, 3000);
}
// ============ SUPPRESSION ============
// Afficher la confirmation de suppression
function showDeleteConfirmation(type, id) {
currentDeletionType = type;
currentDeletionId = id;
if (type === 'announcement') {
confirmDeleteTitleEl.textContent = 'Supprimer l\'annonce';
confirmDeleteMessageEl.textContent = 'Êtes-vous sûr de vouloir supprimer cette annonce ?';
} else if (type === 'monster') {
const questCount = quests.filter(q => q.monsterId === id).length;
confirmDeleteTitleEl.textContent = 'Supprimer le monstre';
confirmDeleteMessageEl.textContent = `Êtes-vous sûr de vouloir supprimer ce monstre ? Cette action supprimera également ${questCount} quête(s) associée(s).`;
}
confirmDeleteModal.show();
}
// Gérer la confirmation de suppression
function handleConfirmDelete() {
if (currentDeletionType === 'announcement') {
announcements = announcements.filter(a => a.id !== currentDeletionId);
renderAnnouncementsList();
} else if (currentDeletionType === 'monster') {
monsters = monsters.filter(m => m.id !== currentDeletionId);
quests = quests.filter(q => q.monsterId !== currentDeletionId);
renderMonstersList();
}
saveData();
confirmDeleteModal.hide();
currentDeletionType = null;
currentDeletionId = null;
}