mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
Drop the health-score card's inert onAskCoach prop and its now-dead pass-through from the hero strip, the buildDashboardBands re-export that no caller reached through the snapshot module, an unused tour-progress status type, and an orphan service-worker cache helper.
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
/**
|
|
* v1.18.6 — resumable module-tour progress.
|
|
*
|
|
* Pure data + Zod schema for the `users.onboarding_tour_progress_json`
|
|
* column. Kept DOM-free + free of Prisma imports so vitest (node env)
|
|
* and the OpenAPI registry can both consume it.
|
|
*
|
|
* The coarse `onboardingTourCompleted` boolean stays the launcher's
|
|
* auto-launch gate; this object is the fine-grained resume point so a
|
|
* mid-tour reload reopens at the right module. `null` = the user has
|
|
* not started the module tour.
|
|
*/
|
|
|
|
import { z } from "zod/v4";
|
|
|
|
/** Terminal / running status of the module tour. */
|
|
export const TOUR_PROGRESS_STATUSES = [
|
|
"in_progress",
|
|
"completed",
|
|
"skipped",
|
|
] as const;
|
|
|
|
/**
|
|
* The persisted progress shape. `lastStopId` seeds the resume index;
|
|
* `completedStopIds` is informational (analytics + future per-module
|
|
* "already seen" hints). Stop ids are bounded strings — the client
|
|
* sends a known stop id from `buildTourStops()`, but the server does
|
|
* not couple to that closed set (a future stop must not 422 an older
|
|
* client and vice-versa), so the field is a length-capped string array
|
|
* rather than a hard enum.
|
|
*/
|
|
export const tourProgressSchema = z.object({
|
|
lastStopId: z.string().min(1).max(64).nullable(),
|
|
completedStopIds: z.array(z.string().min(1).max(64)).max(64).default([]),
|
|
status: z.enum(TOUR_PROGRESS_STATUSES),
|
|
updatedAt: z.iso.datetime(),
|
|
});
|
|
|
|
export type TourProgress = z.infer<typeof tourProgressSchema>;
|
|
|
|
/**
|
|
* Parse a value read from the JSON column. Returns `null` for a null /
|
|
* absent column AND for any malformed payload — the resume point is a
|
|
* non-critical convenience, so a corrupt blob degrades to "start from
|
|
* the top" rather than throwing into the auth/me read path.
|
|
*/
|
|
export function parseTourProgress(value: unknown): TourProgress | null {
|
|
if (value == null) return null;
|
|
const parsed = tourProgressSchema.safeParse(value);
|
|
return parsed.success ? parsed.data : null;
|
|
}
|