idea / static /seed.html
vsmdvic's picture
Upload 20 files
469a4d4 verified
<!DOCTYPE html>
<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>IDEA | 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;">IDEA</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>