From 9272daa59c58d7016b214b28054d6aa37bbbb439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 3 Oct 2026 21:24:12 +0200 Subject: [PATCH] feat(symptoms): log a symptom in one step and show it on the illness pages - A new capture kind "symptom" (illness module, illness write grant) in the bottom bar's picker and the dashboard Add menu. The sheet follows the measurement and mood forms: the person's symptoms as chips with the cycle sheet's dashed "new symptom" chip, the 0-10 slider with its anchors, the time prefilled with now, an optional note, and a "during" selector only while an illness episode is open. - "Your symptoms" on the illness page: one line per symptom (how often in 30 days, how strong at worst, when last), the last 30 days grouped by day, edit and delete per entry, rename, icon, hide and delete per symptom. Renders nothing until a symptom exists. - "Symptoms logged" on an episode's page: the entries filed against it or logged while it ran, the filed ones marked. This is the reader of the episode link. - Query keys live under the illness root, so either side's writes refresh both. --- .../__tests__/dashboard-header.test.tsx | 4 +- src/components/dashboard/dashboard-header.tsx | 17 +- .../dashboard/quick-entry-sheets.tsx | 25 +- .../illness/illness-episode-detail.tsx | 5 + src/components/illness/illness-view.tsx | 36 +- src/components/layout/capture-picker.tsx | 25 +- .../__tests__/symptom-entry-form.test.tsx | 114 ++++ src/components/symptoms/add-symptom-chip.tsx | 165 ++++++ .../symptoms/episode-symptoms-card.tsx | 135 +++++ .../symptoms/symptom-edit-sheets.tsx | 267 +++++++++ .../symptoms/symptom-entry-form.tsx | 395 +++++++++++++ src/components/symptoms/symptom-icons.ts | 79 +++ src/components/symptoms/symptoms-section.tsx | 524 ++++++++++++++++++ src/components/symptoms/use-symptoms.ts | 154 +++++ .../__tests__/surface-module-registry.test.ts | 1 + src/lib/modules/surface.ts | 2 + src/lib/query-keys/illness.ts | 11 + 17 files changed, 1940 insertions(+), 19 deletions(-) create mode 100644 src/components/symptoms/__tests__/symptom-entry-form.test.tsx create mode 100644 src/components/symptoms/add-symptom-chip.tsx create mode 100644 src/components/symptoms/episode-symptoms-card.tsx create mode 100644 src/components/symptoms/symptom-edit-sheets.tsx create mode 100644 src/components/symptoms/symptom-entry-form.tsx create mode 100644 src/components/symptoms/symptom-icons.ts create mode 100644 src/components/symptoms/symptoms-section.tsx create mode 100644 src/components/symptoms/use-symptoms.ts diff --git a/src/components/dashboard/__tests__/dashboard-header.test.tsx b/src/components/dashboard/__tests__/dashboard-header.test.tsx index 0e5579c44..ab0909ef2 100644 --- a/src/components/dashboard/__tests__/dashboard-header.test.tsx +++ b/src/components/dashboard/__tests__/dashboard-header.test.tsx @@ -153,7 +153,8 @@ describe(" — every entry follows its module, as the capture p { mood: false }, { medications: false }, { workouts: false }, - { mood: false, medications: false, workouts: false }, + { illness: false }, + { mood: false, medications: false, workouts: false, illness: false }, ]; for (const modules of cases) { modulesRef.value = modules; @@ -170,6 +171,7 @@ describe(" — every entry follows its module, as the capture p measurement: "Log measurement", medication: "Log medication intake", mood: "Log mood", + symptom: "Log symptom", workout: "Log workout", } as const; for (const kind of CAPTURE_KIND_ORDER) { diff --git a/src/components/dashboard/dashboard-header.tsx b/src/components/dashboard/dashboard-header.tsx index db6ad7cc0..c969eb495 100644 --- a/src/components/dashboard/dashboard-header.tsx +++ b/src/components/dashboard/dashboard-header.tsx @@ -12,7 +12,15 @@ */ import { useMemo } from "react"; import Link from "next/link"; -import { Activity, Footprints, Pill, Plus, Waves, Wrench } from "lucide-react"; +import { + Activity, + Footprints, + Pill, + Plus, + Stethoscope, + Waves, + Wrench, +} from "lucide-react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -62,6 +70,7 @@ export function DashboardHeader({ const canAddMeasurement = offered.includes("measurement"); const canAddIntake = offered.includes("medication"); const canAddMood = offered.includes("mood"); + const canAddSymptom = offered.includes("symptom"); const canAddWorkout = offered.includes("workout"); const canAddAnything = offered.length > 0; @@ -198,6 +207,12 @@ export function DashboardHeader({ {t("dashboard.quickAddMedicationIntake")} )} + {canAddSymptom && ( + onQuickEntry("symptom")}> + + )} {canAddWorkout && ( onQuickEntry("workout")}>