mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
fix(reminders): an edit that does not change the cycle keeps the open slot
Renaming an overdue booster check-up on the web still moved it to next year. The edit sheet sends the first due date as the browser's local midnight on every save, a booster row stores the dose instant plus N days, and the route read the different instant as a new first due date. The route now compares the first due date by calendar day in the profile timezone and drops a resent same-day value from the write. The edit sheet sends only the fields that changed. Re-enabling a reminder that stays due after it is sent keeps the slot it was on instead of scheduling from now; a short-cycle reminder is still scheduled from now. Moving the notify hour later on the day a reminder was already sent carries the last-sent cursor along, so the slot does not go out a second time at the new hour.
This commit is contained in:
1 parent
31e4c95487
commit
7aefde67e2
5 files changed
+233
-26
No files matched your search
@@ -51,6 +51,10 @@ import {
|
||||
isOverdueDue,
|
||||
relativeDueKey,
|
||||
} from "@/lib/measurement-reminders/due-day";
|
||||
import {
|
||||
changedReminderFields,
|
||||
type ReminderEditBody,
|
||||
} from "@/lib/measurement-reminders/edit-body";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { applyOrder, useModuleListPrefs } from "@/lib/module-list-prefs";
|
||||
import { EncounterSheet } from "@/components/encounters/encounter-sheet";
|
||||
@@ -259,6 +263,8 @@ export function VorsorgeSection({
|
||||
setVisitSession((n) => n + 1);
|
||||
};
|
||||
const [form, setForm] = useState<FormState>(EMPTY_FORM);
|
||||
// The form as it opened, so an edit sends only what changed.
|
||||
const [initialForm, setInitialForm] = useState<FormState>(EMPTY_FORM);
|
||||
// The value-capture sheet: holds the reminder whose measurement we are
|
||||
// entering. Non-null ⇒ the MeasurementForm sheet is open for that row.
|
||||
const [capturing, setCapturing] = useState<MeasurementReminder | null>(null);
|
||||
@@ -292,7 +298,7 @@ export function VorsorgeSection({
|
||||
: interval != null
|
||||
? CADENCE_CUSTOM
|
||||
: "7";
|
||||
setForm({
|
||||
const opened: FormState = {
|
||||
label: resolveReminderLabel(reminder, t),
|
||||
kind: reminder.measurementType ? "type" : "freeText",
|
||||
measurementType: reminder.measurementType ?? "BLOOD_PRESSURE_SYS",
|
||||
@@ -303,7 +309,9 @@ export function VorsorgeSection({
|
||||
anchorDate: toDateInputValue(reminder.anchorDate),
|
||||
notifyHour: reminder.notifyHour,
|
||||
location: reminder.location ?? "",
|
||||
});
|
||||
};
|
||||
setForm(opened);
|
||||
setInitialForm(opened);
|
||||
setEditing(reminder);
|
||||
}
|
||||
|
||||
@@ -314,36 +322,45 @@ export function VorsorgeSection({
|
||||
|
||||
// Resolve the picker state to the mutually-exclusive cadence pair the
|
||||
// schema expects (exactly one of intervalDays / rrule).
|
||||
function resolveCadence(): {
|
||||
function resolveCadence(state: FormState): {
|
||||
intervalDays: number | null;
|
||||
rrule: string | null;
|
||||
} {
|
||||
if (form.cadenceChoice === CADENCE_RRULE) {
|
||||
const trimmed = form.rrule.trim();
|
||||
if (state.cadenceChoice === CADENCE_RRULE) {
|
||||
const trimmed = state.rrule.trim();
|
||||
return { intervalDays: null, rrule: trimmed || null };
|
||||
}
|
||||
if (form.cadenceChoice === CADENCE_CUSTOM) {
|
||||
return { intervalDays: form.customIntervalDays, rrule: null };
|
||||
if (state.cadenceChoice === CADENCE_CUSTOM) {
|
||||
return { intervalDays: state.customIntervalDays, rrule: null };
|
||||
}
|
||||
return { intervalDays: Number(form.cadenceChoice), rrule: null };
|
||||
return { intervalDays: Number(state.cadenceChoice), rrule: null };
|
||||
}
|
||||
|
||||
function toEditBody(state: FormState): ReminderEditBody {
|
||||
const { intervalDays, rrule } = resolveCadence(state);
|
||||
return {
|
||||
label: state.label.trim(),
|
||||
measurementType: state.kind === "type" ? state.measurementType : null,
|
||||
intervalDays,
|
||||
rrule,
|
||||
anchorDate: fromDateInputValue(state.anchorDate),
|
||||
notifyHour: state.notifyHour,
|
||||
location: state.location.trim() || null,
|
||||
};
|
||||
}
|
||||
|
||||
function submit() {
|
||||
const trimmed = form.label.trim();
|
||||
if (!trimmed) return;
|
||||
const { intervalDays, rrule } = resolveCadence();
|
||||
const body = {
|
||||
label: trimmed,
|
||||
measurementType: form.kind === "type" ? form.measurementType : null,
|
||||
intervalDays,
|
||||
rrule,
|
||||
anchorDate: fromDateInputValue(form.anchorDate),
|
||||
notifyHour: form.notifyHour,
|
||||
location: form.location.trim() || null,
|
||||
};
|
||||
const body = toEditBody(form);
|
||||
if (isEdit) {
|
||||
// Only what changed: an untouched first due date resent as local
|
||||
// midnight used to read as a new one and move an overdue check-up on.
|
||||
update.mutate(
|
||||
{ id: (editing as MeasurementReminder).id, body },
|
||||
{
|
||||
id: (editing as MeasurementReminder).id,
|
||||
body: changedReminderFields(toEditBody(initialForm), body),
|
||||
},
|
||||
{ onSuccess: closeSheet },
|
||||
);
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user