mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
merge: measurement-reminder completion route
Add an idempotent, owner-scoped completion endpoint for measurement reminders that records satisfaction without firing a notification.
This commit is contained in:
commit
39505a5d35
5 files changed
+321
No files matched your search
@@ -12,6 +12,7 @@ import {
|
||||
createMeasurementReminderSchema,
|
||||
updateMeasurementReminderSchema,
|
||||
measurementReminderDto,
|
||||
measurementReminderCompletionDto,
|
||||
} from "@/lib/validations/measurement-reminders";
|
||||
import { dataEnvelope, errorEnvelope, stdResponses } from "./shared";
|
||||
|
||||
@@ -169,4 +170,29 @@ export const measurementReminderPaths: NonNullable<
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/measurement-reminders/{id}/complete": {
|
||||
post: {
|
||||
tags: ["MeasurementReminders"],
|
||||
summary: "Complete a Vorsorge reminder (v1.18.6)",
|
||||
description:
|
||||
"Explicit user-action completion (iOS #23): the app marks a reminder done server-side instead of only dismissing it locally. Routes through the same satisfaction primitive as the cron auto-resolve — stamps lastSatisfiedAt = now, re-anchors nextDueAt, fires no notification. Idempotent: completing an already-completed / auto-satisfied reminder returns 200 with completed=false. Owner-scoped.",
|
||||
requestParams: { path: z.object({ id: z.string() }) },
|
||||
responses: {
|
||||
"200": {
|
||||
description:
|
||||
"Completion applied (completed=true) or already-satisfied no-op (completed=false); reminder carries the canonical post-completion DTO.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: dataEnvelope(
|
||||
measurementReminderCompletionDto,
|
||||
"MeasurementReminderCompleteEnvelope",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
...reminderNotFound,
|
||||
...stdResponses,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -184,3 +184,26 @@ export const measurementReminderDto = z
|
||||
description:
|
||||
"A Vorsorge reminder. nextDueAt is server-computed (server-authoritative). A free-text reminder carries measurementType=null and resolves only on a manual satisfy. origin distinguishes a user-created (VORSORGE) reminder from one minted by a Coach cadence suggestion (COACH); endsOn bounds a finite course window (null = open-ended).",
|
||||
});
|
||||
|
||||
/**
|
||||
* v1.18.6 — explicit-completion result. The `complete` route is the
|
||||
* user-action equivalent of the cron auto-satisfy: it stamps
|
||||
* `lastSatisfiedAt` and re-anchors `nextDueAt` through the SAME shared
|
||||
* primitive, so it fires no notification of its own and is idempotent.
|
||||
*
|
||||
* `completed` reports whether THIS call advanced the reminder (true) or was
|
||||
* a forward-only no-op because a prior satisfy / matching reading already
|
||||
* fulfilled the current cycle (false). Either way the response is a 200 so
|
||||
* a client that completes an already-completed reminder need not special-case
|
||||
* the second tap. `reminder` carries the canonical post-completion DTO.
|
||||
*/
|
||||
export const measurementReminderCompletionDto = z
|
||||
.object({
|
||||
completed: z.boolean(),
|
||||
reminder: measurementReminderDto,
|
||||
})
|
||||
.meta({
|
||||
id: "MeasurementReminderCompletion",
|
||||
description:
|
||||
"Result of an explicit reminder completion. completed=true when this call advanced lastSatisfiedAt; completed=false when an earlier satisfy or a matching reading had already fulfilled the current cycle (idempotent no-op). reminder is the canonical post-completion DTO.",
|
||||
});
|
||||
Reference in new issue
Block a user