prod
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test Bascule CP</title>
|
||||
<style>
|
||||
body { font-family: Arial; padding: 30px; max-width: 1000px; margin: 0 auto; background: #f9fafb; }
|
||||
h1 { color: #1e40af; }
|
||||
h2 { color: #374151; margin-top: 30px; }
|
||||
button { padding: 12px 24px; margin: 8px; border: none; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: bold; }
|
||||
.btn-verif { background: #3b82f6; color: white; }
|
||||
.btn-bascule { background: #ef4444; color: white; }
|
||||
input { padding: 10px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 14px; }
|
||||
.result-box { background: white; border: 1px solid #e5e7eb; border-radius: 8px; padding: 20px; margin-top: 15px; overflow: auto; max-height: 500px; }
|
||||
.stat { display: inline-block; background: #dbeafe; color: #1e40af; padding: 8px 16px; border-radius: 20px; margin: 4px; font-weight: bold; }
|
||||
.stat.rouge { background: #fee2e2; color: #dc2626; }
|
||||
.stat.vert { background: #dcfce7; color: #16a34a; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||||
th { background: #f3f4f6; padding: 8px; text-align: left; border-bottom: 2px solid #e5e7eb; }
|
||||
td { padding: 7px 8px; border-bottom: 1px solid #f3f4f6; }
|
||||
tr.negatif { background: #fee2e2; font-weight: bold; }
|
||||
tr.vide { background: #fef9c3; }
|
||||
.badge { padding: 3px 10px; border-radius: 12px; font-size: 12px; font-weight: bold; }
|
||||
.badge.ok { background: #dcfce7; color: #16a34a; }
|
||||
.badge.negatif { background: #fee2e2; color: #dc2626; }
|
||||
.badge.vide { background: #fef9c3; color: #92400e; }
|
||||
.warning { background: #fef3c7; border: 1px solid #f59e0b; border-radius: 8px; padding: 15px; margin: 10px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>🗓️ Test Bascule CP 31 mai 2026</h1>
|
||||
|
||||
<div>
|
||||
<label>URL du serveur dev :</label><br>
|
||||
<input type="text" id="serverUrl" value="http://localhost:3000" style="width:280px">
|
||||
<button onclick="setUrl()" style="background:#6b7280;color:white">Mettre à jour</button>
|
||||
</div>
|
||||
|
||||
<h2>Étape 1 — Vérifier l'état avant bascule</h2>
|
||||
<button class="btn-verif" onclick="verifier()">🔍 Vérifier les compteurs CP</button>
|
||||
|
||||
<h2>Étape 2 — Lancer la bascule</h2>
|
||||
<div class="warning">
|
||||
⚠️ À ne faire qu'une seule fois. En prod : le 31 mai soir uniquement.
|
||||
</div>
|
||||
<input type="password" id="secret" placeholder="Secret admin" style="width:200px">
|
||||
<button class="btn-bascule" onclick="basculer()">🔄 Lancer la bascule CP 2026 → 2027</button>
|
||||
|
||||
<h2>Étape 3 — Vérifier le résultat après bascule</h2>
|
||||
<button class="btn-verif" onclick="verifier()">✅ Revérifier les compteurs</button>
|
||||
|
||||
<div id="result" class="result-box">
|
||||
<p style="color:#9ca3af">Lance une vérification pour voir les données...</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let BASE_URL = 'http://localhost:3004';
|
||||
|
||||
function setUrl() {
|
||||
BASE_URL = document.getElementById('serverUrl').value.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
async function verifier() {
|
||||
document.getElementById('result').innerHTML = '<p>⏳ Chargement...</p>';
|
||||
try {
|
||||
const res = await fetch(`${BASE_URL}/api/admin/verif-bascule-cp`);
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.success) {
|
||||
document.getElementById('result').innerHTML = `<p style="color:red">Erreur: ${data.message}</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
const s = data.stats;
|
||||
let html = `
|
||||
<div style="margin-bottom:15px">
|
||||
<span class="stat">Total lignes: ${s.total_lignes}</span>
|
||||
<span class="stat ${s.negatifs > 0 ? 'rouge' : 'vert'}">⚠️ Négatifs: ${s.negatifs}</span>
|
||||
<span class="stat">2025: ${s.annee_2025}</span>
|
||||
<span class="stat">2026: ${s.annee_2026}</span>
|
||||
<span class="stat">2027: ${s.annee_2027}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (data.attention.length > 0) {
|
||||
html += `<p style="color:#dc2626;font-weight:bold">🚨 ${data.attention.length} compteur(s) négatif(s) :</p>`;
|
||||
html += buildTable(data.attention);
|
||||
html += `<hr style="margin:15px 0">`;
|
||||
}
|
||||
|
||||
html += `<p style="color:#374151;font-weight:bold">Tous les compteurs :</p>`;
|
||||
html += buildTable(data.data);
|
||||
|
||||
document.getElementById('result').innerHTML = html;
|
||||
|
||||
} catch (err) {
|
||||
document.getElementById('result').innerHTML =
|
||||
`<p style="color:red">❌ Erreur connexion: ${err.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function buildTable(rows) {
|
||||
let t = `<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Collaborateur</th>
|
||||
<th>Année</th>
|
||||
<th>Total acquis</th>
|
||||
<th>Solde</th>
|
||||
<th>Report</th>
|
||||
<th>État</th>
|
||||
</tr>
|
||||
</thead><tbody>`;
|
||||
|
||||
rows.forEach(r => {
|
||||
const cls = r.etat === 'NEGATIF' ? 'negatif' : r.etat === 'VIDE' ? 'vide' : '';
|
||||
const badge = `<span class="badge ${r.etat.toLowerCase()}">${r.etat}</span>`;
|
||||
t += `<tr class="${cls}">
|
||||
<td>${r.collaborateur}</td>
|
||||
<td><strong>${r.Annee}</strong></td>
|
||||
<td>${r.Total}</td>
|
||||
<td><strong>${r.Solde}</strong></td>
|
||||
<td>${r.SoldeReporte}</td>
|
||||
<td>${badge}</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
t += '</tbody></table>';
|
||||
return t;
|
||||
}
|
||||
|
||||
async function basculer() {
|
||||
const secret = document.getElementById('secret').value;
|
||||
if (!secret) { alert('Entre le secret admin'); return; }
|
||||
|
||||
if (!confirm('⚠️ Confirmes-tu le lancement de la bascule CP 2026→2027 ?\n\nCette action modifie tous les compteurs.')) return;
|
||||
|
||||
document.getElementById('result').innerHTML = '<p>⏳ Bascule en cours...</p>';
|
||||
|
||||
try {
|
||||
const res = await fetch(`${BASE_URL}/api/admin/basculement-cp-2026`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ secret })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.success) {
|
||||
document.getElementById('result').innerHTML =
|
||||
`<p style="color:red">❌ Erreur: ${data.message}</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
let html = `
|
||||
<p style="color:#16a34a;font-size:18px;font-weight:bold">
|
||||
✅ Bascule terminée — ${data.rapport.length} opérations sur ${data.total_collaborateurs} collaborateurs
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Collaborateur</th><th>Étape</th><th>Détail</th></tr>
|
||||
</thead><tbody>
|
||||
`;
|
||||
|
||||
data.rapport.forEach(r => {
|
||||
html += `<tr>
|
||||
<td>${r.collaborateur}</td>
|
||||
<td>${r.etape}</td>
|
||||
<td>${r.detail}</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
html += '</tbody></table>';
|
||||
html += `<p style="margin-top:15px;color:#374151">👆 Lance maintenant l'Étape 3 pour vérifier le résultat.</p>`;
|
||||
|
||||
document.getElementById('result').innerHTML = html;
|
||||
|
||||
} catch (err) {
|
||||
document.getElementById('result').innerHTML =
|
||||
`<p style="color:red">❌ Erreur connexion: ${err.message}</p>`;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user