diff --git a/index.html b/index.html index 6a448a2..8a78056 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - MBTips + MBTips_MBTI AI 대화 시뮬레이션
diff --git a/package-lock.json b/package-lock.json index 0e4d4d2..171617a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-ga4": "^2.1.0", + "react-helmet": "^6.1.0", "react-router-dom": "^7.1.5", "tailwindcss": "^4.0.3", "zustand": "^5.0.3" @@ -24,6 +25,7 @@ "@types/node": "^22.13.13", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", + "@types/react-helmet": "^6.1.11", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.19.0", "eslint-config-prettier": "^10.0.1", @@ -1650,6 +1652,16 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/react-helmet": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz", + "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.27.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", @@ -4512,7 +4524,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4909,7 +4920,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4979,17 +4989,37 @@ "react": "^18.3.1" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, "node_modules/react-ga4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz", "integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==", "license": "MIT" }, + "node_modules/react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.3.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, "node_modules/react-refresh": { @@ -5042,6 +5072,15 @@ "react-dom": ">=18" } }, + "node_modules/react-side-effect": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", + "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", diff --git a/package.json b/package.json index e7aa450..cfe8e2e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-ga4": "^2.1.0", + "react-helmet": "^6.1.0", "react-router-dom": "^7.1.5", "tailwindcss": "^4.0.3", "zustand": "^5.0.3" @@ -27,6 +28,7 @@ "@types/node": "^22.13.13", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", + "@types/react-helmet": "^6.1.11", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.19.0", "eslint-config-prettier": "^10.0.1", diff --git a/public/image/og_image.png b/public/image/og_image.png new file mode 100644 index 0000000..186bef3 Binary files /dev/null and b/public/image/og_image.png differ diff --git a/src/App.tsx b/src/App.tsx index a7bd089..d4aae6c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import { useLocation } from "react-router-dom"; import { initGA, trackPageView } from "@/libs/analytics"; +import { Helmet } from "react-helmet"; import Home from "@/pages/Home"; import SelectInfo from "@/pages/SelectInfo"; import Chat from "@/pages/Chat"; @@ -102,6 +103,18 @@ const App = () => { onClose={() => setToastMessage("")} /> )} + + + + + + + + + } /> } /> @@ -118,7 +131,7 @@ const App = () => { } /> } /> } /> - } /> + } /> } /> diff --git a/src/components/header/MainHeader.tsx b/src/components/header/MainHeader.tsx index 8e734f0..b5fa4e2 100644 --- a/src/components/header/MainHeader.tsx +++ b/src/components/header/MainHeader.tsx @@ -11,7 +11,7 @@ const MainHeader = ({ isLoggedIn }: { isLoggedIn: boolean }) => { }; return ( -
+
{ }; return ( -
-
- -
- - {/* 메시지 리스트 */} - {messages.map((msg, idx) => ( -
- {/* 캐릭터 아이콘 */} - {msg.role === "assistant" && ( - MBTI ICON - )} - {/* 채팅 메시지 */} -
- + <> + + + + + + +
+
+ +
+ + {/* 메시지 리스트 */} + {messages.map((msg, idx) => ( +
+ {/* 캐릭터 아이콘 */} + {msg.role === "assistant" && ( + MBTI ICON + )} + {/* 채팅 메시지 */} +
+ +
-
- ))} + ))} -
-
+
+
+ + handleSend(input)} + /> - handleSend(input)} - /> - - {isOpen && } -
+ {isOpen && } +
+ ); }; diff --git a/src/pages/ChatRecommend.tsx b/src/pages/ChatRecommend.tsx index ef94f41..523a0b4 100644 --- a/src/pages/ChatRecommend.tsx +++ b/src/pages/ChatRecommend.tsx @@ -1,4 +1,5 @@ import { useParams } from "react-router-dom"; +import { Helmet } from "react-helmet"; import { Mbti } from "@/types/mbti"; import { chatRecommend } from "@/mock/chatRecommend"; import Header from "@/components/header/Header"; @@ -18,22 +19,30 @@ const ChatRecommend = () => { } else return ; return ( -
-
-
- mbti 이미지 + + + + + + +
+
-

{title}

- {description} -
-
+
+ mbti 이미지 +

{title}

+ {description} +
+
+ ); }; diff --git a/src/pages/ChatTemperature.tsx b/src/pages/ChatTemperature.tsx index 8037eaa..14aa2d3 100644 --- a/src/pages/ChatTemperature.tsx +++ b/src/pages/ChatTemperature.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; +import { Helmet } from "react-helmet"; import instance from "@/api/axios"; import Header from "@/components/header/Header"; @@ -31,28 +32,40 @@ const ChatTemperature = () => { }, []); return ( -
-
-
- mbti 온도 이미지 + + + + + + +
+
-

- 방금까지 나눈 대화로 온도를 측정했어요! -

- {temperature ? ( - - 현재까지 나눈 대화의 온도는 {temperature}도에요 - - ) : ( - - ...대화의 온도를 불러오는 중 - - )} -
-
+
+ mbti 온도 이미지 +

+ 방금까지 나눈 대화로 온도를 측정했어요! +

+ {temperature ? ( + + 현재까지 나눈 대화의 온도는 {temperature}도에요 + + ) : ( + + ...대화의 온도를 불러오는 중 + + )} +
+
+ ); }; diff --git a/src/pages/ChatTips.tsx b/src/pages/ChatTips.tsx index 1264cf9..b18352a 100644 --- a/src/pages/ChatTips.tsx +++ b/src/pages/ChatTips.tsx @@ -1,4 +1,5 @@ import { useParams } from "react-router-dom"; +import { Helmet } from "react-helmet"; import { Mbti } from "@/types/mbti"; import { tips } from "@/mock/tips"; import Header from "@/components/header/Header"; @@ -18,18 +19,30 @@ const ChatTips = () => { } else return ; return ( -
-
-
- mbti 이미지 + + + + + + +
+
-

{title}

- {description} -
-
+
+ mbti 이미지 +

{title}

+ {description} +
+
+ ); }; diff --git a/src/pages/Content.tsx b/src/pages/Content.tsx index 416d327..46a6be1 100644 --- a/src/pages/Content.tsx +++ b/src/pages/Content.tsx @@ -1,8 +1,9 @@ -import Header from "@/components/header/Header"; +import { Helmet } from "react-helmet"; +import { useNavigate, useParams } from "react-router-dom"; import { CONTENT_DATA } from "@/constants/CONTENT"; import { trackEvent } from "@/libs/analytics"; import React from "react"; -import { useNavigate, useParams } from "react-router-dom"; +import Header from "@/components/header/Header"; const Content = () => { const navigate = useNavigate(); @@ -33,44 +34,79 @@ const Content = () => { }; return ( -
-
+ <> + + + + + -
- {/* 상단 배너 */} -
- - - - {content.title} - -
+
+
- {/* 서브 제목 */} - {content.subTitle && ( -

- {content.subTitle} -

- )} +
+ {/* 상단 배너 */} +
+ + + + {content.title} + +
- {/* 본문 내용 */} -
- {content.content && renderContentWithLineBreaks(content.content)} -
+ {/* 서브 제목 */} + {content.subTitle && ( +

+ {content.subTitle} +

+ )} - {/* 하단 버튼 */} - + {/* 본문 내용 */} +
+ {content.content && renderContentWithLineBreaks(content.content)} +
+ + {/* 하단 버튼 */} + +
-
+ ); }; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index d3499a0..72a8ae1 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -10,6 +10,7 @@ import ChatStartButton from "@/components/button/ChatStartButton"; import Header from "@/components/header/Header"; import useAuthStore from "@/store/useAuthStore"; import ProfileContainer from "@/components/ProfileContainer"; +import { Helmet } from "react-helmet"; const Home = () => { const navigate = useNavigate(); @@ -34,37 +35,44 @@ const Home = () => { }, [isLoggedIn]); return ( -
-
-
-
- -
-
-
- -
-
- -
-
-
-
- -
-
- {isLoggedIn && virtualFreindList.length > 0 ? ( - - ) : ( - - )} -
-
-
-
+ <> + + + + + +
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ {isLoggedIn && virtualFreindList.length > 0 ? ( + + ) : ( + + )} +
+
+
+
+ ); }; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 619fbed..96a28cc 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { Helmet } from "react-helmet"; import KakaoLoginButton from "@/components/button/KakaoLoginButton"; import TermsAndPrivacy from "@/components/TermsAndPrivacy"; import TermsAndPrivacyModal from "@/components/modal/TermsAndPrivacyModal"; @@ -26,36 +27,44 @@ const Login = () => { const isTerms = isModalOpen.mode === "terms"; return ( -
- 로그인 페이지 이미지 -

- MBTI 성향 기반 -
- AI 채팅 시뮬레이션으로 -
- 대화 연습과 꿀팁 얻어가세요 -

-
- 대화 연습부터, 피드백까지 드려요 -
-
- -
-
- -
- {isOpen ? ( - isTerms ? ( - - ) : ( - - ) - ) : null} -
+ <> + + + + + + +
+ 로그인 페이지 이미지 +

+ MBTI 성향 기반 +
+ AI 채팅 시뮬레이션으로 +
+ 대화 연습과 꿀팁 얻어가세요 +

+
+ 대화 연습부터, 피드백까지 드려요 +
+
+ +
+
+ +
+ {isOpen ? ( + isTerms ? ( + + ) : ( + + ) + ) : null} +
+ ); }; diff --git a/src/pages/MbtiTestIntro.tsx b/src/pages/MbtiTestIntro.tsx index b167903..9a76258 100644 --- a/src/pages/MbtiTestIntro.tsx +++ b/src/pages/MbtiTestIntro.tsx @@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom"; import Header from "@/components/header/Header"; import useLayoutSize from "@/hooks/useLayoutSize"; import trackClickEvent from "@/utils/trackClickEvent"; +import { Helmet } from "react-helmet"; const MbtiTestIntro = () => { const [name, setName] = useState(""); @@ -29,45 +30,64 @@ const MbtiTestIntro = () => { }; return ( -
-
-
- intro image + + + - - 그 사람의 mbti는 뭘까? - -

- 상대방 MBTI -
- 유추 테스트 -

-
- - + + + + +
+
+
+ intro image - - -
-
+ + + + +
+
+ ); }; diff --git a/src/pages/MbtiTestQuestions.tsx b/src/pages/MbtiTestQuestions.tsx index 41256aa..3f84422 100644 --- a/src/pages/MbtiTestQuestions.tsx +++ b/src/pages/MbtiTestQuestions.tsx @@ -1,4 +1,5 @@ import { useEffect } from "react"; +import { Helmet } from "react-helmet"; import { trackPageView } from "@/libs/analytics"; import { TEST_QNA } from "@/constants/TEST_QNA"; import MbtiAnswerButtons from "@/components/button/MbtiAnswerButtons"; @@ -26,25 +27,44 @@ const MbtiTestQuestions = () => { const content: content = TEST_QNA[Number(currentPage) - 1]; return ( -
-
-
- - {content.number}/12 - -

- {content.question} -

- mbti 테스트 과정 이미지 + + + -
- -
-
-
+ + + + + +
+
+
+ + {content.number}/12 + +

+ {content.question} +

+ mbti 테스트 과정 이미지 +
+ +
+
+
+ ); } else return ; }; diff --git a/src/pages/MbtiTestResult.tsx b/src/pages/MbtiTestResult.tsx index f8a00e1..548ad0f 100644 --- a/src/pages/MbtiTestResult.tsx +++ b/src/pages/MbtiTestResult.tsx @@ -1,3 +1,5 @@ +import { useParams } from "react-router-dom"; +import { Helmet } from "react-helmet"; import { MBTI_RESULT_INFO } from "@/constants/MBTI_RESULT_INFO"; import ShareButton from "@/components/button/ShareButton"; import RestartButton from "@/components/button/RestartButton"; @@ -6,7 +8,7 @@ import useLayoutSize from "@/hooks/useLayoutSize"; import Header from "@/components/header/Header"; const MbtiTestResult = () => { - const mbti = localStorage.getItem("mbti-test-mbti") ?? ""; + const { mbti } = useParams(); const result = MBTI_RESULT_INFO[mbti as keyof typeof MBTI_RESULT_INFO]; const size = useLayoutSize(); const imageURL = @@ -19,52 +21,83 @@ const MbtiTestResult = () => { if (!result) return
404 error occured
; return ( -
-
-
- mbti 테스트 결과 이미지 + + -

- {mbti?.toUpperCase()}는 이런 성향이에요! -

-
    -
  • - {result.tag[0]} -
  • -
  • - {result.tag[1]} -
  • -
-
-

좋아하는 대화 주제

-
    -
  • {result.topic[0]}
  • -
  • {result.topic[1]}
  • -
-

좋아하는 대화 태도

-
    -
  • {result.attitude[0]}
  • -
  • {result.attitude[1]}
  • + + + + + + +
    +
    +
    + mbti 테스트 결과 이미지 +

    + {mbti?.toUpperCase()}는 이런 성향이에요! +

    +
      +
    • + {result.tag[0]} +
    • +
    • + {result.tag[1]} +
    -
    -
    - -
    -
    - - -
    -
-
+
+

좋아하는 대화 주제

+
    +
  • {result.topic[0]}
  • +
  • {result.topic[1]}
  • +
+

좋아하는 대화 태도

+
    +
  • {result.attitude[0]}
  • +
  • {result.attitude[1]}
  • +
+
+
+ +
+
+ + +
+ +
+ ); }; diff --git a/src/pages/SelectInfo.tsx b/src/pages/SelectInfo.tsx index 9b32639..c7b7db1 100644 --- a/src/pages/SelectInfo.tsx +++ b/src/pages/SelectInfo.tsx @@ -1,11 +1,12 @@ import { ChangeEvent, useEffect, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; -import FormButton from "@/components/button/FormButton"; -import Header from "@/components/header/Header"; +import { Helmet } from "react-helmet"; import { getMBTIgroup, mapAgeToNumber } from "@/utils/helpers"; import { authInstance } from "@/api/axios"; -import ToastMessage from "@/components/ToastMessage"; import { trackEvent } from "@/libs/analytics"; +import FormButton from "@/components/button/FormButton"; +import Header from "@/components/header/Header"; +import ToastMessage from "@/components/ToastMessage"; type FastFriendResponse = { header: { @@ -227,154 +228,177 @@ const SelectInfo = () => { }; return ( -
-
- -
- {/* MBTI 선택 */} -
-

- {selectInfoTitle} -

- -
- {mbtiOptions.map((option) => ( - handleMBTISelect(option)} - > - {option} - - ))} -
-
-
+ <> + + + + + -
- -
-
-

- 정보 추가 입력 -

- - {/* 이름 입력 */} -
- - -
+
+
- {/* 나이 선택 */} -
-

- 나이 +

+ {/* MBTI 선택 */} +
+

+ {selectInfoTitle}

-
- {ageOptions.map((option) => ( + +
+ {mbtiOptions.map((option) => ( handleButtonClick(option, setAge, age)} + size="md" + selected={isMBTISelected(option)} + onClick={() => handleMBTISelect(option)} > {option} ))}
+
+ +
- {/* 성별 선택 */} -
-

- 성별 +

+
+

+ 정보 추가 입력

-
- {genderOptions.map((option) => ( - handleButtonClick(option, setGender, gender)} - > - {option} - - ))} + + {/* 이름 입력 */} +
+ +
-
- {/* 관계 선택 */} -
-

- 상대방과 나의 관계 -

-
- {relationshipOptions.map((option) => ( - - handleButtonClick(option, setRelationship, relationship) - } - > - {option} - - ))} + {/* 나이 선택 */} +
+

+ 나이 +

+
+ {ageOptions.map((option) => ( + handleButtonClick(option, setAge, age)} + > + {option} + + ))} +
-
- {/* 관심사 선택 */} -
-

- 관심사 -

-
- {interestOptions.map((option) => ( - handleInterestSelect(option)} - > - {option} - - ))} + {/* 성별 선택 */} +
+

+ 성별 +

+
+ {genderOptions.map((option) => ( + handleButtonClick(option, setGender, gender)} + > + {option} + + ))} +
+
+ + {/* 관계 선택 */} +
+

+ 상대방과 나의 관계 +

+
+ {relationshipOptions.map((option) => ( + + handleButtonClick(option, setRelationship, relationship) + } + > + {option} + + ))} +
+
+ + {/* 관심사 선택 */} +
+

+ 관심사 +

+
+ {interestOptions.map((option) => ( + handleInterestSelect(option)} + > + {option} + + ))} +
-
- {toastMessage && ( - setToastMessage(null)} - /> - )} - - {/* 대화 시작 버튼 */} - + {toastMessage && ( + setToastMessage(null)} + /> + )} + + {/* 대화 시작 버튼 */} + +
-
+ ); }; diff --git a/src/store/useMbtiTestState.ts b/src/store/useMbtiTestState.ts index ed161bd..04ef13b 100644 --- a/src/store/useMbtiTestState.ts +++ b/src/store/useMbtiTestState.ts @@ -3,22 +3,131 @@ import { create } from "zustand"; type PageNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; interface MbtiTestState { - currentPage: PageNumber; - currentMbti: string; - mbtiLog: Record; - setNextStep: () => void; - setPreviousStep: () => void; - setMbtiLog: (mbti: string) => void; - getMbtiByLog: () => void; - validatePrevStepisComplete: (order: PageNumber) => boolean; - setPageComplete: (step: PageNumber) => void; - retry: () => void; + currentPage: PageNumber; + currentMbti: string; + pageIsCompleted: Record; + mbtiLog: Record; + setNextStep: () => void; + setPreviousStep: () => void; + setMbtiLog: (mbti: string) => void; + getMbtiByLog: () => void; + validatePrevStepisComplete: (order: PageNumber) => boolean; + setPageComplete: (step: PageNumber) => void; + retry: () => void; } const useMbtiTestState = create((set, get) => ({ - currentPage: 1, - currentMbti : "", - mbtiLog: { + currentPage: 1, + currentMbti: "", + pageIsCompleted: { + 1: false, + 2: false, + 3: false, + 4: false, + 5: false, + 6: false, + 7: false, + 8: false, + 9: false, + 10: false, + 11: false, + 12: false + }, + mbtiLog: { + E: 0, + I: 0, + N: 0, + S: 0, + F: 0, + T: 0, + J: 0, + P: 0 + }, + setNextStep: () => { + const currentPage = get().currentPage; + const currentMbti = get().currentMbti; + const setPageComplete = get().setPageComplete; + + setPageComplete(currentPage); // 현재 페이지를 완료로 설정 + + // 마지막 페이지라면 결과 페이지로 이동 + if (currentPage === 12) { + get().getMbtiByLog(); + if (currentMbti !== "") + window.location.href = `/mbti-test-result/${currentMbti}`; + else console.error("mbti가 비어있습니다."); + } else { + // 그렇지 않다면 페이지를 증가시킴 + set((state) => ({ + currentPage: (state.currentPage + 1) as PageNumber + })); + } + }, + setPreviousStep: () => { + const currentPage = get().currentPage; + if (currentPage > 1) { + // 페이지가 1보다 클 때만 감소 + set((state) => ({ + currentPage: (state.currentPage - 1) as PageNumber + })); + } + }, + setMbtiLog: (mbti: string) => { + set((state) => ({ + mbtiLog: { + ...state.mbtiLog, + [mbti]: state.mbtiLog[mbti] + 1 + } + })); + }, + getMbtiByLog: () => { + let mbti = ""; + const mbtiLog = get().mbtiLog; + if (mbtiLog.E > mbtiLog.I) mbti += "E"; + else mbti += "I"; + if (mbtiLog.N > mbtiLog.S) mbti += "N"; + else mbti += "S"; + if (mbtiLog.F > mbtiLog.T) mbti += "F"; + else mbti += "T"; + if (mbtiLog.J > mbtiLog.P) mbti += "J"; + else mbti += "P"; + set(() => ({ + currentMbti: mbti + })); + localStorage.setItem("mbti-test-mbti", mbti); + }, + validatePrevStepisComplete: (order: PageNumber) => { + if (order <= 1) { + return false; + } + return !!get().pageIsCompleted[(order - 1) as PageNumber]; + }, + setPageComplete: (step: PageNumber) => { + set((state) => ({ + pageIsCompleted: { + ...state.pageIsCompleted, + [step]: true + } + })); + }, + retry: () => { + set(() => ({ + currentPage: 1, + pageIsCompleted: { + 1: false, + 2: false, + 3: false, + 4: false, + 5: false, + 6: false, + 7: false, + 8: false, + 9: false, + 10: false, + 11: false, + 12: false + }, + log: { E: 0, I: 0, N: 0, @@ -26,98 +135,10 @@ const useMbtiTestState = create((set, get) => ({ F: 0, T: 0, J: 0, - P: 0, - }, - setNextStep: () => { - const currentPage = get().currentPage; - const setPageComplete = get().setPageComplete; - - setPageComplete(currentPage); // 현재 페이지를 완료로 설정 - - // 마지막 페이지라면 결과 페이지로 이동 - if (currentPage === 12) { - get().getMbtiByLog(); - if (get().currentMbti !== "") window.location.href="/mbti-test-result"; - else console.error("mbti가 비어있습니다."); - } else { - // 그렇지 않다면 페이지를 증가시킴 - set((state) => ({ - currentPage: (state.currentPage + 1) as PageNumber, - })); - } - - }, - setPreviousStep: () => { - const currentPage = get().currentPage; - if (currentPage > 1) { // 페이지가 1보다 클 때만 감소 - set((state) => ({ - currentPage: (state.currentPage - 1) as PageNumber, - })); - } - }, - setMbtiLog : (mbti : string) => { - set((state) => ({ - mbtiLog: { - ...state.mbtiLog, - [mbti]: state.mbtiLog[mbti] + 1, - }, - })); - }, - getMbtiByLog:()=>{ - let mbti =""; - const mbtiLog = get().mbtiLog; - if(mbtiLog.E>mbtiLog.I) mbti += "E"; else mbti += "I"; - if(mbtiLog.N>mbtiLog.S) mbti += "N"; else mbti += "S"; - if(mbtiLog.F>mbtiLog.T) mbti += "F"; else mbti += "T"; - if(mbtiLog.J>mbtiLog.P) mbti += "J"; else mbti += "P"; - set(() => ({ - currentMbti: mbti, - })); - localStorage.setItem("mbti-test-mbti", mbti); - }, - validatePrevStepisComplete: (order: PageNumber) => { - if (order <= 1) { - return false; - } - return !!get().pageIsCompleted[order - 1 as PageNumber]; - }, - setPageComplete: (step: PageNumber) => { - set((state) => ({ - pageIsCompleted: { - ...state.pageIsCompleted, - [step]: true, - }, - })); - }, - retry: ()=> { - set(() => ({ - currentPage: 1, - pageIsCompleted: { - 1: false, - 2: false, - 3: false, - 4: false, - 5: false, - 6: false, - 7: false, - 8: false, - 9: false, - 10: false, - 11: false, - 12: false, - }, - log: { - E: 0, - I: 0, - N: 0, - S: 0, - F: 0, - T: 0, - J: 0, - P: 0, - }, - })); - }, + P: 0 + } + })); + } })); -export default useMbtiTestState; \ No newline at end of file +export default useMbtiTestState;