Add school name, passing threshold, and week-start-day settings

- School/family name: saved to DB, appears in printed week/month report headers
- Passing grade threshold: replaces hardcoded 80% in all gradebook/history views
- Week start day (Mon vs Sun): shifts the planner 5-day grid and month view accordingly
- Settings are loaded at unlock time so they apply before any panel opens

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-08-04 14:11:23 -04:00
1 parent a10239ead9
commit 6b7b77829e
4 files changed
+120 -27

No files matched your search

+19 -2
View File
@@ -195,6 +195,8 @@ const updateCardProgress = leitnerUpdater('card_progress', 'card_id');
// Parent-only routes must send the PIN in the x-pin header
const getStoredPin = db.prepare(`SELECT value FROM settings WHERE key = 'pin'`);
const getSetting = (key) => db.prepare(`SELECT value FROM settings WHERE key = ?`).get(key)?.value;
function requirePin(req, res, next) {
const stored = getStoredPin.get().value;
if (sha256(req.get('x-pin') || '') !== stored) {
@@ -666,6 +668,23 @@ app.post('/api/parent/pin', requirePin, (req, res) => {
res.json({ ok: true });
});
app.get('/api/admin/app-settings', requirePin, (req, res) => {
res.json({
school_name: getSetting('school_name') || '',
passing_pct: Number(getSetting('passing_pct') || 80),
week_start_day: getSetting('week_start_day') || 'monday',
});
});
app.post('/api/admin/app-settings', requirePin, (req, res) => {
const { school_name, passing_pct, week_start_day } = req.body;
const upsert = (k, v) => db.prepare(`INSERT INTO settings (key,value) VALUES (?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(k, String(v));
if (school_name !== undefined) upsert('school_name', String(school_name).trim());
if (passing_pct !== undefined) upsert('passing_pct', Math.max(0, Math.min(100, Number(passing_pct))));
if (week_start_day !== undefined && ['monday', 'sunday'].includes(week_start_day)) upsert('week_start_day', week_start_day);
res.json({ ok: true });
});
app.post('/api/students', requirePin, (req, res) => {
const name = String(req.body.name || '').trim();
if (!name) return res.status(400).json({ error: 'Name required' });
@@ -1975,8 +1994,6 @@ app.get('/api/week-report/:studentId', requirePin, (req, res) => {
res.json({ student: student.name, start, tasks, graded, spellingTests });
});
const getSetting = (key) => db.prepare(`SELECT value FROM settings WHERE key = ?`).get(key)?.value;
// ---------- local TTS (Piper) ----------
app.get('/api/tts/status', (_req, res) => res.json({ available: PIPER_OK }));