feat(medications): add mental health as a medication category

Antidepressants, anxiolytics, mood stabilisers and ADHD medication had no
category of their own and ended up under "Other". MENTAL_HEALTH joins the
clinical category list: the add and edit wizard offers it as its own row
with a brain icon, the card badge names it, and it is translated in all
seven languages.

The category is a text value, so no migration is needed. Clients that
read the category as a string show the new value; an app that does not
know it yet falls back to its own label for it.
This commit is contained in:
Marc-André Bombeck committed 2026-09-27 13:51:39 +02:00
1 parent 8295dfe9b6
commit a224875ed9
14 files changed
+53 -4

No files matched your search

+3
View File
@@ -23985,6 +23985,7 @@ components:
- SLEEP_AID
- DIABETES
- ANTIBIOTIC
- MENTAL_HEALTH
- OTHER
treatmentClass:
type: string
@@ -24321,6 +24322,7 @@ components:
- SLEEP_AID
- DIABETES
- ANTIBIOTIC
- MENTAL_HEALTH
- OTHER
treatmentClass:
type: string
@@ -44086,6 +44088,7 @@ components:
- SLEEP_AID
- DIABETES
- ANTIBIOTIC
- MENTAL_HEALTH
- OTHER
description: Clinical taxonomy stored in the `medication_categories` side-table. Orthogonal to `MedicationTreatmentClass`.
CreateMedicationResponse:
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Schlafmittel",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiotikum",
"categoryMentalHealth": "Psychische Gesundheit",
"categoryOther": "Sonstiges",
"daysSun": "So",
"daysMon": "Mo",
@@ -1567,6 +1568,7 @@
"vitamin": "Vitamine",
"supplement": "Nahrungsergänzung",
"antibiotic": "Antibiotikum",
"mentalHealth": "Psychische Gesundheit",
"other": "Sonstiges"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Sleep Aid",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiotic",
"categoryMentalHealth": "Mental health",
"categoryOther": "Other",
"daysSun": "Sun",
"daysMon": "Mon",
@@ -1567,6 +1568,7 @@
"vitamin": "Vitamins",
"supplement": "Supplement",
"antibiotic": "Antibiotic",
"mentalHealth": "Mental health",
"other": "Other"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Para dormir",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiótico",
"categoryMentalHealth": "Salud mental",
"categoryOther": "Otros",
"daysSun": "Do",
"daysMon": "Lu",
@@ -1567,6 +1568,7 @@
"vitamin": "Vitaminas",
"supplement": "Suplemento",
"antibiotic": "Antibiótico",
"mentalHealth": "Salud mental",
"other": "Otro"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Aide au sommeil",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiotique",
"categoryMentalHealth": "Santé mentale",
"categoryOther": "Autres",
"daysSun": "Dim",
"daysMon": "Lun",
@@ -1567,6 +1568,7 @@
"vitamin": "Vitamines",
"supplement": "Complément",
"antibiotic": "Antibiotique",
"mentalHealth": "Santé mentale",
"other": "Autre"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Per dormire",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiotico",
"categoryMentalHealth": "Salute mentale",
"categoryOther": "Altro",
"daysSun": "Dom",
"daysMon": "Lun",
@@ -1567,6 +1568,7 @@
"vitamin": "Vitamine",
"supplement": "Integratore",
"antibiotic": "Antibiotico",
"mentalHealth": "Salute mentale",
"other": "Altro"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "수면 보조",
"categoryDiabetes": "당뇨",
"categoryAntibiotic": "항생제",
"categoryMentalHealth": "정신 건강",
"categoryOther": "기타",
"daysSun": "일",
"daysMon": "월",
@@ -1567,6 +1568,7 @@
"vitamin": "비타민",
"supplement": "보충제",
"antibiotic": "항생제",
"mentalHealth": "정신 건강",
"other": "기타"
},
"cadence": {
+2
View File
@@ -1212,6 +1212,7 @@
"categorySleepAid": "Na sen",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antybiotyk",
"categoryMentalHealth": "Zdrowie psychiczne",
"categoryOther": "Inne",
"daysSun": "Nd",
"daysMon": "Pn",
@@ -1567,6 +1568,7 @@
"vitamin": "Witaminy",
"supplement": "Suplement",
"antibiotic": "Antybiotyk",
"mentalHealth": "Zdrowie psychiczne",
"other": "Inne"
},
"cadence": {
@@ -364,6 +364,18 @@ describe("POST /api/medications — v1.5.4 clinical category extension", () => {
expect(res.status).toBe(201);
});
it("accepts MENTAL_HEALTH as a valid clinical category (v1.39.4, #1041)", async () => {
const res = await POST(
postReq({
name: "Sertraline",
dose: "50 mg",
category: "MENTAL_HEALTH",
schedules: [{ windowStart: "08:00", windowEnd: "09:00" }],
}),
);
expect(res.status).toBe(201);
});
it("still 422s on an unknown category string", async () => {
const res = await POST(
postReq({
@@ -310,6 +310,13 @@ describe("WIZARD_TREATMENT_MAPPING — Step 2 row → request body", () => {
});
});
it("maps Psychische Gesundheit → (GENERIC, MENTAL_HEALTH) — new in v1.39.4", () => {
expect(WIZARD_TREATMENT_MAPPING.mentalHealth).toEqual({
treatmentClass: "GENERIC",
category: "MENTAL_HEALTH",
});
});
it("maps GLP-1-Injektion → (GLP1, OTHER) — only row with GLP1", () => {
expect(WIZARD_TREATMENT_MAPPING.glp1).toEqual({
treatmentClass: "GLP1",
@@ -327,6 +334,7 @@ describe("WIZARD_TREATMENT_MAPPING — Step 2 row → request body", () => {
"vitamin",
"supplement",
"antibiotic",
"mentalHealth",
"other",
];
for (const row of rows) {
@@ -347,6 +355,7 @@ describe("rowFromTreatment — reverse mapping for edit-hydration", () => {
it("ANTIBIOTIC category maps to the antibiotic row", () => {
expect(rowFromTreatment("GENERIC", "ANTIBIOTIC")).toBe("antibiotic");
expect(rowFromTreatment("GENERIC", "MENTAL_HEALTH")).toBe("mentalHealth");
});
it("unknown category falls back to 'other'", () => {
@@ -3,6 +3,7 @@
import {
Activity,
Apple,
Brain,
Droplet,
Flame,
Leaf,
@@ -35,6 +36,7 @@ const ROW_ICONS: Record<WizardTreatmentRow, ComponentType<LucideProps>> = {
vitamin: Apple,
supplement: Leaf,
antibiotic: ShieldCheck,
mentalHealth: Brain,
other: Tag as unknown as LucideIcon,
};
@@ -86,12 +86,13 @@ export type WizardTreatmentRow =
| "vitamin"
| "supplement"
| "antibiotic"
| "mentalHealth"
| "other";
/**
* The ten taxonomy rows in their visible order. maintainer-confirmed (D-1
* §3 Step 2): Blutdruck · Diabetes · Hormone · GLP-1-Injektion ·
* Schmerz · Allergie · Vitamine · Nahrungsergänzung · Antibiotikum ·
* The taxonomy rows in their visible order (D-1 §3 Step 2): Blutdruck ·
* Diabetes · Hormone · GLP-1-Injektion · Schmerz · Allergie · Vitamine ·
* Nahrungsergänzung · Antibiotikum · Psychische Gesundheit (v1.39.4) ·
* Sonstiges.
*/
export const WIZARD_TREATMENT_ROWS: readonly WizardTreatmentRow[] = [
@@ -104,6 +105,7 @@ export const WIZARD_TREATMENT_ROWS: readonly WizardTreatmentRow[] = [
"vitamin",
"supplement",
"antibiotic",
"mentalHealth",
"other",
];
@@ -128,6 +130,7 @@ export const WIZARD_TREATMENT_MAPPING: Record<
vitamin: { treatmentClass: "GENERIC", category: "VITAMIN" },
supplement: { treatmentClass: "GENERIC", category: "SUPPLEMENT" },
antibiotic: { treatmentClass: "GENERIC", category: "ANTIBIOTIC" },
mentalHealth: { treatmentClass: "GENERIC", category: "MENTAL_HEALTH" },
other: { treatmentClass: "GENERIC", category: "OTHER" },
};
@@ -159,6 +162,8 @@ export function rowFromTreatment(
return "supplement";
case "ANTIBIOTIC":
return "antibiotic";
case "MENTAL_HEALTH":
return "mentalHealth";
default:
return "other";
}
+1
View File
@@ -34,6 +34,7 @@ const MEDICATION_CATEGORY_KEYS: Record<string, string> = {
SLEEP_AID: "medications.categorySleepAid",
DIABETES: "medications.categoryDiabetes",
ANTIBIOTIC: "medications.categoryAntibiotic",
MENTAL_HEALTH: "medications.categoryMentalHealth",
OTHER: "medications.categoryOther",
};
+4 -1
View File
@@ -68,7 +68,9 @@ export const rxNormCodeField = z
* wizard's Step 2 taxonomy can write a first-class bucket for those
* two rows instead of collapsing them into `OTHER`. The column is a
* plain TEXT field — no Prisma enum exists to migrate; the Zod values
* list is the only enforcement layer.
* list is the only enforcement layer. v1.39.4 adds `MENTAL_HEALTH`
* (antidepressants, anxiolytics, mood stabilisers, ADHD medication), again
* without a migration.
*/
export const MEDICATION_CATEGORY_VALUES = [
"BLOOD_PRESSURE",
@@ -83,6 +85,7 @@ export const MEDICATION_CATEGORY_VALUES = [
"SLEEP_AID",
"DIABETES",
"ANTIBIOTIC",
"MENTAL_HEALTH",
"OTHER",
] as const;
export type MedicationCategoryValue =