| <!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, viewport-fit=cover"> |
| <title>IDEA | Profesori</title> |
| <link rel="stylesheet" href="style.css"> |
| <style> |
| /* ── LOADING SCREEN — foloseste loader-overlay din style.css ── */ |
|
|
| /* ── LIQUID GLASS TOPBAR ── */ |
| .topbar { |
| background: rgba(15,15,15,0.55) !important; |
| backdrop-filter: blur(1px) saturate(180%) !important; |
| -webkit-backdrop-filter: blur(1px) saturate(180%) !important; |
| border-bottom: 1px solid rgba(255,255,255,0.07) !important; |
| box-shadow: 0 1px 0 rgba(255,255,255,0.04), 0 4px 20px rgba(0,0,0,0.4); |
| } |
|
|
| /* ── LIQUID GLASS CARDS ── */ |
| .glass-card { |
| background: rgba(255,255,255,0.04); |
| backdrop-filter: blur(1px) saturate(160%); |
| -webkit-backdrop-filter: blur(1px) saturate(160%); |
| border: 1px solid rgba(255,255,255,0.09); |
| box-shadow: |
| 0 0 0 0.5px rgba(255,255,255,0.05) inset, |
| 0 8px 32px rgba(0,0,0,0.35), |
| 0 1px 0 rgba(255,255,255,0.06) inset; |
| } |
|
|
| /* Stats row glass */ |
| .stats-row { |
| background: transparent !important; |
| border: none !important; |
| gap: 8px !important; |
| } |
| .stat-box { |
| border-radius: 2px; |
| background: rgba(255,255,255,0.04) !important; |
| backdrop-filter: blur(1px) saturate(150%); |
| -webkit-backdrop-filter: blur(1px) saturate(150%); |
| border: 1px solid rgba(255,255,255,0.08) !important; |
| box-shadow: 0 4px 16px rgba(0,0,0,0.25), 0 1px 0 rgba(255,255,255,0.05) inset; |
| } |
|
|
| /* Table glass */ |
| .data-table { |
| background: rgba(255,255,255,0.02) !important; |
| backdrop-filter: blur(1px); |
| -webkit-backdrop-filter: blur(1px); |
| border: 1px solid rgba(255,255,255,0.07) !important; |
| box-shadow: 0 4px 24px rgba(0,0,0,0.3); |
| } |
| .dt-head { |
| background: rgba(255,255,255,0.05) !important; |
| border-bottom: 1px solid rgba(255,255,255,0.06) !important; |
| } |
| .dt-row { |
| border-bottom: 1px solid rgba(255,255,255,0.04) !important; |
| } |
| .dt-row:hover { background: rgba(255,255,255,0.04) !important; } |
|
|
| /* Drawer glass */ |
| .drawer { |
| background: rgba(255,255,255,0.03); |
| backdrop-filter: blur(1px) saturate(160%); |
| -webkit-backdrop-filter: blur(1px) saturate(160%); |
| border: 1px solid rgba(255,255,255,0.08) !important; |
| box-shadow: 0 8px 32px rgba(0,0,0,0.4); |
| } |
| .drawer-head { |
| background: rgba(255,255,255,0.05) !important; |
| border-bottom: 1px solid rgba(255,255,255,0.07) !important; |
| } |
|
|
| /* Footer glass */ |
| .footer { |
| border-top: 1px solid rgba(255,255,255,0.06) !important; |
| } |
|
|
| /* Table layout */ |
| .elev-row { grid-template-columns: 90px 1fr 56px 80px 90px; } |
| @media(max-width:560px) { |
| .elev-row { grid-template-columns: 1fr auto; } |
| .col-cnt, .col-st { display: none; } |
| } |
|
|
| /* Drawer */ |
| .drawer { display: none; margin-bottom: 16px; } |
| .drawer.show { display: block; } |
| .drawer-head { padding: 13px 14px; display: flex; align-items: center; gap: 12px; } |
| .drawer-head h4 { font-family: 'Cormorant Garamond', serif; font-size: 17px; font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
| .drawer-sub { font-size: 10px; color: var(--white-dim); letter-spacing: 1px; white-space: nowrap; } |
| .drawer-close { cursor: pointer; color: var(--white-dim); font-size: 18px; transition: color 0.15s; flex-shrink: 0; padding: 2px; } |
| .drawer-close:hover { color: #cc5555; } |
| .drawer-body { padding: 16px 14px; } |
| .no-files { font-size: 11px; color: var(--white-dim); letter-spacing: 1px; padding: 4px 0; } |
|
|
| /* File row in drawer */ |
| .file-row { |
| background: rgba(255,255,255,0.03); |
| border: 1px solid rgba(255,255,255,0.07) !important; |
| } |
| .file-row:hover { background: rgba(255,255,255,0.06) !important; border-color: rgba(255,255,255,0.12) !important; } |
| </style> |
| <script>if(localStorage.getItem('idea_maintenance')==='1'){window.location.replace('503.html');}</script> |
| </head> |
| <body> |
|
|
| |
| <div class="loader-overlay" id="loading-screen"> |
| <div class="loader"><div class="inner one"></div><div class="inner two"></div><div class="inner three"></div></div> |
| <div class="loader-text" id="load-status">SE ÎNCARCĂ</div> |
| </div> |
|
|
| <div class="topbar"> |
| <a href="index.html" class="topbar-logo"> |
| <img src="logo.svg" alt="IDEA"> |
| <span class="topbar-name">IDEA</span> |
| </a> |
| <div class="topbar-divider"></div> |
| <span class="topbar-section" id="tb-name">—</span> |
| <div class="topbar-right"> |
| <span class="role-tag">PROF</span> |
| <span class="role-tag" id="tb-mat" style="color:var(--white);">—</span> |
| <button class="btn-ghost" onclick="logout()">Ieșire</button> |
| </div> |
| </div> |
|
|
| <div class="main"> |
|
|
| <div class="stats-row fade-in"> |
| <div class="stat-box"> |
| <div class="stat-num" id="sn" style="font-size:14px;padding-top:5px;">—</div> |
| <div class="stat-lbl">PROFESOR</div> |
| </div> |
| <div class="stat-box"> |
| <div class="stat-num" id="sm" style="font-size:16px;">—</div> |
| <div class="stat-lbl">MATERIE</div> |
| </div> |
| <div class="stat-box"> |
| <div class="stat-num" id="s-elevi">0</div> |
| <div class="stat-lbl">ELEVI</div> |
| </div> |
| <div class="stat-box"> |
| <div class="stat-num" id="s-files">0</div> |
| <div class="stat-lbl">FISIERE</div> |
| </div> |
| </div> |
|
|
| <div class="label fade-in-2">Registrul clasei — <span id="lbl-mat" style="color:var(--white);">—</span></div> |
|
|
| <div class="data-table fade-in-2"> |
| <div class="dt-head elev-row"> |
| <div>VPASS ID</div><div>ELEV</div> |
| <div class="col-cnt" style="text-align:center;">FIS.</div> |
| <div class="col-st">STATUS</div> |
| <div>ACTIUNI</div> |
| </div> |
| <div id="students-list"> |
| <div style="padding:20px 14px;font-size:11px;color:var(--white-dim);">Se incarca...</div> |
| </div> |
| </div> |
|
|
| <div class="drawer" id="drawer"> |
| <div class="drawer-head"> |
| <h4 id="d-name">—</h4> |
| <span class="drawer-sub" id="d-vpass">—</span> |
| <span class="drawer-close" onclick="closeDrawer()">✕</span> |
| </div> |
| <div class="drawer-body" id="d-body"> |
| <div class="no-files">Se incarca fisierele...</div> |
| </div> |
| </div> |
|
|
| <footer class="footer"> |
| <div class="footer-top"> |
| <img src="logo.svg" alt=""> |
| <span>IDEA</span> |
| </div> |
| <div class="footer-divider"></div> |
| <div class="footer-meta">93.117.161.226 — Telenești, Moldova</div> |
| <div class="footer-copy"> |
| © 2026 Victor Rosca — Toate drepturile rezervate<br> |
| Sistem Educational de Gestiune a Fisierelor — v1.0 |
| </div> |
| </footer> |
|
|
| </div> |
|
|
| <script type="module"> |
| import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js"; |
| import { getFirestore, collection, getDocs } 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" |
| }; |
| |
| if (sessionStorage.getItem('vs_role') !== 'profesor') { window.location.href = 'index.html'; } |
| |
| const app = initializeApp(cfg); |
| const db = getFirestore(app); |
| |
| const name = sessionStorage.getItem('vs_name') || '—'; |
| const materie = sessionStorage.getItem('vs_materie') || '—'; |
| |
| document.getElementById('tb-name').textContent = name; |
| document.getElementById('tb-mat').textContent = materie; |
| document.getElementById('sn').textContent = name; |
| document.getElementById('sm').textContent = materie; |
| document.getElementById('lbl-mat').textContent = materie; |
| |
| function setStatus(msg) { |
| document.getElementById('load-status').textContent = msg; |
| } |
| |
| function hideLoader() { |
| const el = document.getElementById('loading-screen'); |
| el.classList.add('hide'); |
| setTimeout(() => el.remove(), 600); |
| } |
| |
| |
| setStatus('Se cauta materia...'); |
| let materieId = ''; |
| try { |
| const mSnap = await getDocs(collection(db, 'materii')); |
| mSnap.forEach(d => { if (d.data().nume === materie) materieId = d.id; }); |
| } catch(e) {} |
| |
| |
| setStatus('Se incarca elevii...'); |
| let elevii = []; |
| try { |
| const snap = await getDocs(collection(db, 'elevi')); |
| snap.forEach(d => elevii.push({ id: d.id, ...d.data() })); |
| elevii.sort((a, b) => (a.pozitie || 0) - (b.pozitie || 0)); |
| |
| const list = document.getElementById('students-list'); list.innerHTML = ''; |
| if (!elevii.length) { |
| list.innerHTML = '<div style="padding:16px 14px;font-size:11px;color:var(--white-dim);">Niciun elev inregistrat.</div>'; |
| } else { |
| elevii.forEach(e => { |
| const row = document.createElement('div'); row.className = 'dt-row elev-row'; |
| row.innerHTML = ` |
| <div style="font-size:10px;color:var(--white-dim);letter-spacing:1px;">${e.vpassId||'—'}</div> |
| <div style="font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${e.nume}</div> |
| <div class="col-cnt" id="cnt-${e.id}" style="text-align:center;font-size:12px;color:var(--white-faint);">—</div> |
| <div class="col-st"><span class="pill empty" id="pill-${e.id}">ASTEPT</span></div> |
| <div><button class="btn-outline" style="font-size:9px;padding:4px 10px;">VIZUALIZ.</button></div>`; |
| row.querySelector('button').onclick = () => openDrawer(e.vpassId||e.id, e.vpassId||e.id, e.nume, materie, materie); |
| list.appendChild(row); |
| }); |
| document.getElementById('s-elevi').textContent = elevii.length; |
| } |
| } catch(e) { console.error(e); } |
| |
| |
| hideLoader(); |
| |
| |
| if (materieId && elevii.length) { |
| let totalFiles = 0; |
| for (const e of elevii) { |
| try { |
| const r = await fetch(`/drive/list?elevId=${encodeURIComponent(e.vpassId||e.id)}&materieId=${encodeURIComponent(materie)}`); |
| const data = await r.json(); |
| const cnt = (data.files || []).length; |
| totalFiles += cnt; |
| const cntEl = document.getElementById(`cnt-${e.id}`); |
| const pillEl = document.getElementById(`pill-${e.id}`); |
| if (cntEl) { cntEl.textContent = cnt; cntEl.style.color = cnt > 0 ? 'var(--white)' : 'var(--white-faint)'; } |
| if (pillEl) { pillEl.textContent = cnt > 0 ? 'TRIMIS' : 'ASTEPT'; pillEl.className = `pill ${cnt > 0 ? 'success' : 'empty'}`; } |
| } catch(err) {} |
| } |
| document.getElementById('s-files').textContent = totalFiles; |
| } |
| |
| async function openDrawer(elevId, vpassId, elevNume, materieId, materie) { |
| document.getElementById('d-name').textContent = elevNume; |
| document.getElementById('d-vpass').textContent = vpassId + ' · ' + materie; |
| const drawer = document.getElementById('drawer'); |
| drawer.classList.add('show'); |
| drawer.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); |
| const body = document.getElementById('d-body'); |
| body.innerHTML = '<div class="no-files">Se incarca...</div>'; |
| if (!materieId) { body.innerHTML = '<div class="no-files">Materie neconfigurată.</div>'; return; } |
| try { |
| if (!materieId) { body.innerHTML = '<div class="no-files">Materie neconfigurată.</div>'; return; } |
| const r = await fetch(`/drive/list?elevId=${encodeURIComponent(elevId)}&materieId=${encodeURIComponent(materie)}`); |
| const data = await r.json(); |
| const files = data.files || []; |
| if (!files.length) { body.innerHTML = '<div class="no-files">Niciun fisier pentru aceasta materie.</div>'; return; } |
| body.innerHTML = ''; |
| files.forEach(f => { |
| const row = document.createElement('div'); row.className = 'file-row'; |
| row.innerHTML = ` |
| <svg class="fr-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"> |
| <path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"/><polyline points="13 2 13 9 20 9"/> |
| </svg> |
| <span class="fr-name">${f.name}</span> |
| <span class="fr-meta">${f.size ? (parseInt(f.size)/1024/1024).toFixed(1)+' MB' : materie}</span> |
| <div style="display:flex;gap:6px;"> |
| <a href="${f.url || '/drive/download/'+encodeURIComponent(f.id)}" target="_blank" class="btn-outline" style="font-size:9px;padding:4px 10px;text-decoration:none;">DESCARCĂ</a> |
| <button class="btn-outline" style="font-size:9px;padding:4px 10px;color:#cc5555;border-color:rgba(200,80,80,0.3);" onclick="deleteFileProf('${f.id}', this, '${elevId}', '${materieId}', '${materie}', '${elevNume}')">ȘTERGE</button> |
| </div>`; |
| body.appendChild(row); |
| }); |
| } catch(e) { body.innerHTML = '<div class="no-files">Eroare la incarcare.</div>'; } |
| } |
| |
| window.openDrawer = openDrawer; |
| |
| window.deleteFileProf = async function(fileId, btn, elevId, materieId, materie, elevNume) { |
| if (!confirm(`Ștergi fișierul lui ${elevNume}?`)) return; |
| btn.disabled = true; btn.textContent = '...'; |
| try { |
| const r = await fetch(`/drive/delete/${fileId}`, { method: 'DELETE' }); |
| if (r.ok) { openDrawer(elevId, elevId, elevNume, materieId, materie); } |
| else { btn.disabled = false; btn.textContent = 'ȘTERGE'; alert('Eroare la ștergere.'); } |
| } catch(e) { btn.disabled = false; btn.textContent = 'ȘTERGE'; } |
| }; |
| </script> |
| <script> |
| function closeDrawer() { document.getElementById('drawer').classList.remove('show'); } |
| function logout() { sessionStorage.clear(); window.location.href = 'index.html'; } |
| |
| document.addEventListener('keydown', e => { |
| if (e.ctrlKey && (e.key === 'e' || e.key === 'E')) { e.preventDefault(); } |
| }); |
| </script> |
| <a href="vhelp.html" class="vhelp-fab" title="VHelp"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.9)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/> |
| <circle cx="9" cy="10" r="0.5" fill="rgba(255,255,255,0.9)"/> |
| <circle cx="12" cy="10" r="0.5" fill="rgba(255,255,255,0.9)"/> |
| <circle cx="15" cy="10" r="0.5" fill="rgba(255,255,255,0.9)"/> |
| </svg> |
| </a> |
| </body> |
| </html> |
|
|