All files / src/hooks/useQna useQna.ts

6.66% Statements 1/15
0% Branches 0/7
0% Functions 0/10
6.66% Lines 1/15

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                                  2x                                                                                                                        
/**
 * useQna Hook (Story 7.5 — "The Apéro Continues")
 *
 * React Query hooks for per-session Q&A.
 */
 
import {
  useMutation,
  useQuery,
  useQueryClient,
  type UseMutationResult,
  type UseQueryResult,
} from '@tanstack/react-query';
import axios from 'axios';
import * as qnaService from '@/services/qnaService';
import type { QnaWindowResponse, QnaPostResponse } from '@/services/qnaService';
 
export const QNA_QUERY_KEYS = {
  thread: (eventCode: string, sessionSlug: string) => ['qna', eventCode, sessionSlug] as const,
};
 
/**
 * Read a session's Q&A thread. A 404 (no window — event not completed) is NOT retried and surfaces
 * as `isError`, which the UI treats as "no Q&A for this session" (renders nothing).
 */
export function useSessionQna(
  eventCode: string,
  sessionSlug: string,
  enabled: boolean
): UseQueryResult<QnaWindowResponse, Error> {
  return useQuery({
    queryKey: QNA_QUERY_KEYS.thread(eventCode, sessionSlug),
    queryFn: () => qnaService.getThread(eventCode, sessionSlug),
    enabled: enabled && !!eventCode && !!sessionSlug,
    staleTime: 60 * 1000,
    retry: (failureCount, error) => {
      if (axios.isAxiosError(error) && error.response?.status === 404) {
        return false;
      }
      return failureCount < 2;
    },
  });
}
 
export interface AddPostVars {
  body: string;
  parentPostId?: string | null;
}
 
/** Post a question/answer; refreshes the thread on success. */
export function useAddQnaPost(
  eventCode: string,
  sessionSlug: string
): UseMutationResult<QnaPostResponse, Error, AddPostVars> {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: ({ body, parentPostId }) =>
      qnaService.addPost(eventCode, sessionSlug, body, parentPostId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: QNA_QUERY_KEYS.thread(eventCode, sessionSlug) });
    },
  });
}
 
/** Organizer takedown; refreshes the thread on success. */
export function useRemoveQnaPost(
  eventCode: string,
  sessionSlug: string
): UseMutationResult<void, Error, string> {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (postId) => qnaService.removePost(eventCode, sessionSlug, postId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: QNA_QUERY_KEYS.thread(eventCode, sessionSlug) });
    },
  });
}