eletrotupi / tcc/ commit / f57cb46

frontend/hooks: invalidation of insights when updating sleep & triggers

Pedro Lucas Porcellis porcellis@eletrotupi.com 1 month ago f57cb463988a5803d09ac705288c041a2cb7ea96
Parents: a7d36a3
3 file(s) changed
  • frontend/hooks/index.ts +10 -1
  • frontend/hooks/useSleepRecord.queries.ts +46 -1
  • frontend/hooks/useTrigger.queries.ts +45 -1
frontend/hooks/index.ts
1 1
// Legacy shit from react native
2 2
export { useThemeColor } from "@/hooks/use-theme-color";
3 3

4 4
export { useColorScheme } from "@/hooks/use-color-scheme";
5 5

▸ 7 unchanged lines
13 13
  useDeleteMoodEntry,
14 14
} from "@/hooks/useMoodEntries.queries";
15 15

16 16
export {
17 17
  useSleepRecords,
18 +
  useSleepRecord,
18 19
  useCreateSleepRecord,
20 +
  useUpdateSleepRecord,
21 +
  useDeleteSleepRecord,
19 22
} from "@/hooks/useSleepRecord.queries";
20 23

21 -
export { useTriggers, useCreateTrigger } from "@/hooks/useTrigger.queries";
24 +
export {
25 +
  useTriggers,
26 +
  useTrigger,
27 +
  useCreateTrigger,
28 +
  useUpdateTrigger,
29 +
  useDeleteTrigger,
30 +
} from "@/hooks/useTrigger.queries";
frontend/hooks/useSleepRecord.queries.ts
1 1
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
2 2

3 -
import { apiClient, SleepRecord, SleepRecordPayload } from "@/lib/api";
3 +
import { apiClient, SleepRecord, SleepRecordPayload, UpdateSleepRecordPayload } from "@/lib/api";
4 4
import { insightKeys } from "./useInsights.queries";
5 5

6 6
export const sleepRecordKeys = {
7 7
  all: () => ["sleep-records"] as const,
8 8
  lists: () => [...sleepRecordKeys.all(), "list"] as const,
▸ 61 unchanged lines
70 70

71 71
    onSuccess: () => {
72 72
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
73 73

74 74
      // Invalidate insights, so we can force refresh
75 +
      setTimeout(() => {
76 +
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("ENERGY_SLEEP_CORRELATION") });
77 +
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("DAILY_SLEEP") });
78 +
      }, 2000);
79 +
    },
80 +
  });
81 +
};
82 +

83 +
// Update a sleep record
84 +
export const useUpdateSleepRecord = () => {
85 +
  const queryClient = useQueryClient();
86 +

87 +
  return useMutation({
88 +
    mutationFn: ({ id, payload }: { id: string; payload: UpdateSleepRecordPayload }) =>
89 +
      apiClient.updateSleepRecord(id, payload),
90 +

91 +
    onMutate: async ({ id, payload }) => {
92 +
      await queryClient.cancelQueries({ queryKey: sleepRecordKeys.detail(id) });
93 +
      await queryClient.cancelQueries({ queryKey: sleepRecordKeys.lists() });
94 +

95 +
      const previousDetail = queryClient.getQueryData(sleepRecordKeys.detail(id));
96 +
      const previousList = queryClient.getQueryData(sleepRecordKeys.list());
97 +

98 +
      if (previousDetail) {
99 +
        queryClient.setQueryData(
100 +
          sleepRecordKeys.detail(id),
101 +
          (old: SleepRecord) => ({ ...old, ...payload }),
102 +
        );
103 +
      }
104 +

105 +
      return { previousDetail, previousList };
106 +
    },
107 +

108 +
    onError: (_err, { id }, context) => {
109 +
      if (context?.previousDetail) {
110 +
        queryClient.setQueryData(sleepRecordKeys.detail(id), context.previousDetail);
111 +
      }
112 +
      if (context?.previousList) {
113 +
        queryClient.setQueryData(sleepRecordKeys.list(), context.previousList);
114 +
      }
115 +
    },
116 +

117 +
    onSuccess: (_data, { id }) => {
118 +
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.detail(id) });
119 +
      queryClient.invalidateQueries({ queryKey: sleepRecordKeys.lists() });
75 120
      setTimeout(() => {
76 121
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("ENERGY_SLEEP_CORRELATION") });
77 122
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("DAILY_SLEEP") });
78 123
      }, 2000);
79 124
    },
▸ 32 unchanged lines
112 157
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("DAILY_SLEEP") });
113 158
      }, 2000);
114 159
    },
115 160
  });
116 161
};
frontend/hooks/useTrigger.queries.ts
1 1
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
2 2

3 -
import { apiClient, Trigger, CreateTriggerPayload } from "@/lib/api";
3 +
import { apiClient, Trigger, CreateTriggerPayload, UpdateTriggerPayload } from "@/lib/api";
4 4
import { insightKeys } from "@/hooks/useInsights.queries";
5 5

6 6
export const triggerKeys = {
7 7
  all: () => ["triggers"] as const,
8 8
  lists: () => [...triggerKeys.all(), "list"] as const,
▸ 71 unchanged lines
80 80

81 81
    // On success, replace optimistic record with real one from server
82 82
    onSuccess: () => {
83 83
      queryClient.invalidateQueries({ queryKey: triggerKeys.lists() });
84 84
      // Delay to allow the async queue job to finish writing the new insight row
85 +
      setTimeout(() => {
86 +
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("TRIGGER_PATTERN") });
87 +
      }, 2000);
88 +
    },
89 +
  });
90 +
};
91 +

92 +
// Update a trigger
93 +
export const useUpdateTrigger = () => {
94 +
  const queryClient = useQueryClient();
95 +

96 +
  return useMutation({
97 +
    mutationFn: ({ id, payload }: { id: string; payload: UpdateTriggerPayload }) =>
98 +
      apiClient.updateTrigger(id, payload),
99 +

100 +
    onMutate: async ({ id, payload }) => {
101 +
      await queryClient.cancelQueries({ queryKey: triggerKeys.detail(id) });
102 +
      await queryClient.cancelQueries({ queryKey: triggerKeys.lists() });
103 +

104 +
      const previousDetail = queryClient.getQueryData(triggerKeys.detail(id));
105 +
      const previousList = queryClient.getQueryData(triggerKeys.list());
106 +

107 +
      if (previousDetail) {
108 +
        queryClient.setQueryData(
109 +
          triggerKeys.detail(id),
110 +
          (old: Trigger) => ({ ...old, ...payload }),
111 +
        );
112 +
      }
113 +

114 +
      return { previousDetail, previousList };
115 +
    },
116 +

117 +
    onError: (_err, { id }, context) => {
118 +
      if (context?.previousDetail) {
119 +
        queryClient.setQueryData(triggerKeys.detail(id), context.previousDetail);
120 +
      }
121 +
      if (context?.previousList) {
122 +
        queryClient.setQueryData(triggerKeys.list(), context.previousList);
123 +
      }
124 +
    },
125 +

126 +
    onSuccess: (_data, { id }) => {
127 +
      queryClient.invalidateQueries({ queryKey: triggerKeys.detail(id) });
128 +
      queryClient.invalidateQueries({ queryKey: triggerKeys.lists() });
85 129
      setTimeout(() => {
86 130
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("TRIGGER_PATTERN") });
87 131
      }, 2000);
88 132
    },
89 133
  });
▸ 29 unchanged lines
119 163
        queryClient.invalidateQueries({ queryKey: insightKeys.byType("TRIGGER_PATTERN") });
120 164
      }, 2000);
121 165
    },
122 166
  });
123 167
};