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

[#19] refactor: 🔨 리팩토링 #22

Merged
merged 2 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 6 additions & 25 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,15 @@
import BestTab from "./component/bestTab/BestTab.jsx";
import Header from "./component/header/Header.jsx";
import PopUpContainer from "./component/popUp/PopUpContainer.jsx";
import ShowMoreBtn from "./component/ShowMoreBtn.jsx";
import SlideContainer from "./component/slideContainer/SlideContainer.jsx";
import GlobalStyle from "./style.js";
import { useState } from "react";
import api from "./api.js";
import Main from "./component/main/Main.jsx";
import GlobalStyle from "./common/style.js";
import { ContextProvider } from './component/Context.jsx';

function App() {
const [toggle, setToggle] = useState(false);
const [detailData, setDetailData] = useState(null);
const onPopUpToggle = () => setToggle(!toggle);

const onFetchDetailData = async (id) => {
const detailData = await api(`/detail/${id}`);
if(detailData) {
setDetailData(detailData);
onPopUpToggle();
}
}

return (
<>
<ContextProvider>
<GlobalStyle />
<Header />
<BestTab onFetchDetailData={onFetchDetailData}/>
<SlideContainer onFetchDetailData={onFetchDetailData}/>
<ShowMoreBtn />
{toggle ? <PopUpContainer detailData={detailData} onPopUpToggle={onPopUpToggle}/> : null}
</>
<Main />
</ContextProvider>
);
}

Expand Down
10 changes: 5 additions & 5 deletions src/api.js → src/common/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const api = () => {
const API = () => {
const URL = "https://codesquad-2021-api.herokuapp.com/sidedish";
const api = (path="", data="") => {
const API = path => {
const req = {
method : 'GET',
headers: {
Expand All @@ -9,12 +9,12 @@ const api = () => {
};
return fetch(URL + path, req);
}
return async(path, data) => {
const result = await api(path, data);
return async (path) => {
const result = await API(path);
let json = await result.json();
if (!json || json.length === 0) json = null;
return json;
}
}

export default api();
export default API();
15 changes: 15 additions & 0 deletions src/common/const.js
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 };
File renamed without changes.
48 changes: 48 additions & 0 deletions src/component/Context.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { createContext, useContext, useState } from "react";
import API from "../common/api.js";

const DetailDataContext = createContext();
const PopUpToggleContext = createContext();
const OnFetchDetailDataContext = createContext();
const SetPopUpToggleContext = createContext();

export function ContextProvider({ children }) {
const [detailData, setDetailData] = useState(null);
const [popUpToggle, setPopUpToggle] = useState(false);

const onFetchDetailData = async (id) => {
const data = await API(`/detail/${id}`);
if(data) {
setDetailData(data);
setPopUpToggle(!popUpToggle);
}
}

return (
<DetailDataContext.Provider value={detailData}>
<OnFetchDetailDataContext.Provider value={onFetchDetailData}>
<PopUpToggleContext.Provider value={popUpToggle}>
<SetPopUpToggleContext.Provider value={setPopUpToggle}>
{children}
</SetPopUpToggleContext.Provider>
</PopUpToggleContext.Provider>
</OnFetchDetailDataContext.Provider>
</DetailDataContext.Provider>
);
}

export function useDetailContext() {
return useContext(DetailDataContext);
}

export function useOnFetchDetailDataContext() {
return useContext(OnFetchDetailDataContext);
}

export function usePopUpToggleContext() {
return useContext(PopUpToggleContext);
}

export function useSetPopUpToggleContext() {
return useContext(SetPopUpToggleContext);
}
45 changes: 0 additions & 45 deletions src/component/bestTab/BestItems.jsx

This file was deleted.

15 changes: 15 additions & 0 deletions src/component/main/Main.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import BestTab from "./bestTab/BestTab.jsx";
import PopUpContainer from "./popUp/PopUpContainer.jsx";
import ShowMoreBtn from "./ShowMoreBtn.jsx";
import SlideContainer from "./slideContainer/SlideContainer.jsx";

export default function Main() {
return (
<>
<BestTab/>
<SlideContainer/>
<ShowMoreBtn />
<PopUpContainer/>
</>
);
}
File renamed without changes.
42 changes: 42 additions & 0 deletions src/component/main/bestTab/BestItems.jsx
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, onFetchDetailData }) {
const getRandom = (n, max) => {
const set = new Set();
while (set.size < n) {
set.add(Math.floor(Math.random() * max));
}
return Array.from(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}
onFetchDetailData={onFetchDetailData}
/>
))}
</BestItemsStyle>
);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState, useEffect } from 'react';
import { useState, useEffect } from "react";
import styled from "styled-components";
import BestTabContainer from "./BestTabContainer";
import BestTabNavigator from "./BestTabNavigator";
import api from '../../api';
import api from "../../../common/api.js";

const BestTabStyle = styled.div`
h2 {
Expand All @@ -11,27 +11,34 @@ const BestTabStyle = styled.div`
margin-bottom: 5rem;
`;

export default function BestTab({onFetchDetailData}) {
export default function BestTab({ onFetchDetailData }) {
const [active, setActive] = useState(0);
const [bestItems, setBestItems] = useState(null);

useEffect(() => {
if (!bestItems) {
(async() => {
const data = await api('/best');
setBestItems(data);
(async () => {
const data = await api("/best");
setBestItems(data);
})();
}
return;
}, [bestItems]);

if(!bestItems) return null;
if (!bestItems) return null;

return (
<BestTabStyle>
<h2>후기가 증명하는 베스트 반찬</h2>
<BestTabNavigator bestItems={bestItems} active={active} setActive={setActive}/>
<BestTabContainer bestItem={bestItems[active]} onFetchDetailData={onFetchDetailData}/>
<BestTabNavigator
bestItems={bestItems}
active={active}
setActive={setActive}
/>
<BestTabContainer
bestItem={bestItems[active]}
onFetchDetailData={onFetchDetailData}
/>
</BestTabStyle>
)
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ const BestTabNavigatorStyle = styled.div`

const BestTabNavigatorItemStyle = styled.div.attrs(props => ({
weight: props.active ? 600 : 400,
color: props.active ? "#333" : "#828282"
color: props.active ? "#333" : "#828282",
bgColor: props.active ? "#EEF4FA" : "#F5F5F5"
}))`
font-size: 1.125rem;
background-color: #EEF4FA;
background-color: ${(props) => props.bgColor};
padding: 1rem 2rem;
text-align: center;
font-weight: ${(props) => props.weight};
Expand Down
71 changes: 71 additions & 0 deletions src/component/main/popUp/PopUpContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import styled from "styled-components";
import { FaTimes } from "react-icons/fa";
import PopUpImages from "./PopUpImages";
import PopUpInformations from "./PopUpInformations";
import {
usePopUpToggleContext,
useSetPopUpToggleContext,
} from "../../Context";

const PopUpContainerStyle = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;

&:before {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: -1;
}
`;

const PopUpDetailContainerStyle = styled.div`
display: grid;
grid-template-columns: 24.5rem auto;
padding: 3rem;
grid-gap: 2rem;
background-color: #fff;
width: 60rem;
margin: 6vh auto;
position: relative;
`;

const CloseBtnStyle = styled.button`
color: #fff;
opacity: 0.8;
position: absolute;
right: -2.5rem;
font-size: 1.25rem;
cursor: pointer;

&:hover {
opacity: 1;
}
`;

export default function PopUpContainer() {
const toggle = usePopUpToggleContext();
const dispatch = useSetPopUpToggleContext();
const onClick = () => {
dispatch();
};
if (!toggle) return null;
return (
<PopUpContainerStyle>
<PopUpDetailContainerStyle>
<CloseBtnStyle onClick={onClick}>
<FaTimes></FaTimes>
</CloseBtnStyle>
<PopUpImages />
<PopUpInformations />
</PopUpDetailContainerStyle>
</PopUpContainerStyle>
);
}
Loading