/**
* ============================================
* MAP.JS - Carte des places de parking
* Smart Parking v2.0
* MODIFIÉ : polling API toutes les 3s pour recevoir
* les mises à jour en temps réel depuis Arduino
* ============================================
*/
const MAP_CONFIG = {
totalSpots: 10,
updateInterval: 3000 // Refresh depuis l'API toutes les 3 secondes
};
let spotsState = {
spots: [],
selectedSpot: null
};
const SPOT_STATUS = { FREE: 'free', OCCUPIED: 'occupied', RESERVED: 'reserved' };
// ============================================
// INITIALISATION
// ============================================
document.addEventListener('DOMContentLoaded', () => {
console.log('🗺️ Initialisation de la carte...');
initParkingMap();
});
async function initParkingMap() {
// Essayer d'abord de charger depuis l'API (données MariaDB + Arduino)
const loaded = await loadSpotsFromAPI();
// Si pas d'API disponible, utiliser le localStorage (mode offline)
if (!loaded) {
loadSpotsFromStorage();
}
renderMap();
updateStats();
updateReservationForm();
// ⭐ Polling toutes les 3 secondes pour recevoir les updates Arduino
startAPIPolling();
}
// ============================================
// CHARGEMENT DES PLACES
// ============================================
/**
* Charge les places depuis l'API (MariaDB)
* Retourne true si succès, false si hors-ligne
*/
async function loadSpotsFromAPI() {
try {
const token = localStorage.getItem('smart_parking_token');
if (!token) return false;
const response = await fetch('/api/spots', {
headers: { 'Authorization': 'Bearer ' + token }
});
if (!response.ok) return false;
const data = await response.json();
if (!data.success || !data.data.length) return false;
// Convertir le format API → format interne
spotsState.spots = data.data.map(s => ({
id: s.id,
number: s.number,
status: s.status,
lastUpdate: s.last_update,
sensorId: s.sensor_id
}));
// Synchroniser avec localStorage pour le mode offline
saveSpots();
return true;
} catch (_err) {
// Serveur non joignable → mode offline
return false;
}
}
/**
* Charge les places depuis le localStorage (mode offline)
*/
function loadSpotsFromStorage() {
const stored = localStorage.getItem('smart_parking_spots');
if (stored) {
spotsState.spots = JSON.parse(stored);
} else {
createDefaultSpots();
}
}
function createDefaultSpots() {
spotsState.spots = [];
for (let i = 1; i <= MAP_CONFIG.totalSpots; i++) {
spotsState.spots.push({
id: i,
number: i,
status: SPOT_STATUS.FREE,
lastUpdate: new Date().toISOString(),
sensorId: `SENSOR_${String(i).padStart(3, '0')}`
});
}
saveSpots();
}
function saveSpots() {
localStorage.setItem('smart_parking_spots', JSON.stringify(spotsState.spots));
}
// ============================================
// ⭐ POLLING TEMPS RÉEL (mises à jour Arduino)
// ============================================
/**
* Interroge l'API toutes les 3 secondes.
* Si l'Arduino a changé l'état d'une place via MQTT,
* la carte se met à jour automatiquement.
*/
function startAPIPolling() {
setInterval(async () => {
const loaded = await loadSpotsFromAPI();
if (loaded) {
renderMap();
updateStats();
updateReservationForm();
// Rafraîchir les détails si une place est sélectionnée
if (spotsState.selectedSpot) {
const updated = spotsState.spots.find(s => s.id === spotsState.selectedSpot.id);
if (updated) {
spotsState.selectedSpot = updated;
showSpotDetails(updated);
}
}
}
}, MAP_CONFIG.updateInterval);
}
// ============================================
// RENDU DE LA CARTE
// ============================================
function renderMap() {
const mapContainer = document.getElementById('parkingMap');
if (!mapContainer) return;
mapContainer.innerHTML = spotsState.spots.map(spot => `