/** * Auth React Query hooks * Updated for atomic registration architecture with 3DS support */ import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'; import { authService } from '../services/auth'; import { UserRegistration, UserLogin, TokenResponse, PasswordChange, PasswordReset, UserResponse, UserUpdate, TokenVerification, RegistrationStartResponse, RegistrationCompletionResponse, RegistrationVerification, } from '../types/auth'; import { ApiError } from '../client'; import { useAuthStore } from '../../stores/auth.store'; // Query Keys export const authKeys = { all: ['auth'] as const, profile: () => [...authKeys.all, 'profile'] as const, health: () => [...authKeys.all, 'health'] as const, verify: (token?: string) => [...authKeys.all, 'verify', token] as const, } as const; // Queries export const useAuthProfile = ( options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: authKeys.profile(), queryFn: () => authService.getProfile(), staleTime: 5 * 60 * 1000, // 5 minutes ...options, }); }; export const useAuthHealth = ( options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery<{ status: string; service: string }, ApiError>({ queryKey: authKeys.health(), queryFn: () => authService.healthCheck(), staleTime: 30 * 1000, // 30 seconds ...options, }); }; export const useVerifyToken = ( token?: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: authKeys.verify(token), queryFn: () => authService.verifyToken(token), enabled: !!token, staleTime: 5 * 60 * 1000, // 5 minutes ...options, }); }; // Mutations export const useStartRegistration = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (userData: UserRegistration) => authService.startRegistration(userData), onSuccess: (data) => { // If no 3DS required, update profile query with new user data if (data.user) { queryClient.setQueryData(authKeys.profile(), data.user); } }, ...options, }); }; /** * Hook for completing registration after 3DS verification * This is the second step in the atomic registration flow */ export const useCompleteRegistration = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (verificationData: RegistrationVerification) => authService.completeRegistration(verificationData), onSuccess: (data) => { // Update profile query with new user data if (data.user) { queryClient.setQueryData(authKeys.profile(), data.user); } // Invalidate all queries to refresh data queryClient.invalidateQueries({ queryKey: ['auth'] }); }, ...options, }); }; export const useLogin = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (loginData: UserLogin) => authService.login(loginData), onSuccess: (data) => { // Update profile query with new user data if (data.user) { queryClient.setQueryData(authKeys.profile(), data.user); } // Invalidate all queries to refresh data queryClient.invalidateQueries({ queryKey: ['auth'] }); }, ...options, }); }; export const useRefreshToken = ( options?: UseMutationOptions ) => { return useMutation({ mutationFn: (refreshToken: string) => authService.refreshToken(refreshToken), ...options, }); }; export const useLogout = ( options?: UseMutationOptions<{ message: string }, ApiError, string> ) => { const queryClient = useQueryClient(); return useMutation<{ message: string }, ApiError, string>({ mutationFn: (refreshToken: string) => authService.logout(refreshToken), onSuccess: () => { // Clear all queries on logout queryClient.clear(); }, ...options, }); }; export const useChangePassword = ( options?: UseMutationOptions<{ message: string }, ApiError, PasswordChange> ) => { return useMutation<{ message: string }, ApiError, PasswordChange>({ mutationFn: (passwordData: PasswordChange) => authService.changePassword(passwordData), ...options, }); }; export const useResetPassword = ( options?: UseMutationOptions<{ message: string }, ApiError, PasswordReset> ) => { return useMutation<{ message: string }, ApiError, PasswordReset>({ mutationFn: (resetData: PasswordReset) => authService.resetPassword(resetData), ...options, }); }; export const useUpdateProfile = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (updateData: UserUpdate) => authService.updateProfile(updateData), onSuccess: (data) => { // Update the profile cache queryClient.setQueryData(authKeys.profile(), data); // Update the auth store user to maintain consistency const authStore = useAuthStore.getState(); if (authStore.user) { authStore.updateUser(data as any); } }, ...options, }); }; export const useVerifyEmail = ( options?: UseMutationOptions<{ message: string }, ApiError, { userId: string; verificationToken: string }> ) => { const queryClient = useQueryClient(); return useMutation<{ message: string }, ApiError, { userId: string; verificationToken: string }>({ mutationFn: ({ userId, verificationToken }) => authService.verifyEmail(userId, verificationToken), onSuccess: () => { // Invalidate profile to get updated verification status queryClient.invalidateQueries({ queryKey: authKeys.profile() }); }, ...options, }); };