Spaces:
Sleeping
Sleeping
| <html lang="ro"> | |
| <head> | |
| <link rel="icon" type="image/svg+xml" href="favicon.svg"> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>VSERVERS | Seed Date</title> | |
| <link rel="stylesheet" href="style.css"> | |
| <style> | |
| body { display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:100dvh; padding:20px 14px; } | |
| .wrap { width:100%; max-width:500px; } | |
| .seed-row { display:grid; grid-template-columns:50px 1fr 90px 80px; gap:8px; padding:8px 12px; border-bottom:1px solid rgba(255,255,255,0.04); font-size:11px; align-items:center; } | |
| .seed-row.head { font-size:9px; letter-spacing:2px; color:var(--white-dim); background:rgba(255,255,255,0.03); } | |
| .seed-status { font-size:9px; padding:2px 6px; border:1px solid rgba(255,255,255,0.1); text-align:center; } | |
| .seed-status.ok { border-color:rgba(60,120,60,0.5); color:#5a9a5a; } | |
| .seed-status.err { border-color:rgba(120,40,40,0.5); color:#cc5555; } | |
| .seed-status.wait { color:var(--white-dim); } | |
| .log-box { background:rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.07); padding:14px; font-size:11px; color:var(--white-dim); line-height:2; height:140px; overflow-y:auto; margin-top:14px; font-family:'DM Mono',monospace; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrap"> | |
| <div class="login-header fade-in" style="text-align:center;margin-bottom:24px;"> | |
| <img src="logo.svg" style="width:36px;height:36px;margin:0 auto 10px;display:block;"> | |
| <h1 style="font-family:'Cormorant Garamond',serif;font-size:22px;letter-spacing:3px;">VSERVERS</h1> | |
| <p style="font-size:9px;letter-spacing:2px;color:var(--white-dim);">SEED DATE — CLASA 7B</p> | |
| </div> | |
| <div class="card fade-in-2"> | |
| <div class="card-title">Import automat elevi</div> | |
| <p style="font-size:11px;color:var(--white-dim);margin-bottom:16px;line-height:1.8;"> | |
| Această pagină va adăuga toți cei 32 de elevi ai clasei 7B în Firestore, fără parolă (pin: null). Elevii își vor seta parola la primul login. | |
| </p> | |
| <div style="margin-bottom:14px;"> | |
| <div class="field"><label>Parolă Admin (verificare)</label> | |
| <input type="password" id="admin-check" placeholder="••••••"> | |
| </div> | |
| </div> | |
| <button class="btn-primary" onclick="runSeed()" id="btn-seed">PORNEȘTE IMPORT</button> | |
| <div class="alert error" id="seed-err" style="margin-top:12px;"></div> | |
| </div> | |
| <div class="card fade-in-3" id="progress-card" style="display:none;"> | |
| <div class="card-title" id="prog-title">Se importă...</div> | |
| <div class="data-table"> | |
| <div class="seed-row head"><div>NR.</div><div>ELEV</div><div>VPASS ID</div><div>STATUS</div></div> | |
| <div id="seed-list"></div> | |
| </div> | |
| <div class="log-box" id="log-box">Inițializare...<br></div> | |
| <div class="alert success" id="seed-ok" style="margin-top:12px;display:none;"> | |
| ✓ Import finalizat! <a href="index.html" style="color:inherit;text-decoration:underline;">Mergi la login →</a> | |
| </div> | |
| </div> | |
| </div> | |
| <script type="module"> | |
| import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js"; | |
| import { getFirestore, collection, addDoc, getDocs, query, where } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-firestore.js"; | |
| const cfg = { | |
| apiKey:"AIzaSyB9--Onx3-_YjD-YzblhZjaWSVVqTQJ1lU", authDomain:"vservers1.firebaseapp.com", | |
| projectId:"vservers1", storageBucket:"vservers1.firebasestorage.app", | |
| messagingSenderId:"42433037358", appId:"1:42433037358:web:fde70fec79542428b60bbf" | |
| }; | |
| const app = initializeApp(cfg); | |
| const db = getFirestore(app); | |
| const ELEVI = [ | |
| { pozitie:1, nume:"Andronic Aniela", vpassId:"AA-0001" }, | |
| { pozitie:2, nume:"Badan Alexandra", vpassId:"BA-0002" }, | |
| { pozitie:3, nume:"Bunescu Lavinia", vpassId:"BL-0003" }, | |
| { pozitie:4, nume:"Bunescu Lorena", vpassId:"BL-0004" }, | |
| { pozitie:5, nume:"Burdujan Damian", vpassId:"BD-0005" }, | |
| { pozitie:6, nume:"Ceban Madalina", vpassId:"CM-0006" }, | |
| { pozitie:7, nume:"Ceban Valeria", vpassId:"CV-0007" }, | |
| { pozitie:8, nume:"Cebanu Nichita", vpassId:"CN-0008" }, | |
| { pozitie:9, nume:"Chele Ilinca", vpassId:"CI-0009" }, | |
| { pozitie:10, nume:"Chihai Mirela", vpassId:"CM-0010" }, | |
| { pozitie:11, nume:"Cojocari Ciprian", vpassId:"CC-0011" }, | |
| { pozitie:12, nume:"Creciun Leonard", vpassId:"CL-0012" }, | |
| { pozitie:13, nume:"Lozovan Sanda", vpassId:"LS-0013" }, | |
| { pozitie:14, nume:"Lungu Sergiu", vpassId:"LS-0014" }, | |
| { pozitie:15, nume:"Mahnea Adelina", vpassId:"MA-0015" }, | |
| { pozitie:16, nume:"Morcan Ina", vpassId:"MI-0016" }, | |
| { pozitie:17, nume:"Morcan Ion", vpassId:"MI-0017" }, | |
| { pozitie:18, nume:"Popa Cristina", vpassId:"PC-0018" }, | |
| { pozitie:19, nume:"Pricob Adelina", vpassId:"PA-0019" }, | |
| { pozitie:20, nume:"Prinos Catalina", vpassId:"PC-0020" }, | |
| { pozitie:21, nume:"Radu Daniela", vpassId:"RD-0021" }, | |
| { pozitie:22, nume:"Rosca Victor", vpassId:"RV-0022" }, | |
| { pozitie:23, nume:"Rotari Cristian", vpassId:"RC-0023" }, | |
| { pozitie:24, nume:"Rotaru Camelia", vpassId:"RC-0024" }, | |
| { pozitie:25, nume:"Sambris Stanislav", vpassId:"SS-0025" }, | |
| { pozitie:26, nume:"Sirbu Delia", vpassId:"SD-0026" }, | |
| { pozitie:27, nume:"Soltoian Elena", vpassId:"SE-0027" }, | |
| { pozitie:28, nume:"Tabuncic Chiril", vpassId:"TC-0028" }, | |
| { pozitie:29, nume:"Turcan Gabriel", vpassId:"TG-0029" }, | |
| { pozitie:30, nume:"Turcan Mihai", vpassId:"TM-0030" }, | |
| { pozitie:31, nume:"Turcanu Ilie", vpassId:"TI-0031" }, | |
| { pozitie:32, nume:"Virlan Daniela", vpassId:"VD-0032" }, | |
| ]; | |
| const ADMIN_PASS = '122012'; | |
| function log(msg) { | |
| const box = document.getElementById('log-box'); | |
| box.innerHTML += msg + '<br>'; | |
| box.scrollTop = box.scrollHeight; | |
| } | |
| function setRowStatus(idx, status, text) { | |
| const el = document.getElementById(`sr-${idx}`); | |
| if (el) { el.className = 'seed-status ' + status; el.textContent = text; } | |
| } | |
| window.runSeed = async function() { | |
| if (document.getElementById('admin-check').value !== ADMIN_PASS) { | |
| const e = document.getElementById('seed-err'); | |
| e.textContent = 'err-020 — Parolă administrator incorectă.'; | |
| e.classList.add('show'); return; | |
| } | |
| document.getElementById('seed-err').classList.remove('show'); | |
| document.getElementById('btn-seed').disabled = true; | |
| document.getElementById('progress-card').style.display = 'block'; | |
| document.getElementById('progress-card').scrollIntoView({ behavior:'smooth' }); | |
| // Render rows | |
| const list = document.getElementById('seed-list'); | |
| list.innerHTML = ELEVI.map((e,i) => ` | |
| <div class="seed-row"> | |
| <div style="color:var(--white-dim);">${String(e.pozitie).padStart(2,'0')}</div> | |
| <div style="font-size:12px;">${e.nume}</div> | |
| <div style="font-size:10px;color:var(--white-dim);letter-spacing:1px;">${e.vpassId}</div> | |
| <div><span class="seed-status wait" id="sr-${i}">—</span></div> | |
| </div>`).join(''); | |
| log('▶ Pornire import — ' + ELEVI.length + ' elevi...'); | |
| let ok = 0, skip = 0, fail = 0; | |
| for (let i = 0; i < ELEVI.length; i++) { | |
| const e = ELEVI[i]; | |
| try { | |
| // Check if exists | |
| const q = query(collection(db,'elevi'), where('vpassId','==',e.vpassId)); | |
| const existing = await getDocs(q); | |
| if (!existing.empty) { | |
| setRowStatus(i, 'ok', 'EXISTA'); | |
| log(`⚠ ${e.vpassId} — deja există, sărit`); | |
| skip++; continue; | |
| } | |
| await addDoc(collection(db,'elevi'), { | |
| nume: e.nume, | |
| vpassId: e.vpassId, | |
| pozitie: e.pozitie, | |
| pin: null, // neînregistrat | |
| confirmed: false | |
| }); | |
| setRowStatus(i, 'ok', 'OK'); | |
| log(`✓ ${e.vpassId} — ${e.nume}`); | |
| ok++; | |
| } catch(err) { | |
| setRowStatus(i, 'err', 'ERR'); | |
| log(`✗ ${e.vpassId} — err-025: ${err.message}`); | |
| fail++; | |
| } | |
| await new Promise(r => setTimeout(r, 120)); // mică pauză între scrieri | |
| } | |
| log(`\n════ FINALIZAT: ${ok} adăugați, ${skip} existenți, ${fail} erori ════`); | |
| document.getElementById('prog-title').textContent = 'Import finalizat'; | |
| document.getElementById('seed-ok').style.display = 'block'; | |
| }; | |
| </script> | |
| </body> | |
| </html> | |