Azfalte · Mobilité vélo
Journée d'essai vélos
Réservez un créneau de 15 minutes pour tester un vélo à assistance électrique. 5 places disponibles par créneau.
Horaires10h00 – 14h00
Durée15 minutes / créneau
Places5 par créneau
Places disponibles
Presque complet
Complet
Retrouver ou annuler ma réservation
Entrez votre code agent pour retrouver votre créneau.
Espace organisateur
Vue d'ensemble des inscriptions — visible par toute personne accédant à cet outil.
Créneau
${left <= 0 ? 'Complet' : left + ' place' + (left>1?'s':'') + ' restante' + (left>1?'s':'')}
`;
if(left > 0){
btn.addEventListener('click', ()=>openModal(slot));
}
grid.appendChild(btn);
});
}
function openModal(slot){
currentSlot = slot;
document.getElementById('modalTime').textContent = "Créneau " + slot;
document.getElementById('modalSpots').textContent = spotsLeft(slot) + " place(s) restante(s) sur " + CAPACITY;
['fNom','fPrenom','fEmail','fTel','fId'].forEach(id=>document.getElementById(id).value='');
const msg = document.getElementById('formMsg');
msg.className = 'msg'; msg.textContent='';
document.getElementById('overlay').classList.add('show');
}
function closeModal(){
document.getElementById('overlay').classList.remove('show');
currentSlot = null;
}
function findExistingBooking(idCollab){
const norm = idCollab.trim().toLowerCase();
for(const slot of SLOTS){
const list = bookings[slot] || [];
const found = list.find(b => b.id.trim().toLowerCase() === norm);
if(found) return {slot, entry: found};
}
return null;
}
async function submitBooking(){
const nom = document.getElementById('fNom').value.trim();
const prenom = document.getElementById('fPrenom').value.trim();
const email = document.getElementById('fEmail').value.trim();
const tel = document.getElementById('fTel').value.trim();
const id = document.getElementById('fId').value.trim();
const taille = document.getElementById('fTaille').value.trim();
const msg = document.getElementById('formMsg');
if(!nom || !prenom || !email || !tel || !id || !taille){
msg.className = 'msg err show';
msg.textContent = 'Merci de remplir tous les champs.';
return;
}
await loadBookings(); // refresh in case others booked meanwhile
if(spotsLeft(currentSlot) <= 0){
msg.className = 'msg err show';
msg.textContent = 'Ce créneau vient de se remplir. Choisissez un autre créneau.';
renderGrid();
return;
}
const existing = findExistingBooking(id);
if(existing){
msg.className = 'msg err show';
msg.textContent = 'Ce code agent est déjà inscrit au créneau ' + existing.slot + '.';
return;
}
if(!bookings[currentSlot]) bookings[currentSlot] = [];
bookings[currentSlot].push({nom, prenom, email, tel, id, taille, ts: Date.now()});
try{
await saveBookings();
msg.className = 'msg ok show';
msg.textContent = 'Réservation confirmée pour ' + currentSlot + ' !';
renderGrid();
setTimeout(closeModal, 1100);
}catch(e){
msg.className = 'msg err show';
msg.textContent = "Erreur lors de l'enregistrement. Réessayez.";
}
}
async function lookupBooking(){
const id = document.getElementById('lookupId').value.trim();
const resultDiv = document.getElementById('lookupResult');
if(!id){ resultDiv.innerHTML = '
Entrez un code agent.
'; return; } await loadBookings(); const found = findExistingBooking(id); if(!found){ resultDiv.innerHTML = 'Aucune réservation trouvée pour ce code agent.
'; return; } resultDiv.innerHTML = `
Réservation trouvée : créneau ${found.slot} — ${found.entry.prenom} ${found.entry.nom}
`;
document.getElementById('cancelBookingBtn').addEventListener('click', async ()=>{
bookings[found.slot] = bookings[found.slot].filter(b => b.id.trim().toLowerCase() !== id.trim().toLowerCase());
await saveBookings();
renderGrid();
resultDiv.innerHTML = 'Réservation annulée.
'; }); } function renderAdmin(){ const wrap = document.getElementById('adminTableWrap'); const rows = []; SLOTS.forEach(slot=>{ (bookings[slot]||[]).forEach(b=>{ rows.push({slot, ...b}); }); }); if(rows.length === 0){ wrap.innerHTML = 'Aucune inscription pour le moment.
'; return; } let html = '| Créneau | Nom | Prénom | Téléphone | Code agent | Taille | ||
|---|---|---|---|---|---|---|---|
| ${r.slot} | ${escapeHtml(r.nom)} | ${escapeHtml(r.prenom)} | ${escapeHtml(r.email)} | ${escapeHtml(r.tel)} | ${escapeHtml(r.id)} | ${escapeHtml(r.taille || '')} cm | Supprimer |