From fcf87c153ec46c6cf802c3a829d0917ae95591d2 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Tue, 17 Jun 2025 15:40:14 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=A7=80=EB=B6=95=EC=9E=AC?= =?UTF-8?q?=EC=A0=81=ED=95=A9=EC=84=B1=20=EC=97=90=EB=9F=AC=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/popup/SuitableDetailPopup.tsx | 12 ++++-- src/components/suitable/SuitableButton.tsx | 8 +++- src/components/suitable/SuitableList.tsx | 7 ++++ src/hooks/useCommCode.ts | 2 +- src/hooks/useSuitable.ts | 44 +++++++++++++++----- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/components/popup/SuitableDetailPopup.tsx b/src/components/popup/SuitableDetailPopup.tsx index 6c41daf..7d45613 100644 --- a/src/components/popup/SuitableDetailPopup.tsx +++ b/src/components/popup/SuitableDetailPopup.tsx @@ -9,7 +9,7 @@ import { SUITABLE_HEAD_CODE, type Suitable, type SuitableDetail } from '@/types/ export default function SuitableDetailPopup() { const popupController = usePopupController() - const { toCodeName, toSuitableDetail, suitableCheckIcon, suitableCheckMemo, getSelectedSuitables } = useSuitable() + const { toCodeName, toSuitableDetail, suitableCheckIcon, suitableCheckMemo, getSelectedSuitables, suitableErrorAlert } = useSuitable() const [openItems, setOpenItems] = useState>(new Set()) const [selectedSuitables, setSelectedSuitables] = useState([]) @@ -24,9 +24,13 @@ export default function SuitableDetailPopup() { }, []) useEffect(() => { - getSelectedSuitables().then((res) => { - setSelectedSuitables(res) - }) + getSelectedSuitables() + .then((res) => { + setSelectedSuitables(res) + }) + .catch(() => { + suitableErrorAlert() + }) }, []) return ( diff --git a/src/components/suitable/SuitableButton.tsx b/src/components/suitable/SuitableButton.tsx index 3ce8a3c..ba2e7fa 100644 --- a/src/components/suitable/SuitableButton.tsx +++ b/src/components/suitable/SuitableButton.tsx @@ -6,12 +6,16 @@ import { useSuitableStore } from '@/store/useSuitableStore' export default function SuitableButton() { const popupController = usePopupController() - const { getSuitableIds, clearSuitableStore, downloadSuitablePdf } = useSuitable() + const { getSuitableIds, clearSuitableStore, downloadSuitablePdf, suitableErrorAlert } = useSuitable() const { selectedItems, addAllSelectedItem } = useSuitableStore() /* 데이터 전체 선택 */ const handleSelectAll = async () => { - addAllSelectedItem(await getSuitableIds()) + try { + addAllSelectedItem(await getSuitableIds()) + } catch (error) { + suitableErrorAlert() + } } /* 상세 팝업 열기 */ diff --git a/src/components/suitable/SuitableList.tsx b/src/components/suitable/SuitableList.tsx index 3e87f54..461beb9 100644 --- a/src/components/suitable/SuitableList.tsx +++ b/src/components/suitable/SuitableList.tsx @@ -19,7 +19,9 @@ export default function SuitableList() { hasNextPage, isFetchingNextPage, isLoading, + isError, suitableCheckIcon, + suitableErrorAlert, } = useSuitable() const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore() const [openItems, setOpenItems] = useState>(new Set()) @@ -144,6 +146,11 @@ export default function SuitableList() { useSpinnerStore.getState().setIsShow(isLoading || isFetchingNextPage) }, [isLoading, isFetchingNextPage]) + /* 조회 데이터 오류 처리 */ + useEffect(() => { + if (isError) suitableErrorAlert() + }, [isError]) + /* 조회 데이터 없는 경우 */ if (!suitableList.length) return diff --git a/src/hooks/useCommCode.ts b/src/hooks/useCommCode.ts index 6c78183..73f3918 100644 --- a/src/hooks/useCommCode.ts +++ b/src/hooks/useCommCode.ts @@ -9,7 +9,7 @@ export function useCommCode() { return response.data } catch (error) { console.error(`common code (${headCode}) load failed:`, error) - return [] + throw error } } diff --git a/src/hooks/useSuitable.ts b/src/hooks/useSuitable.ts index 4acb024..eb0b366 100644 --- a/src/hooks/useSuitable.ts +++ b/src/hooks/useSuitable.ts @@ -51,7 +51,7 @@ export function useSuitable() { return response.data } catch (error) { console.error(`지붕재 적합성 데이터 조회 실패: ${error}`) - return [] + throw error } } @@ -69,7 +69,7 @@ export function useSuitable() { return response.data } catch (error) { console.error(`지붕재 적합성 데이터 아이디 조회 실패: ${error}`) - return [] + throw error } } @@ -89,7 +89,7 @@ export function useSuitable() { return response.data } catch (error) { console.error(`지붕재 적합성 상세 데이터 조회 실패: ${error}`) - return [] + throw error } } @@ -101,9 +101,13 @@ export function useSuitable() { const getSuitableCommCode = (): void => { const headCodes = Object.values(SUITABLE_HEAD_CODE) as SUITABLE_HEAD_CODE[] for (const code of headCodes) { - getCommCode(code).then((res) => { - setSuitableCommCode(code, res) - }) + getCommCode(code) + .then((res) => { + setSuitableCommCode(code, res) + }) + .catch(() => { + suitableErrorAlert() + }) } } @@ -169,8 +173,8 @@ export function useSuitable() { hasNextPage, isFetchingNextPage, isLoading, - // isError, - // error, + isError, + error, } = useInfiniteQuery({ queryKey: ['suitables', 'list', searchCategory, searchKeyword], queryFn: async (context) => { @@ -189,6 +193,8 @@ export function useSuitable() { staleTime: 1000 * 60 * 10, gcTime: 1000 * 60 * 10, enabled: searchCategory !== '' || searchKeyword !== '', + retry: 1, + retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), }) /** @@ -263,8 +269,12 @@ export function useSuitable() { * @returns {Promise} 선택된 지붕재 적합성 데이터 */ const getSelectedSuitables = async (): Promise => { - const { ids, detailIds } = serializeSelectedItems() - return await getSuitableDetails(ids, detailIds) + try { + const { ids, detailIds } = serializeSelectedItems() + return await getSuitableDetails(ids, detailIds) + } catch (error) { + throw error + } } /** @@ -308,11 +318,20 @@ export function useSuitable() { document.body.removeChild(form) } catch (error) { console.error(`지붕재 적합성 상세 데이터 pdf 다운로드 실패: ${error}`) + suitableErrorAlert() } } + /** + * @description 지붕재 적합성 오류 알림 표시 + * + * @returns {void} + */ + const suitableErrorAlert = (): void => { + alert('一時的なエラーが発生しました。 継続的な場合は、管理者に連絡してください。') + } + return { - getSuitables, getSuitableIds, getSuitableCommCode, toCodeName, @@ -323,10 +342,13 @@ export function useSuitable() { hasNextPage, isFetchingNextPage, isLoading, + isError, + error, getSelectedSuitables, clearSuitableStore, suitableCheckIcon, suitableCheckMemo, downloadSuitablePdf, + suitableErrorAlert, } }