Skip to content

Commit 95242d2

Browse files
authored
Merge pull request #4 from CarToi/refactor/#2/legacy
[refactor] #2 기존 코드 구조 개선 및 재사용성 향상 작업
2 parents e78a3c4 + db0c7fa commit 95242d2

File tree

29 files changed

+634
-743
lines changed

29 files changed

+634
-743
lines changed

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
},
1111
"dependencies": {
1212
"axios": "^1.10.0",
13+
"clsx": "^2.1.1",
1314
"framer-motion": "^12.17.3",
1415
"next": "15.3.3",
1516
"postcss": "^8.5.5",
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
"use client";
22

3-
import Walk from "@/assets/icons/walk.png";
3+
import Logo from "@/assets/icons/logo.png";
4+
import { createNewUser } from "@/utils/createNewUser";
45
import Image from "next/image";
56
import { useEffect } from "react";
67

7-
export default function LandingPage3({ routing }) {
8+
export default function LandingPage({
9+
routing,
10+
}: {
11+
routing: (page: string) => void;
12+
}) {
813
useEffect(() => {
14+
createNewUser();
915
setTimeout(() => {
10-
routing("RecommendPage");
16+
routing("OnboardingSurvey");
1117
}, 1000);
12-
}, []);
18+
}, [routing]);
1319

1420
return (
1521
<div className="flex items-center w-full h-screen bg-[#F7F9FD]">
1622
<div className="flex flex-col items-center gap-[40px] w-full">
17-
<Image src={Walk} alt="" />
23+
<Image src={Logo} alt="" />
1824
<div className="flex flex-col items-center gap-[24px] w-full">
1925
<h2 className="text-[#142448] text-center text-[36px] font-[700] leading-[120%]">
20-
오늘의 기분에 딱 맞는
21-
<br />
22-
퇴근길을 고르는 중이이에요...
26+
새길에 오신 것을 환영해요!
2327
</h2>
2428
<p className="text-[#7F9CDC] text-center text-[22px] font-[600] leading-[150%]">
25-
조금만 기다려주세요
29+
먼저 간단한 정보부터 시작해볼까요?
2630
</p>
2731
</div>
2832
</div>
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export default function ProgressBar({ progress }) {
2-
return (
3-
<div className="w-full h-[12px] bg-[#CFDAF2]">
4-
<div
5-
className="h-[12px] bg-[#3560C0] rounded-lg"
6-
style={{ width: `${progress}%` }}
7-
></div>
8-
</div>
9-
);
10-
}
1+
export default function ProgressBar({ progress }) {
2+
return (
3+
<div className="w-full h-[12px] bg-[#CFDAF2]">
4+
<div
5+
className="h-[12px] bg-[#3560C0] rounded-lg"
6+
style={{ width: `${progress}%` }}
7+
></div>
8+
</div>
9+
);
10+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import clsx from "clsx";
2+
import Image from "next/image";
3+
import checkDefault from "@/assets/icons/check.png";
4+
import checkActive from "@/assets/icons/check_current.png";
5+
6+
interface SurveyOptionProps {
7+
text: string;
8+
isSelected: boolean;
9+
onClick: () => void;
10+
}
11+
12+
export default function SurveyOption({
13+
text,
14+
isSelected,
15+
onClick,
16+
}: SurveyOptionProps) {
17+
return (
18+
<div
19+
onClick={onClick}
20+
className={clsx(
21+
"flex justify-between items-center pl-[24px] pr-[40px] py-[16px] bg-[#F7F9FD] rounded-[12px] border-[2px]",
22+
isSelected ? "border-[#577DD1]" : "border-[#F7F9FD]"
23+
)}
24+
>
25+
<p
26+
className={clsx(
27+
"text-[20px] font-[600] leading-[150%]",
28+
isSelected ? "text-[#3560C0]" : "text-[#B3B9C6]"
29+
)}
30+
>
31+
{text}
32+
</p>
33+
<Image src={isSelected ? checkActive : checkDefault} alt="" />
34+
</div>
35+
);
36+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { useState } from "react";
2+
import { surveyData } from "@/constants/surveyData";
3+
4+
interface UseSurveyProps {
5+
type: "onboarding" | "todayMood";
6+
routing: (page: string) => void;
7+
}
8+
9+
export default function useSurvey({ type, routing }: UseSurveyProps) {
10+
const questions = surveyData[type];
11+
const storageKey = `${type}Answers`;
12+
13+
const [answers, setAnswers] = useState(
14+
JSON.parse(localStorage.getItem(storageKey) ?? "[]")
15+
);
16+
17+
const [currentQuestion, setCurrentQuestion] = useState(0);
18+
19+
const progress =
20+
((questions.length -
21+
answers.filter((element: string) => element === "").length) /
22+
questions.length) *
23+
100;
24+
25+
const handleAnswerClick = (answer: string) => {
26+
const updatedAnswers = [...answers];
27+
updatedAnswers[currentQuestion] = answer;
28+
localStorage.setItem(storageKey, JSON.stringify(updatedAnswers));
29+
setAnswers(updatedAnswers);
30+
};
31+
32+
const handlePrevClick = () => {
33+
setCurrentQuestion((prev) => prev - 1);
34+
};
35+
36+
const handleNextClick = () => {
37+
if (currentQuestion === questions.length - 1) {
38+
routing(
39+
type === "onboarding" ? "ToMoodTransition" : "ToRecommendTransition"
40+
);
41+
} else {
42+
setCurrentQuestion((prev) => prev + 1);
43+
}
44+
};
45+
46+
return {
47+
questions,
48+
answers,
49+
progress,
50+
currentQuestion,
51+
handleAnswerClick,
52+
handlePrevClick,
53+
handleNextClick,
54+
};
55+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"use client";
2+
3+
import useSurvey from "./hooks/useSurvey";
4+
import ProgressBar from "@/app/_components/SurveyScreen/ProgressBar";
5+
import SurveyOption from "./SurveyOption";
6+
import Button from "@/components/Button";
7+
8+
interface SurveyScreenProps {
9+
type: "onboarding" | "todayMood";
10+
routing: (page: string) => void;
11+
}
12+
13+
export default function SurveyScreen({ type, routing }: SurveyScreenProps) {
14+
const {
15+
questions,
16+
answers,
17+
progress,
18+
currentQuestion,
19+
handleAnswerClick,
20+
handlePrevClick,
21+
handleNextClick,
22+
} = useSurvey({ type, routing });
23+
24+
return (
25+
<div className="flex flex-col justify-between items-center w-full h-screen">
26+
<ProgressBar progress={progress} />
27+
<div className="flex flex-col justify-center gap-[64px] w-[700px]">
28+
<div className="flex flex-col justify-between gap-[12px]">
29+
<h2 className="text-[#1F2229] text-[28px] font-[600] leading-[120%]">
30+
{questions[currentQuestion].title}
31+
</h2>
32+
<p className="text-[#79839A] text-[20px] font-[600] leading-[150%]">
33+
{questions[currentQuestion].contents}
34+
</p>
35+
</div>
36+
<div className="flex flex-col justify-between gap-[12px] w-[700px]">
37+
{questions[currentQuestion].items.map((item, index) => (
38+
<SurveyOption
39+
key={index}
40+
text={item}
41+
isSelected={item === answers[currentQuestion]}
42+
onClick={() => handleAnswerClick(item)}
43+
/>
44+
))}
45+
</div>
46+
<div className="flex gap-[12px] items-center self-end">
47+
{currentQuestion > 0 && (
48+
<Button variant="secondary" width={120} onClick={handlePrevClick}>
49+
이전
50+
</Button>
51+
)}
52+
<Button
53+
variant="primary"
54+
width={120}
55+
onClick={handleNextClick}
56+
disabled={!answers[currentQuestion]}
57+
>
58+
다음
59+
</Button>
60+
</div>
61+
</div>
62+
<div></div>
63+
</div>
64+
);
65+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
import { useRouter } from "next/navigation";
5+
import { transitionData } from "@/constants/transitionData";
6+
import Image from "next/image";
7+
8+
interface TransitionScreenProps {
9+
type: "toMood" | "toRecommend";
10+
routing?: (page: string) => void;
11+
}
12+
13+
export default function TransitionScreen({
14+
type,
15+
routing,
16+
}: TransitionScreenProps) {
17+
const router = useRouter();
18+
const transitionContent = transitionData[type];
19+
20+
useEffect(() => {
21+
setTimeout(() => {
22+
if (routing) {
23+
routing("TodayMoodSurvey");
24+
} else {
25+
router.push("/recommend");
26+
}
27+
}, 1000);
28+
}, [transitionContent, routing, router]);
29+
30+
return (
31+
<div className="flex items-center w-full h-screen bg-[#F7F9FD]">
32+
<div className="flex flex-col items-center gap-[40px] w-full">
33+
<Image src={transitionContent.image} alt="" />
34+
<div className="flex flex-col items-center gap-[24px] w-full">
35+
<h2 className="text-[#142448] text-center text-[36px] font-[700] leading-[120%] whitespace-pre-line">
36+
{transitionContent.title}
37+
</h2>
38+
<p className="text-[#7F9CDC] text-center text-[22px] font-[600] leading-[150%]">
39+
{transitionContent.subtitle}
40+
</p>
41+
</div>
42+
</div>
43+
</div>
44+
);
45+
}

src/app/lib/api.ts

Whitespace-only changes.

src/app/lib/type.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface RecommendationResponse {
2+
title: string;
3+
position: string;
4+
category: string;
5+
image: string;
6+
url: string;
7+
}

0 commit comments

Comments
 (0)