mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
Merge feat/w-d-mental-wellbeing into release/v1.27.6
The Vorsorge card resolves both rules at once: the action button keeps its constant look in every state (v1.27.5), and a screening reminder's action reads 'start the check-in' instead of the numeric measure wording (this wave).
This commit is contained in:
commit
f1e5df52ab
28 files changed
+657
-886
No files matched your search
@@ -14,7 +14,7 @@ import {
|
||||
describe("measurementReminderTypeEnum (V3 — completeness)", () => {
|
||||
const allowed = measurementReminderTypeEnum.options;
|
||||
|
||||
it("exposes the full active set: vitals + body composition", () => {
|
||||
it("exposes the full active set: vitals + body composition + screenings", () => {
|
||||
expect(new Set(allowed)).toEqual(
|
||||
new Set([
|
||||
// Vitals
|
||||
@@ -34,10 +34,22 @@ describe("measurementReminderTypeEnum (V3 — completeness)", () => {
|
||||
"TOTAL_BODY_WATER",
|
||||
"VISCERAL_FAT",
|
||||
"BODY_MASS_INDEX",
|
||||
// v1.27.6 — plannable mental-wellbeing screenings
|
||||
"PHQ9_SCORE",
|
||||
"GAD7_SCORE",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("accepts a plannable screening reminder with the 4-week default cadence", () => {
|
||||
const parsed = createMeasurementReminderSchema.safeParse({
|
||||
label: "PHQ-9 Check-in",
|
||||
measurementType: "PHQ9_SCORE",
|
||||
intervalDays: 28,
|
||||
});
|
||||
expect(parsed.success).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts a newly-added body-composition type on create", () => {
|
||||
const parsed = createMeasurementReminderSchema.safeParse({
|
||||
label: "Körperzusammensetzung messen",
|
||||
|
||||
@@ -470,6 +470,24 @@ describe("measurement validation", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects a COMPUTED-attributed screener score row on a client write", () => {
|
||||
// v1.27.6 — the mental-wellbeing screener projects each completed
|
||||
// administration onto a COMPUTED-source PHQ9_SCORE / GAD7_SCORE row
|
||||
// (the RECOVERY_SCORE precedent). COMPUTED is not client-attributable,
|
||||
// so a client can never mint a server-owned score trend point.
|
||||
for (const type of ["PHQ9_SCORE", "GAD7_SCORE"]) {
|
||||
const parsed = createMeasurementSchema.safeParse({
|
||||
type,
|
||||
value: 5,
|
||||
measuredAt: "2026-06-02T12:00:00Z",
|
||||
source: "COMPUTED",
|
||||
});
|
||||
expect(parsed.success, `expected COMPUTED ${type} to be rejected`).toBe(
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("accepts the client-writable sources MANUAL and APPLE_HEALTH", () => {
|
||||
for (const source of ["MANUAL", "APPLE_HEALTH"]) {
|
||||
const parsed = createMeasurementSchema.safeParse({
|
||||
|
||||
@@ -56,17 +56,44 @@ export const measurementReminderTypeEnum = z
|
||||
"TOTAL_BODY_WATER",
|
||||
"VISCERAL_FAT",
|
||||
"BODY_MASS_INDEX",
|
||||
// v1.27.6 — the mental-wellbeing screeners become plannable Vorsorge
|
||||
// items. Not a passive wearable score: a screening is an active "go and
|
||||
// do it" action exactly like stepping on the scale. Auto-resolves from
|
||||
// the server-owned COMPUTED PHQ9_SCORE / GAD7_SCORE row the assessment
|
||||
// route writes on completion. Gated on the opt-in mentalHealth module in
|
||||
// the dispatcher (see `moduleForMeasurementType`).
|
||||
"PHQ9_SCORE",
|
||||
"GAD7_SCORE",
|
||||
])
|
||||
.meta({
|
||||
id: "MeasurementReminderType",
|
||||
description:
|
||||
"Auto-resolve target metric (vitals + body-composition family). BP resolves on BLOOD_PRESSURE_SYS (the SYS row is the 'a BP was measured' sentinel). Omit for a free-text Vorsorge that resolves only on a manual satisfy or a matching lab result.",
|
||||
"Auto-resolve target metric (vitals + body-composition family + the PHQ-9 / GAD-7 screenings). BP resolves on BLOOD_PRESSURE_SYS (the SYS row is the 'a BP was measured' sentinel); a screening reminder resolves on the server-written PHQ9_SCORE / GAD7_SCORE row when a check-in completes. Omit for a free-text Vorsorge that resolves only on a manual satisfy or a matching lab result.",
|
||||
});
|
||||
|
||||
export type MeasurementReminderType = z.infer<
|
||||
typeof measurementReminderTypeEnum
|
||||
>;
|
||||
|
||||
/**
|
||||
* v1.27.6 — the reminder types that are SCREENINGS, not numeric readings.
|
||||
* Every surface with a per-reminder primary action branches on this: a
|
||||
* screening routes to the check-in page (`/mental-wellbeing`) instead of
|
||||
* opening the numeric MeasurementForm — a score is never typed in, it
|
||||
* falls out of a completed test (which then auto-satisfies the reminder).
|
||||
*/
|
||||
export const SCREENING_REMINDER_TYPES: ReadonlySet<string> = new Set([
|
||||
"PHQ9_SCORE",
|
||||
"GAD7_SCORE",
|
||||
]);
|
||||
|
||||
/** Whether a reminder's `measurementType` targets a screening check-in. */
|
||||
export function isScreeningReminderType(
|
||||
type: string | null | undefined,
|
||||
): boolean {
|
||||
return type != null && SCREENING_REMINDER_TYPES.has(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC-5545 RRULE guard. The recurrence engine parses it; here we only
|
||||
* bound the length and require the `FREQ=` token so a typo doesn't reach
|
||||
|
||||
Reference in new issue
Block a user