From ac9b88fa14c2924a1af4d9b50b222a5539279de7 Mon Sep 17 00:00:00 2001 From: juhyojeong Date: Sun, 11 Aug 2024 19:08:59 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A8=B8=EC=A7=80=20=ED=9B=84=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CasperCustom/CasperCustomFinish.tsx | 8 +++- .../CasperCustom/CasperCustomFinishing.tsx | 9 ++++- client/src/hooks/useBlockNavigation.ts | 37 +++++++++++++++++++ client/src/pages/CasperCustom/index.tsx | 14 ++++++- client/src/types/lotteryApi.ts | 3 +- 5 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 client/src/hooks/useBlockNavigation.ts diff --git a/client/src/features/CasperCustom/CasperCustomFinish.tsx b/client/src/features/CasperCustom/CasperCustomFinish.tsx index 54c4e1ed..4e0b8914 100644 --- a/client/src/features/CasperCustom/CasperCustomFinish.tsx +++ b/client/src/features/CasperCustom/CasperCustomFinish.tsx @@ -21,9 +21,13 @@ import ArrowIcon from "/public/assets/icons/arrow.svg?react"; interface CasperCustomFinishProps { handleResetStep: () => void; + unblockNavigation: () => void; } -export function CasperCustomFinish({ handleResetStep }: CasperCustomFinishProps) { +export function CasperCustomFinish({ + handleResetStep, + unblockNavigation, +}: CasperCustomFinishProps) { const [cookies] = useCookies([COOKIE_TOKEN_KEY]); const { @@ -41,6 +45,8 @@ export function CasperCustomFinish({ handleResetStep }: CasperCustomFinishProps) if (!cookies[COOKIE_TOKEN_KEY]) { return; } + + unblockNavigation(); getApplyCount(); }, [cookies]); diff --git a/client/src/features/CasperCustom/CasperCustomFinishing.tsx b/client/src/features/CasperCustom/CasperCustomFinishing.tsx index e99b4681..a5befcba 100644 --- a/client/src/features/CasperCustom/CasperCustomFinishing.tsx +++ b/client/src/features/CasperCustom/CasperCustomFinishing.tsx @@ -27,13 +27,18 @@ export function CasperCustomFinishing({ navigateNextStep }: CasperCustomFinishin useEffect(() => { showToast(); - setTimeout(() => { + const flipTimer = setTimeout(() => { setIsFlipped(true); }, 3000); - setTimeout(() => { + const navigateTimer = setTimeout(() => { navigateNextStep(); }, 6000); + + return () => { + clearTimeout(flipTimer); + clearTimeout(navigateTimer); + }; }, []); return ( diff --git a/client/src/hooks/useBlockNavigation.ts b/client/src/hooks/useBlockNavigation.ts new file mode 100644 index 00000000..e43d4c0c --- /dev/null +++ b/client/src/hooks/useBlockNavigation.ts @@ -0,0 +1,37 @@ +import { useEffect, useState } from "react"; +import { unstable_usePrompt, useLocation } from "react-router-dom"; + +export function useBlockNavigation(message: string) { + const location = useLocation(); + const [isBlocking, setIsBlocking] = useState(false); + + unstable_usePrompt({ when: isBlocking, message }); + + const unblockNavigation = () => { + setIsBlocking(false); + }; + + const handleBeforeUnload = (e: BeforeUnloadEvent) => { + if (isBlocking) { + e.preventDefault(); + e.returnValue = ""; + } + }; + + useEffect(() => { + setIsBlocking(true); + + return () => { + setIsBlocking(false); + }; + }, [location]); + useEffect(() => { + window.addEventListener("beforeunload", handleBeforeUnload); + + return () => { + window.removeEventListener("beforeunload", handleBeforeUnload); + }; + }, [isBlocking]); + + return { unblockNavigation }; +} diff --git a/client/src/pages/CasperCustom/index.tsx b/client/src/pages/CasperCustom/index.tsx index 91655af9..6155e1d9 100644 --- a/client/src/pages/CasperCustom/index.tsx +++ b/client/src/pages/CasperCustom/index.tsx @@ -14,12 +14,17 @@ import { CasperCustomForm, CasperCustomProcess, } from "@/features/CasperCustom"; +import { useBlockNavigation } from "@/hooks/useBlockNavigation"; import useHeaderStyleObserver from "@/hooks/useHeaderStyleObserver"; import { SCROLL_MOTION } from "../../constants/animation"; const INITIAL_STEP = 0; export default function CasperCustom() { + const { unblockNavigation } = useBlockNavigation( + "이 페이지를 떠나면 모든 변경 사항이 저장되지 않습니다. 페이지를 떠나시겠습니까?" + ); + const containerRef = useHeaderStyleObserver({ darkSections: [CASPER_CUSTOM_SECTIONS.CUSTOM], }); @@ -28,7 +33,7 @@ export default function CasperCustom() { const selectedStep = CUSTOM_STEP_OPTION_ARRAY[selectedStepIdx]; const handleClickNextStep = () => { - setSelectedStepIdx(selectedStepIdx + 1); + setSelectedStepIdx((prevSelectedIdx) => prevSelectedIdx + 1); }; const handleResetStep = () => { @@ -43,7 +48,12 @@ export default function CasperCustom() { } else if (selectedStep === CUSTOM_STEP_OPTION.FINISHING) { return ; } else if (selectedStep === CUSTOM_STEP_OPTION.FINISH) { - return ; + return ( + + ); } return <>; }; diff --git a/client/src/types/lotteryApi.ts b/client/src/types/lotteryApi.ts index 3b7d9c40..55b5253d 100644 --- a/client/src/types/lotteryApi.ts +++ b/client/src/types/lotteryApi.ts @@ -24,8 +24,7 @@ export interface GetApplyCountResponse { } export interface GetLotteryResponse { - lotteryEventId: number; eventStartDate: string; eventEndDate: string; - winnerCount: number; + activePeriod: number; }