add photo placeholder, mirrored camera capture, configurable footer, and student .url zip export

This commit is contained in:
dev
2026-09-06 11:22:00 +03:00
parent 03bb23a548
commit d7a479c008
9 changed files with 130 additions and 12 deletions
+26 -1
View File
@@ -24,6 +24,25 @@
</div>
</div>
<div class="settings-card">
<h3 style="margin:0 0 8px">Футер на форме</h3>
<p class="hint" style="margin-bottom:16px">Тексты показываются внизу формы ответа ученика.</p>
<div class="settings-row">
<div>
<label for="footerLeft">Текст слева</label>
<p class="hint">Нижняя часть формы, слева</p>
</div>
<input type="text" id="footerLeft" style="width:280px;padding:10px 14px;border:1px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);font-size:.9rem" placeholder="">
</div>
<div class="settings-row" style="margin-top:16px">
<div>
<label for="footerRight">Текст справа</label>
<p class="hint">Нижняя часть формы, справа</p>
</div>
<input type="text" id="footerRight" style="width:280px;padding:10px 14px;border:1px solid var(--border);border-radius:8px;background:var(--card);color:var(--text);font-size:.9rem" placeholder="">
</div>
</div>
<div class="settings-card">
<h3 style="margin:0 0 8px">Резервная копия</h3>
<p class="hint">Скачайте архив со всеми данными (ученики, группы, журнал, настройки) и фотографиями. Восстановление полностью заменит текущие данные.</p>
@@ -43,6 +62,8 @@ async function loadSettings() {
const res = await fetch(`${API}/api/settings`, { headers: hdr() });
const s = await res.json();
if (s.spam_interval_min !== undefined) document.getElementById('spamInterval').value = s.spam_interval_min;
document.getElementById('footerLeft').value = s.footer_left || '';
document.getElementById('footerRight').value = s.footer_right || '';
}
async function saveSettings() {
@@ -51,7 +72,11 @@ async function saveSettings() {
const res = await fetch(`${API}/api/settings`, {
method: 'PUT',
headers: hdrJson(),
body: JSON.stringify({ settings: { spam_interval_min: String(Math.round(Number(v))) } })
body: JSON.stringify({ settings: {
spam_interval_min: String(Math.round(Number(v))),
footer_left: document.getElementById('footerLeft').value.trim(),
footer_right: document.getElementById('footerRight').value.trim(),
} })
});
if (res.ok) showToast('Настройки сохранены');
else { const e = await res.json(); alert(e.error); }