All files / src/hooks/useUserManagement useUpdateUserRoles.ts

94.11% Statements 16/17
66.66% Branches 4/6
100% Functions 8/8
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64                                22x 13x   13x 7x         7x     7x     7x     2x   2x   3x           7x         2x 2x 1x             7x 7x        
/**
 * useUpdateUserRoles Hook
 *
 * React Query mutation hook for updating user roles with optimistic updates.
 * Story 2.5.2: User Management Frontend - AC3
 */
 
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { updateUserRoles } from '@/services/api/userManagementApi';
import type { User, Role } from '@/types/user.types';
 
interface UpdateRolesParams {
  id: string;
  roles: Role[];
}
 
export const useUpdateUserRoles = () => {
  const queryClient = useQueryClient();
 
  return useMutation({
    mutationFn: ({ id, roles }: UpdateRolesParams) => updateUserRoles(id, roles),
 
    // Optimistic update
    onMutate: async ({ id, roles }) => {
      // Cancel any outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['users', 'list'] });
 
      // Snapshot the previous value
      const previousData = queryClient.getQueriesData({ queryKey: ['users', 'list'] });
 
      // Optimistically update all user list queries
      queryClient.setQueriesData(
        { queryKey: ['users', 'list'] },
        (old: { data: User[] } | undefined) => {
          Iif (!old?.data) return old;
 
          return {
            ...old,
            data: old.data.map((user: User) => (user.id === id ? { ...user, roles } : user)),
          };
        }
      );
 
      // Return context with previous data
      return { previousData };
    },
 
    // On error, rollback to previous state
    onError: (_err, _variables, context) => {
      Eif (context?.previousData) {
        context.previousData.forEach(([queryKey, data]) => {
          queryClient.setQueryData(queryKey, data);
        });
      }
    },
 
    // Always refetch after success or error
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['users', 'list'] });
      queryClient.invalidateQueries({ queryKey: ['users', 'detail'] });
    },
  });
};