mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
feat(onboarding): add resumable module-tour progress field + API
Add nullable onboarding_tour_progress_json to users (migration 0173), a Zod-validated progress shape, and extend POST /api/onboarding/tour to accept a mid-tour resume checkpoint and clear it on replay. Surface the resume point on GET /api/auth/me and register the contract in OpenAPI so the native client mirrors it.
This commit is contained in:
1 parent
b474ea1489
commit
59e7b33285
15 files changed
+442
-17
No files matched your search
@@ -42,6 +42,7 @@ import { measurementReminderPaths } from "./measurement-reminders";
|
||||
import { medicationPaths, medicationResource } from "./medications";
|
||||
import { metaPaths } from "./meta";
|
||||
import { moodPaths } from "./mood";
|
||||
import { onboardingPaths } from "./onboarding";
|
||||
import { profilePaths } from "./profile";
|
||||
import { settingsPaths } from "./settings";
|
||||
import { syncPaths } from "./sync";
|
||||
@@ -72,6 +73,7 @@ export const openApiPaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
...labsPaths,
|
||||
...biomarkerPaths,
|
||||
...illnessPaths,
|
||||
...onboardingPaths,
|
||||
};
|
||||
|
||||
export const openApiComponents: NonNullable<ZodOpenApiObject["components"]> = {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* OpenAPI route table — onboarding module tour.
|
||||
*
|
||||
* Part of the OpenAPI route table; aggregated in `./index.ts`.
|
||||
* The request schema comes from `src/lib/onboarding/tour-progress.ts`
|
||||
* so the wire contract stays single-source with the runtime parser.
|
||||
*
|
||||
* v1.18.6 — the resumable module-tour contract the iOS client mirrors:
|
||||
* a fire-and-forget progress checkpoint plus the coarse completion
|
||||
* flip. The resume point also rides `GET /api/auth/me` as
|
||||
* `onboardingTourProgress`.
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
import type { ZodOpenApiObject } from "zod-openapi";
|
||||
|
||||
import { tourProgressSchema } from "@/lib/onboarding/tour-progress";
|
||||
import { dataEnvelope, stdResponses } from "./shared";
|
||||
|
||||
const tourProgressResource = tourProgressSchema.meta({
|
||||
id: "TourProgress",
|
||||
description:
|
||||
"Resumable module-tour progress point. `lastStopId` seeds the resume index; `status` is the running/terminal state.",
|
||||
});
|
||||
|
||||
const tourUpdateRequest = z
|
||||
.object({
|
||||
completed: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"Flip the coarse completion flag. `false` is a replay reset and clears the stored progress point.",
|
||||
),
|
||||
outcome: z
|
||||
.enum(["completed", "skipped"])
|
||||
.optional()
|
||||
.describe("Informational — distinguishes reaching the end from a skip."),
|
||||
progress: tourProgressResource
|
||||
.optional()
|
||||
.describe("Mid-tour resume checkpoint. May arrive alone or with `completed`."),
|
||||
})
|
||||
.meta({
|
||||
id: "TourUpdateRequest",
|
||||
description:
|
||||
"Update the module-tour state. Provide `completed` and/or `progress`.",
|
||||
});
|
||||
|
||||
const tourUpdateResponse = z
|
||||
.object({
|
||||
onboardingTourCompleted: z.boolean(),
|
||||
progress: tourProgressResource.nullable(),
|
||||
})
|
||||
.meta({
|
||||
id: "TourUpdateResponse",
|
||||
description: "The persisted completion flag and resume point after the write.",
|
||||
});
|
||||
|
||||
export const onboardingPaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
"/api/onboarding/tour": {
|
||||
post: {
|
||||
tags: ["Onboarding"],
|
||||
summary: "Update module-tour completion + resume point",
|
||||
description:
|
||||
"Persists the module-tour state. The client posts a fire-and-forget `progress` checkpoint on each step so a reload resumes at the right module, and a terminal `completed:true` with `outcome` when the tour ends. `completed:false` is a replay reset that also clears the resume point.",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: { "application/json": { schema: tourUpdateRequest } },
|
||||
},
|
||||
responses: {
|
||||
"200": {
|
||||
description: "Tour state updated.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: dataEnvelope(tourUpdateResponse, "TourUpdateEnvelope"),
|
||||
},
|
||||
},
|
||||
},
|
||||
...stdResponses,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user