From 3b1341a0c2e711a9a566231f1f453380650ca7cf Mon Sep 17 00:00:00 2001 From: dev Date: Sat, 5 Sep 2026 20:26:21 +0300 Subject: [PATCH] add autocomplete input for student selection in journal filters, link creation, and links admin --- db/init.sql | 1 + db/migration.sql | 1 + public/journal.html | 34 +++++++++++++++++++++++++--------- public/links.html | 34 +++++++++++++++++++++++++++++----- server.js | 18 ++++++++++-------- 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/db/init.sql b/db/init.sql index 13dd7dd..947bc55 100644 --- a/db/init.sql +++ b/db/init.sql @@ -33,6 +33,7 @@ CREATE TABLE IF NOT EXISTS share_links ( token VARCHAR(40) UNIQUE NOT NULL, name VARCHAR(200) NOT NULL, group_id INT REFERENCES groups(id), + student_name VARCHAR(150), date_from DATE, date_to DATE, created_at TIMESTAMPTZ DEFAULT now() diff --git a/db/migration.sql b/db/migration.sql index 8343c6e..495932a 100644 --- a/db/migration.sql +++ b/db/migration.sql @@ -19,6 +19,7 @@ CREATE TABLE IF NOT EXISTS share_links ( token VARCHAR(40) UNIQUE NOT NULL, name VARCHAR(200) NOT NULL, group_id INT REFERENCES groups(id), + student_name VARCHAR(150), date_from DATE, date_to DATE, created_at TIMESTAMPTZ DEFAULT now() diff --git a/public/journal.html b/public/journal.html index 388d63a..b28dbf9 100644 --- a/public/journal.html +++ b/public/journal.html @@ -13,7 +13,7 @@

Журнал

-
+
@@ -67,6 +67,14 @@
+
+ + +
+
+ + +
@@ -184,15 +192,10 @@ async function loadGroupOptions() { async function loadStudentOptions() { if (studentsLoaded) return; - const sel = document.getElementById('studentFilter'); - while (sel.options.length > 1) sel.remove(1); + const dl = document.getElementById('studentFilterList'); const res = await fetch(`${API}/api/students/names`, { headers: hdr() }); const names = await res.json(); - names.forEach(n => { - const o = document.createElement('option'); - o.value = n; o.textContent = n; - sel.appendChild(o); - }); + dl.innerHTML = names.map(n => `
- + +
+
+ +
@@ -50,6 +54,7 @@ let links = []; let groups = []; let editingId = null; +let studentsLoaded = false; function linkUrl(token) { return `${location.origin}/s/${token}`; } @@ -63,7 +68,8 @@ async function loadLinks() {
${esc(l.name)}
- Группа: ${esc(l.group_name || '—')} + ${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('.') : '…'}` : ' · весь период'} · создана ${new Date(l.created_at).toLocaleString('ru')}
@@ -89,7 +95,15 @@ async function openLinkModal() { if (!groups.length) { const res = await fetch(`${API}/api/groups`, { headers: hdr() }); groups = await res.json(); - document.getElementById('linkGroup').innerHTML = groups.map(g => ``).join(''); + 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 => ``).join(''); + document.getElementById('linkGroup').innerHTML = '' + + 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 => `