Présence FLE · ApLenguas
📋
Nouvelle session de présence
📊
Résultats de la session
`);
}// ══════════════════════════════════════════════════════
// HELPERS
// ══════════════════════════════════════════════════════
function copyLink() {
const input = document.getElementById('qr-link-input');
navigator.clipboard.writeText(input.value)
.then(() => showAlert('✅ Lien copié !', 'success'))
.catch(() => { input.select(); document.execCommand('copy'); });
}function showAlert(msg, type='info') {
const el = document.createElement('div');
el.className = 'alert alert-' + type;
el.innerHTML = msg;
el.style.cssText = 'position:fixed;bottom:20px;right:20px;z-index:9999;max-width:360px;animation:fadeIn .3s ease';
document.body.appendChild(el);
setTimeout(() => el.remove(), 4000);
}function save() {
localStorage.setItem('apl_sessions', JSON.stringify(sessions));
localStorage.setItem('apl_attend', JSON.stringify(attendances));
}
function v(id) { return (document.getElementById(id)?.value||'').trim(); }
function validEmail(e) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e); }
function fmtDate(d) {
if (!d) return '';
const parts = d.split('-');
return `${parts[2]}/${parts[1]}/${parts[0]}`;
}
function esc(s) {
return String(s||'').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');
}
function alert2(id, msg, type) {
const el = document.getElementById(id);
if (!el) return;
el.innerHTML = `
${msg}
`;
setTimeout(()=>{ if(el) el.innerHTML=''; }, 6000);
}