238 lines
8.1 KiB
HTML
238 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Fix Token - Tirage au Sort</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 20px;
|
|
}
|
|
.card {
|
|
background: white;
|
|
border-radius: 20px;
|
|
padding: 40px;
|
|
max-width: 600px;
|
|
width: 100%;
|
|
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
}
|
|
h1 {
|
|
font-size: 32px;
|
|
color: #333;
|
|
margin-bottom: 10px;
|
|
text-align: center;
|
|
}
|
|
.emoji {
|
|
font-size: 48px;
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
.status {
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
margin: 20px 0;
|
|
font-size: 16px;
|
|
text-align: center;
|
|
font-weight: 500;
|
|
}
|
|
.success { background: #d4edda; color: #155724; border: 2px solid #c3e6cb; }
|
|
.error { background: #f8d7da; color: #721c24; border: 2px solid #f5c6cb; }
|
|
.warning { background: #fff3cd; color: #856404; border: 2px solid #ffeeba; }
|
|
.info { background: #d1ecf1; color: #0c5460; border: 2px solid #bee5eb; }
|
|
button {
|
|
width: 100%;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
border: none;
|
|
padding: 18px;
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
border-radius: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
}
|
|
button:hover { transform: translateY(-2px); box-shadow: 0 10px 25px rgba(0,0,0,0.2); }
|
|
button:active { transform: translateY(0); }
|
|
button:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
.steps {
|
|
background: #f8f9fa;
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
margin: 20px 0;
|
|
}
|
|
.step {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 10px 0;
|
|
font-size: 14px;
|
|
}
|
|
.step-num {
|
|
background: #667eea;
|
|
color: white;
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
margin-right: 15px;
|
|
flex-shrink: 0;
|
|
}
|
|
.step.done .step-num { background: #28a745; }
|
|
.countdown {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #667eea;
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="card">
|
|
<div class="emoji" id="emoji">🔑</div>
|
|
<h1 id="title">Mise à Jour du Token</h1>
|
|
|
|
<div id="status"></div>
|
|
|
|
<div class="steps">
|
|
<div class="step" id="step1">
|
|
<div class="step-num">1</div>
|
|
<div>Suppression de l'ancien token</div>
|
|
</div>
|
|
<div class="step" id="step2">
|
|
<div class="step-num">2</div>
|
|
<div>Installation du nouveau token</div>
|
|
</div>
|
|
<div class="step" id="step3">
|
|
<div class="step-num">3</div>
|
|
<div>Vérification du token</div>
|
|
</div>
|
|
<div class="step" id="step4">
|
|
<div class="step-num">4</div>
|
|
<div>Redirection vers la page de tirage</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button id="fixBtn" onclick="fixToken()">
|
|
🚀 Corriger le Token Maintenant
|
|
</button>
|
|
</div>
|
|
|
|
<script>
|
|
const NEW_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YTIzOThkZi00NWNiLTQyOGQtOWY1ZS04YzQwNzQxNzEyNGIiLCJpYXQiOjE3NjMwODM0NjksImV4cCI6MTc2MzY4ODI2OX0.fCxlIzy-RkCqvCwjatHmIZ5pjqC61Vs-RAnZwulNd_Q';
|
|
|
|
function showStatus(message, type) {
|
|
const status = document.getElementById('status');
|
|
status.className = 'status ' + type;
|
|
status.innerHTML = message;
|
|
}
|
|
|
|
function markStepDone(stepNum) {
|
|
document.getElementById('step' + stepNum).classList.add('done');
|
|
}
|
|
|
|
async function fixToken() {
|
|
const btn = document.getElementById('fixBtn');
|
|
btn.disabled = true;
|
|
btn.textContent = '⏳ Correction en cours...';
|
|
|
|
try {
|
|
// Étape 1
|
|
showStatus('🗑️ Suppression de l\'ancien token...', 'info');
|
|
await sleep(800);
|
|
|
|
localStorage.removeItem('token');
|
|
localStorage.removeItem('user');
|
|
sessionStorage.clear();
|
|
|
|
markStepDone(1);
|
|
|
|
// Étape 2
|
|
showStatus('✏️ Installation du nouveau token...', 'info');
|
|
await sleep(800);
|
|
|
|
localStorage.setItem('token', NEW_TOKEN);
|
|
|
|
markStepDone(2);
|
|
|
|
// Étape 3
|
|
showStatus('🔍 Vérification du token...', 'info');
|
|
await sleep(800);
|
|
|
|
const savedToken = localStorage.getItem('token');
|
|
if (savedToken !== NEW_TOKEN) {
|
|
throw new Error('Le token n\'a pas été enregistré correctement');
|
|
}
|
|
|
|
markStepDone(3);
|
|
|
|
// Test de connexion au backend
|
|
try {
|
|
const response = await fetch('http://localhost:4000/api/draw/eligible-participants?minTickets=1&verified=true', {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + NEW_TOKEN
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Erreur ' + response.status + ': ' + response.statusText);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
showStatus('✅ Token installé avec succès ! ' + data.data.total + ' participants trouvés', 'success');
|
|
document.getElementById('emoji').textContent = '✅';
|
|
|
|
} catch (err) {
|
|
showStatus('⚠️ Token installé mais serveur inaccessible. Vérifiez que le backend est lancé.', 'warning');
|
|
}
|
|
|
|
markStepDone(3);
|
|
|
|
// Étape 4 - Countdown
|
|
showStatus('✅ Token installé ! Redirection dans...', 'success');
|
|
|
|
for (let i = 3; i > 0; i--) {
|
|
document.getElementById('status').innerHTML =
|
|
`✅ Token installé avec succès !<br><div class="countdown">${i}</div>`;
|
|
await sleep(1000);
|
|
}
|
|
|
|
markStepDone(4);
|
|
|
|
window.location.href = 'http://localhost:3000/admin/tirages';
|
|
|
|
} catch (error) {
|
|
showStatus('❌ Erreur : ' + error.message, 'error');
|
|
document.getElementById('emoji').textContent = '❌';
|
|
btn.disabled = false;
|
|
btn.textContent = '🔄 Réessayer';
|
|
}
|
|
}
|
|
|
|
function sleep(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
// Auto-démarrage si on est sur localhost:3000
|
|
window.addEventListener('load', () => {
|
|
if (window.location.hostname === 'localhost' && window.location.port === '3000') {
|
|
showStatus('📍 Détecté sur localhost:3000 - Prêt à corriger le token', 'info');
|
|
} else {
|
|
showStatus('⚠️ Cette page doit être ouverte depuis http://localhost:3000', 'warning');
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|