mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
fix(forms): close the sheet as soon as a save lands
Saving a weight, a mood, a workout, a measurement edit or a quick-add dose emptied the form and kept the button spinning until every read the write touches had refetched (snapshot, digest, charts, insights). On a slow connection that looked like nothing had been saved. The vaccination, visit, address-book, symptom and check-up hooks did the same through an onSuccess that returned the refetch, which a mutation waits for. The forms now report and close first and start the refresh without waiting for it; the hooks no longer return it. The quick-add loses a second sweep of the inline compliance charts that the medication bundle already covers, and its source pin follows.
This commit is contained in:
1 parent
971d5d32cc
commit
4721914cac
13 files changed
+56
-33
No files matched your search
@@ -105,6 +105,22 @@ describe("saveManualWorkout — the wire", () => {
|
||||
expect(keys).toContain(JSON.stringify(queryKeys.timelineRoot()));
|
||||
});
|
||||
|
||||
it("returns once the entry is stored, without waiting for the refetches", async () => {
|
||||
// The sheet closes on this answer; on a slow connection the reads it
|
||||
// refreshes can take seconds, and the person would watch a spinner.
|
||||
fetchSpy.mockResolvedValue(
|
||||
envelope({ entries: [{ index: 0, status: "inserted" }] }),
|
||||
);
|
||||
const client = {
|
||||
...fakeClient(),
|
||||
invalidateQueries: vi.fn(() => new Promise(() => {})),
|
||||
};
|
||||
|
||||
await expect(
|
||||
saveManualWorkout(ENTRY, client as unknown as QueryClient),
|
||||
).resolves.toBe("inserted");
|
||||
});
|
||||
|
||||
it("treats a duplicate (the same form submitted twice) as saved", async () => {
|
||||
fetchSpy.mockResolvedValue(
|
||||
envelope({ entries: [{ index: 0, status: "duplicate" }] }),
|
||||
|
||||
@@ -53,8 +53,8 @@ export async function deleteManualWorkout(
|
||||
): Promise<void> {
|
||||
await apiDelete(`/api/workouts/${encodeURIComponent(id)}`);
|
||||
queryClient.removeQueries({ queryKey: queryKeys.workoutDetail(id) });
|
||||
await invalidateKeys(queryClient, workoutDependentKeys);
|
||||
await refetchInactiveDailyReads(queryClient);
|
||||
void invalidateKeys(queryClient, workoutDependentKeys);
|
||||
void refetchInactiveDailyReads(queryClient);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,7 +94,8 @@ interface BatchResult {
|
||||
export type ManualWorkoutSaveOutcome = "inserted" | "duplicate" | "updated";
|
||||
|
||||
/**
|
||||
* Post the entry and refresh what shows workouts. A `duplicate` is a success:
|
||||
* Post the entry and start refreshing what shows workouts; the caller reports
|
||||
* the save without waiting for those reads. A `duplicate` is a success:
|
||||
* the same form already landed this session (a second tap, a retry), so the
|
||||
* row exists exactly once. A `skipped` entry was refused and throws.
|
||||
*/
|
||||
@@ -112,8 +113,8 @@ export async function saveManualWorkout(
|
||||
// The form also opens from the capture picker on any page, where the
|
||||
// Today hero and the dashboard snapshot are unmounted, so those two are
|
||||
// refetched outright.
|
||||
await invalidateKeys(queryClient, workoutDependentKeys);
|
||||
await refetchInactiveDailyReads(queryClient);
|
||||
void invalidateKeys(queryClient, workoutDependentKeys);
|
||||
void refetchInactiveDailyReads(queryClient);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user