mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
fix(api): return 409 on duplicate-timestamp measurement edit
The PUT /api/measurements/[id] handler dispatched the Prisma
update without a try/catch, so re-pointing measuredAt onto an
existing (userId, type, measuredAt, source, sleepStage) tuple
bubbled the P2002 violation as a 500 and the row-edit Sheet
rendered the generic save-error toast.
Mirror the POST handler's P2002 catch: return a clean 409 with a
stable `meta.errorCode = "measurement.duplicate_timestamp"` and a
new measurements.duplicateTimestamp i18n key across the six
locales. The mutation in measurement-list.tsx reads the error
code from the response envelope and surfaces the localised
banner instead of the upstream English fallback.
iOS contract — PATCH /api/measurements/{id}: additive. The 200
happy-path response shape (MeasurementWireDTO), the 422
validation path and the updateMeasurementSchema are untouched.
The new 409 path is strictly clearer than the 500 it replaces.
This commit is contained in:
1 parent
948fcd9318
commit
538b44f74d
9 files changed
+213
-10
No files matched your search
@@ -232,9 +232,24 @@ export function MeasurementList({ onEdit, onAddFirst }: MeasurementListProps) {
|
||||
}),
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
const json = (await res.json()) as {
|
||||
error?: string;
|
||||
meta?: { errorCode?: string };
|
||||
};
|
||||
if (!res.ok) {
|
||||
throw new Error(json.error ?? "Update failed");
|
||||
// v1.4.28 FB-B1 — the PUT route now returns a 409 with
|
||||
// `meta.errorCode === "measurement.duplicate_timestamp"` when
|
||||
// the edit collides with an existing row's
|
||||
// `(type, measuredAt, source, sleepStage)` tuple. Forward the
|
||||
// code alongside the message so `onError` can pick the
|
||||
// localised string.
|
||||
const err = new Error(json.error ?? "Update failed") as Error & {
|
||||
errorCode?: string;
|
||||
status?: number;
|
||||
};
|
||||
err.errorCode = json.meta?.errorCode;
|
||||
err.status = res.status;
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
onSuccess: async () => {
|
||||
@@ -243,6 +258,11 @@ export function MeasurementList({ onEdit, onAddFirst }: MeasurementListProps) {
|
||||
setEditError(null);
|
||||
},
|
||||
onError: (err) => {
|
||||
const errWithCode = err as Error & { errorCode?: string };
|
||||
if (errWithCode.errorCode === "measurement.duplicate_timestamp") {
|
||||
setEditError(t("measurements.duplicateTimestamp"));
|
||||
return;
|
||||
}
|
||||
setEditError(
|
||||
err instanceof Error ? err.message : t("measurements.saveError"),
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user