All files / src/hooks useAiAssist.ts

100% Statements 29/29
100% Branches 4/4
100% Functions 9/9
100% Lines 29/29

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                                                86x   86x   3x 3x     1x   2x 2x 1x 1x             5x   5x   3x 3x 3x     2x   1x             5x 5x   5x   3x 3x   1x       2x           4x   4x   2x 2x     1x   1x          
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import apiClient from '@/services/api/apiClient';
 
interface DescriptionResponse {
  description: string;
}
interface ThemeImageRequest {
  seed?: string;
}
interface ThemeImageResponse {
  imageUrl: string;
  s3Key: string;
}
interface AbstractResponse {
  noPromotionScore: number;
  noPromotionFeedback: string;
  lessonsLearnedScore: number;
  lessonsLearnedFeedback: string;
  wordCount: number;
  shortenedAbstract: string | null;
}
 
export function useAiGenerateDescription(eventCode: string) {
  const { t } = useTranslation('organizer');
 
  return useMutation<DescriptionResponse, Error, void>({
    mutationFn: async () => {
      try {
        const response = await apiClient.post<DescriptionResponse>(
          `/events/${eventCode}/ai/description`
        );
        return response.data;
      } catch (err: unknown) {
        const axiosErr = err as { response?: { status?: number } };
        if (axiosErr?.response?.status === 503)
          throw new Error(t('aiAssist.disabled'), { cause: err });
        throw new Error(t('aiAssist.error'), { cause: err });
      }
    },
  });
}
 
export function useAiGenerateThemeImage(eventCode: string) {
  const { t } = useTranslation('organizer');
 
  return useMutation<ThemeImageResponse, Error, ThemeImageRequest>({
    mutationFn: async (req) => {
      try {
        const qs = req.seed ? `?seed=${encodeURIComponent(req.seed)}` : '';
        const response = await apiClient.post<ThemeImageResponse>(
          `/events/${eventCode}/ai/theme-image${qs}`
        );
        return response.data;
      } catch {
        throw new Error(t('aiAssist.error'));
      }
    },
  });
}
 
export function useAiApplyThemeImage(eventCode: string) {
  const queryClient = useQueryClient();
  const { t } = useTranslation('organizer');
 
  return useMutation<void, Error, { imageUrl: string }>({
    mutationFn: async ({ imageUrl }) => {
      try {
        await apiClient.post(`/events/${eventCode}/ai/theme-image/apply`, { imageUrl });
      } catch {
        throw new Error(t('aiAssist.error'));
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['event', eventCode] });
    },
  });
}
 
export function useAiAnalyzeAbstract(speakerPoolId: string) {
  const { t } = useTranslation('organizer');
 
  return useMutation<AbstractResponse, Error, void>({
    mutationFn: async () => {
      try {
        const response = await apiClient.post<AbstractResponse>(
          `/speakers/${speakerPoolId}/ai/analyze-abstract`
        );
        return response.data;
      } catch {
        throw new Error(t('aiAssist.error'));
      }
    },
  });
}