let links = [];
let groups = [];
let editingId = null;
let studentsLoaded = false;
let linkSettings = null;
let linkPage = 1;
const LINK_PAGE_SIZE = 20;
async function loadLinkSettings() {
if (!linkSettings) {
const res = await fetch(`${API}/api/settings`, { headers: hdr() });
linkSettings = await res.json().catch(() => ({}));
}
return linkSettings;
}
function linkUrl(token) { return `${location.origin}/s/${token}`; }
async function loadLinks() {
await loadLinkSettings();
const p = new URLSearchParams();
p.set('limit', LINK_PAGE_SIZE);
p.set('offset', (linkPage - 1) * LINK_PAGE_SIZE);
const res = await fetch(`${API}/api/links?${p}`, { headers: hdr() });
const data = await res.json();
links = data.items;
const total = data.total;
const el = document.getElementById('linksList');
if (!links.length) { el.innerHTML = `
${linkPage > 1 ? 'На этой странице ссылок нет.' : 'Ссылок пока нет. Создайте её в Журнале кнопкой «Ссылка».'}
`; renderPager(document.getElementById('pager'), 1, 1, goLinkPage); return; }
const now = Date.now();
el.innerHTML = links.map(l => {
const namesHidden = l.show_student_names != null ? !l.show_student_names : linkSettings.share_show_student_names === 'false';
const expired = l.expires_at && new Date(l.expires_at).getTime() < now;
const daysLeft = l.expires_at ? Math.ceil((new Date(l.expires_at).getTime() - now) / 86400000) : null;
const soon = !expired && daysLeft !== null && daysLeft <= 1;
return `
${esc(l.name)}${expired ? ' истекла' : soon ? ' истекает' : ''}
${l.group_name ? `Группа: ${esc(l.group_name)}` : ''}
${l.student_name ? `${l.group_name ? ' · ' : ''}Ученик: ${esc(l.student_name)}` : ''}
${l.date_from || l.date_to ? ` · период: ${l.date_from ? l.date_from.split('-').reverse().join('.') : '…'} — ${l.date_to ? l.date_to.split('-').reverse().join('.') : '…'}` : ' · весь период'}
${expired ? ` · срок действия истёк ${fmtDateFull(l.expires_at)}` : l.expires_at ? ` · истекает ${fmtDateFull(l.expires_at)}` : ''}
${namesHidden ? ` · имена скрыты` : ''}
${l.access_password_hash ? ` · 🔒 пароль` : ''}
· создана ${fmtFull(l.created_at)}
`;}).join('');
renderPager(document.getElementById('pager'), linkPage, Math.max(1, Math.ceil(total / LINK_PAGE_SIZE)), goLinkPage);
}
function goLinkPage(p) {
linkPage = p;
loadLinks();
}
function fmtDate(d) { const [y, m, day] = (d || '').split('-'); return d ? `${day}.${m}.${y}` : ''; }
async function openLinkModal() {
editingId = null;
document.getElementById('linkModalTitle').textContent = 'Новая ссылка';
document.getElementById('linkName').value = '';
document.getElementById('linkDateFrom').value = '';
document.getElementById('linkDateTo').value = '';
document.getElementById('linkExpiresDays').value = '7';
document.getElementById('linkShowNames').checked = false;
document.getElementById('linkPassword').value = '';
document.getElementById('linkMessage').value = '';
document.getElementById('linkUrl').value = '';
const s = await loadLinkSettings();
document.getElementById('linkShowNames').checked = s.share_show_student_names !== 'false';
document.getElementById('linkShowMessage').checked = s.share_show_student_message === 'true';
document.getElementById('linkShowDate').checked = s.share_show_entry_date === 'true';
document.getElementById('linkShowPhotos').checked = s.share_show_group_photos !== 'false';
if (!groups.length) {
const res = await fetch(`${API}/api/groups`, { headers: hdr() });
groups = await res.json();
document.getElementById('linkGroup').innerHTML = '' +
groups.map(g => ``).join('');
}
if (!studentsLoaded) {
const res = await fetch(`${API}/api/students/names`, { headers: hdr() });
const names = await res.json();
const dl = document.getElementById('linkStudentList');
dl.innerHTML = names.map(n => `' +
groups.map(g => ``).join('');
}
document.getElementById('linkGroup').value = l.group_id || '';
if (!studentsLoaded) {
const res = await fetch(`${API}/api/students/names`, { headers: hdr() });
const names = await res.json();
const dl = document.getElementById('linkStudentList');
dl.innerHTML = names.map(n => `