idea / static /profesor-dashboard.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, 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>
<!-- LOADING SCREEN -->
<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 &mdash; <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()">&#x2715;</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 &nbsp;&mdash;&nbsp; Telenești, Moldova</div>
<div class="footer-copy">
&copy; 2026 Victor Rosca &mdash; Toate drepturile rezervate<br>
Sistem Educational de Gestiune a Fisierelor &mdash; 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);
}
// Find materie ID
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) {}
// Load students — afiseaza lista imediat, fara sa astepte Drive
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); }
// Ascunde loader-ul INTOTDEAUNA, indiferent de ce s-a intamplat
hideLoader();
// Incarca numarul de fisiere din Drive in fundal (pagina e deja vizibila)
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'; }
// Previne shortcut-uri de browser care ar putea declanșa logout accidental
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>