fix(meds): collapse the medication-level oneShot toggle to a single source

The flat form's oneShot switch now drives the picker's allowed kinds
directly; the picker can no longer encode a contradictory shape.
Multi-schedule medications surface a confirmation when the switch
flips on, since the existing logic drops every schedule but the
first.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-28 10:23:28 +02:00
1 parent 22164c6c8b
commit 2a9f0c1e06
7 files changed
+40 -9

No files matched your search

+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "Das Enddatum muss am oder nach dem Startdatum liegen."
},
"oneShot": {
"section": "Einmaldosis"
"section": "Einmaldosis",
"collapseWarning": "Einmaldosis aktiv — alle weiteren Pläne wurden auf den ersten zusammengeführt."
},
"legacyWindow": {
"section": "Erinnerungsfenster (alt)",
+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "End date must be on or after the start date."
},
"oneShot": {
"section": "Single dose"
"section": "Single dose",
"collapseWarning": "Single dose enabled — every other schedule was merged into the first."
},
"legacyWindow": {
"section": "Reminder window (legacy)",
+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "End date must be on or after the start date."
},
"oneShot": {
"section": "Single dose"
"section": "Single dose",
"collapseWarning": "Single dose enabled — every other schedule was merged into the first."
},
"legacyWindow": {
"section": "Reminder window (legacy)",
+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "End date must be on or after the start date."
},
"oneShot": {
"section": "Single dose"
"section": "Single dose",
"collapseWarning": "Single dose enabled — every other schedule was merged into the first."
},
"legacyWindow": {
"section": "Reminder window (legacy)",
+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "End date must be on or after the start date."
},
"oneShot": {
"section": "Single dose"
"section": "Single dose",
"collapseWarning": "Single dose enabled — every other schedule was merged into the first."
},
"legacyWindow": {
"section": "Reminder window (legacy)",
+2 -1
View File
@@ -740,7 +740,8 @@
"invalidRange": "End date must be on or after the start date."
},
"oneShot": {
"section": "Single dose"
"section": "Single dose",
"collapseWarning": "Single dose enabled — every other schedule was merged into the first."
},
"legacyWindow": {
"section": "Reminder window (legacy)",
+28 -3
View File
@@ -70,10 +70,28 @@ import {
} from "@/components/medications/scheduling/TimesOfDayChips";
import { CourseWindowRow } from "@/components/medications/scheduling/CourseWindowRow";
import {
type CadenceKind,
type CadenceSubControls,
type CadenceValue,
DEFAULT_SUB_CONTROLS,
} from "@/components/medications/scheduling/types";
/**
* Cadence kinds the schedule-level picker exposes when the
* medication-level `oneShot` switch is off. `"oneShot"` lives on the
* medication-level switch above; surfacing it on the per-schedule
* picker would invite a contradictory shape (`oneShot = false` at the
* medication level + `cadence.kind = "oneShot"` on a schedule).
*/
const RECURRING_CADENCE_KINDS: readonly CadenceKind[] = [
"daily",
"weekdays",
"everyNWeeks",
"monthly",
"everyNMonths",
"yearly",
"rolling",
];
import {
inferCadenceFromLegacy,
legacyPairFromCadence,
@@ -860,9 +878,15 @@ export function MedicationForm({
onCheckedChange={(checked) => {
setOneShot(checked);
if (checked) {
// One-shot ⇒ collapse to a single schedule with one
// timesOfDay entry and no cadence; the picker stays
// hidden under `!oneShot` below.
// Flipping into one-shot collapses to a single
// schedule with one timesOfDay entry. Warn the user
// when this would drop additional schedules so the
// collapse stops being a silent data loss.
if (schedules.length > 1) {
toast.warning(
t("medications.scheduling.oneShot.collapseWarning"),
);
}
setSchedules((prev) => {
const head = prev[0] ?? { ...DEFAULT_SCHEDULE };
const singleTime =
@@ -998,6 +1022,7 @@ export function MedicationForm({
<CadencePicker
value={s.cadence}
subControls={s.cadenceSub}
allowedKinds={RECURRING_CADENCE_KINDS}
onChange={(nextValue, nextSub) =>
patchSchedule(i, {
cadence: nextValue,