import { InquiryList, Inquiry, InquirySaveResponse, CommonCode } from '@/types/Inquiry' import { useAxios } from '@/hooks/useAxios' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useInquiryFilterStore } from '@/store/inquiryFilterStore' import { useMemo } from 'react' import { useRouter } from 'next/navigation' import { useAlertMsg } from '@/hooks/useAlertMsg' import { CommCode } from '@/types/CommCode' /** * @description 문의사항 관련 기능을 제공하는 커스텀 훅 * * @param {number} [qnoNo] 문의사항 번호 * @param {string} [compCd] 회사 코드 * @returns {Object} 문의사항 관련 기능과 데이터 * @returns {InquiryList[]} inquiryList - 문의사항 목록 * @returns {boolean} isLoadingInquiryList - 문의사항 목록 로딩 상태 * @returns {Inquiry|null} inquiryDetail - 문의사항 상세 정보 * @returns {boolean} isLoadingInquiryDetail - 문의사항 상세 정보 로딩 상태 * @returns {boolean} isSavingInquiry - 문의사항 저장 중 상태 * @returns {Function} saveInquiry - 문의사항 저장 함수 * @returns {Function} downloadFile - 파일 다운로드 함수 * @returns {CommonCode[]} commonCodeList - 공통 코드 목록 */ export function useInquiry( qnoNo?: number, isList?: boolean, ): { inquiryList: InquiryList[] isLoadingInquiryList: boolean inquiryDetail: Inquiry | null isLoadingInquiryDetail: boolean isSavingInquiry: boolean saveInquiry: (formData: FormData) => Promise downloadFile: (encodeFileNo: number, srcFileNm: string) => Promise commonCodeList: CommonCode[] } { const queryClient = useQueryClient() const { inquiryListRequest, offset, isMyInquiry } = useInquiryFilterStore() const { axiosInstance } = useAxios() const router = useRouter() const { showErrorAlert } = useAlertMsg() /** * @description API 에러 처리 및 라우팅 * * @param {any} error 에러 객체 * @returns {void} 라우팅 처리 */ const handleError = (error: any, isThrow?: boolean) => { const status = error.response?.status const errorMsg = error.response?.data.error console.error('❌ AXIOS INSTANCE ERROR : ', error) if (errorMsg) { showErrorAlert(errorMsg) } if (isThrow) { throw new Error(error) } switch (status) { // session 없는 경우 case 401: router.replace('/login') break // 조회 권한 없는 경우 case 403: router.replace('/inquiry/list') break // 데이터 DB상 존재하지 않는 경우 case 404: router.replace('/inquiry/list') break // 서버 오류 case 500: router.back() break default: break } } /** * @description 비동기 함수 try-catch 처리 함수 * @param {() => Promise} func 비동기 함수 * @param {boolean} isList 목록 조회 여부 * @param {boolean} isThrow 에러 던지기 여부 * @returns {Promise} 함수 결과 또는 빈 데이터 */ const tryFunction = async (func: () => Promise, isList?: boolean, isThrow?: boolean): Promise => { try { return await func() } catch (error) { handleError(error, isThrow) if (isList) { return { data: [], count: 0 } } return null } } /** * @description 문의사항 목록 조회 * * @returns {Object} 문의사항 목록 데이터 * @returns {InquiryList[]} data - 문의사항 목록 * @returns {boolean} isLoading - 문의사항 목록 로딩 상태 */ const { data: inquiryList, isLoading: isLoadingInquiryList } = useQuery({ queryKey: ['inquiryList', inquiryListRequest.loginId, inquiryListRequest.schTitle, inquiryListRequest.schAnswerYn, offset, isMyInquiry], queryFn: async () => { const isListQuery = true const shouldThrowError = false const resp = await tryFunction( () => axiosInstance(null).get<{ data: InquiryList[] }>(`/api/qna/list`, { params: { inquiryListRequest, startRow: offset, endRow: offset + 9, schRegId: isMyInquiry }, }), isListQuery, shouldThrowError, ) return resp.data }, enabled: isList, }) /** * @description 문의사항 목록 데이터 메모이제이션 * * @returns {Object} 메모이제이션된 문의사항 목록 데이터 * @returns {InquiryList[]} inquiryList - 문의사항 목록 */ const inquriyListData = useMemo(() => { if (isLoadingInquiryList) { return { inquiryList: [] } } return { inquiryList: inquiryList ?? [], } }, [inquiryList, isLoadingInquiryList]) /** * @description 문의사항 상세 정보 조회 * * @returns {Object} 문의사항 상세 정보 데이터 * @returns {Inquiry|null} data - 문의사항 상세 정보 * @returns {boolean} isLoading - 문의사항 상세 정보 로딩 상태 */ const { data: inquiryDetail, isLoading: isLoadingInquiryDetail } = useQuery({ queryKey: ['inquiryDetail', qnoNo], queryFn: async () => { const isListQuery = false const shouldThrowError = false const resp = await tryFunction( () => axiosInstance(null).get<{ data: Inquiry }>(`/api/qna/detail`, { params: { qnoNo, compCd: '5200', langCd: 'JA' }, }), isListQuery, shouldThrowError, ) return resp?.data ?? null }, enabled: qnoNo !== undefined, }) /** * @description 문의사항 저장 * * @param {FormData} formData 저장할 문의사항 데이터 * @returns {Promise} 저장된 문의사항 응답 데이터 */ const { mutateAsync: saveInquiry, isPending: isSavingInquiry } = useMutation({ mutationFn: async (formData: FormData) => { const isListQuery = false const shouldThrowError = true const resp = await tryFunction( () => axiosInstance(null).post<{ data: InquirySaveResponse }>('/api/qna/save', formData), isListQuery, shouldThrowError, ) return resp?.data ?? null }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['inquiryList'] }) }, onError: (error: any) => { handleError(error, true) }, }) /** * @description 파일 다운로드 * * @param {number} encodeFileNo 인코딩된 파일 번호 * @param {string} srcFileNm 원본 파일명 * @returns {Promise} 다운로드된 파일 데이터 또는 null */ const downloadFile = async (encodeFileNo: number, srcFileNm: string) => { const isListQuery = false const shouldThrowError = true const resp = await tryFunction(() => fetch(`/api/qna/file?encodeFileNo=${encodeFileNo}&srcFileNm=${srcFileNm}`), isListQuery, shouldThrowError) const blob = await resp.blob() const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = srcFileNm document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) return blob } /** * @description 공통 코드 목록 조회 * * @returns {Object} 공통 코드 목록 데이터 * @returns {CommonCode[]} data - 공통 코드 목록 * @returns {boolean} isLoading - 공통 코드 목록 로딩 상태 */ const { data: commonCodeList, isLoading: isLoadingCommonCodeList } = useQuery({ queryKey: ['commonCodeList'], queryFn: async () => { const isListQuery = false const shouldThrowError = false const resp = await tryFunction( () => axiosInstance(null).get('/api/comm-code', { params: { headCode: 'QNA_CD' } }), isListQuery, shouldThrowError, ) return resp?.data ?? [] }, staleTime: Infinity, gcTime: Infinity, }) return { inquiryList: inquriyListData.inquiryList, inquiryDetail: inquiryDetail ?? null, isLoadingInquiryList, isLoadingInquiryDetail, isSavingInquiry, saveInquiry, downloadFile, commonCodeList: commonCodeList ?? [], } }