mise à jour

This commit is contained in:
2026-03-26 15:28:17 +01:00
parent c6954c1f50
commit 90f10674a3
7 changed files with 644 additions and 1096 deletions

View File

@@ -2,70 +2,48 @@
* ============================================
* DASHBOARD.JS - Gestion du dashboard
* Smart Parking - BTS CIEL IR
* CORRIGÉ : cancelReservation utilisait spotNumber
* au lieu de spotId pour libérer la place
* ============================================
*/
// Configuration
const API_URL = 'http://localhost:3000/api';
// État global
let dashboardState = {
user: null,
user: null,
currentPage: 'map'
};
// Initialisation
document.addEventListener('DOMContentLoaded', () => {
console.log('🚗 Initialisation du dashboard...');
// Vérifier l'authentification
checkAuthentication();
// Initialiser la navigation
initNavigation();
// Initialiser la déconnexion
initLogout();
// Charger les données utilisateur
loadUserData();
});
/**
* Vérifie que l'utilisateur est authentifié
*/
function checkAuthentication() {
const token = localStorage.getItem('smart_parking_token');
const user = localStorage.getItem('smart_parking_user');
const user = localStorage.getItem('smart_parking_user');
if (!token || !user) {
// Rediriger vers la page de connexion
window.location.href = '../index.html';
return;
}
dashboardState.user = JSON.parse(user);
}
/**
* Initialise la navigation
*/
function initNavigation() {
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const page = link.getAttribute('data-page');
navigateToPage(page);
// Mettre à jour la classe active
navLinks.forEach(l => l.classList.remove('active'));
link.classList.add('active');
});
});
// Afficher le lien admin si l'utilisateur est admin
if (dashboardState.user && dashboardState.user.role === 'admin') {
const adminLink = document.querySelector('.admin-only');
if (adminLink) {
@@ -75,25 +53,18 @@ function initNavigation() {
}
}
/**
* Navigation entre les pages
*/
function navigateToPage(page) {
// Cacher toutes les pages
const pages = document.querySelectorAll('.page');
pages.forEach(p => {
document.querySelectorAll('.page').forEach(p => {
p.classList.add('hidden');
p.classList.remove('active');
});
// Afficher la page demandée
const targetPage = document.getElementById(page);
if (targetPage) {
targetPage.classList.remove('hidden');
targetPage.classList.add('active');
dashboardState.currentPage = page;
// Rafraîchir les données selon la page
if (page === 'map' && window.ParkingMap) {
window.ParkingMap.refresh();
} else if (page === 'my-reservations') {
@@ -104,9 +75,6 @@ function navigateToPage(page) {
}
}
/**
* Initialise la déconnexion
*/
function initLogout() {
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
@@ -118,78 +86,59 @@ function initLogout() {
}
}
/**
* Charge les données utilisateur
*/
function loadUserData() {
const user = dashboardState.user;
if (!user) return;
// Mettre à jour l'affichage
document.getElementById('userName').textContent = user.name;
document.getElementById('userRole').textContent = user.role === 'admin' ? 'Administrateur' : 'Client';
// Page profil
document.getElementById('profileName').textContent = user.name;
document.getElementById('profileNameInput').value = user.name;
document.getElementById('profileEmailInput').value = user.email;
document.getElementById('profilePhoneInput').value = user.phone || '';
// Badge rôle
document.getElementById('profileName').textContent = user.name;
document.getElementById('profileNameInput').value = user.name;
document.getElementById('profileEmailInput').value = user.email;
document.getElementById('profilePhoneInput').value = user.phone || '';
const roleBadge = document.getElementById('profileRole');
if (roleBadge) {
roleBadge.textContent = user.role === 'admin' ? 'Administrateur' : 'Client';
roleBadge.className = 'role-badge ' + (user.role === 'admin' ? 'badge-admin' : 'badge-client');
roleBadge.className = 'role-badge ' + (user.role === 'admin' ? 'badge-admin' : 'badge-client');
}
// Charger les statistiques
loadUserStats();
}
/**
* Charge les statistiques utilisateur
*/
function loadUserStats() {
const reservations = JSON.parse(localStorage.getItem('smart_parking_reservations') || '[]');
const reservations = JSON.parse(localStorage.getItem('smart_parking_reservations') || '[]');
const userReservations = reservations.filter(r => r.userId === dashboardState.user.id);
const totalReservations = userReservations.length;
const activeReservations = userReservations.filter(r => r.status === 'active').length;
const totalSpent = userReservations.reduce((sum, r) => sum + (r.price || 0), 0);
document.getElementById('totalReservations').textContent = totalReservations;
document.getElementById('activeReservations').textContent = activeReservations;
document.getElementById('totalSpent').textContent = totalSpent + '€';
document.getElementById('totalReservations').textContent = userReservations.length;
document.getElementById('activeReservations').textContent = userReservations.filter(r => r.status === 'active').length;
document.getElementById('totalSpent').textContent = userReservations.reduce((s, r) => s + (r.price || 0), 0) + '€';
}
/**
* Charge les réservations de l'utilisateur
*/
function loadMyReservations() {
const container = document.getElementById('myReservationsList');
const container = document.getElementById('myReservationsList');
const emptyState = document.getElementById('noReservations');
if (!container || !emptyState) return;
const reservations = JSON.parse(localStorage.getItem('smart_parking_reservations') || '[]');
const reservations = JSON.parse(localStorage.getItem('smart_parking_reservations') || '[]');
const userReservations = reservations.filter(r => r.userId === dashboardState.user.id);
if (userReservations.length === 0) {
container.innerHTML = '';
emptyState.classList.remove('hidden');
return;
}
emptyState.classList.add('hidden');
container.innerHTML = userReservations.map(res => `
container.innerHTML = userReservations.slice().reverse().map(res => `
<div class="reservation-card">
<div class="reservation-info">
<h4>Place ${res.spotNumber}</h4>
<div class="reservation-details">
<span>📅 ${res.date}</span>
<span>🕐 ${res.startTime}</span>
<span>⏱️ ${res.duration} min</span>
<span>⏱️ ${formatDurationLabel(res.duration)}</span>
<span>🚗 ${res.vehicle || 'N/A'}</span>
</div>
</div>
@@ -207,94 +156,75 @@ function loadMyReservations() {
}
/**
* Annule une réservation
* CORRIGÉ : utilisait reservation.spotNumber (le numéro visible)
* au lieu de reservation.spotId (l'id interne), ce qui empêchait
* la place d'être libérée sur la carte.
*/
function cancelReservation(reservationId) {
if (!confirm('Êtes-vous sûr de vouloir annuler cette réservation ?')) return;
let reservations = JSON.parse(localStorage.getItem('smart_parking_reservations') || '[]');
const reservation = reservations.find(r => r.id === reservationId);
if (reservation) {
// Mettre à jour le statut
reservation.status = 'cancelled';
localStorage.setItem('smart_parking_reservations', JSON.stringify(reservations));
// Libérer la place
// CORRIGÉ : spotId au lieu de spotNumber
if (window.ParkingMap) {
window.ParkingMap.setSpotStatus(reservation.spotNumber, 'free');
window.ParkingMap.setSpotStatus(reservation.spotId, 'free');
}
showToast('Réservation annulée', 'success');
loadMyReservations();
loadUserStats();
}
}
/**
* Met à jour le profil
*/
// Mise à jour du profil
document.getElementById('profileForm')?.addEventListener('submit', (e) => {
e.preventDefault();
const phone = document.getElementById('profilePhoneInput').value;
const phone = document.getElementById('profilePhoneInput').value;
const newPassword = document.getElementById('profileNewPassword').value;
// Mettre à jour l'utilisateur
let user = dashboardState.user;
user.phone = phone;
if (newPassword) {
user.password = newPassword;
}
// Sauvegarder
if (newPassword) user.password = newPassword;
localStorage.setItem('smart_parking_user', JSON.stringify(user));
// Mettre à jour aussi dans la liste des utilisateurs
let users = JSON.parse(localStorage.getItem('smart_parking_users') || '[]');
const userIndex = users.findIndex(u => u.id === user.id);
if (userIndex !== -1) {
users[userIndex] = user;
const idx = users.findIndex(u => u.id === user.id);
if (idx !== -1) {
users[idx] = user;
localStorage.setItem('smart_parking_users', JSON.stringify(users));
}
showToast('Profil mis à jour', 'success');
});
/**
* Retourne le label du statut
*/
function getStatusLabel(status) {
const labels = {
'active': 'Active',
'completed': 'Terminée',
'cancelled': 'Annulée'
};
return labels[status] || status;
return { active: 'Active', completed: 'Terminée', cancelled: 'Annulée' }[status] || status;
}
function formatDurationLabel(minutes) {
if (minutes >= 480) return 'Journée';
if (minutes >= 60) return Math.floor(minutes / 60) + 'h' + (minutes % 60 ? (minutes % 60) + 'min' : '');
return minutes + ' min';
}
/**
* Affiche une notification toast
*/
function showToast(message, type = 'info') {
const container = document.getElementById('toastContainer');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
container.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
setTimeout(() => toast.remove(), 3000);
}
// Exporter les fonctions
window.Dashboard = {
navigateToPage,
showToast,
getUser: () => dashboardState.user,
getUser: () => dashboardState.user,
refreshStats: loadUserStats
};
};