← back to AbramsOS
health: lapsed-habit BP reading reminders (only nudges prior loggers, never new users)
85982870ba68133e452b37fba050b4591a222c1b · 2026-07-13 01:13:32 -0700 · Steve
- lib/vitals-reminders.js: fires 'time for a BP check' only if a person logged BP before but not in 14d; deduped via reminder engine
- reminder-engine.generateForUser hooks it in alongside returns/warranty/recall reminders
- verified: lapsed(20d)=fire, recent(2d)=skip, never-logged=skip
Files touched
M lib/reminder-engine.jsA lib/vitals-reminders.js
Diff
commit 85982870ba68133e452b37fba050b4591a222c1b
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Jul 13 01:13:32 2026 -0700
health: lapsed-habit BP reading reminders (only nudges prior loggers, never new users)
- lib/vitals-reminders.js: fires 'time for a BP check' only if a person logged BP before but not in 14d; deduped via reminder engine
- reminder-engine.generateForUser hooks it in alongside returns/warranty/recall reminders
- verified: lapsed(20d)=fire, recent(2d)=skip, never-logged=skip
---
lib/reminder-engine.js | 3 +++
lib/vitals-reminders.js | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/lib/reminder-engine.js b/lib/reminder-engine.js
index d9ef012..0021f65 100644
--- a/lib/reminder-engine.js
+++ b/lib/reminder-engine.js
@@ -140,6 +140,9 @@ async function generateForUser(userId) {
}
}
+ // Health: gentle "time for a BP check" nudge for lapsed loggers (never nags new users).
+ inserted += await require('./vitals-reminders').generateReadingReminders(userId, tryInsert);
+
return inserted;
}
diff --git a/lib/vitals-reminders.js b/lib/vitals-reminders.js
new file mode 100644
index 0000000..a176a64
--- /dev/null
+++ b/lib/vitals-reminders.js
@@ -0,0 +1,44 @@
+// vitals-reminders.js — gentle "time for a BP check" reminders.
+//
+// Design rule (don't nag about an unadopted feature): a reminder fires ONLY for a person
+// who has logged blood pressure BEFORE but not in the last N days (a lapsed habit). If they
+// have never logged a reading, no reminder. Deduped by the reminder engine, so it can't spam.
+const db = require('./db');
+
+const REMIND_AFTER_DAYS = 14;
+
+async function generateReadingReminders(userId, tryInsert) {
+ let inserted = 0;
+ const rows = (await db.query(
+ `SELECT person_id, max(measured_at) AS last, count(*)::int AS n
+ FROM health_reading WHERE user_id = $1 AND metric = 'blood_pressure'
+ GROUP BY person_id`,
+ [userId]
+ )).rows;
+
+ for (const r of rows) {
+ if (!r.n) continue; // never logged → don't nudge
+ const days = (Date.now() - new Date(r.last).getTime()) / 86400e3;
+ if (days < REMIND_AFTER_DAYS) continue; // logged recently → fine
+
+ let personName = null;
+ if (r.person_id) {
+ const p = await db.query(`SELECT full_name FROM person WHERE id = $1`, [r.person_id]);
+ personName = p.rows[0] && p.rows[0].full_name;
+ }
+ const rr = await tryInsert({
+ userId,
+ ownerTable: 'health_reading',
+ ownerId: `bp-${r.person_id || 'self'}`,
+ dueAt: new Date(),
+ reasonCode: 'bp_reading_due',
+ title: personName ? `Time for ${personName}'s blood-pressure check` : 'Time for a blood-pressure check',
+ body: `It's been ${Math.floor(days)} days since the last reading. A quick check keeps the trend meaningful.`,
+ metadata: { medical: true, person_id: r.person_id || null },
+ });
+ if (rr) inserted += 1;
+ }
+ return inserted;
+}
+
+module.exports = { generateReadingReminders, REMIND_AFTER_DAYS };
← 355389e health: BP-medication context — show active meds that raise/
·
back to AbramsOS
·
assets: net-worth tracker — enter home by address + current a78d4ae →