import { useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '../../shared/api/endpoints'; import { queryKeys } from '../../shared/api/queryKeys'; import type { Job, JobId, JobUpdate } from '../../shared/api/types/jobs'; type JobChange = { id: JobId; update: JobUpdate; }; function withJobChange( jobs: readonly Job[] | undefined, change: JobChange ): Job[] | undefined { return jobs?.map( ( job ) => job.id === change.id ? { ...job, ...change.update } : job ); } function withSavedJob( jobs: readonly Job[] | undefined, savedJob: Job ): Job[] | undefined { return jobs?.map( ( job ) => ( job.id === savedJob.id ? savedJob : job ) ); } export function useUpdateJob() { const queryClient = useQueryClient(); return useMutation( { mutationFn: ( change: JobChange ) => api.updateJob( change.id, change.update ), onMutate: async ( change: JobChange ) => { await queryClient.cancelQueries( { queryKey: queryKeys.jobs } ); const jobsBefore = queryClient.getQueryData< Job[] >( queryKeys.jobs ); queryClient.setQueryData< Job[] >( queryKeys.jobs, ( jobs ) => withJobChange( jobs, change ) ); return { jobsBefore }; }, onError: ( _error, _change, context ) => { queryClient.setQueryData( queryKeys.jobs, context?.jobsBefore ); }, onSuccess: ( savedJob: Job ) => { queryClient.setQueryData< Job[] >( queryKeys.jobs, ( jobs ) => withSavedJob( jobs, savedJob ) ); }, } ); } export function useRunJobs() { const queryClient = useQueryClient(); return useMutation( { mutationFn: () => api.runJobs(), onSuccess: ( jobs: Job[] ) => { queryClient.setQueryData( queryKeys.jobs, jobs ); void queryClient.invalidateQueries( { queryKey: queryKeys.status, } ); }, } ); }