/** * Onboarding React Query hooks */ import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'; import { onboardingService } from '../services/onboarding'; import { UserProgress, UpdateStepRequest } from '../types/onboarding'; import { ApiError } from '../client'; // Query Keys export const onboardingKeys = { all: ['onboarding'] as const, progress: (userId: string) => [...onboardingKeys.all, 'progress', userId] as const, steps: () => [...onboardingKeys.all, 'steps'] as const, stepDetail: (stepName: string) => [...onboardingKeys.steps(), stepName] as const, } as const; // Queries export const useUserProgress = ( userId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: onboardingKeys.progress(userId), queryFn: () => onboardingService.getUserProgress(userId), enabled: !!userId, staleTime: 30 * 1000, // 30 seconds ...options, }); }; export const useAllSteps = ( options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: onboardingKeys.steps(), queryFn: () => onboardingService.getAllSteps(), staleTime: 10 * 60 * 1000, // 10 minutes ...options, }); }; export const useStepDetails = ( stepName: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery<{ name: string; description: string; dependencies: string[]; estimated_time_minutes: number; }, ApiError>({ queryKey: onboardingKeys.stepDetail(stepName), queryFn: () => onboardingService.getStepDetails(stepName), enabled: !!stepName, staleTime: 10 * 60 * 1000, // 10 minutes ...options, }); }; // Mutations export const useUpdateStep = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ userId, stepData }) => onboardingService.updateStep(userId, stepData), onSuccess: (data, { userId }) => { // Update progress cache queryClient.setQueryData(onboardingKeys.progress(userId), data); }, ...options, }); }; export const useMarkStepCompleted = ( options?: UseMutationOptions< UserProgress, ApiError, { userId: string; stepName: string; data?: Record } > ) => { const queryClient = useQueryClient(); return useMutation< UserProgress, ApiError, { userId: string; stepName: string; data?: Record } >({ mutationFn: ({ userId, stepName, data }) => onboardingService.markStepCompleted(userId, stepName, data), onSuccess: (data, { userId }) => { // Update progress cache with new data queryClient.setQueryData(onboardingKeys.progress(userId), data); // Invalidate the query to ensure fresh data on next access queryClient.invalidateQueries({ queryKey: onboardingKeys.progress(userId) }); }, onError: (error, { userId, stepName }) => { console.error(`Failed to complete step ${stepName} for user ${userId}:`, error); // Invalidate queries on error to ensure we get fresh data queryClient.invalidateQueries({ queryKey: onboardingKeys.progress(userId) }); }, // Prevent duplicate requests by using the step name as a mutation key mutationKey: (variables) => ['markStepCompleted', variables?.userId, variables?.stepName], ...options, }); }; export const useResetProgress = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (userId: string) => onboardingService.resetProgress(userId), onSuccess: (data, userId) => { // Update progress cache queryClient.setQueryData(onboardingKeys.progress(userId), data); }, ...options, }); };