From 7a67d62f0821eb2891c134633c8230d36db10c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8B=A4=EC=9D=80?= Date: Sun, 8 Sep 2024 23:51:31 +0900 Subject: [PATCH 01/10] =?UTF-8?q?Feat:=20step5=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=97=B0=EC=8A=B5=ED=9A=9F=EC=88=98atom=20=EC=A6=9D=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ProgressContents.jsx | 16 ++++++++-------- src/pages/practiceMode/step5/Step5.jsx | 26 +++++++++++++++++++++++--- src/pages/selectMode/SelectMode.jsx | 2 +- src/store/atom.js | 9 ++++++++- src/util/resetAtom.js | 1 + 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/pages/ProgressContents.jsx b/src/pages/ProgressContents.jsx index 3ec1634f..841fb6b1 100644 --- a/src/pages/ProgressContents.jsx +++ b/src/pages/ProgressContents.jsx @@ -80,14 +80,14 @@ const ProgressContents = ({ text, practiceMode, challengeMode }) => { // 현재 경로가 step0인지 확인하기 위한 변수 정의 const isStep0Path = location.pathname.includes("step0"); - // 시간이 초과되었을 때 타임아웃 모달 열리도록 설정 - useEffect(() => { - // 남은 시간 0 이하일 때만 모달이 열리도록 설정 - if (timeSpent <= 0 && !isStep0Path) { - setIsTimeoutModalContentsOpen(true); - setTimerControl(false); // 타이머 정지 - } - }, [timeSpent, setTimerControl]); + // // 시간이 초과되었을 때 타임아웃 모달 열리도록 설정 + // useEffect(() => { + // // 남은 시간 0 이하일 때만 모달이 열리도록 설정 + // if (timeSpent <= 0 && !isStep0Path) { + // setIsTimeoutModalContentsOpen(true); + // setTimerControl(false); // 타이머 정지 + // } + // }, [timeSpent, setTimerControl]); const handleModalOpen = () => { setIsModalOpen(true); diff --git a/src/pages/practiceMode/step5/Step5.jsx b/src/pages/practiceMode/step5/Step5.jsx index 9c0b857b..77acb656 100644 --- a/src/pages/practiceMode/step5/Step5.jsx +++ b/src/pages/practiceMode/step5/Step5.jsx @@ -1,8 +1,14 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import styled from "styled-components"; import Button from "../../../components/button/Button"; import { useAtom, useSetAtom } from "jotai"; -import { levelAtom, progressAtom, themeSiteAtom } from "../../../store/atom"; +import { + levelAtom, + progressAtom, + themeSiteAtom, + practiceCountAtom, + isPracticeCountIncreasedAtom +} from "../../../store/atom"; import { useNavigate } from "react-router-dom"; import resetAtom from "../../../util/resetAtom"; const Step5Container = styled.div` @@ -48,9 +54,23 @@ const Step5 = () => { const setThemeSite = useSetAtom(themeSiteAtom); + //연습 횟수 증가 로직 + const [practiceCount, setPracticeCount] = useAtom(practiceCountAtom); + const [isPracticeCountIncreased, setIsPracticeCountIncreased] = useAtom( + isPracticeCountIncreasedAtom + ); + const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { setProgress(5); - }, [setProgress]); + if (!isLoaded) { + setIsLoaded(true); + } + // 연습 횟수 증가 여부 확인후 증가 + if (!isPracticeCountIncreased && isLoaded) { + setPracticeCount((prev) => prev + 1); + setIsPracticeCountIncreased(true); + } + }, [isLoaded]); // 난이도 선택 창으로 const handlePracticeModeClick = () => { diff --git a/src/pages/selectMode/SelectMode.jsx b/src/pages/selectMode/SelectMode.jsx index baf58688..2fac5006 100644 --- a/src/pages/selectMode/SelectMode.jsx +++ b/src/pages/selectMode/SelectMode.jsx @@ -37,7 +37,7 @@ const SelectMode = () => { const PracticeCount = useAtomValue(practiceCountAtom); const nav = useNavigate(); - const recommendedMode = PracticeCount < 10 ? "연습모드" : "실전모드"; + const recommendedMode = PracticeCount < 15 ? "연습모드" : "실전모드"; const modes = ["연습모드", "실전모드"]; const handleClick = (mode) => { diff --git a/src/store/atom.js b/src/store/atom.js index e783b315..69bd7e4c 100644 --- a/src/store/atom.js +++ b/src/store/atom.js @@ -74,7 +74,14 @@ export const userNameAtom = atomWithStorage("userName", "", storage); export const userNameErrorAtom = atom(false); //연습모드 완료 횟수 -export const practiceCountAtom = atomWithStorage("practiceCount", 0, storage); +export const practiceCountAtom = atomWithStorage("practiceCount", 0); + +//practiceCount 증가 완료 +export const isPracticeCountIncreasedAtom = atomWithStorage( + "isPracticeCountIncreased", + false, + storage +); //좌석 매수 개수 export const seatCountAtom = atomWithStorage("seatCount", 0, storage); diff --git a/src/util/resetAtom.js b/src/util/resetAtom.js index 13049b46..ae3b86cb 100644 --- a/src/util/resetAtom.js +++ b/src/util/resetAtom.js @@ -13,6 +13,7 @@ const resetAtom = () => { sessionStorage.removeItem("minute"); sessionStorage.removeItem("helpTextNumber"); sessionStorage.removeItem("fakeAllowedSeat"); + sessionStorage.removeItem("isPracticeCountIncreased"); }; export default resetAtom; From 3cbffe6505a824f861c5383756bc6040f181073b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8B=A4=EC=9D=80?= Date: Fri, 13 Sep 2024 22:37:10 +0900 Subject: [PATCH 02/10] =?UTF-8?q?Fix:=20=EC=A2=8C=EC=84=9D/=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EB=AF=B8=EC=84=A0=ED=83=9D=EC=8B=9C=20alret=20?= =?UTF-8?q?=EB=82=98=ED=83=80=EB=82=98=EA=B2=8C,=20seatchart1=20=EC=97=90?= =?UTF-8?q?=20flex=EC=A0=81=EC=9A=A9=ED=95=B4=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95=EC=A0=95,SelectSeatchallengeMode?= =?UTF-8?q?=20=EC=B4=88=EA=B8=B0=ED=99=94=ED=95=98=EB=A9=B4=20atom=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/seatChart/SeatChart1.jsx | 10 ++++++++-- src/components/seatInfo/SeatInfo.jsx | 19 ++++++++++++------- .../selectSeat/SelectSeatChallangeMode.jsx | 11 +++++++++-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/components/seatChart/SeatChart1.jsx b/src/components/seatChart/SeatChart1.jsx index 325f6051..781ec716 100644 --- a/src/components/seatChart/SeatChart1.jsx +++ b/src/components/seatChart/SeatChart1.jsx @@ -9,6 +9,12 @@ const SectionName = styled.div` font-family: "pretendardB"; margin: 20px; `; +const SeatChartContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +`; const SeatChart = () => { const allowedSection = useAtomValue(allowedSectionAtom); @@ -26,10 +32,10 @@ const SeatChart = () => { useFakeAllowedSeat(0, 9, 9); return ( - <> + {allowedSection}구역 - + ); }; diff --git a/src/components/seatInfo/SeatInfo.jsx b/src/components/seatInfo/SeatInfo.jsx index 80164ca1..40e3f71c 100644 --- a/src/components/seatInfo/SeatInfo.jsx +++ b/src/components/seatInfo/SeatInfo.jsx @@ -2,6 +2,7 @@ import Button from "../button/Button"; import { useAtomValue, useAtom } from "jotai"; import { isSeatSelectedAtom, + isSectionSelectedAtom, allowedSeatAtom, levelAtom, postersAtom, @@ -30,6 +31,7 @@ import { useLocation } from "react-router-dom"; const SeatInfo = () => { const isSeatSelected = useAtomValue(isSeatSelectedAtom); + const isSectionSelected = useAtomValue(isSectionSelectedAtom); const allowedSeat = useAtomValue(allowedSeatAtom); const level = useAtomValue(levelAtom); const posters = useAtomValue(postersAtom); @@ -61,18 +63,21 @@ const SeatInfo = () => { const nav = useNavigate(); const handleButtonClick = () => { - if (themeSite === "practice") { - nav("../step3-1"); - return; - } if (isSeatSelected) { if (path.includes("challenge")) { nav("../step3/step4"); - } else { - nav("../step3-1"); + return; } - } else { + nav("../step3-1"); + } + + if (!isSectionSelected) { + alert("구역을 선택해주세요."); + return; + } + if (!isSeatSelected) { alert("좌석을 선택해주세요."); + return; } }; diff --git a/src/pages/challengeMode/selectSeat/SelectSeatChallangeMode.jsx b/src/pages/challengeMode/selectSeat/SelectSeatChallangeMode.jsx index b12cc928..9e0d182d 100644 --- a/src/pages/challengeMode/selectSeat/SelectSeatChallangeMode.jsx +++ b/src/pages/challengeMode/selectSeat/SelectSeatChallangeMode.jsx @@ -3,9 +3,10 @@ import styled from "styled-components"; import SecureModalContents from "../../../components/modal/modalContents/SecureModalContents"; import SeatChart from "../../../components/seatChart/SeatChart1"; import SeatSection from "../../../components/seatSection/SeatSection"; -import { useAtomValue, useSetAtom } from "jotai"; +import { useAtomValue, useSetAtom, useAtom } from "jotai"; import { isSectionSelectedAtom, + isSeatSelectedAtom, progressAtom, themeSiteAtom } from "../../../store/atom"; @@ -27,17 +28,23 @@ const SeatInfoContainer = styled.div` const TooltipText = styled.div` width: 380px; + font-size: 16px; font-family: PretendardM; `; const SelectSeatChallengeMode = () => { const [isModalOpen, setIsModalOpen] = useState(true); - const isSectionSelected = useAtomValue(isSectionSelectedAtom); + const [isSectionSelected, setIsSectionSelected] = useAtom( + isSectionSelectedAtom + ); + const [isSeatSelected, setIsSeatSelected] = useAtom(isSeatSelectedAtom); const setProgress = useSetAtom(progressAtom); const themeSite = useAtomValue(themeSiteAtom); useEffect(() => { setProgress(2); + setIsSectionSelected(false); + setIsSeatSelected(false); }, []); const closeModal = () => { From 773cdd6cc62d680436ffee7079289ea005f9d62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8B=A4=EC=9D=80?= Date: Fri, 13 Sep 2024 22:42:54 +0900 Subject: [PATCH 03/10] =?UTF-8?q?Fix:=20step3/step4=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EA=B3=A0=EC=B9=A8=EC=8B=9C=20seatCount=20Atom=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94,=20usevalidatehook=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A2=8C=EC=84=9D=EC=9D=84=20=EC=84=A0=ED=83=9D=ED=95=B4?= =?UTF-8?q?=EC=A3=BC=EC=84=B8=EC=9A=94->=EC=A2=8C=EC=84=9D=20=EB=A7=A4?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EC=84=A0=ED=83=9D=ED=95=B4=EC=A3=BC?= =?UTF-8?q?=EC=84=B8=EC=9A=94=20=EB=A1=9C=20=EB=B0=94=EA=BF=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SeatCount.jsx | 4 +++- src/hooks/useBookingValidate.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/SeatCount.jsx b/src/components/SeatCount.jsx index 7484adc6..690ba7d1 100644 --- a/src/components/SeatCount.jsx +++ b/src/components/SeatCount.jsx @@ -59,7 +59,9 @@ const SeatCount = () => { const handleSeatCountChange = (event) => { setSeatCount(Number(event.target.value)); }; - + useEffect(() => { + setSeatCount(0); + }, []); useEffect(() => { if (seatCount === 0 && level === "low") { setFocus(true); diff --git a/src/hooks/useBookingValidate.js b/src/hooks/useBookingValidate.js index 4e6e3932..121a79ea 100644 --- a/src/hooks/useBookingValidate.js +++ b/src/hooks/useBookingValidate.js @@ -20,7 +20,7 @@ export const useBookingValidate = ( // 연습모드 // 좌석 매수가 0일 경우 경고창 출력 if (seatCount === 0) { - alert("좌석을 선택해주세요."); + alert("좌석매수를 선택해주세요."); return; } addStage(2); From bc6c4f4bfee31f30d0d68e399ebea0da965a2bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8B=A4=EC=9D=80?= Date: Fri, 13 Sep 2024 23:02:24 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ProgressContents.jsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pages/ProgressContents.jsx b/src/pages/ProgressContents.jsx index 841fb6b1..3ec1634f 100644 --- a/src/pages/ProgressContents.jsx +++ b/src/pages/ProgressContents.jsx @@ -80,14 +80,14 @@ const ProgressContents = ({ text, practiceMode, challengeMode }) => { // 현재 경로가 step0인지 확인하기 위한 변수 정의 const isStep0Path = location.pathname.includes("step0"); - // // 시간이 초과되었을 때 타임아웃 모달 열리도록 설정 - // useEffect(() => { - // // 남은 시간 0 이하일 때만 모달이 열리도록 설정 - // if (timeSpent <= 0 && !isStep0Path) { - // setIsTimeoutModalContentsOpen(true); - // setTimerControl(false); // 타이머 정지 - // } - // }, [timeSpent, setTimerControl]); + // 시간이 초과되었을 때 타임아웃 모달 열리도록 설정 + useEffect(() => { + // 남은 시간 0 이하일 때만 모달이 열리도록 설정 + if (timeSpent <= 0 && !isStep0Path) { + setIsTimeoutModalContentsOpen(true); + setTimerControl(false); // 타이머 정지 + } + }, [timeSpent, setTimerControl]); const handleModalOpen = () => { setIsModalOpen(true); From 2147e8b238cf77a62b3ebbfc93d6813d611736c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8B=A4=EC=9D=80?= Date: Fri, 13 Sep 2024 23:05:30 +0900 Subject: [PATCH 05/10] =?UTF-8?q?Fix:=20s=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/card/settings/vertical/VerticalFront.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/card/settings/vertical/VerticalFront.jsx b/src/components/card/settings/vertical/VerticalFront.jsx index 3c0660b3..bcf2fd19 100644 --- a/src/components/card/settings/vertical/VerticalFront.jsx +++ b/src/components/card/settings/vertical/VerticalFront.jsx @@ -5,7 +5,7 @@ import { CardWrap, Number } from "../CardStyles"; const VerticalFront = () => { return ( - {/*카드 앞부분 */}s + {/*카드 앞부분 */} ); From 091b28b7728630ff9b130be2723f05ea3ee87172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=81?= <77565980+abyss-s@users.noreply.github.com> Date: Fri, 13 Sep 2024 23:06:23 +0900 Subject: [PATCH 06/10] =?UTF-8?q?Fix:=20=ED=83=80=EC=9E=84=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EB=AA=A8=EB=8B=AC=EC=B0=BD=20=EC=A0=9C=EC=96=B4?= =?UTF-8?q?=EC=8B=9C=20=EB=A1=9C=EB=94=A9=EC=B0=BD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ProgressContents.jsx | 125 +++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/src/pages/ProgressContents.jsx b/src/pages/ProgressContents.jsx index 3ec1634f..bdb0797d 100644 --- a/src/pages/ProgressContents.jsx +++ b/src/pages/ProgressContents.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import styled from "styled-components"; -import { useNavigate, useLocation, Outlet } from "react-router-dom"; +import { useLocation, Outlet } from "react-router-dom"; import { useAtom, useAtomValue, useSetAtom } from "jotai"; import Button from "../components/button/Button"; import Modal from "../components/modal/Modal"; @@ -76,18 +76,33 @@ const ProgressContents = ({ text, practiceMode, challengeMode }) => { // 일시정지 모달창 제어 const [isPaused, setIsPaused] = useState(false); - const path = useLocation().pathname; + const [isLoading, setIsLoading] = useState(true); + const location = useLocation(); + const path = location.pathname; // 현재 경로가 step0인지 확인하기 위한 변수 정의 - const isStep0Path = location.pathname.includes("step0"); + const isStep0Path = path.includes("step0"); // 시간이 초과되었을 때 타임아웃 모달 열리도록 설정 + useEffect(() => { + // 초기 로딩이 완료되면 로딩 상태를 false로 설정 + const timer = setTimeout(() => { + setIsLoading(false); + }, 100); // 0.1초 딜레이 + + return () => clearTimeout(timer); + }, []); + useEffect(() => { // 남은 시간 0 이하일 때만 모달이 열리도록 설정 - if (timeSpent <= 0 && !isStep0Path) { + if (isLoading) return; // 로딩 중일 때는 useEffect 실행하지 않음 + + if (isStep0Path) { + setIsTimeoutModalContentsOpen(false); + } else if (timeSpent <= 0) { setIsTimeoutModalContentsOpen(true); setTimerControl(false); // 타이머 정지 } - }, [timeSpent, setTimerControl]); + }, [timeSpent, isStep0Path, isLoading, setTimerControl]); const handleModalOpen = () => { setIsModalOpen(true); @@ -129,53 +144,61 @@ const ProgressContents = ({ text, practiceMode, challengeMode }) => { return ( {/*프로그래스 바*/} - - - - {/*고급 level일 경우에만 Timer 설정 */} - {/*모달이 열렸을 경우 Timer 정지 - isModalOpen, isPaused*/} - {level === "high" && themeSite === "practice" && } - {themeSite !== "practice" && } - {!path.includes("challenge") && {stepText}} - - {/*도움말 버튼 */} - {showHelpButton && ( - -