mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
Merge branch 'feat/v139-targets-and-links' into release/v1.39.0
This commit is contained in:
commit
e89f41710a
58 files changed
+2785
-214
No files matched your search
@@ -128,6 +128,7 @@ export const ERROR_CODE_CATALOGUE: Readonly<Record<string, readonly string[]>> =
|
||||
"documents.inbound.restoreGone",
|
||||
"documents.inbound.uploadBusy",
|
||||
"documents.inbound.uploadTimeout",
|
||||
"documents.inbound.vaccinationNotFound",
|
||||
],
|
||||
encounter: [
|
||||
"encounter.invalid",
|
||||
|
||||
@@ -98,7 +98,7 @@ const inboundFactEditRequest = inboundFactEditSchema.meta({
|
||||
const documentUpdateRequest = documentUpdateSchema.meta({
|
||||
id: "DocumentUpdateRequest",
|
||||
description:
|
||||
"Metadata edit for a stored document: `title` (user label; null clears it), `kind` (category), `documentDate` (user filing date, YYYY-MM-DD; null clears it), `episodeIds` (REPLACE-SET of condition links — the document's links become exactly this set; an empty array unlinks everything; every id must be a live episode of the caller or the whole request answers 404), `encounterIds` (the same replace-set semantics over the caller's visits). At least one field required. No `userId` field — narrowed from the session and fed to the Prisma `where` with the row id.",
|
||||
"Metadata edit for a stored document: `title` (user label; null clears it), `kind` (category), `documentDate` (user filing date, YYYY-MM-DD; null clears it), `episodeIds` (REPLACE-SET of condition links — the document's links become exactly this set; an empty array unlinks everything; every id must be a live episode of the caller or the whole request answers 404), `encounterIds` (the same replace-set semantics over the caller's visits), `vaccinationIds` (the same replace-set semantics over the caller's vaccination doses, up to 100 so one childhood record can be filed against a whole primary schedule). At least one field required. No `userId` field — narrowed from the session and fed to the Prisma `where` with the row id.",
|
||||
});
|
||||
|
||||
const documentBulkRequest = documentBulkSchema.meta({
|
||||
@@ -156,6 +156,19 @@ const encounterLink = z
|
||||
"A link to one of the caller's visits — \"this letter belongs to that appointment\". `kind` is the visit-kind ENUM CONSTANT rather than a rendered name: unlike a condition label, which is the person's own words, a visit kind is one of eight closed values whose human name the reader's own bundle owns, so publishing the constant is what lets a German reader and an English one each see it named correctly.",
|
||||
});
|
||||
|
||||
const vaccinationLink = z
|
||||
.object({
|
||||
vaccinationId: z.string(),
|
||||
occurredAt: z.string().nullable(),
|
||||
catalogSlug: z.string().nullable(),
|
||||
vaccineName: z.string().nullable(),
|
||||
})
|
||||
.meta({
|
||||
id: "DocumentVaccinationLink",
|
||||
description:
|
||||
"A link to one of the caller's vaccination doses — \"this page records that dose\". `catalogSlug` is the catalogue entry when this release still knows the dose's slug, for the reader's own bundle to name; null is the signal to show `vaccineName`, the person's own wording. The same table the dose's own `/api/vaccinations/{id}/links` writes from the other end.",
|
||||
});
|
||||
|
||||
const inboundDocument = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
@@ -203,6 +216,10 @@ const inboundDocument = z
|
||||
const inboundDocumentDetail = inboundDocument
|
||||
.extend({
|
||||
facts: z.array(extractedFact),
|
||||
vaccinationLinks: z.array(vaccinationLink).nullable().meta({
|
||||
description:
|
||||
"Vaccination doses this document is filed against. Null when the caller acts inside somebody else's record under a grant that does not cover the health background the doses live in: the page is shared, the doses are not, and an empty list would claim the page records none.",
|
||||
}),
|
||||
summary: z.string().nullable(),
|
||||
summaryGeneratedAt: z.string().nullable(),
|
||||
summaryState: z.enum(DOCUMENT_SUMMARY_STATES),
|
||||
|
||||
@@ -1201,6 +1201,24 @@ export const dashboardSnapshotResponse = z
|
||||
.describe(
|
||||
"Non-null when two writer buckets reported clearly different asleep totals for the latest night's main session (> 45 min apart and > 20% of the larger total). Observational only — the served summary stays the winning writer's totals; clients may show a discreet 'sources disagree' hint next to the sleep tile's headline. Null when the writers agree or the sleep module is off; optional for older cached snapshots.",
|
||||
),
|
||||
weightTrend: z
|
||||
.object({
|
||||
direction: z
|
||||
.enum(["up-good", "up-bad", "hold"])
|
||||
.describe(
|
||||
"How the weight tile colours a change. `up-good`: a rise is progress (below the target band). `up-bad`: a fall is progress (above the band, and the reading when no target is stored). `hold`: the weight is inside the band, so a flat change is progress and a move either way is neutral, never a setback.",
|
||||
),
|
||||
targetPosition: z
|
||||
.enum(["below", "inside", "above"])
|
||||
.nullable()
|
||||
.describe(
|
||||
"Where the 7-day average (else the latest reading) sits against the person's own stored weight target. Null when no target is stored or there is no reading.",
|
||||
),
|
||||
})
|
||||
.optional()
|
||||
.describe(
|
||||
"Which way a weight change counts as progress, judged against the person's own stored target rather than assuming a fall is good. Render the arrow, 7-day delta and comparison caption from `direction`; do not recompute it. Optional for older cached snapshots; when absent, treat it as `up-bad`.",
|
||||
),
|
||||
}),
|
||||
extras: z
|
||||
.object({
|
||||
|
||||
@@ -175,11 +175,33 @@ const vaccination = z
|
||||
"One administered dose. `occurredAt` is a day at UTC midnight — the source record carries dates, never times. `series` carries one entry per component antigen, so a combined preparation reports several at once and each may be at a different position: a dose can be a booster for one antigen and a first dose for another in the same act. An empty `series` means the dose has no resolvable antigen (free text only, or a slug this release does not know) and nothing is guessed from the name. `note` is the decrypted free text, or null on a key-rotation gap — fail-soft, never a 500. `reminderId` names the booster reminder this dose settled, when one matched. `documents` is present on the detail response and absent from the list.",
|
||||
});
|
||||
|
||||
const vaccinationList = z.object({ vaccinations: z.array(vaccination) }).meta({
|
||||
id: "VaccinationList",
|
||||
description:
|
||||
"The caller's immunization history, newest dose first, with every entry's series already resolved over the whole live set — never over the filtered page, which would report the oldest dose in a window as the first ever given.",
|
||||
});
|
||||
const vaccinationRenewal = z
|
||||
.object({
|
||||
antigen: z.string(),
|
||||
reminderId: z.string(),
|
||||
dueAt: z.string(),
|
||||
daysUntil: z.number().int(),
|
||||
state: z.enum(["current", "dueSoon", "overdue"]),
|
||||
})
|
||||
.meta({
|
||||
id: "VaccinationRenewal",
|
||||
description:
|
||||
"One antigen's renewal state, read from the booster reminder the person confirmed for it (`dueAt` is that reminder's next due instant). `daysUntil` counts calendar days on the person's own clock and is negative once the date has passed. `state` is `overdue` once it has passed, `dueSoon` within 30 days, `current` otherwise. Render from `state`; do not recompute it. Nothing here is derived from age, history or the catalogue: an antigen without a confirmed booster has no entry.",
|
||||
});
|
||||
|
||||
const vaccinationList = z
|
||||
.object({
|
||||
vaccinations: z.array(vaccination),
|
||||
renewals: z.array(vaccinationRenewal).nullable().meta({
|
||||
description:
|
||||
"Each antigen's renewal state, earliest due first. Null when the caller acts under a grant that does not cover the measurements section the booster reminders live in.",
|
||||
}),
|
||||
})
|
||||
.meta({
|
||||
id: "VaccinationList",
|
||||
description:
|
||||
"The caller's immunization history, newest dose first, with every entry's series already resolved over the whole live set — never over the filtered page, which would report the oldest dose in a window as the first ever given.",
|
||||
});
|
||||
|
||||
const vaccinationSuggestion = z
|
||||
.object({
|
||||
|
||||
Reference in new issue
Block a user