-
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
[Team19][Json, Dico] Sidedish 2주차 PR (Final) #73
Changes from all commits
e8f1390
c7655be
c0aa248
72df72f
875b6d6
d48fb37
05f641c
2b7ab1a
65ec0e1
a819c98
a2ca5f7
a9858a0
64fe99d
968ecc8
f81d4f2
23f093c
2e4ac0e
f2f604b
470f167
b6c0f1f
8415588
a7b68cc
66a24ee
3360398
7071ea4
7be6a0e
732e74f
83ad42c
5680059
e951ead
3be4a7c
ed90c4d
1f85635
266cb39
8337c41
d06246c
96ae43b
ebb234a
ff16e70
3f66aa9
0dbfff7
044d89a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,36 @@ | ||
# sidedish | ||
# 🥑 sidedish | ||
## Team19 (a.k.a DJ) | ||
### 조원 | ||
Json | ||
### Members | ||
[Json😇](https://github.com/kowoohyuk), [Dico🌷](https://github.com/ha3158987) | ||
|
||
---- | ||
## 📝 Table of Contents | ||
- [Links](#links) | ||
- [Customized NPM Module](#module) | ||
- [Skeleton UI](#Skeleton) | ||
- [UI](#ui) | ||
---- | ||
## 🔗 [Links](#Links) | ||
### [Git Strategy](https://github.com/ha3158987/sidedish/wiki/Git-Strategy-%F0%9F%8C%B3) | ||
### [Naming Rule](https://github.com/ha3158987/sidedish/wiki/Naming-Rule-%F0%9F%8D%92) | ||
### [Reference](https://github.com/ha3158987/sidedish/wiki/Reference-%F0%9F%93%94) | ||
### Blueprint | ||
- [Component](https://www.notion.so/Component-f3ea0a6769d14acf97b0f2bc13b63ca9) | ||
- [Carousel](https://www.notion.so/DicoJsonCarousel-4a8ccb91cb9e4edb9b4e3bfffae1f7ca) | ||
- [Notion](https://www.notion.so/Sidedish-Json-Dico-cb7c0605253840da922952c6e910ea60) | ||
|
||
---- | ||
## 🎠 [Customized NPM Module](#module) | ||
[dico-json-carousel NPM](https://npmjs.com/package/dico-json-carousel) | ||
![Carousel](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/1f61e9d5-f75b-428c-af74-52357bf1522f/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210502%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210502T134930Z&X-Amz-Expires=86400&X-Amz-Signature=e6c4ff35984ebe0977a127959b9494172e7c61802dfbac4029af6c88ab330ee3&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) | ||
|
||
----- | ||
## ☠️ [Skeleton UI](#Skeleton) | ||
![Skeleton UI](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/eadb8270-8871-4b16-b63e-f233ca888319/_2021_04_30_16_54_31_768.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210502%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210502T134428Z&X-Amz-Expires=86400&X-Amz-Signature=6c68fa970a8b048efbf29f5166f9d224b9d355a0be969d6cad45081a68ed1ad7&X-Amz-SignedHeaders=host) | ||
|
||
---- | ||
## 🏠 [UI](#ui) | ||
![screencapture-localhost-3000-2021-05-02-22_42_10](https://user-images.githubusercontent.com/65105537/116815304-d52f7280-ab97-11eb-93c2-220afdd5c943.png) | ||
|
||
|
||
Dico | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const API = () => { | ||
const URL = "https://codesquad-2021-api.herokuapp.com/sidedish"; | ||
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. url이 소스코드에 있는건 위험하긴해요. CRA Replace url 이런키워드 검색~ |
||
const API = path => { | ||
const req = { | ||
method : 'GET', | ||
headers: { | ||
"Content-Type": "application/json", | ||
} | ||
}; | ||
return fetch(URL + path, req); | ||
} | ||
return async (path) => { | ||
let json; | ||
try { | ||
const result = await API(path); | ||
json = await result.json(); | ||
} catch(e) { | ||
console.log(e); | ||
} finally { | ||
if(!json || json.length === 0) { | ||
json = null; | ||
} | ||
} | ||
return json; | ||
} | ||
} | ||
|
||
export default API(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
const TEXT = { | ||
"bestTab-title": "후기가 증명하는 베스트 반찬", | ||
"order" : { | ||
true : { | ||
"title": "주문 성공", | ||
"content": "감사합니다! \r\n맛있게 준비해드릴게요!" | ||
}, | ||
false : { | ||
"title": "주문 실패", | ||
"content": "재고가 부족합니다!" | ||
} | ||
} | ||
}; | ||
|
||
export { TEXT }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { createGlobalStyle } from "styled-components"; | ||
|
||
const GlobalStyle = createGlobalStyle` | ||
body { | ||
overflow-x: hidden; | ||
color: #333; | ||
} | ||
button { | ||
background-color: transparent; | ||
border:none; | ||
cursor: pointer; | ||
} | ||
input { | ||
border: none; | ||
} | ||
input:focus { | ||
outline:none; | ||
} | ||
button:focus { | ||
outline:none; | ||
} | ||
* { | ||
box-sizing: border-box; | ||
} | ||
`; | ||
|
||
export default GlobalStyle; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const addCommaToNumber = (number) => number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { createContext, useContext, useEffect, useState } from "react"; | ||
import API from "../common/api.js"; | ||
|
||
const DetailDataContext = createContext(); | ||
const PopUpToggleContext = createContext(); | ||
const OnFetchDetailDataContext = createContext(); | ||
const SetPopUpToggleContext = createContext(); | ||
const MainItemsContext = createContext(); | ||
const MainItemsActiveContext = createContext(); | ||
const SetMainItemsActiveContext = createContext(); | ||
|
||
export function ContextProvider({ children }) { | ||
const [detailData, setDetailData] = useState(null); | ||
const [popUpToggle, setPopUpToggle] = useState(false); | ||
const [mainItems, setMainItems] = useState(null); | ||
const [mainItemsActive, setMainItemsActive] = useState(false); | ||
|
||
useEffect(() => { | ||
if (!mainItems) { | ||
(async () => { | ||
const data = await API("/main"); | ||
setMainItems(data); | ||
})(); | ||
} | ||
return; | ||
}, [mainItems]); | ||
|
||
const onFetchDetailData = async (id) => { | ||
setPopUpToggle(true); | ||
setDetailData(null); | ||
const data = await API(`/detail/${id}`); | ||
if (data) { | ||
setTimeout(() => setDetailData(data), 1000); | ||
} | ||
}; | ||
|
||
return ( | ||
<DetailDataContext.Provider value={detailData}> | ||
<OnFetchDetailDataContext.Provider value={onFetchDetailData}> | ||
<PopUpToggleContext.Provider value={popUpToggle}> | ||
<SetPopUpToggleContext.Provider value={setPopUpToggle}> | ||
<MainItemsContext.Provider value={mainItems}> | ||
<MainItemsActiveContext.Provider value={mainItemsActive}> | ||
<SetMainItemsActiveContext.Provider value={setMainItemsActive}> | ||
{children} | ||
</SetMainItemsActiveContext.Provider> | ||
</MainItemsActiveContext.Provider> | ||
</MainItemsContext.Provider> | ||
</SetPopUpToggleContext.Provider> | ||
</PopUpToggleContext.Provider> | ||
</OnFetchDetailDataContext.Provider> | ||
</DetailDataContext.Provider> | ||
Comment on lines
+38
to
+52
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. 어머나. 먼저 Context 를 여러개 지정하는 것이 반드시 필요할까? 생각해봐야하고요. 두번째로 Context정의를 최상단 root 영역에서 해야만하는가? |
||
); | ||
} | ||
|
||
export function useDetailContext() { | ||
return useContext(DetailDataContext); | ||
} | ||
|
||
export function useOnFetchDetailDataContext() { | ||
return useContext(OnFetchDetailDataContext); | ||
} | ||
|
||
export function usePopUpToggleContext() { | ||
return useContext(PopUpToggleContext); | ||
} | ||
Comment on lines
+64
to
+66
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. 이렇게 useContext 를 반환하는 함수를 사용하는 경우가 있더군요. |
||
|
||
export function useSetPopUpToggleContext() { | ||
return useContext(SetPopUpToggleContext); | ||
} | ||
|
||
export function useMainItemsContext() { | ||
return useContext(MainItemsContext); | ||
} | ||
|
||
export function useMainItemsActiveContext() { | ||
return useContext(MainItemsActiveContext); | ||
} | ||
|
||
export function useSetMainItemsActiveContext() { | ||
return useContext(SetMainItemsActiveContext); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { useEffect, useState } from "react"; | ||
import BestTab from "./bestTab/BestTab.jsx"; | ||
import PopUpContainer from "./popUp/PopUpContainer.jsx"; | ||
import ShowMoreBtn from "./ShowMoreBtn.jsx"; | ||
import API from "../../common/api.js"; | ||
import { DicoJsonCarousel } from "../util/dj-slider/DicoJsonCarousel.jsx"; | ||
Comment on lines
+5
to
+6
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. 요거만 보면 팀이 정하기 나름인데, 얼핏봐도 두 개가 어떤 차이가 있는지 구별이 되도록 이름 지으면 더 좋을 거 같아요. |
||
import ItemCard from "../util/ItemCard"; | ||
import styled from "styled-components"; | ||
|
||
import { | ||
useMainItemsContext, | ||
useMainItemsActiveContext, | ||
useSetMainItemsActiveContext, | ||
} from "../Context"; | ||
|
||
const CarouselContainer = styled.div` | ||
margin-bottom: 5rem; | ||
`; | ||
|
||
export default function Main() { | ||
const mainItems = useMainItemsContext(); | ||
const active = useMainItemsActiveContext(); | ||
const setActive = useSetMainItemsActiveContext(); | ||
|
||
const onShowMoreItems = () => { | ||
setActive(true); | ||
}; | ||
const getSalePrice = (price, discountRate) => { | ||
return price - price * (discountRate / 100); | ||
}; | ||
if (!mainItems) return null; | ||
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. 이렇게 빨리 반환하는거 아주 좋네요. |
||
return ( | ||
<> | ||
<BestTab /> | ||
{active ? ( | ||
mainItems.map((mainItem, id) => ( | ||
<CarouselContainer key={id}> | ||
<h2>{mainItem.title}</h2> | ||
<DicoJsonCarousel> | ||
{mainItem.childs.map((item, idx) => ( | ||
<ItemCard | ||
src={item.main_image} | ||
title={item.title} | ||
description={item.description} | ||
salePrice={getSalePrice(item.price, item.discount)} | ||
normalPrice={item.price} | ||
labels={item.label} | ||
key={idx} | ||
id={item._id} | ||
/> | ||
))} | ||
</DicoJsonCarousel> | ||
Comment on lines
+39
to
+52
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. 이렇게 사용되는 구조만 보면 직관적이고 꽤 편리해보이네요. |
||
</CarouselContainer> | ||
)) | ||
) : ( | ||
<CarouselContainer> | ||
<h2>{mainItems[0].title}</h2> | ||
<DicoJsonCarousel options={{ loop: true }}> | ||
{mainItems[0].childs.map((item, idx) => ( | ||
<ItemCard | ||
src={item.main_image} | ||
title={item.title} | ||
description={item.description} | ||
salePrice={getSalePrice(item.price, item.discount)} | ||
normalPrice={item.price} | ||
labels={item.label} | ||
key={idx} | ||
id={item._id} | ||
/> | ||
))} | ||
</DicoJsonCarousel> | ||
</CarouselContainer> | ||
)} | ||
<ShowMoreBtn active={active} onShowMoreItems={onShowMoreItems} /> | ||
<PopUpContainer /> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import styled from "styled-components"; | ||
|
||
const ShowMoreBtnStyle = styled.div` | ||
margin: 0 -4rem; | ||
font-size: 1.125rem; | ||
font-weight: 600; | ||
padding: 2.321225rem; | ||
text-align: center; | ||
background-color: #F5F5F7; | ||
box-shadow: inset 0px 4px 4px rgba(0, 0, 0, 0.05); | ||
cursor: pointer; | ||
display: ${props => props.active ? 'none' : 'block'}; | ||
`; | ||
|
||
export default function ShowMoreBtn({ active, onShowMoreItems }) { | ||
return <ShowMoreBtnStyle active={active} onClick={onShowMoreItems}>모든 카테고리 보기</ShowMoreBtnStyle>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import styled from "styled-components"; | ||
import ItemCard from "../../util/ItemCard"; | ||
|
||
const BestItemsStyle = styled.div` | ||
background-color: #eef4fa; | ||
display: grid; | ||
grid-template-columns: repeat(3, 1fr); | ||
grid-gap: 1.5rem; | ||
padding: 2.5rem; | ||
`; | ||
|
||
export default function BestItems({ childs }) { | ||
const getRandom = (n, max) => { | ||
const set = new Set(); | ||
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. set과 array의 차이도 알아두시면 좋죠. |
||
while (set.size < n) { | ||
set.add(Math.floor(Math.random() * max)); | ||
} | ||
return Array.from(set); | ||
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. return [...set] 도 될거에요. |
||
}; | ||
|
||
const getSalePrice = (price, discountRate) => { | ||
return price - price * (discountRate / 100); | ||
}; | ||
|
||
return ( | ||
<BestItemsStyle> | ||
{getRandom(3, childs.length).map((idx) => ( | ||
<ItemCard | ||
src={childs[idx].main_image} | ||
title={childs[idx].title} | ||
description={childs[idx].description} | ||
salePrice={getSalePrice(childs[idx].price, childs[idx].discount)} | ||
normalPrice={childs[idx].price} | ||
labels={childs[idx].label} | ||
key={idx} | ||
id={childs[idx]._id} | ||
large={true} | ||
/> | ||
))} | ||
</BestItemsStyle> | ||
); | ||
} |
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.
이런건 만드는건 아주 좋고요.
다음 프로젝트에서도 사용하면서 업그레이드 계속 해보세요.