Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3주차 기본/심화 과제] 🍚 점메추 🍚 #4

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
412dad5
feat: 초기 세팅 완료
eonseok-jeon Nov 5, 2023
36e128e
feat: header 추가
eonseok-jeon Nov 5, 2023
c99db20
feat: main section 구현
eonseok-jeon Nov 5, 2023
9b1a195
feat: 각 항목 선택 시 로직 구현
eonseok-jeon Nov 5, 2023
1937506
feat: 처음으로 버튼 로직 구현
eonseok-jeon Nov 5, 2023
0d41769
refactor: main section content를 다른 컴포넌트로 분리
eonseok-jeon Nov 5, 2023
dae31af
feat: 취향대로 추천 로직 구현
eonseok-jeon Nov 5, 2023
a7b4409
refactor: 폴더 구조 변경
eonseok-jeon Nov 5, 2023
6bd0124
feat: 이전으로 다음으로 버튼 기능 구현
eonseok-jeon Nov 5, 2023
7917026
?
eonseok-jeon Nov 6, 2023
4a399b9
start
eonseok-jeon Nov 16, 2023
567fa12
style: Card UI 구현
eonseok-jeon Nov 16, 2023
da8d2bd
style: Button UI 구현
eonseok-jeon Nov 16, 2023
3a1ace5
style: Input UI 구현
eonseok-jeon Nov 16, 2023
7617813
feat: 각 페이지 UI 구현
eonseok-jeon Nov 16, 2023
86fb735
feat: router 구현
eonseok-jeon Nov 17, 2023
c65640e
feat: enter key down 기능 구현
eonseok-jeon Nov 17, 2023
4c4d6cc
feat: api 붙이기
eonseok-jeon Nov 17, 2023
11076c8
feat: 중복체크 색 추가
eonseok-jeon Nov 17, 2023
2691036
feat: 회원가입 비활성화 기능 구현
eonseok-jeon Nov 17, 2023
c2d12dd
feat: 마이 페이지 api 연결
eonseok-jeon Nov 17, 2023
d61afe5
docs: 생각 과제
eonseok-jeon Nov 17, 2023
12eed6a
feat: 항목 선택시 백그라운드 색 변경
eonseok-jeon Dec 13, 2023
4697aab
feat: button disabled 처리
eonseok-jeon Dec 13, 2023
5fd6995
refactor: useReducer를 이용하여 상태 관리
eonseok-jeon Dec 14, 2023
c861290
feat: 추천 음식 뜨게 하기
eonseok-jeon Dec 14, 2023
00922f5
feat: 랜덤 추천 기능 구현
eonseok-jeon Dec 14, 2023
38f798b
design: 숫자 카운팅 애니메이션 효과 추가
eonseok-jeon Dec 14, 2023
3f50410
docs: 생각 과제
eonseok-jeon Dec 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions node_modules/.yarn-integrity

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions week3/menu-recommend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react", "react-hooks", "@typescript-eslint", "prettier"],
"rules": {
"quotes": ["error", "single"],
"no-duplicate-imports": "error",
"no-console": ["warn", { "allow": ["warn", "error", "info"] }],
"no-unused-vars": "error",
"no-multiple-empty-lines": "error"
},
"settings": {
"import/resolver": {
"typescript": {}
}
}
}
24 changes: 24 additions & 0 deletions week3/menu-recommend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
10 changes: 10 additions & 0 deletions week3/menu-recommend/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "es5",
"useTabs": false,
"arrowParens": "always",
"bracketSpacing": true,
"bracketSameLine": false
}
8 changes: 8 additions & 0 deletions week3/menu-recommend/.stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-recess-order",
"stylelint-config-prettier"
],
"customSyntax": "postcss-styled-syntax"
}
3 changes: 3 additions & 0 deletions week3/menu-recommend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 점메츄

## 점심 메뉴 츄천
19 changes: 19 additions & 0 deletions week3/menu-recommend/THINKING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
컴포넌트 분리 기준:

단일 책임 원칙 (Single Responsibility Principle): 컴포넌트는 한 가지 기능 또는 역할에 집중해야 한다.
재사용성: 여러 곳에서 사용될 수 있도록 설계되어야 한다.
가독성: 각 컴포넌트는 명확하게 구분되어야 하며, 컴포넌트의 이름과 구조가 코드를 읽기 쉽게 만들어야 합니다.

좋은 상태 관리:

최소한의 상태 유지: 컴포넌트가 필요 이상으로 많은 상태를 가지면 복잡성이 증가할 수 있다.
상태 불변성 유지: 상태를 직접 변경하는 것이 아니라 setState를 사용하여 상태를 변경하면서 불변성을 유지해야 힌다.

렌더링 효과적 관리:

PureComponent 및 memoization 활용: PureComponent나 React.memo를 사용하여 불필요한 렌더링을 방지한다.

Props Drilling과 해결 방법:

Props Drilling: 여러 레벨의 하위 컴포넌트로 props를 전달하는 과정에서 코드가 복잡해지고 유지보수가 어려워지는 상황.
Context API 사용: React의 Context API를 사용하여 전역적으로 상태를 관리하고, 필요한 컴포넌트에서 필요한 값을 가져올 수 있다.
12 changes: 12 additions & 0 deletions week3/menu-recommend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>점메추 - 굶을래?</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
39 changes: 39 additions & 0 deletions week3/menu-recommend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "menu-recommend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"format": "prettier --write --cache ."
},
"resolutions": {
"styled-components": "^5"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"styled-components": "^6.1.0"
},
"devDependencies": {
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.3",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss-styled-syntax": "^0.5.0",
"prettier": "^3.0.3",
"stylelint": "^15.11.0",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-recess-order": "^4.3.0",
"stylelint-config-standard": "^34.0.0",
"vite": "^4.4.5"
}
}
34 changes: 34 additions & 0 deletions week3/menu-recommend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useState } from 'react';
import Header from '@components/Header';
import MainSection from '@components/MainSection';
import GlobalStyle from '@styles/GlobalStyle';

export default function App() {
const [selectOption, setSelectOption] = useState('');
const [startPick, setStartPick] = useState(false);

return (
<>
<GlobalStyle />
<Header
selectOption={selectOption}
selectOptionHandler={(selected) => {
setSelectOption(selected);
}}
startPickHandler={(isStart) => {
setStartPick(isStart);
}}
/>
<MainSection
selectOption={selectOption}
startPick={startPick}
selectOptionHandler={(selected) => {
setSelectOption(selected);
}}
startPickHandler={(isStart) => {
setStartPick(isStart);
}}
/>
</>
);
}
Binary file added week3/menu-recommend/src/assets/1-1-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/1-1-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/1-2-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/1-2-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/1-3-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/1-3-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-1-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-1-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-2-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-2-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-3-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/2-3-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-1-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-1-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-2-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-2-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-3-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week3/menu-recommend/src/assets/3-3-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions week3/menu-recommend/src/components/Header/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as S from './style';

const Header = ({ selectOption, selectOptionHandler, startPickHandler }) => {
return (
<S.HeaderStyle>
<h1>🍛 오늘의 점메추 🍛</h1>
{selectOption !== '' && (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{selectOption !== '' && (
{selectOption && (

이렇게만 해도 되겠다! 빈 문자열은 falsy값, 빈 문자열이 아니면 truthy 값이라서 가능합니당

<S.ReStartButton
onClick={() => {
selectOptionHandler('');
startPickHandler(false);
}}
>
처음으로
</S.ReStartButton>
)}
</S.HeaderStyle>
);
};

export default Header;
28 changes: 28 additions & 0 deletions week3/menu-recommend/src/components/Header/style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import styled from 'styled-components';

const HeaderStyle = styled.header`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

시맨틱하게 잘했다 !!

position: relative;
width: 100%;
padding: 5rem 0;
font-size: 3.6rem;
text-align: center;
border: 1px solid #555;
`;

const ReStartButton = styled.button`
position: absolute;
top: 50%;
right: 10rem;
padding: 1rem 2rem;
font-size: 2.4rem;
border: 1px solid #555;
border-radius: 1rem;
transition: all 0.3s ease;
transform: translateY(-50%);

&:hover {
background-color: #222;
}
`;

export { HeaderStyle, ReStartButton };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

선택되지 않았을 때 0, 선택된 항목 순서에 따라서 1 ,2, 3 이렇게 숫자값을 준 것 같은데, 그 숫자가 각 항목을 뜻한다는걸 좀 보고 난 뒤에야 알았거든! 그래서 의미가 나타나지 않는 이런 숫자를 쓰기보다는 의미가 담긴 값(예를 들면 string)을 사용하면 좋을 것 같아! 그럼에도 나는 숫자값으로 관리를 하고 싶다면

export const SELECT_OPTION = {
none: 0,
first : 1,
second : 2,
third : 3,
}

이런식으로 만들어놓고 가져다 쓰는 것도 괜찮겠당. 뭔가 상수 얘기를 많이 하게 되는군 크크

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as S from '../style';

const FirstChoice = ({ firstChoice, selectOptionHandler, startPickHandler, dispatchHandler }) => {
return (
<>
<S.SubTitleStyle>오늘은 어떤 종류가 먹고 싶어?</S.SubTitleStyle>
<S.CountParagraph>1 / 3</S.CountParagraph>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런것두 다 매직 넘붤이다

<S.MainSectionStyle>
<S.ArticleStyle
$isClicked={firstChoice === 1 ? true : false}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$isClicked={firstChoice === 1 ? true : false}
$isClicked={firstChoice === 1}

이렇게만 줘도 되겠네용 !

onClick={() => {
dispatchHandler('first', 1);
}}
>
<a href="#">한식</a>
</S.ArticleStyle>
<S.ArticleStyle
$isClicked={firstChoice === 2 ? true : false}
onClick={() => {
dispatchHandler('first', 2);
}}
>
<a href="#">일식</a>
</S.ArticleStyle>
<S.ArticleStyle
$isClicked={firstChoice === 3 ? true : false}
onClick={() => {
dispatchHandler('first', 3);
}}
>
<a href="#">중식</a>
</S.ArticleStyle>
</S.MainSectionStyle>
<S.ButtonBox>
<S.NextButton
onClick={() => {
selectOptionHandler('');
startPickHandler(false);
}}
>
이전으로
</S.NextButton>
<S.NextButton
disabled={firstChoice === 0}
onClick={() => {
dispatchHandler('done', 2);
}}
>
다음으로
</S.NextButton>
</S.ButtonBox>
</>
);
};

export default FirstChoice;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as S from '../style';

const LastChoice = ({ thirdChoice, dispatchHandler }) => {
return (
<>
<S.SubTitleStyle>마지막으로 골라줘!</S.SubTitleStyle>
<S.CountParagraph>3 / 3</S.CountParagraph>
<S.MainSectionStyle>
<S.ArticleStyle
$isClicked={thirdChoice === 1 ? true : false}
onClick={() => {
dispatchHandler('third', 1);
}}
>
<a href="#">국물 X</a>
</S.ArticleStyle>
<S.ArticleStyle
$isClicked={thirdChoice === 2 ? true : false}
onClick={() => {
dispatchHandler('third', 2);
}}
>
<a href="#">국물 O</a>
</S.ArticleStyle>
</S.MainSectionStyle>
<S.ButtonBox>
<S.NextButton
onClick={() => {
dispatchHandler('done', 2);
}}
>
이전으로
</S.NextButton>
<S.NextButton
disabled={thirdChoice === 0}
onClick={() => {
dispatchHandler('done', 4);
}}
>
결과보기
</S.NextButton>
</S.ButtonBox>
</>
);
};

export default LastChoice;
Loading