frontend: fetch a single sleep entry record
Parents:
384a4a62 file(s) changed
- frontend/hooks/useSleepRecord.queries.ts +40 -0
- frontend/lib/api/client.ts +8 -0
frontend/hooks/useSleepRecord.queries.ts
1 1
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
2 2
3 3
import { apiClient, SleepRecord, SleepRecordPayload } from "@/lib/api";
4 4
5 5
export const sleepRecordKeys = {
▸ 15 unchanged lines
21 21
queryKey: sleepRecordKeys.list(filters),
22 22
queryFn: () => apiClient.getSleepRecords(filters),
23 23
});
24 24
};
25 25
26 +
// Single entry detail
27 +
export const useSleepRecord = (id: string) => {
28 +
return useQuery({
29 +
queryKey: sleepRecordKeys.detail(id),
30 +
queryFn: () => apiClient.getSleepRecord(id),
31 +
enabled: !!id,
32 +
});
33 +
};
34 +
26 35
export const useCreateSleepRecord = () => {
27 36
const queryClient = useQueryClient();
28 37
29 38
return useMutation({
30 39
mutationFn: (payload: SleepRecordPayload) =>
▸ 30 unchanged lines
61 70
onSuccess: () => {
62 71
queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
63 72
},
64 73
});
65 74
};
75 +
76 +
// Delete a sleep record with optimistic removal
77 +
export const useDeleteSleepRecord = () => {
78 +
const queryClient = useQueryClient();
79 +
80 +
return useMutation({
81 +
mutationFn: (id: string) => apiClient.deleteSleepRecord(id),
82 +
83 +
onMutate: async (id) => {
84 +
await queryClient.cancelQueries({ queryKey: sleepRecordKeys.lists() });
85 +
const previous = queryClient.getQueryData(sleepRecordKeys.list());
86 +
87 +
queryClient.setQueryData(
88 +
sleepRecordKeys.list(),
89 +
(old: SleepRecord[] = []) => old.filter((e) => e.id !== Number(id)),
90 +
);
91 +
92 +
return { previous };
93 +
},
94 +
95 +
onError: (_err, _id, context) => {
96 +
if (context?.previous) {
97 +
queryClient.setQueryData(sleepRecordKeys.list(), context.previous);
98 +
}
99 +
},
100 +
101 +
onSuccess: () => {
102 +
queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
103 +
},
104 +
});
105 +
};
frontend/lib/api/client.ts
1 1
import * as SecureStore from "expo-secure-store";
2 2
import {
3 3
User,
4 4
AuthResponse,
5 5
VerifyTokenResponse,
▸ 234 unchanged lines
240 240
241 241
const qs = query.toString();
242 242
return this.request(`/sleep_records${qs ? `?${qs}` : ""}`);
243 243
}
244 244
245 +
async getSleepRecord(id: string): Promise<SleepRecord> {
246 +
return this.request(`/sleep_records/${id}`);
247 +
}
248 +
249 +
async deleteSleepRecord(id: string): Promise<void> {
250 +
return this.request(`/sleep_records/${id}`, { method: "DELETE" });
251 +
}
252 +
245 253
// Trigger
246 254
async createTrigger(trigger: CreateTriggerPayload): Promise<TriggerResponse> {
247 255
return await this.request(`/triggers`, {
248 256
method: "POST",
249 257
body: JSON.stringify({ trigger }),
▸ 39 unchanged lines
289 297
return this.request(`/insights${qs ? `?${qs}` : ""}`);
290 298
}
291 299
}
292 300
293 301
export const apiClient = new ApiClient();