Files
HealthLog/src/components/illness/symptom-catalog.ts
T
Marc-André Bombeck b079431a8d feat(illness): add the condition-journal MVP behind a born-gated module
Introduce a retrospective illness/condition journal: episodes with a
lifecycle (acute / chronic-ongoing / recurring / flare) and a daily
symptom timeline forked structurally from the cycle log-day surface. The
journal is a record, not a medical device — no prediction or diagnosis UI.

- Register `illness` as a born-gated (opt-in / default-off) module. The
  gate resolver flips the disabled-allowlist default to off for born-gated
  keys, so the surface stays dark until the account opts in from the
  Modules hub. `isIllnessEnabled` + `requireIllnessEnabled` delegate to the
  module foundation (one source of truth) and re-stamp an illness errorCode.
- Episode CRUD under /api/illness: list / create / get / edit / resolve /
  delete, plus a per-episode-day day-log upsert on (episodeId, date). Every
  route wraps apiHandler, Zod-validates with returnAllZodIssues, narrows
  userId from auth, builds data field-by-field, and gates the module.
  Free-text notes encrypt at rest through the shared Bytes codec.
- Log-day sheet (cycle fork): ~8 Jackson/WURSS symptom chips 0-3 + a
  functional-impact group + fever + an encrypted note, one row per day.
- Episode history page + a born-gated nav entry, neutral palette, status
  via a neutral Badge, retrospective-only copy. i18n across all six locales.
- Cover the new routes in the module-route-gate inventory; unit tests for
  the day-log upsert, the gate enforcement, and the born-gated resolver.

The /api/auth/me module map now projects the `illness` flag (openapi.yaml
regenerated).
2026-06-16 21:09:35 +02:00

49 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* v1.18.1 — the seeded illness-symptom catalog, mirrored client-side.
*
* The keys are fixed at the migration seed (0171). The `key` is the
* snake_case DB key the day-log write resolves against; the `labelKey` is
* the i18n leaf under `illness.symptom.*`; the `icon` is the Lucide name
* from the seed. Keep this in lockstep with the seed in
* `prisma/migrations/0171_v1181_illness_episode/migration.sql` and the
* `illness.symptom.*` i18n leaves.
*
* The set is Jackson / WURSS-derived (~8 cardinal upper-respiratory + viral
* symptoms, 0–3 severity). Fever lives on the day row (`feverC`), not as a
* symptom chip; functional impact is a separate slider.
*/
import {
BatteryLow,
Brain,
Droplets,
Flame,
Megaphone,
PersonStanding,
Waves,
Wind,
type LucideIcon,
} from "lucide-react";
export interface IllnessSymptom {
/** snake_case DB key — the value sent in `symptoms[].key`. */
key: string;
/** i18n leaf under `illness.symptom.*`. */
labelKey: string;
icon: LucideIcon;
}
export const ILLNESS_SYMPTOM_CATALOG: IllnessSymptom[] = [
{ key: "runny_nose", labelKey: "illness.symptom.runnyNose", icon: Droplets },
{ key: "stuffy_nose", labelKey: "illness.symptom.stuffyNose", icon: Wind },
{ key: "sneezing", labelKey: "illness.symptom.sneezing", icon: Waves },
{ key: "sore_throat", labelKey: "illness.symptom.soreThroat", icon: Flame },
{ key: "cough", labelKey: "illness.symptom.cough", icon: Megaphone },
{ key: "headache", labelKey: "illness.symptom.headache", icon: Brain },
{
key: "body_aches",
labelKey: "illness.symptom.bodyAches",
icon: PersonStanding,
},
{ key: "fatigue", labelKey: "illness.symptom.fatigue", icon: BatteryLow },
];