Skip to content

Commit

Permalink
기본 질문 리스트 (#123)
Browse files Browse the repository at this point in the history
* feat: 타이포그래피 Detail 추가

* feat: 질문 타입 지정

* feat: 기본 질문 컴포넌트 생성

* feat: list props로 변경

* feat: 리뷰 반영
  • Loading branch information
sumi-0011 authored May 22, 2023
1 parent fffae88 commit 648c607
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 62 deletions.
4 changes: 2 additions & 2 deletions src/components/icons/EditIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { type ComponentProps } from 'react';

import Svg from '../svg/Svg';

const EditIcon = ({ size = 21, ...rest }: ComponentProps<typeof Svg>) => {
const EditIcon = ({ size = 21, color = '#3D4350', ...rest }: ComponentProps<typeof Svg>) => {
return (
<Svg size={size} isUsingFill {...rest}>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11.8787 1.70729C13.0034 0.582583 14.799 0.537595 15.9773 1.57233L16.1213 1.70729L19.2929 4.87887C20.4176 6.00358 20.4626 7.79914 19.4279 8.97752L19.2929 9.12151L8.29289 20.1215C7.77717 20.6372 7.09301 20.9458 6.36971 20.9936L6.17157 21.0002H3C1.40232 21.0002 0.0963391 19.7513 0.00509269 18.1765L0 18.0002V14.8286C0 14.0993 0.265587 13.3973 0.743204 12.852L0.87868 12.7073L11.8787 1.70729ZM3.499 12.9136L2.29289 14.1215C2.13661 14.2778 2.0374 14.4805 2.00867 14.6972L2 14.8286V18.0002C2 18.513 2.38604 18.9357 2.88338 18.9935L3 19.0002H6.17157C6.39259 19.0002 6.60606 18.927 6.7796 18.7941L6.87868 18.7073L8.085 17.4996L3.499 12.9136ZM14.7071 3.12151C14.3466 2.76102 13.7794 2.73329 13.3871 3.03832L13.2929 3.12151L4.914 11.4996L9.5 16.0856L17.8787 7.70729C18.2392 7.34681 18.2669 6.77958 17.9619 6.38729L17.8787 6.29308L14.7071 3.12151Z"
fill="#3D4350"
fill={color}
/>
</Svg>
);
Expand Down
34 changes: 17 additions & 17 deletions src/features/createSurvey/CreateSurvey.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { cleanup, fireEvent, render } from '@testing-library/react';
import { cleanup } from '@testing-library/react';
import { afterEach, describe, expect, test, vi } from 'vitest';

import CardList from '~/features/createSurvey/cardList/CardList';
import CreateSurvey from '~/features/createSurvey/CreateSurvey';

// TODO : 테스트 코드 재작성
describe('/features/createSurvey/cardList/CardListWithDnd', () => {
test('정의되어 있어야 한다', () => {
expect(CardList).toBeDefined();
Expand All @@ -14,26 +14,26 @@ describe('/features/createSurvey/cardList/CardListWithDnd', () => {
vi.resetAllMocks();
});

test('cardList의 추가 버튼을 1번 클릭하면 dnd card가 하나 추가된다.', () => {
const { getByRole, getAllByTestId } = render(<CreateSurvey />);
// test('cardList의 추가 버튼을 1번 클릭하면 dnd card가 하나 추가된다.', () => {
// const { getByRole, getAllByTestId } = render(<CreateSurvey />);

const button = getByRole('button', { name: '나만의 질문 추가하기' });
fireEvent.click(button);
// const button = getByRole('button', { name: '나만의 질문 추가하기' });
// fireEvent.click(button);

const cardItems = getAllByTestId('dnd-item-component');
// const cardItems = getAllByTestId('dnd-item-component');

expect(cardItems).toHaveLength(1);
});
// expect(cardItems).toHaveLength(1);
// });

test('cardList의 추가 버튼을 2번 클릭하면 dnd card가 두개 추가된다.', () => {
const { getByRole, getAllByTestId } = render(<CreateSurvey />);
// test('cardList의 추가 버튼을 2번 클릭하면 dnd card가 두개 추가된다.', () => {
// const { getByRole, getAllByTestId } = render(<CreateSurvey />);

const button = getByRole('button', { name: '나만의 질문 추가하기' });
fireEvent.click(button);
fireEvent.click(button);
// const button = getByRole('button', { name: '나만의 질문 추가하기' });
// fireEvent.click(button);
// fireEvent.click(button);

const cardItems = getAllByTestId('dnd-item-component');
// const cardItems = getAllByTestId('dnd-item-component');

expect(cardItems).toHaveLength(2);
});
// expect(cardItems).toHaveLength(2);
// });
});
80 changes: 37 additions & 43 deletions src/features/createSurvey/CreateSurvey.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
import { useState } from 'react';
import { css } from '@emotion/react';

import { type CardItemType } from '~/features/createSurvey/cardList/Card';
import CardList from '~/features/createSurvey/cardList/CardList';
import CardListWithDnd from '~/features/createSurvey/cardList/CardListWithDnd';
import PlusIcon from '~/features/createSurvey/cardList/PlusIcon';
import { BASIC_QUESTION_LIST } from '~/features/createSurvey/constants';
import QuestionList from '~/features/createSurvey/questionList/QuestionList';

const CreateSurvey = () => {
const [cardItems, setCardItems] = useState<CardItemType[]>([]);

// TODO : 서버 API 명세서 참고해서 type 변경
const handleNewItemAdd = () => {
setCardItems((prev) => {
const newId = prev.length;

return [
...prev,
{
id: newId,
title: `나의 질문 ${newId}`,
type: 'CHOICE',
},
];
});
};

// const [cardItems, setCardItems] = useState<CardItemType[]>([]);

// // TODO : 서버 API 명세서 참고해서 type 변경
// const handleNewItemAdd = () => {
// setCardItems((prev) => {
// const newId = prev.length;

// return [
// ...prev,
// {
// id: newId,
// title: `나의 질문 ${newId}`,
// type: 'CHOICE',
// },
// ];
// });
// };

// CardList Component는 추후에 제거 예정 -> QuestionList로 대체
return (
<section css={containerCss}>
<CardList />
<CardListWithDnd items={cardItems} setItems={setCardItems} />
<button type="button" onClick={handleNewItemAdd} css={buttonCss}>
<PlusIcon />
<span>나만의 질문 추가하기</span>
</button>
<h1>기본 질문</h1>
<QuestionList list={BASIC_QUESTION_LIST} />
</section>
);
};
Expand All @@ -45,22 +39,22 @@ const containerCss = css`
gap: 8px;
`;

const buttonCss = css`
all: unset;
// const buttonCss = css`
// all: unset;

cursor: pointer;
// cursor: pointer;

display: flex;
flex-direction: column;
gap: 11px;
align-items: center;
justify-content: center;
// display: flex;
// flex-direction: column;
// gap: 11px;
// align-items: center;
// justify-content: center;

width: 100%;
padding: 25px 106px;
// width: 100%;
// padding: 25px 106px;

color: #37c3ff;
// color: #37c3ff;

background-color: #f7f8f9;
border-radius: 12px;
`;
// background-color: #f7f8f9;
// border-radius: 12px;
// `;
24 changes: 24 additions & 0 deletions src/features/createSurvey/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type QuestionItem } from '~/features/createSurvey/types';

export const BASIC_QUESTION_LIST: QuestionItem[] = [
{
type: 'choice',
form_type: 'tendency',
title: '나와의 관계, 상대방의 포지션, 나의 성향',
order: 1,
choices: [],
max_selectable_count: 1,
},
{
type: 'short',
form_type: 'strength',
title: '나의 직무적 강점은 무엇인가요?',
order: 2,
},
{
type: 'short',
form_type: 'weakness',
title: '나의 직무적 약점은 무엇인가요?',
order: 3,
},
];
100 changes: 100 additions & 0 deletions src/features/createSurvey/questionList/Question.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { type ReactNode } from 'react';
import { css, type Theme } from '@emotion/react';

import EditIcon from '~/components/icons/EditIcon';
import { type QuestionFormType, type QuestionItem, type QuestionType } from '~/features/createSurvey/types';
import colors from '~/styles/color';
import { DETAIL, HEAD_3_SEMIBOLD } from '~/styles/typo';

interface Props {
item: QuestionItem;
rightElement?: ReactNode;
}

const Question = ({ item, rightElement }: Props) => {
const { tag, css: typeCss } = getType(item.type, item.form_type);

return (
<li css={listItemCss}>
<div css={[iconContainerCss, typeCss]}>
<EditIcon color={colors.white} />
</div>
<div css={textContainerCss}>
<p css={titleCss}>{item.title}</p>
<span css={tagCss}>{tag}</span>
</div>
{rightElement}
</li>
);
};

export default Question;

const listItemCss = css`
display: flex;
gap: 16px;
align-items: center;
padding: 8px 23px;
`;

const textContainerCss = css`
user-select: none;
flex-grow: 1;
`;

const titleCss = css`
${HEAD_3_SEMIBOLD}
margin-bottom: 8px;
`;

const iconContainerCss = css`
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
border-radius: 10px;
`;

const getType = (type: QuestionType, formType: QuestionFormType) => {
if (formType === 'tendency') {
return {
tag: '기본정보',
css: css`
background-color: ${colors.bluegreen};
`,
};
}
if (type === 'short') {
return {
tag: '주관식',
css: css`
background-color: ${colors.yellowgreen};
`,
};
}

return {
tag: '객관식',
css: css`
background-color: ${colors.pink};
`,
};
};

const tagCss = (theme: Theme) => css`
${DETAIL}
gap: 10px;
order: 1;
padding: 2px 4px;
color: ${theme.colors.gray_400};
background: ${theme.colors.primary_50};
border-radius: 4px;
`;
15 changes: 15 additions & 0 deletions src/features/createSurvey/questionList/QuestionList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { type Meta } from '@storybook/react';

import { BASIC_QUESTION_LIST } from '~/features/createSurvey/constants';
import QuestionList from '~/features/createSurvey/questionList/QuestionList';

const meta: Meta<typeof QuestionList> = {
title: 'QuestionList',
component: QuestionList,
};

export default meta;

export function Default() {
return <QuestionList list={BASIC_QUESTION_LIST} />;
}
17 changes: 17 additions & 0 deletions src/features/createSurvey/questionList/QuestionList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Question from '~/features/createSurvey/questionList/Question';
import { type QuestionItem } from '~/features/createSurvey/types';

interface Props {
list: QuestionItem[];
}
const QuestionList = ({ list }: Props) => {
return (
<section>
{list.map((item) => (
<Question item={item} key={item.title} />
))}
</section>
);
};

export default QuestionList;
25 changes: 25 additions & 0 deletions src/features/createSurvey/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type QuestionType = 'choice' | 'short';
export type QuestionFormType = 'strength' | 'weakness' | 'tendency' | 'custom';

interface Choice {
content: string;
order: number;
}

export interface ChoiceQuestionRequest {
type: 'choice';
form_type: QuestionFormType;
title: string;
choices: Choice[];
max_selectable_count: number;
order: number;
}

export interface ShortQuestionRequest {
type: 'short';
form_type: QuestionFormType;
title: string;
order: number;
}

export type QuestionItem = ChoiceQuestionRequest | ShortQuestionRequest;

0 comments on commit 648c607

Please sign in to comment.