eletrotupi / tcc/ frontend/hooks/useSleepRecord.queries.ts24f49f7fa94d199c1c1ba1f8424a195cd7e6ee9d
2.9 KB | 105 lines Raw
1
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
2

3
import { apiClient, SleepRecord, SleepRecordPayload } from "@/lib/api";
4

5
export const sleepRecordKeys = {
6
  all: () => ["sleep-records"] as const,
7
  lists: () => [...sleepRecordKeys.all(), "list"] as const,
8
  list: (filters?: SleepRecordFilters) =>
9
    [...sleepRecordKeys.lists(), filters] as const,
10
  detail: (id: string) => [...sleepRecordKeys.all(), "detail", id] as const,
11
};
12

13
interface SleepRecordFilters {
14
  from?: string; // ISO date
15
  to?: string; // ISO date
16
  limit?: number;
17
}
18

19
export const useSleepRecords = (filters?: SleepRecordFilters) => {
20
  return useQuery({
21
    queryKey: sleepRecordKeys.list(filters),
22
    queryFn: () => apiClient.getSleepRecords(filters),
23
  });
24
};
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

35
export const useCreateSleepRecord = () => {
36
  const queryClient = useQueryClient();
37

38
  return useMutation({
39
    mutationFn: (payload: SleepRecordPayload) =>
40
      apiClient.createSleepRecord(payload),
41

42
    onMutate: async (payload) => {
43
      await queryClient.cancelQueries({ queryKey: sleepRecordKeys.lists() });
44

45
      const previous = queryClient.getQueryData(sleepRecordKeys.list());
46

47
      // TODO: might as well create a shared attrs that we're keeping it
48
      queryClient.setQueryData(
49
        sleepRecordKeys.list(),
50
        (old: SleepRecord[] = []) => [
51
          {
52
            ...payload,
53
            id: `temp-${Date.now()}`,
54
            createdAt: new Date().toISOString(),
55
            _optimistic: true,
56
          },
57
          ...old,
58
        ],
59
      );
60

61
      return { previous };
62
    },
63

64
    onError: (_err, _payload, context) => {
65
      if (context?.previous) {
66
        queryClient.setQueryData(sleepRecordKeys.list(), context.previous);
67
      }
68
    },
69

70
    onSuccess: () => {
71
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
72
    },
73
  });
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
};