-
Notifications
You must be signed in to change notification settings - Fork 50
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
[점심 뭐 먹지 미션 Step 2] 우디(류정우) 미션 제출합니다. #85
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
294a3b5
refactor: 리액트 컴포넌트와 스타일 컴포넌트를 분리
jw-r 73cc234
refactor: 클래스 컴포넌트를 함수 컴포넌트로 변경
jw-r beb983d
chore: 컴파일 옵션에 strictNullChecks:false 추가
jw-r d57834a
refactor: ChangeEvent타입에 HTML 엘리먼트 제네릭을 추가해서 타입을 구체화
jw-r a1a9f81
refactor: 삼항 연산자를 사용해서 정렬 로직 단순화
jw-r fa29519
refactor: 음식점 필터링, 정렬에 대한 로직을 useFilter로 추상화하여 분리
jw-r d6468b0
feat(index.html): 주석 제거 및 modal-root를 id로 가지는 div태그 추가
jw-r 0cd6194
refactor: main 태그의 1개의 자식 컴포넌트를 Filter, RestaurantList로 분리
jw-r a468f6f
feat: 모달이 활성화 상태일 때, body에 대한 스크롤이 적용되지 않는 기능 구현
jw-r 98dde2f
feat: 모달창이 떠있는 상태에서 ESC를 누르면 모달창을 닫는 기능 구현
jw-r 0730972
refactor: localStorage 로직을 custom hook으로 분리
jw-r 1855af9
refactor: 모달의C 상태 타입 intarface이름 수정
jw-r dc1a252
chore: @types/*를 devDependencies에 작성
jw-r 027ab89
refactor: mixin 생성을 문자열이 아닌 styled-components의 css 사용하기
jw-r File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,57 @@ | ||
import { Category, Restaurant, SortingType } from './types/restaurant'; | ||
import { Restaurant } from './types/restaurant'; | ||
|
||
import React from 'react'; | ||
import { Header, RestaurantList, RestaurantDetail } from './components'; | ||
import React, { useState } from 'react'; | ||
import { Header, RestaurantList, RestaurantDetail, Filter } from './components'; | ||
|
||
import mockData from './mockData.json'; | ||
import { useRestaurantFilter } from './hooks/useFilter'; | ||
import { useLocalStorage } from './hooks/useLocalStorage'; | ||
|
||
interface Props {} | ||
|
||
interface State { | ||
restaurants: Restaurant[]; | ||
category: string; | ||
sortingType: SortingType; | ||
interface ModalState { | ||
isModalOpen: boolean; | ||
detailId: Restaurant['id']; | ||
detailId?: Restaurant['id']; | ||
} | ||
|
||
class App extends React.Component<Props, State> { | ||
constructor(props: Props) { | ||
super(props); | ||
|
||
if (!localStorage.getItem('restaurants')) { | ||
localStorage.setItem('restaurants', JSON.stringify(mockData.restaurants)); | ||
} | ||
|
||
const restaurants = JSON.parse(localStorage.getItem('restaurants') || '[]'); | ||
this.state = { | ||
restaurants, | ||
category: '전체', | ||
sortingType: '이름순', | ||
isModalOpen: false, | ||
detailId: '1' | ||
}; | ||
|
||
window.addEventListener('keyup', ({ key }) => { | ||
if (this.state.isModalOpen && key === 'Escape') { | ||
this.closeModal(); | ||
} | ||
}); | ||
} | ||
const App = () => { | ||
const localRestaurantsData = useLocalStorage('restaurants'); | ||
const [modalState, setModalState] = useState<ModalState>({ | ||
isModalOpen: false, | ||
}); | ||
const [restaurants, { setCategory, setSortingType }] = useRestaurantFilter(localRestaurantsData); | ||
|
||
openModal = (id: Restaurant['id']) => { | ||
this.setState({ | ||
const openModal = (id: Restaurant['id']) => { | ||
setModalState({ | ||
...modalState, | ||
detailId: id, | ||
isModalOpen: true | ||
}); | ||
}; | ||
|
||
closeModal = () => { | ||
this.setState({ | ||
isModalOpen: false | ||
}); | ||
}; | ||
|
||
setCategory = (category: Category) => { | ||
this.setState({ | ||
category | ||
}); | ||
}; | ||
|
||
setSortingType = (sortingType: SortingType) => { | ||
this.setState({ | ||
sortingType | ||
isModalOpen: true, | ||
}); | ||
}; | ||
|
||
filterRestaurants = () => { | ||
const { category, sortingType } = this.state; | ||
|
||
const restaurants = this.state.restaurants.filter( | ||
restaurant => category === '전체' || restaurant.category === category | ||
); | ||
|
||
const getPivot = (restaurant: Restaurant) => { | ||
return sortingType === '이름순' ? restaurant.name : restaurant.distance; | ||
}; | ||
|
||
return restaurants.sort((a, b) => { | ||
const A = getPivot(a); | ||
const B = getPivot(b); | ||
if (A > B) return 1; | ||
if (A < B) return -1; | ||
return 0; | ||
const closeModal = () => { | ||
setModalState({ | ||
...modalState, | ||
isModalOpen: false, | ||
Comment on lines
+30
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. setModalState 파라미터로 함수를 넘길 수도 있습니다! setState((prev) => ({ ...prev, ... }); |
||
}); | ||
}; | ||
|
||
render() { | ||
return ( | ||
<div className="App"> | ||
<Header /> | ||
|
||
<RestaurantList | ||
restaurants={this.filterRestaurants()} | ||
openModal={this.openModal} | ||
setCategory={this.setCategory} | ||
setSortingType={this.setSortingType} | ||
return ( | ||
<div className="App"> | ||
<Header /> | ||
|
||
<main> | ||
<Filter setCategory={setCategory} setSortingType={setSortingType} /> | ||
<RestaurantList restaurants={restaurants} openModal={openModal} /> | ||
</main> | ||
|
||
{modalState.isModalOpen && ( | ||
<RestaurantDetail | ||
closeModal={closeModal} | ||
restaurant={ | ||
restaurants.find((restaurant) => restaurant.id === modalState.detailId) as Restaurant | ||
} | ||
/> | ||
|
||
{this.state.isModalOpen && ( | ||
<RestaurantDetail | ||
closeModal={this.closeModal} | ||
restaurant={ | ||
mockData.restaurants.find( | ||
restaurant => restaurant.id === this.state.detailId | ||
) as Restaurant | ||
} | ||
/> | ||
)} | ||
</div> | ||
); | ||
} | ||
} | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const CategoryImageWrapper = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
width: 64px; | ||
height: 64px; | ||
min-width: 64px; | ||
min-height: 64px; | ||
|
||
margin-right: 16px; | ||
|
||
border-radius: 50%; | ||
background: var(--lighten-color); | ||
|
||
img { | ||
width: 36px; | ||
height: 36px; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Category } from '../../types/restaurant'; | ||
|
||
import React from 'react'; | ||
import * as styled from './CategoryImage.styles'; | ||
|
||
import { CATEGORY_IMAGE_MAP } from '../../constants'; | ||
|
||
interface Props { | ||
category: Category; | ||
} | ||
|
||
const CategoryImage = (props: Props) => { | ||
return ( | ||
<styled.CategoryImageWrapper> | ||
<img src={`./img/${CATEGORY_IMAGE_MAP[props.category]}`} alt={props.category} /> | ||
</styled.CategoryImageWrapper> | ||
); | ||
}; | ||
|
||
export default CategoryImage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const FilterContainer = styled.section` | ||
display: flex; | ||
justify-content: space-between; | ||
|
||
margin-top: 24px; | ||
padding: 0 16px; | ||
|
||
select { | ||
height: 44px; | ||
min-width: 125px; | ||
|
||
border: 1px solid #d0d5dd; | ||
border-radius: 8px; | ||
padding: 8px; | ||
|
||
background: transparent; | ||
font-size: 16px; | ||
} | ||
`; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setState 의 파라미터를 함수로 정의할 수도 있습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헤인트의 예시처럼 이전 상태를 참조하고 반환하는 방식이 더 안정적이겠군요!
제가 쓴 코드는 객체를 병합하고 있기 때문에, 이전 상태와 충돌할 가능성이 있겠네요
감사합니다🤩