Add records, Elijah scores, per-session notes, and PWA update prompt
App features: - Personal-best records per metric: manually settable in Settings and auto-updated when a session beats them; shown in the log modal and a new dashboard "Personal records" card. - Juggling now counts by 1 instead of 5. - 1-on-1 with Elijah gains Technical Skill and Effort scores (out of 10) as manual inputs, plus an optional per-session note. - Service worker now uses a controlled update flow: an in-app "new version ready" banner activates the update on tap and reloads. Data model: - category_metrics gains track_record + record; entries gains note. - Idempotent migrations bring existing databases up to date (juggling step/record, Elijah score metrics) alongside the updated seed. StartOS package: - Bump to 0.1.2:0 with release notes. - Build x86_64 only (drop aarch64) per deployment target.
This commit is contained in:
@@ -34,9 +34,10 @@ export default async function categoryRoutes(app) {
|
||||
: [{ name: 'Minutes', unit: 'min', kind: 'duration', step: 5 }];
|
||||
list.forEach((m, i) => {
|
||||
db.prepare(
|
||||
'INSERT INTO category_metrics (category_id, name, unit, kind, step, higher_is_better, sort_order) ' +
|
||||
'VALUES (?, ?, ?, ?, ?, ?, ?)'
|
||||
).run(catId, m.name || 'Value', m.unit || '', m.kind || 'count', m.step || 1, m.higher_is_better ?? 1, i);
|
||||
'INSERT INTO category_metrics (category_id, name, unit, kind, step, higher_is_better, track_record, sort_order) ' +
|
||||
'VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
).run(catId, m.name || 'Value', m.unit || '', m.kind || 'count', m.step || 1,
|
||||
m.higher_is_better ?? 1, m.track_record ? 1 : 0, i);
|
||||
});
|
||||
return categoriesWithMetrics({ includeArchived: true }).find((c) => c.id === Number(catId));
|
||||
});
|
||||
@@ -58,17 +59,44 @@ export default async function categoryRoutes(app) {
|
||||
const id = Number(req.params.id);
|
||||
const cat = db.prepare('SELECT id FROM categories WHERE id = ?').get(id);
|
||||
if (!cat) return reply.code(404).send({ error: 'Not found' });
|
||||
const { name, unit, kind, step, higher_is_better } = req.body || {};
|
||||
const { name, unit, kind, step, higher_is_better, track_record } = req.body || {};
|
||||
const maxOrder = db.prepare(
|
||||
'SELECT COALESCE(MAX(sort_order), -1) AS m FROM category_metrics WHERE category_id = ?'
|
||||
).get(id).m;
|
||||
db.prepare(
|
||||
'INSERT INTO category_metrics (category_id, name, unit, kind, step, higher_is_better, sort_order) ' +
|
||||
'VALUES (?, ?, ?, ?, ?, ?, ?)'
|
||||
).run(id, name || 'Value', unit || '', kind || 'count', step || 1, higher_is_better ?? 1, maxOrder + 1);
|
||||
'INSERT INTO category_metrics (category_id, name, unit, kind, step, higher_is_better, track_record, sort_order) ' +
|
||||
'VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
).run(id, name || 'Value', unit || '', kind || 'count', step || 1,
|
||||
higher_is_better ?? 1, track_record ? 1 : 0, maxOrder + 1);
|
||||
return categoriesWithMetrics({ includeArchived: true }).find((c) => c.id === id);
|
||||
});
|
||||
|
||||
// Update an existing metric (step, record tracking, manual record value, etc.).
|
||||
app.put('/api/metrics/:id', async (req, reply) => {
|
||||
const id = Number(req.params.id);
|
||||
const m = db.prepare('SELECT * FROM category_metrics WHERE id = ?').get(id);
|
||||
if (!m) return reply.code(404).send({ error: 'Not found' });
|
||||
const b = req.body || {};
|
||||
// `record` may be explicitly set to null to clear it.
|
||||
const record = 'record' in b
|
||||
? (b.record === null || b.record === '' ? null : Number(b.record))
|
||||
: m.record;
|
||||
db.prepare(
|
||||
'UPDATE category_metrics SET name = ?, unit = ?, kind = ?, step = ?, ' +
|
||||
'higher_is_better = ?, track_record = ?, record = ? WHERE id = ?'
|
||||
).run(
|
||||
b.name != null ? String(b.name) : m.name,
|
||||
b.unit != null ? String(b.unit) : m.unit,
|
||||
b.kind != null ? String(b.kind) : m.kind,
|
||||
b.step != null ? Number(b.step) || 1 : m.step,
|
||||
b.higher_is_better != null ? (b.higher_is_better ? 1 : 0) : m.higher_is_better,
|
||||
b.track_record != null ? (b.track_record ? 1 : 0) : m.track_record,
|
||||
record,
|
||||
id,
|
||||
);
|
||||
return db.prepare('SELECT * FROM category_metrics WHERE id = ?').get(id);
|
||||
});
|
||||
|
||||
app.delete('/api/metrics/:id', async (req, reply) => {
|
||||
const id = Number(req.params.id);
|
||||
db.prepare('DELETE FROM category_metrics WHERE id = ?').run(id);
|
||||
|
||||
Reference in New Issue
Block a user