Acces admin par icone engrenage + mot de passe 1234

Remplace l'appui long invisible par un petit engrenage discret
dans le coin bas-droit. Clic dessus ouvre un popup de saisie
de mot de passe (1234). Icone quasi invisible (15% opacite).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 23:11:24 +01:00
parent d9de999d74
commit f9c600c026
3 changed files with 128 additions and 35 deletions

View File

@@ -94,13 +94,81 @@ html, body {
100% { transform: scale(1); opacity: 0.7; } 100% { transform: scale(1); opacity: 0.7; }
} }
/* Zone admin invisible */ /* Bouton admin discret */
.zone-admin { .btn-admin {
position: absolute; position: absolute;
bottom: 0; bottom: 12px;
right: 0; right: 12px;
width: 80px; width: 40px;
height: 80px; height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
color: rgba(255,255,255,0.15);
cursor: pointer;
border-radius: 50%;
transition: color 0.3s;
}
.btn-admin:hover, .btn-admin:active {
color: rgba(255,255,255,0.4);
}
/* Popup mot de passe */
.popup-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.popup-box {
background: var(--fond-carte);
border-radius: var(--rayon);
padding: 2rem;
min-width: 300px;
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
box-shadow: var(--ombre);
}
.popup-box h3 {
color: var(--texte);
margin: 0;
}
.popup-box input {
background: var(--fond);
border: 2px solid #333;
border-radius: 8px;
padding: 0.8rem 1.2rem;
color: var(--texte);
font-size: 1.5rem;
text-align: center;
letter-spacing: 0.3em;
width: 200px;
outline: none;
}
.popup-box input:focus {
border-color: var(--primaire);
}
.popup-actions {
display: flex;
gap: 1rem;
}
.mdp-erreur {
color: var(--danger);
font-size: 0.9rem;
} }
/* === Choix du mode === */ /* === Choix du mode === */

View File

@@ -21,8 +21,8 @@
<span id="compteur-restant">400</span> / <span id="compteur-limite">400</span> <span id="compteur-restant">400</span> / <span id="compteur-limite">400</span>
</div> </div>
</div> </div>
<!-- Zone admin : coin bas-droit, appui long 3s --> <!-- Icone admin coin bas-droit -->
<div id="zone-admin" class="zone-admin"></div> <div id="btn-admin" class="btn-admin" onclick="ouvrirAdmin()">&#9881;</div>
</section> </section>
<!-- Choix du mode --> <!-- Choix du mode -->
@@ -323,6 +323,19 @@
</div> </div>
</section> </section>
<!-- Popup mot de passe admin -->
<div id="popup-mdp" class="popup-overlay cache">
<div class="popup-box">
<h3>Acces administration</h3>
<input type="password" id="input-mdp-admin" placeholder="Mot de passe" inputmode="numeric" autocomplete="off">
<div class="popup-actions">
<button class="btn-action" onclick="validerMdpAdmin()">OK</button>
<button class="btn-secondaire" onclick="fermerPopupMdp()">Annuler</button>
</div>
<p id="mdp-erreur" class="mdp-erreur cache">Mot de passe incorrect</p>
</div>
</div>
</div> </div>
<script src="/js/websocket.js"></script> <script src="/js/websocket.js"></script>

View File

@@ -73,38 +73,50 @@ function recommencer() {
function setupEcranAccueil() { function setupEcranAccueil() {
const accueil = document.getElementById('ecran-accueil'); const accueil = document.getElementById('ecran-accueil');
// Toucher pour commencer // Toucher pour commencer (ignorer le bouton admin et le popup)
accueil.addEventListener('click', (e) => { accueil.addEventListener('click', (e) => {
// Ignorer si c'est la zone admin if (e.target.closest('.btn-admin')) return;
if (e.target.closest('.zone-admin')) return;
allerA('mode'); allerA('mode');
}); });
// Zone admin : appui long 3s
const zoneAdmin = document.getElementById('zone-admin');
let timerAdmin = null;
zoneAdmin.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
timerAdmin = setTimeout(() => allerA('admin'), 3000);
});
zoneAdmin.addEventListener('touchend', () => {
if (timerAdmin) clearTimeout(timerAdmin);
});
// Support souris aussi (pour dev)
zoneAdmin.addEventListener('mousedown', (e) => {
e.stopPropagation();
timerAdmin = setTimeout(() => allerA('admin'), 3000);
});
zoneAdmin.addEventListener('mouseup', () => {
if (timerAdmin) clearTimeout(timerAdmin);
});
} }
// --- Admin : icone + mot de passe ---
const MDP_ADMIN = '1234';
function ouvrirAdmin() {
const popup = document.getElementById('popup-mdp');
const input = document.getElementById('input-mdp-admin');
popup.classList.remove('cache');
input.value = '';
document.getElementById('mdp-erreur').classList.add('cache');
setTimeout(() => input.focus(), 100);
}
function fermerPopupMdp() {
document.getElementById('popup-mdp').classList.add('cache');
document.getElementById('input-mdp-admin').value = '';
}
function validerMdpAdmin() {
const input = document.getElementById('input-mdp-admin');
if (input.value === MDP_ADMIN) {
fermerPopupMdp();
allerA('admin');
} else {
document.getElementById('mdp-erreur').classList.remove('cache');
input.value = '';
input.focus();
}
}
// Valider avec Entree
document.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !document.getElementById('popup-mdp').classList.contains('cache')) {
validerMdpAdmin();
}
});
// --- Modes --- // --- Modes ---
function setupModes() { function setupModes() {