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 { useSessionStore } from '@/store/session' import { useRouter } from 'next/navigation' /** * @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, compCd?: string, ): { 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 } = useInquiryFilterStore() const { session } = useSessionStore() const { axiosInstance } = useAxios() const router = useRouter() /** * @description API 에러 처리 및 라우팅 * * @param {any} error 에러 객체 * @returns {void} 라우팅 처리 */ const errorRouter = (error: any) => { const status = error.response?.status alert(error.response?.data.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 문의사항 목록 조회 * * @returns {Object} 문의사항 목록 데이터 * @returns {InquiryList[]} data - 문의사항 목록 * @returns {boolean} isLoading - 문의사항 목록 로딩 상태 */ const { data: inquiryList, isLoading: isLoadingInquiryList } = useQuery({ queryKey: ['inquiryList', inquiryListRequest, offset], queryFn: async () => { try { const resp = await axiosInstance(null).get<{ data: InquiryList[] }>(`/api/qna/list`, { params: { inquiryListRequest, startRow: offset, endRow: offset + 9 }, }) return resp.data.data } catch (error: any) { errorRouter(error) return [] } }, enabled: !!inquiryListRequest, }) /** * @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, compCd, session?.userId], queryFn: async () => { try { const resp = await axiosInstance(null).get<{ data: Inquiry }>(`/api/qna/detail`, { params: { qnoNo, compCd, langCd: 'JA', loginId: session?.userId ?? '' }, }) return resp.data.data } catch (error: any) { errorRouter(error) return null } }, enabled: qnoNo !== undefined && compCd !== undefined, }) /** * @description 문의사항 저장 * * @param {FormData} formData 저장할 문의사항 데이터 * @returns {Promise} 저장된 문의사항 응답 데이터 */ const { mutateAsync: saveInquiry, isPending: isSavingInquiry } = useMutation({ mutationFn: async (formData: FormData) => { const resp = await axiosInstance(null).post<{ data: InquirySaveResponse }>('/api/qna/save', formData) return resp.data.data }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['inquiryList'] }) }, onError: (error: any) => { errorRouter(error) }, }) /** * @description 파일 다운로드 * * @param {number} encodeFileNo 인코딩된 파일 번호 * @param {string} srcFileNm 원본 파일명 * @returns {Promise} 다운로드된 파일 데이터 또는 null */ const downloadFile = async (encodeFileNo: number, srcFileNm: string) => { try { const resp = await fetch(`/api/qna/file?encodeFileNo=${encodeFileNo}&srcFileNm=${srcFileNm}`) 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 } catch (error) { alert('ファイルのダウンロードに失敗しました') return null } } /** * @description 공통 코드 목록 조회 * * @returns {Object} 공통 코드 목록 데이터 * @returns {CommonCode[]} data - 공통 코드 목록 * @returns {boolean} isLoading - 공통 코드 목록 로딩 상태 */ const { data: commonCodeList, isLoading: isLoadingCommonCodeList } = useQuery({ queryKey: ['commonCodeList'], queryFn: async () => { const resp = await axiosInstance(null).get<{ data: CommonCode[] }>(`/api/qna`) return resp.data }, staleTime: Infinity, gcTime: Infinity, }) return { inquiryList: inquriyListData.inquiryList, inquiryDetail: inquiryDetail ?? null, isLoadingInquiryList, isLoadingInquiryDetail, isSavingInquiry, saveInquiry, downloadFile, commonCodeList: commonCodeList?.data ?? [], } }