Skip to content

Commit 7657e1f

Browse files
authored
Merge pull request #62 from SOPT-36-NINEDOT/feat/#60/survey
[Feat]: Survey 컴포넌트 제작
2 parents b531588 + 6b9faef commit 7657e1f

File tree

12 files changed

+191
-0
lines changed

12 files changed

+191
-0
lines changed

public/svg/ic_radio_checked.svg

Lines changed: 5 additions & 0 deletions
Loading

public/svg/ic_radio_default.svg

Lines changed: 3 additions & 0 deletions
Loading

src/assets/svg/IcRadioChecked.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { SVGProps } from 'react';
2+
const SvgIcRadioChecked = (props: SVGProps<SVGSVGElement>) => (
3+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20" {...props}>
4+
<rect width={18.5} height={18.5} x={0.75} y={0.75} fill="#282C33" rx={9.25} />
5+
<rect
6+
width={18.5}
7+
height={18.5}
8+
x={0.75}
9+
y={0.75}
10+
stroke="#3E72F3"
11+
strokeWidth={1.5}
12+
rx={9.25}
13+
/>
14+
<circle cx={10} cy={10} r={4} fill="#3E72F3" />
15+
</svg>
16+
);
17+
export default SvgIcRadioChecked;

src/assets/svg/IcRadioDefault.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { SVGProps } from 'react';
2+
const SvgIcRadioDefault = (props: SVGProps<SVGSVGElement>) => (
3+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20" {...props}>
4+
<circle cx={10} cy={10} r={10} fill="#282C33" />
5+
</svg>
6+
);
7+
export default SvgIcRadioDefault;

src/assets/svg/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export { default as IcCheckboxChecked } from './IcCheckboxChecked';
55
export { default as IcCheckboxDefault } from './IcCheckboxDefault';
66
export { default as IcDropdown } from './IcDropdown';
77
export { default as IcModalDelete } from './IcModalDelete';
8+
export { default as IcRadioChecked } from './IcRadioChecked';
9+
export { default as IcRadioDefault } from './IcRadioDefault';
810
export { default as IcTooltipDelete } from './IcTooltipDelete';
911
export { default as IcTriangle } from './IcTriangle';
1012
export { default as Vite } from './Vite';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { style } from '@vanilla-extract/css';
2+
3+
import { colors, fonts } from '@/style/token';
4+
5+
export const surveyWrapper = style({
6+
display: 'flex',
7+
flexDirection: 'column',
8+
gap: '5.4rem',
9+
});
10+
11+
export const surveyContainer = style({
12+
display: 'flex',
13+
flexDirection: 'column',
14+
gap: '1.6rem',
15+
});
16+
17+
export const surveyTitle = style({
18+
marginBottom: '0.8rem',
19+
color: colors.grey11,
20+
...fonts.body01,
21+
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { useState } from 'react';
2+
3+
import {
4+
surveyWrapper,
5+
surveyContainer,
6+
surveyTitle,
7+
} from '@/page/signup/component/Survey/Survey.css';
8+
import SurveyItem from '@/page/signup/component/SurveyItem/SurveyItem';
9+
import { questionList } from '@/page/signup/component/Survey/data';
10+
11+
export const Survey = () => {
12+
const [answers, setAnswers] = useState<Record<number, number>>({});
13+
14+
const handleSelect = (questionId: number, optionId: number) => {
15+
setAnswers((prev) => ({
16+
...prev,
17+
[questionId]: optionId,
18+
}));
19+
};
20+
21+
return (
22+
<div className={surveyWrapper}>
23+
{questionList.map((question) => (
24+
<div key={question.id} className={surveyContainer}>
25+
<h3 className={surveyTitle}>{question.content}</h3>
26+
{question.optionList.map((option) => (
27+
<SurveyItem
28+
key={option.id}
29+
item={option}
30+
isChecked={answers[question.id] === option.id}
31+
onClick={() => handleSelect(question.id, option.id)}
32+
/>
33+
))}
34+
</div>
35+
))}
36+
</div>
37+
);
38+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { QuestionType } from '@/page/signup/component/type/questionType';
2+
3+
export const questionList: QuestionType[] = [
4+
{
5+
id: 1,
6+
type: '객관식',
7+
content: '어떤 방식으로 목표를 실천하는 것을 선호하시나요?',
8+
optionList: [
9+
{ id: 1, content: '구체적인 실행 계획이 필요해요' },
10+
{ id: 2, content: '감성적 동기부여가 중요해요' },
11+
{ id: 3, content: '간단한 할 일을 쌓아가는 게 좋아요' },
12+
{ id: 4, content: '일정 기반으로 진행하는 걸 좋아해요' },
13+
{ id: 5, content: '해당하는 게 없어요' },
14+
],
15+
},
16+
{
17+
id: 2,
18+
type: '객관식',
19+
content: '혼자 할 때와 함께할 때, 어떤 게 더 동기부여가 되나요?',
20+
optionList: [
21+
{ id: 1, content: '혼자 조용히 하는 게 편해요' },
22+
{ id: 2, content: '누군가와 함께 하면 더 힘이 나요' },
23+
{ id: 3, content: '둘 다 비슷해요' },
24+
],
25+
},
26+
{
27+
id: 3,
28+
type: '객관식',
29+
content: '당신이 목표를 이루는 데 어려움을 겪는 가장 큰 이유는 무엇인가요?',
30+
optionList: [
31+
{ id: 1, content: '의지는 있지만 자꾸 미뤄요' },
32+
{ id: 2, content: '중간에 동기 부여가 떨어져요' },
33+
{ id: 3, content: '외부 자극이 없으면 움직이지 않아요' },
34+
{ id: 4, content: '시간 관리가 잘 안 돼요' },
35+
{ id: 5, content: '해당하는 게 없어요' },
36+
],
37+
},
38+
];
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { style } from '@vanilla-extract/css';
2+
3+
import { colors, fonts } from '@/style/token';
4+
5+
export const itemContainer = style({
6+
display: 'flex',
7+
gap: '1.2rem',
8+
});
9+
10+
export const itemText = style({
11+
color: colors.grey11,
12+
...fonts.body03,
13+
});
14+
15+
export const radioIcon = style({
16+
width: '2rem',
17+
height: '2rem',
18+
19+
cursor: 'pointer',
20+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
itemContainer,
3+
itemText,
4+
radioIcon,
5+
} from '@/page/signup/component/SurveyItem/SurveyItem.css';
6+
import { IcRadioDefault, IcRadioChecked } from '@/assets/svg';
7+
import type { OptionType } from '@/page/signup/component/type/optionType';
8+
9+
type itemProps = {
10+
item: OptionType;
11+
isChecked: boolean;
12+
onClick: () => void;
13+
};
14+
15+
const SurveyItem = ({ item, isChecked, onClick }: itemProps) => {
16+
const RadioIcon = isChecked ? IcRadioChecked : IcRadioDefault;
17+
18+
return (
19+
<div className={itemContainer}>
20+
<button onClick={onClick}>
21+
<RadioIcon className={radioIcon} />
22+
</button>
23+
<span className={itemText}>{item.content}</span>
24+
</div>
25+
);
26+
};
27+
28+
export default SurveyItem;

0 commit comments

Comments
 (0)