mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
feat(coach,admin): finish the self-context and invite surfaces end to end
Invites move into their own admin section with a real ledger: status badges, expiry, uses, a redemption history of who joined when (new redemption table, revocation is now soft so history survives), and an honest one-time link/QR moment. The assistant self-context grows structured fields for conditions, allergies and focus — encrypted like the free text — merges age and gender from the profile into one fenced prompt block, and asks up to three targeted follow-up questions that surface as tappable chips above the coach composer. A fourth nudge trigger gently suggests a check-up when the self-context is stale and the coach is actually in use.
This commit is contained in:
1 parent
9fe5673251
commit
5b75184649
32 files changed
+2648
-423
No files matched your search
@@ -1,5 +1,9 @@
|
||||
/**
|
||||
* v1.15.20 — request schema for `PUT /api/coach/about-me`.
|
||||
* v1.16.0 — extended with three structured self-context fields
|
||||
* (conditions, allergies, coach focus). Age/gender deliberately stay
|
||||
* on the User profile and are merged into the prompt block at assembly
|
||||
* time — the questionnaire never duplicates them.
|
||||
*
|
||||
* Lives outside the route file so the OpenAPI registry
|
||||
* (`src/lib/openapi/routes.ts`) can import it without touching the
|
||||
@@ -12,6 +16,20 @@ import { z } from "zod/v4";
|
||||
/** Hard cap enforced BEFORE encryption. */
|
||||
export const ABOUT_ME_MAX_CHARS = 4000;
|
||||
|
||||
/** Per-field cap for the structured answers, BEFORE encryption. */
|
||||
export const ABOUT_ME_FIELD_MAX_CHARS = 500;
|
||||
|
||||
const structuredField = z
|
||||
.string()
|
||||
.max(
|
||||
ABOUT_ME_FIELD_MAX_CHARS,
|
||||
`Maximum ${ABOUT_ME_FIELD_MAX_CHARS} characters`,
|
||||
)
|
||||
// Optional so older clients that only send `aboutMe` keep working;
|
||||
// an omitted field leaves the stored value untouched, an empty
|
||||
// string clears it (mirrors the `aboutMe` semantics).
|
||||
.optional();
|
||||
|
||||
export const aboutMePutSchema = z.object({
|
||||
/**
|
||||
* The user's free-text self-description. An empty / whitespace-only
|
||||
@@ -20,6 +38,12 @@ export const aboutMePutSchema = z.object({
|
||||
aboutMe: z
|
||||
.string()
|
||||
.max(ABOUT_ME_MAX_CHARS, `Maximum ${ABOUT_ME_MAX_CHARS} characters`),
|
||||
/** Chronic conditions, short free text. */
|
||||
conditions: structuredField,
|
||||
/** Allergies / intolerances, short free text. */
|
||||
allergies: structuredField,
|
||||
/** What the Coach should pay attention to, short free text. */
|
||||
coachFocus: structuredField,
|
||||
});
|
||||
|
||||
export type AboutMePutInput = z.infer<typeof aboutMePutSchema>;
|
||||
Reference in new issue
Block a user