fix(forms): send one Idempotency-Key per opened create form

A mood, symptom, lab value, custom metric value, unscheduled dose,
allergy, vaccination, visit or measurement saved on a weak signal could
be stored twice: the POST committed, the answer missed the 15 s
timeout, the form said it could not save, and the second tap was a new
call with a new key, so the server ran it again.

useIdempotentPost keeps one key until a save lands and renews it for the
next entry, so the retry replays the first answer. The create forms and
the three create hooks post through it; the comment on the per-call key
in api-fetch now says what that key does and does not cover.

LabForm and MoodForm each gain the one line that mounts the key, so
their function-size baselines go up by one. The intake toast guard now
recognises a dose posted through the hook.
This commit is contained in:
Marc-André Bombeck committed 2026-11-11 20:02:40 +01:00
1 parent 121b23f4a2
commit f761500247
15 files changed
+172 -35

No files matched your search

+4 -2
View File
@@ -17,7 +17,8 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { apiPost, apiPut } from "@/lib/api/api-fetch";
import { apiPut } from "@/lib/api/api-fetch";
import { useIdempotentPost } from "@/lib/api/use-idempotent-post";
import { localizedApiError } from "@/lib/api/localized-error";
import {
allergyCategoryEnum,
@@ -67,6 +68,7 @@ export function AllergyForm({
footerSlot,
}: AllergyFormProps) {
const { t } = useTranslations();
const post = useIdempotentPost();
const formId = useId();
const [substance, setSubstance] = useState(existing?.substance ?? "");
@@ -106,7 +108,7 @@ export function AllergyForm({
try {
const saved = existing
? await apiPut<AllergyDTO>(`/api/allergies/${existing.id}`, body)
: await apiPost<AllergyDTO>("/api/allergies", body);
: await post<AllergyDTO>("/api/allergies", body);
toast.success(
existing
? t("records.allergies.form.updatedToast")