All files / src/hooks/usePartnerMutations usePartnerMutations.ts

100% Statements 23/23
100% Branches 4/4
100% Functions 9/9
100% Lines 22/22

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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                                                    10x 90x 90x   90x 7x     6x 6x     6x                               10x 93x   93x 8x           8x     8x     8x 2x             8x         5x 5x 5x         3x 1x          
/**
 * usePartnerMutations Hooks (Story 2.8.3)
 *
 * React Query mutation hooks for partner create/update operations with optimistic updates
 * AC 8 (Create Partnership), AC 9 (Edit Partnership)
 */
 
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { createPartner, updatePartner } from '@/services/api/partnerApi';
import type {
  PartnerResponse,
  CreatePartnerRequest,
  UpdatePartnerRequest,
} from '@/services/api/partnerApi';
 
/**
 * Create new partnership mutation
 *
 * Features:
 * - Automatic cache invalidation of partners list and statistics
 * - Navigation to detail view on success
 * - Error handling with correlation IDs
 *
 * @returns Mutation hook for creating partnerships
 */
export const useCreatePartner = () => {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
 
  return useMutation({
    mutationFn: (data: CreatePartnerRequest) => createPartner(data),
    onSuccess: (data) => {
      // Invalidate partners list and statistics to refetch with new partnership
      queryClient.invalidateQueries({ queryKey: ['partners'] });
      queryClient.invalidateQueries({ queryKey: ['partner-statistics'] });
 
      // Navigate to detail view
      navigate(`/organizer/partners/${data.companyName}`);
    },
  });
};
 
/**
 * Update existing partnership mutation with optimistic updates
 *
 * Features:
 * - Optimistic UI updates (immediate feedback)
 * - Rollback on error
 * - Cache invalidation of both list and detail
 * - Partial update support (only changed fields)
 *
 * @returns Mutation hook for updating partnerships
 */
export const useUpdatePartner = () => {
  const queryClient = useQueryClient();
 
  return useMutation({
    mutationFn: ({ companyName, data }: { companyName: string; data: UpdatePartnerRequest }) =>
      updatePartner(companyName, data),
 
    // Optimistic update (AC 9 - immediate UI feedback)
    onMutate: async ({ companyName, data }) => {
      // Cancel any outgoing refetches to prevent overwriting optimistic update
      await queryClient.cancelQueries({ queryKey: ['partner', companyName] });
 
      // Snapshot the previous value for rollback
      const previousPartner = queryClient.getQueryData(['partner', companyName, undefined]);
 
      // Optimistically update to the new value
      if (previousPartner) {
        queryClient.setQueryData(['partner', companyName, undefined], (old: PartnerResponse) => ({
          ...old,
          ...data,
        }));
      }
 
      // Return context with snapshot for rollback
      return { previousPartner };
    },
 
    // On success, invalidate caches to refetch fresh data
    onSuccess: (_, { companyName }) => {
      queryClient.invalidateQueries({ queryKey: ['partners'] });
      queryClient.invalidateQueries({ queryKey: ['partner', companyName] });
      queryClient.invalidateQueries({ queryKey: ['partner-statistics'] });
    },
 
    // Rollback on error (AC 9 - error handling with rollback)
    onError: (_error, { companyName }, context) => {
      if (context?.previousPartner) {
        queryClient.setQueryData(['partner', companyName, undefined], context.previousPartner);
      }
    },
  });
};