@@ -2,7 +2,11 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
22import { api } from "../api" ;
33import { DefaultMutationOptions , MutationFnAsync } from "./mutations" ;
44import { z } from "zod" ;
5- import { timeTrackingQueries } from "../queries/time-tracking" ;
5+ import {
6+ GetTimerResponse ,
7+ TimerResponse ,
8+ timeTrackingQueries ,
9+ } from "../queries/time-tracking" ;
610import { useTimeTrackingActions } from "@/hooks/useTimeTrackingStore" ;
711
812export const timeTrackingMutations = {
@@ -127,8 +131,24 @@ function useSaveTimer(options?: DefaultMutationOptions<SaveTimerPayload>) {
127131 } ) ;
128132}
129133
134+ function mergeOptimisticTimerEdit (
135+ timer : TimerResponse ,
136+ body : EditTimerPayload ,
137+ ) : TimerResponse {
138+ return {
139+ ...timer ,
140+ note : body . userNote ?? timer . note ,
141+ projectId : body . projectId ?? timer . projectId ,
142+ projectName : body . projectName ?? timer . projectName ,
143+ activityId : body . activityId ?? timer . activityId ,
144+ activityName : body . activityName ?? timer . activityName ,
145+ startTime : body . startTime ?? timer . startTime ,
146+ } ;
147+ }
148+
130149function useEditTimer ( options ?: DefaultMutationOptions < EditTimerPayload > ) {
131150 const queryClient = useQueryClient ( ) ;
151+ const timerQueryKey = timeTrackingQueries . getTimer ( ) . queryKey ;
132152
133153 return useMutation ( {
134154 mutationKey : [ "time-tracking" , "editTimer" ] ,
@@ -137,11 +157,48 @@ function useEditTimer(options?: DefaultMutationOptions<EditTimerPayload>) {
137157 json : body ,
138158 } ) ,
139159 ...options ,
160+ onMutate : async ( vars ) => {
161+ await queryClient . cancelQueries ( {
162+ queryKey : timerQueryKey ,
163+ } ) ;
164+
165+ const previousTimer =
166+ queryClient . getQueryData < GetTimerResponse > ( timerQueryKey ) ;
167+
168+ queryClient . setQueryData < GetTimerResponse | undefined > (
169+ timerQueryKey ,
170+ ( current ) =>
171+ current ?. timer
172+ ? {
173+ ...current ,
174+ timer : mergeOptimisticTimerEdit ( current . timer , vars ) ,
175+ }
176+ : current ,
177+ ) ;
178+
179+ const optionsContext = await options ?. onMutate ?.( vars ) ;
180+ return { previousTimer, optionsContext } satisfies {
181+ previousTimer : GetTimerResponse | undefined ;
182+ optionsContext : unknown ;
183+ } ;
184+ } ,
140185 onSuccess : ( data , v , c ) => {
186+ options ?. onSuccess ?.( data , v , c ?. optionsContext ) ;
187+ } ,
188+ onError : ( error , v , c ) => {
189+ if ( c ?. previousTimer !== undefined ) {
190+ queryClient . setQueryData < GetTimerResponse > (
191+ timerQueryKey ,
192+ c . previousTimer ,
193+ ) ;
194+ }
195+ options ?. onError ?.( error , v , c ?. optionsContext ) ;
196+ } ,
197+ onSettled : ( data , error , v , c ) => {
141198 queryClient . invalidateQueries ( {
142- queryKey : timeTrackingQueries . getTimer ( ) . queryKey ,
199+ queryKey : timerQueryKey ,
143200 } ) ;
144- options ?. onSuccess ?.( data , v , c ) ;
201+ options ?. onSettled ?.( data , error , v , c ?. optionsContext ) ;
145202 } ,
146203 } ) ;
147204}
0 commit comments