From bd841aee991032593a6a49c42ec220cf9a99516f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 17 May 2026 15:29:56 +0200 Subject: [PATCH] fix(dashboard): clarify dose field is informational only in medication quick-add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dose field on the medication-intake quick-add sheet was rendered editable but the POST body has no `dose` slot — any user edit was silently dropped, so a user typing "5 mg" for a half-pill day saw the catalogue dose recorded instead. The previous hint copy did not warn about the constraint, leaving the user's mental model out of sync with the persisted data. Render the field read-only with a muted background, drop the tab order on the input, and rewrite the hint copy across all six locales so the user knows that variable doses are coming in a later version and the standard dose is recorded for now. The setDoseOverride state holder stays so the reset-on-medication-switch keeps working when the v1.4.38 doseOverride schema lands. --- messages/de.json | 2 +- messages/en.json | 2 +- messages/es.json | 2 +- messages/fr.json | 2 +- messages/it.json | 2 +- messages/pl.json | 2 +- .../dashboard/medication-intake-quick-add.tsx | 42 ++++++++++--------- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/messages/de.json b/messages/de.json index ab939a7b6..c244e9d47 100644 --- a/messages/de.json +++ b/messages/de.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Medikament auswählen", "doseLabel": "Dosis", "dosePlaceholder": "z. B. 5 mg", - "doseHint": "Vorbelegt mit der Standarddosis. Bei Bedarf anpassen.", + "doseHint": "Aktuell wird die Standarddosis erfasst. Abweichende Dosen kommen in einer kommenden Version.", "timeLabel": "Zeitpunkt", "saveError": "Einnahme konnte nicht gespeichert werden.", "emptyTitle": "Noch keine Medikamente angelegt", diff --git a/messages/en.json b/messages/en.json index 25ebf14e5..cc8043984 100644 --- a/messages/en.json +++ b/messages/en.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Select a medication", "doseLabel": "Dose", "dosePlaceholder": "e.g. 5 mg", - "doseHint": "Pre-filled with the default dose. Adjust if needed.", + "doseHint": "Currently the standard dose is recorded. Variable doses are coming in a later version.", "timeLabel": "Time taken", "saveError": "Could not save medication intake.", "emptyTitle": "No medications yet", diff --git a/messages/es.json b/messages/es.json index 6b708be3f..f34fcd586 100644 --- a/messages/es.json +++ b/messages/es.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Select a medication", "doseLabel": "Dose", "dosePlaceholder": "e.g. 5 mg", - "doseHint": "Pre-filled with the default dose. Adjust if needed.", + "doseHint": "Currently the standard dose is recorded. Variable doses are coming in a later version.", "timeLabel": "Time taken", "saveError": "Could not save medication intake.", "emptyTitle": "No medications yet", diff --git a/messages/fr.json b/messages/fr.json index d999c37d2..487cc74ba 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Select a medication", "doseLabel": "Dose", "dosePlaceholder": "e.g. 5 mg", - "doseHint": "Pre-filled with the default dose. Adjust if needed.", + "doseHint": "Currently the standard dose is recorded. Variable doses are coming in a later version.", "timeLabel": "Time taken", "saveError": "Could not save medication intake.", "emptyTitle": "No medications yet", diff --git a/messages/it.json b/messages/it.json index 38b5b3858..d097cfde7 100644 --- a/messages/it.json +++ b/messages/it.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Select a medication", "doseLabel": "Dose", "dosePlaceholder": "e.g. 5 mg", - "doseHint": "Pre-filled with the default dose. Adjust if needed.", + "doseHint": "Currently the standard dose is recorded. Variable doses are coming in a later version.", "timeLabel": "Time taken", "saveError": "Could not save medication intake.", "emptyTitle": "No medications yet", diff --git a/messages/pl.json b/messages/pl.json index c4c09d344..f703dc4e3 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -252,7 +252,7 @@ "medicationPlaceholder": "Select a medication", "doseLabel": "Dose", "dosePlaceholder": "e.g. 5 mg", - "doseHint": "Pre-filled with the default dose. Adjust if needed.", + "doseHint": "Currently the standard dose is recorded. Variable doses are coming in a later version.", "timeLabel": "Time taken", "saveError": "Could not save medication intake.", "emptyTitle": "No medications yet", diff --git a/src/components/dashboard/medication-intake-quick-add.tsx b/src/components/dashboard/medication-intake-quick-add.tsx index 1d3bf5f5c..de49811f0 100644 --- a/src/components/dashboard/medication-intake-quick-add.tsx +++ b/src/components/dashboard/medication-intake-quick-add.tsx @@ -46,15 +46,14 @@ import { * sheet body renders an EmptyState-style hint instead of an * unusable form. * 2. Dose. Pre-filled from the medication's catalogue dose for - * visual confirmation ("this is the strength I'm logging"); the - * field is editable but the POST body does NOT carry the dose - * override yet — the intake event always references the - * medication's current catalogue dose. The boundary lives in the - * `intakeSchema` (no `dose` field), so when the user wants to - * record a half/double dose they still edit the medication - * itself on `/medications`. Keeping the input editable preserves - * the visual contract Marc asked for ("show me what I'm - * logging") without misrepresenting the wire shape. + * visual confirmation ("this is the strength I'm logging"). + * v1.4.37 W10 — rendered read-only because the POST body has no + * `dose` field; any user edit would be silently dropped. When + * the user wants to record a half/double dose they still edit + * the medication itself on `/medications` until the v1.4.38 + * schema grows a `doseOverride` slot. Hint copy below the + * field warns about the constraint so the user's mental model + * tracks what the server persists. * 3. Time taken. Defaults to `now` (local datetime-local format * shaped the same as `MoodForm`). * @@ -190,11 +189,13 @@ export function MedicationIntakeQuickAdd({ const [medicationOverride, setMedicationOverride] = useState( null, ); - // User-driven dose override; `null` means "use the medication's - // default". The picker auto-prefills the dose input by deriving it - // from the selected medication during render — keeping it state-free - // until the user actually types so we don't fight the linter's - // `react-hooks/set-state-in-effect` guard. + // v1.4.37 W10 — the dose field is informational only. The intake + // POST body has no `dose` slot, so any user edit would be silently + // dropped on submit. Until the v1.4.38 schema grows a `doseOverride` + // field, render the input as read-only so the user's mental model + // tracks what the server actually persists. The state holder is + // kept (as `null`) so the medication-switch handler still resets + // the slot cleanly if the schema ever grows the field. const [doseOverride, setDoseOverride] = useState(null); const [takenAt, setTakenAt] = useState(getDefaultIntakeAtValue); const [loading, setLoading] = useState(false); @@ -215,8 +216,10 @@ export function MedicationIntakeQuickAdd({ function handleMedicationChange(value: string) { setMedicationOverride(value); // Reset the dose override when the medication changes so the new - // default flows through on the next render. The user can still - // override it after the selection by typing into the dose field. + // default flows through on the next render. The dose field is + // currently read-only (see v1.4.37 W10 note above), but the reset + // stays in place so the slot is ready to switch back to editable + // when the v1.4.38 doseOverride schema lands. setDoseOverride(null); } @@ -401,14 +404,15 @@ export function MedicationIntakeQuickAdd({ id="medication-intake-dose" data-testid="medication-intake-quick-add-dose" value={dose} - onChange={(e) => setDoseOverride(e.target.value)} + readOnly + aria-readonly="true" + tabIndex={-1} placeholder={ selectedMedication?.dose ?? t("dashboard.medicationIntakeQuickAdd.dosePlaceholder") } - enterKeyHint="done" autoComplete="off" - className="min-h-11" + className="min-h-11 bg-muted/40" />

{t("dashboard.medicationIntakeQuickAdd.doseHint")}