mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
feat(medications): per-slot dose and units in the create wizard
Give each parallel schedule its own optional dose and units-per-dose input on the times step, so a split plan (a whole tablet in the morning, a half at noon) is ONE medication with three schedules instead of two drugs that double-count. Leaving both blank inherits the medication-level values, so a single-dose plan is unchanged. An as-needed slot that sits alongside scheduled ones now rides the same medication as a PRN schedule rather than flipping the whole-medication as-needed flag. New keys land in all six locales.
This commit is contained in:
1 parent
88123c53da
commit
64093d2124
8 files changed
+201
-3
No files matched your search
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Abends",
|
||||
"night": "Nachts"
|
||||
},
|
||||
"overrideHint": "Optional — für diese Uhrzeit eine abweichende Dosis oder Stückzahl festlegen. Leer lassen, um den Standard des Medikaments zu verwenden.",
|
||||
"doseOverrideLabel": "Dosis für diese Uhrzeit (optional)",
|
||||
"doseOverridePlaceholder": "z. B. eine halbe Tablette",
|
||||
"unitsOverrideLabel": "Verbrauchte Einheiten zu dieser Uhrzeit",
|
||||
"unitsOverrideInherit": "Standard",
|
||||
"short": "Zeiten"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Stelle speichern",
|
||||
"logInjectionSiteNoneAvailable": "Keine Injektionsstelle verfügbar — alle Stellen sind in deinen Einstellungen ausgeschlossen.",
|
||||
"logInjectionSiteSaveFailed": "Injektionsstelle konnte nicht gespeichert werden. Bitte versuche es erneut.",
|
||||
"perSlotUnits": "{units} pro Dosis",
|
||||
"trackInjectionSitesToggle": "Injektionsstellen erfassen",
|
||||
"trackInjectionSitesHint": "Nach einer eingenommenen Dosis nach der verwendeten Stelle fragen und die nächste Rotation vorschlagen.",
|
||||
"allowedSitesLabel": "Erlaubte Stellen",
|
||||
|
||||
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Evening",
|
||||
"night": "Night"
|
||||
},
|
||||
"overrideHint": "Optional — set a different dose or unit count just for this time of day. Leave blank to use the medication's default.",
|
||||
"doseOverrideLabel": "Dose for this time (optional)",
|
||||
"doseOverridePlaceholder": "e.g. half a tablet",
|
||||
"unitsOverrideLabel": "Units consumed at this time",
|
||||
"unitsOverrideInherit": "Default",
|
||||
"short": "Times"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Save site",
|
||||
"logInjectionSiteNoneAvailable": "No injection site is available — every site is excluded in your settings.",
|
||||
"logInjectionSiteSaveFailed": "Could not save the injection site. Please try again.",
|
||||
"perSlotUnits": "{units} per dose",
|
||||
"trackInjectionSitesToggle": "Track injection sites",
|
||||
"trackInjectionSitesHint": "After a dose is taken, ask which site was used and suggest the next rotation.",
|
||||
"allowedSitesLabel": "Allowed sites",
|
||||
|
||||
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Tarde",
|
||||
"night": "Noche"
|
||||
},
|
||||
"overrideHint": "Opcional: define una dosis o un número de unidades distinto solo para esta hora. Déjalo en blanco para usar el valor predeterminado del medicamento.",
|
||||
"doseOverrideLabel": "Dosis para esta hora (opcional)",
|
||||
"doseOverridePlaceholder": "p. ej. media pastilla",
|
||||
"unitsOverrideLabel": "Unidades consumidas a esta hora",
|
||||
"unitsOverrideInherit": "Predeterminado",
|
||||
"short": "Horas"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Guardar sitio",
|
||||
"logInjectionSiteNoneAvailable": "No hay ningún sitio de inyección disponible: todos los sitios están excluidos en tu configuración.",
|
||||
"logInjectionSiteSaveFailed": "No se pudo guardar el sitio de inyección. Inténtalo de nuevo.",
|
||||
"perSlotUnits": "{units} por dosis",
|
||||
"trackInjectionSitesToggle": "Registrar sitios de inyección",
|
||||
"trackInjectionSitesHint": "Tras administrar una dosis, pregunta qué sitio se usó y sugiere la siguiente rotación.",
|
||||
"allowedSitesLabel": "Sitios permitidos",
|
||||
|
||||
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Soir",
|
||||
"night": "Nuit"
|
||||
},
|
||||
"overrideHint": "Facultatif — définissez une dose ou un nombre d'unités différent pour cet horaire uniquement. Laissez vide pour utiliser la valeur par défaut du médicament.",
|
||||
"doseOverrideLabel": "Dose pour cet horaire (facultatif)",
|
||||
"doseOverridePlaceholder": "ex. un demi-comprimé",
|
||||
"unitsOverrideLabel": "Unités consommées à cet horaire",
|
||||
"unitsOverrideInherit": "Par défaut",
|
||||
"short": "Heures"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Enregistrer le site",
|
||||
"logInjectionSiteNoneAvailable": "Aucun site d'injection disponible — tous les sites sont exclus dans vos réglages.",
|
||||
"logInjectionSiteSaveFailed": "Impossible d’enregistrer le site d’injection. Veuillez réessayer.",
|
||||
"perSlotUnits": "{units} par dose",
|
||||
"trackInjectionSitesToggle": "Suivre les sites d'injection",
|
||||
"trackInjectionSitesHint": "Après la prise d'une dose, demander quel site a été utilisé et suggérer la prochaine rotation.",
|
||||
"allowedSitesLabel": "Sites autorisés",
|
||||
|
||||
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Sera",
|
||||
"night": "Notte"
|
||||
},
|
||||
"overrideHint": "Facoltativo: imposta una dose o un numero di unità diverso solo per questo orario. Lascia vuoto per usare il valore predefinito del farmaco.",
|
||||
"doseOverrideLabel": "Dose per questo orario (facoltativo)",
|
||||
"doseOverridePlaceholder": "es. mezza compressa",
|
||||
"unitsOverrideLabel": "Unità consumate a questo orario",
|
||||
"unitsOverrideInherit": "Predefinito",
|
||||
"short": "Orari"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Salva il sito",
|
||||
"logInjectionSiteNoneAvailable": "Nessun sito di iniezione disponibile: tutti i siti sono esclusi nelle tue impostazioni.",
|
||||
"logInjectionSiteSaveFailed": "Impossibile salvare il sito di iniezione. Riprova.",
|
||||
"perSlotUnits": "{units} per dose",
|
||||
"trackInjectionSitesToggle": "Registra i siti di iniezione",
|
||||
"trackInjectionSitesHint": "Dopo l'assunzione di una dose, chiedi quale sito è stato usato e suggerisci la rotazione successiva.",
|
||||
"allowedSitesLabel": "Siti consentiti",
|
||||
|
||||
@@ -1476,6 +1476,11 @@
|
||||
"evening": "Wieczór",
|
||||
"night": "Noc"
|
||||
},
|
||||
"overrideHint": "Opcjonalnie — ustaw inną dawkę lub liczbę jednostek tylko dla tej pory. Pozostaw puste, aby użyć wartości domyślnej leku.",
|
||||
"doseOverrideLabel": "Dawka dla tej pory (opcjonalnie)",
|
||||
"doseOverridePlaceholder": "np. pół tabletki",
|
||||
"unitsOverrideLabel": "Jednostki zużyte o tej porze",
|
||||
"unitsOverrideInherit": "Domyślnie",
|
||||
"short": "Godziny"
|
||||
},
|
||||
"step8": {
|
||||
@@ -2061,6 +2066,7 @@
|
||||
"logInjectionSiteConfirm": "Zapisz miejsce",
|
||||
"logInjectionSiteNoneAvailable": "Brak dostępnego miejsca iniekcji — wszystkie miejsca są wykluczone w Twoich ustawieniach.",
|
||||
"logInjectionSiteSaveFailed": "Nie udało się zapisać miejsca iniekcji. Spróbuj ponownie.",
|
||||
"perSlotUnits": "{units} na dawkę",
|
||||
"trackInjectionSitesToggle": "Rejestruj miejsca iniekcji",
|
||||
"trackInjectionSitesHint": "Po przyjęciu dawki zapytaj, którego miejsca użyto, i zaproponuj kolejną rotację.",
|
||||
"allowedSitesLabel": "Dozwolone miejsca",
|
||||
|
||||
@@ -5,6 +5,10 @@ import { Moon, Sun, Sunrise, Sunset } from "lucide-react";
|
||||
import { TimesOfDayChips } from "@/components/medications/scheduling/times-of-day-chips";
|
||||
import { DoseWindowEditor } from "@/components/medications/scheduling/dose-window-editor";
|
||||
import type { DoseWindowScale } from "@/components/medications/scheduling/dose-window";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { UNITS_PER_DOSE_OPTIONS } from "@/components/medications/units-per-dose";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
|
||||
import type { StepProps } from "./step1-name";
|
||||
@@ -105,6 +109,73 @@ export function Step7Times({ payload, applyPartial }: StepProps) {
|
||||
onChange={(doseWindows) => applyPartial({ doseWindows })}
|
||||
scale={scaleForCadence(payload)}
|
||||
/>
|
||||
|
||||
{/* #219 — per-schedule dose + units override. Leaving both blank keeps
|
||||
the medication-level values, so a single-dose plan is unchanged; a
|
||||
split plan (a whole tablet in the morning, a half at noon) sets a
|
||||
different value on each schedule of ONE medication. */}
|
||||
<div
|
||||
className="border-border/60 space-y-3 rounded-lg border p-3"
|
||||
data-slot="wizard-schedule-override"
|
||||
>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{t("medications.wizard.steps.step7.overrideHint")}
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="wizard-schedule-dose" className="text-sm">
|
||||
{t("medications.wizard.steps.step7.doseOverrideLabel")}
|
||||
</Label>
|
||||
<Input
|
||||
id="wizard-schedule-dose"
|
||||
type="text"
|
||||
value={payload.scheduleDose}
|
||||
onChange={(e) => applyPartial({ scheduleDose: e.target.value })}
|
||||
placeholder={t("medications.wizard.steps.step7.doseOverridePlaceholder")}
|
||||
maxLength={50}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label id="wizard-schedule-units-label" className="text-sm">
|
||||
{t("medications.wizard.steps.step7.unitsOverrideLabel")}
|
||||
</Label>
|
||||
<div
|
||||
role="group"
|
||||
aria-labelledby="wizard-schedule-units-label"
|
||||
data-slot="wizard-schedule-units"
|
||||
className="flex flex-wrap gap-1.5"
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={payload.scheduleUnitsPerDose === "" ? "default" : "outline"}
|
||||
aria-pressed={payload.scheduleUnitsPerDose === ""}
|
||||
className="min-w-10"
|
||||
onClick={() => applyPartial({ scheduleUnitsPerDose: "" })}
|
||||
>
|
||||
{t("medications.wizard.steps.step7.unitsOverrideInherit")}
|
||||
</Button>
|
||||
{UNITS_PER_DOSE_OPTIONS.map((opt) => {
|
||||
const selected = payload.scheduleUnitsPerDose === opt.raw;
|
||||
return (
|
||||
<Button
|
||||
key={opt.raw}
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={selected ? "default" : "outline"}
|
||||
aria-pressed={selected}
|
||||
className="min-w-10 tabular-nums"
|
||||
onClick={() =>
|
||||
applyPartial({ scheduleUnitsPerDose: opt.raw })
|
||||
}
|
||||
>
|
||||
{opt.label}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -183,6 +183,18 @@ export interface ScheduleDraft {
|
||||
cadence: CadenceValue;
|
||||
subControls: CadenceSubControls;
|
||||
timesOfDay: string[];
|
||||
/**
|
||||
* #219 — per-schedule dose override (empty = inherit the medication
|
||||
* `dose`). Lets a "1-0.5-0.5" split ride ONE medication with three
|
||||
* schedules at different doses instead of three separate drugs.
|
||||
*/
|
||||
dose?: string;
|
||||
/**
|
||||
* #219 — per-schedule units-consumed-per-dose (empty = inherit the
|
||||
* medication `unitsPerDose`). Decrements the right tablet count for a
|
||||
* morning-whole / noon-half plan.
|
||||
*/
|
||||
unitsPerDose?: string;
|
||||
/**
|
||||
* v1.15.18 — per-dose explicit on-time windows. One entry per dose
|
||||
* time the user widened beyond the symmetric ±1h default; a time with
|
||||
@@ -247,6 +259,15 @@ export interface WizardPayload {
|
||||
subControls: CadenceSubControls;
|
||||
/** Mirrors `schedules[activeScheduleIndex].timesOfDay`. */
|
||||
timesOfDay: string[];
|
||||
/**
|
||||
* #219 — mirrors `schedules[activeScheduleIndex].dose`. The per-slot
|
||||
* dose + units inputs on Step 7 read + write these flat slots; the
|
||||
* active-draft helpers keep them in sync with the schedule list. Empty
|
||||
* string = inherit the medication-level value.
|
||||
*/
|
||||
scheduleDose: string;
|
||||
/** #219 — mirrors `schedules[activeScheduleIndex].unitsPerDose`. */
|
||||
scheduleUnitsPerDose: string;
|
||||
/**
|
||||
* v1.15.18 — mirrors `schedules[activeScheduleIndex].doseWindows`. The
|
||||
* per-dose window editor in Step 7 reads + writes this flat slot; the
|
||||
@@ -298,6 +319,8 @@ export function emptyWizardPayload(): WizardPayload {
|
||||
cadence: draft.cadence,
|
||||
subControls: draft.subControls,
|
||||
timesOfDay: draft.timesOfDay,
|
||||
scheduleDose: draft.dose ?? "",
|
||||
scheduleUnitsPerDose: draft.unitsPerDose ?? "",
|
||||
doseWindows: draft.doseWindows ?? [],
|
||||
startsOn: todayUtc(),
|
||||
endsOn: null,
|
||||
@@ -326,6 +349,14 @@ export function commitActiveDraft(payload: WizardPayload): WizardPayload {
|
||||
cadence: payload.cadence,
|
||||
subControls: payload.subControls,
|
||||
timesOfDay: payload.timesOfDay,
|
||||
// #219 — project the per-slot dose / units flat mirror onto the draft.
|
||||
// Empty string collapses to undefined so the encode path omits the
|
||||
// field and the schedule inherits the medication-level value.
|
||||
dose: payload.scheduleDose.trim() === "" ? undefined : payload.scheduleDose,
|
||||
unitsPerDose:
|
||||
payload.scheduleUnitsPerDose.trim() === ""
|
||||
? undefined
|
||||
: payload.scheduleUnitsPerDose,
|
||||
doseWindows: payload.doseWindows,
|
||||
};
|
||||
const schedules = payload.schedules.slice();
|
||||
@@ -351,6 +382,8 @@ export function setActiveSchedule(
|
||||
cadence: draft.cadence,
|
||||
subControls: draft.subControls,
|
||||
timesOfDay: draft.timesOfDay,
|
||||
scheduleDose: draft.dose ?? "",
|
||||
scheduleUnitsPerDose: draft.unitsPerDose ?? "",
|
||||
doseWindows: draft.doseWindows ?? [],
|
||||
};
|
||||
}
|
||||
@@ -372,6 +405,8 @@ export function addSchedule(payload: WizardPayload): WizardPayload {
|
||||
cadence: draft.cadence,
|
||||
subControls: draft.subControls,
|
||||
timesOfDay: draft.timesOfDay,
|
||||
scheduleDose: draft.dose ?? "",
|
||||
scheduleUnitsPerDose: draft.unitsPerDose ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -397,6 +432,8 @@ export function removeSchedule(
|
||||
cadence: draft.cadence,
|
||||
subControls: draft.subControls,
|
||||
timesOfDay: draft.timesOfDay,
|
||||
scheduleDose: draft.dose ?? "",
|
||||
scheduleUnitsPerDose: draft.unitsPerDose ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -578,6 +615,17 @@ export interface CreateMedicationBody {
|
||||
rollingIntervalDays?: number;
|
||||
daysOfWeek?: number[];
|
||||
intervalWeeks?: number;
|
||||
/** #219 — per-schedule dose override. Omitted = inherit `dose`. */
|
||||
dose?: string;
|
||||
/** #219 — per-schedule units per dose. Omitted = inherit `unitsPerDose`. */
|
||||
unitsPerDose?: number;
|
||||
/**
|
||||
* #219 — schedule type. PRN routes a per-draft as-needed slot onto the
|
||||
* SAME medication (an as-needed extra dose alongside scheduled ones)
|
||||
* instead of flipping the whole-medication `asNeeded` flag. Omitted =
|
||||
* SCHEDULED.
|
||||
*/
|
||||
scheduleType?: "SCHEDULED" | "PRN";
|
||||
/** v1.15.18 — per-dose explicit on-time windows. Omitted when none. */
|
||||
doseWindows?: DoseWindowEntry[];
|
||||
}>;
|
||||
@@ -626,6 +674,11 @@ export function encodeScheduleDraft(
|
||||
oneShotMedication: boolean,
|
||||
): CreateMedicationBody["schedules"][number] {
|
||||
const isOneShot = oneShotMedication || draft.mode === "oneShot";
|
||||
// #219 — a per-draft as-needed slot rides the SAME medication as a PRN
|
||||
// schedule (never due / reminded / scored), so an as-needed extra dose
|
||||
// sits alongside the scheduled ones instead of splitting into a second
|
||||
// drug. A PRN slot carries no cadence.
|
||||
const isPrn = draft.mode === "asNeeded";
|
||||
const times = sortTimes(
|
||||
isOneShot ? draft.timesOfDay.slice(0, 1) : draft.timesOfDay,
|
||||
);
|
||||
@@ -638,6 +691,14 @@ export function encodeScheduleDraft(
|
||||
timesOfDay: times,
|
||||
};
|
||||
if (draft.id) out.id = draft.id;
|
||||
// #219 — per-slot dose + units overrides. Empty / whitespace collapses to
|
||||
// omitted so the schedule inherits the medication-level value.
|
||||
if (draft.dose && draft.dose.trim() !== "") out.dose = draft.dose.trim();
|
||||
if (draft.unitsPerDose && draft.unitsPerDose.trim() !== "") {
|
||||
const parsed = Number.parseFloat(draft.unitsPerDose);
|
||||
if (Number.isFinite(parsed) && parsed > 0) out.unitsPerDose = parsed;
|
||||
}
|
||||
if (isPrn) out.scheduleType = "PRN";
|
||||
// v1.15.18 — emit only the explicit windows that still name a live dose
|
||||
// time and actually differ from the default ±1h band (a point-equivalent
|
||||
// window leaves the column on the default derivation).
|
||||
@@ -648,7 +709,10 @@ export function encodeScheduleDraft(
|
||||
);
|
||||
if (windows.length > 0) out.doseWindows = windows;
|
||||
}
|
||||
if (!isOneShot) {
|
||||
// #219 — a PRN slot carries no cadence (the schedule validator rejects a
|
||||
// PRN with rrule / rollingIntervalDays), so suppress the recurrence block
|
||||
// exactly as the one-shot path does.
|
||||
if (!isOneShot && !isPrn) {
|
||||
if (draft.cadence.rrule !== null) {
|
||||
out.rrule = draft.cadence.rrule;
|
||||
} else if (draft.cadence.rollingIntervalDays !== null) {
|
||||
@@ -695,7 +759,15 @@ export function buildCreateBody(
|
||||
// v1.16.11 — an as-needed medication carries NO schedule at all; the
|
||||
// wizard clears the list client-side (the server 422s otherwise).
|
||||
const isOneShot = committed.mode === "oneShot";
|
||||
const isAsNeeded = committed.mode === "asNeeded";
|
||||
// #219 — an as-needed slot only flips the WHOLE-medication asNeeded flag
|
||||
// (zero schedules, never due / scored) when EVERY draft is as-needed. When
|
||||
// an as-needed draft sits alongside scheduled ones it is emitted as a PRN
|
||||
// schedule on the same medication (see `encodeScheduleDraft`), so a
|
||||
// scheduled plan can carry an as-needed extra dose without a second drug.
|
||||
const hasScheduledDraft = committed.schedules.some(
|
||||
(d) => d.mode !== "asNeeded",
|
||||
);
|
||||
const isAsNeeded = !isOneShot && !hasScheduledDraft;
|
||||
const draftsToEmit = isAsNeeded
|
||||
? []
|
||||
: isOneShot
|
||||
@@ -972,11 +1044,15 @@ export interface MedicationPayload {
|
||||
windowEnd: string;
|
||||
label?: string | null;
|
||||
dose?: string | null;
|
||||
/** #219 — per-schedule units per dose (edit-hydrate). NULL = inherit. */
|
||||
unitsPerDose?: number | null;
|
||||
daysOfWeek?: number[];
|
||||
intervalWeeks?: number;
|
||||
timesOfDay?: string[];
|
||||
rrule?: string | null;
|
||||
rollingIntervalDays?: number | null;
|
||||
/** #219 — per-schedule as-needed slot (PRN) round-trips as a mode. */
|
||||
scheduleType?: string | null;
|
||||
/** v1.15.18 — per-dose explicit on-time windows (edit-hydrate). */
|
||||
doseWindows?: DoseWindowEntry[] | null;
|
||||
}>;
|
||||
@@ -1004,6 +1080,9 @@ interface MedicationScheduleSnapshot {
|
||||
id?: string;
|
||||
windowStart: string;
|
||||
windowEnd: string;
|
||||
dose?: string | null;
|
||||
unitsPerDose?: number | null;
|
||||
scheduleType?: string | null;
|
||||
daysOfWeek?: number[];
|
||||
intervalWeeks?: number;
|
||||
timesOfDay?: string[];
|
||||
@@ -1023,13 +1102,23 @@ function hydrateScheduleDraft(
|
||||
: schedule.windowStart
|
||||
? [schedule.windowStart]
|
||||
: ["08:00"];
|
||||
// #219 — a PRN schedule round-trips as an as-needed draft; every other
|
||||
// type hydrates as recurring (one-shot is driven by the medication flag).
|
||||
const isPrn = !oneShot && schedule.scheduleType === "PRN";
|
||||
const draft: ScheduleDraft = {
|
||||
mode: oneShot ? "oneShot" : "recurring",
|
||||
mode: oneShot ? "oneShot" : isPrn ? "asNeeded" : "recurring",
|
||||
cadence: cadence.value,
|
||||
subControls: cadence.subControls,
|
||||
timesOfDay: times,
|
||||
};
|
||||
if (schedule.id) draft.id = schedule.id;
|
||||
// #219 — round-trip the per-slot dose + units so an edit keeps the split.
|
||||
if (typeof schedule.dose === "string" && schedule.dose.trim() !== "") {
|
||||
draft.dose = schedule.dose;
|
||||
}
|
||||
if (typeof schedule.unitsPerDose === "number" && schedule.unitsPerDose > 0) {
|
||||
draft.unitsPerDose = String(schedule.unitsPerDose);
|
||||
}
|
||||
// v1.15.18 — round-trip the persisted per-dose windows so an edit keeps
|
||||
// the user's explicit ranges instead of resetting them to the default.
|
||||
if (schedule.doseWindows && schedule.doseWindows.length > 0) {
|
||||
@@ -1089,6 +1178,8 @@ export function hydrateWizardPayload(
|
||||
cadence: first.cadence,
|
||||
subControls: first.subControls,
|
||||
timesOfDay: first.timesOfDay,
|
||||
scheduleDose: first.dose ?? "",
|
||||
scheduleUnitsPerDose: first.unitsPerDose ?? "",
|
||||
doseWindows: first.doseWindows ?? [],
|
||||
startsOn: initial.startsOn ?? base.startsOn,
|
||||
endsOn: initial.endsOn,
|
||||
|
||||
Reference in new issue
Block a user