function esc(s){return String(s==null?'':s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"')} function fmt(d){return d?d.split('-').reverse().join('.'):'весь период'} function showImg(src){document.getElementById('lightboxImg').src=src;document.getElementById('lightbox').classList.add('open')} function isImageFile(name){return /\.(jpe?g|png|gif|webp|bmp|avif|svg|ico)$/i.test(name||'')} function fileType(name){ if(/\.(jpe?g|png|gif|webp|bmp|avif|svg|ico)$/i.test(name||'')) return 'image'; if(/\.(mp3|wav|ogg|flac|m4a|aac|opus)$/i.test(name||'')) return 'music'; if(/\.(pptx?|odp|key)$/i.test(name||'')) return 'presentation'; if(/\.(pdf|docx?|xlsx?|txt|rtf|odt|ods|csv|md)$/i.test(name||'')) return 'document'; return 'other'; } function fileIcon(t){ const icons = {image:'🖼️',music:'🎵',presentation:'📊',document:'📄',other:'📁'}; return icons[t]||icons.other; } function filesHTML(files, password, shareToken){ if(!files||!files.length)return ''; const pw = password ? `?password=${encodeURIComponent(password)}` : ''; return `
Работы резидента
${files.map(f=>{ const t = fileType(f.name); const url = `/api/share/${shareToken}/files/${f.token}${pw}`; return ` ${fileIcon(t)} `; }).join('')}
`; } let currentToken = ''; let currentPassword = null; async function fetchShareData(token, password) { const headers = {}; if (password) headers['x-share-password'] = password; const res = await fetch('/api/share/' + token, { headers }); const data = await res.json().catch(() => ({})); return { ok: res.ok, status: res.status, data }; } async function loadShare() { const token = location.pathname.split('/').filter(Boolean).pop() || ''; currentToken = token; currentPassword = null; const tryLoad = async (pwd) => { const result = await fetchShareData(token, pwd); if (result.ok) { renderShare(result.data, pwd); return true; } if (result.status === 401 && result.data.passwordRequired) { showPasswordModal(); return false; } if (result.status === 410) { showError('Срок действия ссылки истёк'); return true; } showError('Ссылка не найдена или была удалена'); return true; }; await tryLoad(null); } function showPasswordModal() { document.getElementById('passwordInput').value = ''; document.getElementById('passwordModal').classList.add('open'); document.getElementById('passwordInput').focus(); } function hidePasswordModal() { document.getElementById('passwordModal').classList.remove('open'); } async function submitPassword() { const pwd = document.getElementById('passwordInput').value; if (!pwd) return; const result = await fetchShareData(currentToken, pwd); if (result.ok) { hidePasswordModal(); currentPassword = pwd; renderShare(result.data, pwd); } else { alert('Неверный пароль'); document.getElementById('passwordInput').value = ''; document.getElementById('passwordInput').focus(); } } function showError(msg) { document.getElementById('title').textContent = msg; document.getElementById('grid').innerHTML = `
🤔
${esc(msg)}
`; document.getElementById('photosBlock').style.display = 'none'; } function renderShare(data, password) { const heading = data.group_name || data.name || 'Записи занятий'; document.title = heading; document.getElementById('title').textContent = heading; const chips = []; if (data.group_name) chips.push(`Группа: ${esc(data.group_name)}`); if (data.date_from || data.date_to) chips.push(`Период: ${fmt(data.date_from)} — ${fmt(data.date_to)}`); document.getElementById('chips').innerHTML = chips.map(c => `${c}`).join(''); const pb = document.getElementById('photosBlock'); if (data.photos && data.photos.length) { document.getElementById('photosGrid').innerHTML = data.photos.map(p => ` ${esc(p.caption || '')} ${p.caption ? `
${esc(p.caption)}
` : ''}
`).join(''); pb.style.display = 'block'; } else { pb.style.display = 'none'; } const grid = document.getElementById('grid'); if (!data.entries.length) { grid.innerHTML = '
🎈
Записей пока нет
'; return; } const isAnonymized = data.anonymize_names; grid.innerHTML = data.entries.map(e => `
${e.photo_path ? `` : `
`}
${!isAnonymized ? `
${esc(e.student_name)}
` : ''} ${!isAnonymized && e.group_name ? `
${esc(e.group_name)}
` : ''}
${esc(e.description)}
${filesHTML(e.files, password, currentToken)}
${new Date(e.created_at).toLocaleString('ru',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'})}
`).join(''); } document.getElementById('lightbox').addEventListener('click', () => document.getElementById('lightbox').classList.remove('open')); document.getElementById('passwordModal').querySelector('button').addEventListener('click', submitPassword); document.addEventListener('click', e => { const imgEl = e.target.closest('[data-img]'); if (imgEl) { e.preventDefault(); showImg(imgEl.dataset.img); } }); (async()=>{ await loadShare(); })();