Skip to content

Commit

Permalink
Merge pull request #12 from zel0rd/fe/feature/MenuDetailModal
Browse files Browse the repository at this point in the history
Fe/feature/menu detail modal
  • Loading branch information
cchoongh committed Apr 25, 2021
2 parents 45f445d + 66beb47 commit f7a1621
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 126 deletions.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,40 @@ import Preview from './Preview/Preview.js';
import OrderInfo from './OrderInfo/OrderInfo.js';
import RecommendSlider from './RecommendSlider/RecommendSlider.js';

// FIXME: these are images for test
import rvimg from './MOCK_IMGS/redvelvet.png';
import bpimg from './MOCK_IMGS/blackpink.png';

const MOCK_DATA = {
"hash": "H9881",
"data": {
"top_image": "https://cdn.bmf.kr/_data/product/H9881/910a01a81c49cb75414edb759237501f.jpg",
"thumb_images": [
"https://cdn.bmf.kr/_data/product/H9881/910a01a81c49cb75414edb759237501f.jpg",
"https://cdn.bmf.kr/_data/product/H9881/fbf29077698ca16f8050e43476b47f38.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c96c6949efc3391148e9b280a2c5ed0b.jpg",
"https://cdn.bmf.kr/_data/product/H9881/71411e15d2d961df496f87f08648b345.jpg",
"https://cdn.bmf.kr/_data/product/H9881/437196dacf46b52b11d0bccbc4231558.jpg"
],
"product_description": "경상도 명물 요리 세 가지를 한 상에!",
"point": "312원",
"delivery_info": "서울 경기 새벽배송 / 전국택배 (제주 및 도서산간 불가) [화 · 수 · 목 · 금 · 토] 수령 가능한 상품입니다.",
"delivery_fee": "2,500원 (40,000원 이상 구매 시 무료)",
"prices": ["39,000원", "31,200원"],
"detail_section": [
"https://cdn.bmf.kr/_data/product/H9881/7fb1ddf1adeadc5410cecd79441f7b65.jpg",
"https://cdn.bmf.kr/_data/product/H9881/b776c59544b516a184d1363c2c802789.jpg",
"https://cdn.bmf.kr/_data/product/H9881/cc2b4a61db410096db0e3c497096d63f.jpg",
"https://cdn.bmf.kr/_data/product/H9881/77970960c8efe0992f9746c37062e1e4.jpg",
"https://cdn.bmf.kr/_data/product/H9881/aa56cec7d2fe4dde0b124c17a06ffda6.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c9fbe313767400ce21ea83bb2b9d8e96.jpg",
"https://cdn.bmf.kr/_data/product/H9881/320939f0d0fbe8e4846e20111f1aa4ce.jpg",
"https://cdn.bmf.kr/_data/product/H9881/5778ae933121c5d131889ecbf5e2874c.jpg",
"https://cdn.bmf.kr/_data/product/H9881/785291ed7fe3f2a8c7e06f443dea7553.jpg",
"https://cdn.bmf.kr/_data/product/H9881/92ef47f6efdd0286f6af7f712c3c838d.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c0319354245ee2963ccb97d60943e8ff.jpg",
"https://cdn.bmf.kr/_data/product/H9881/07b1864a06f3b0b26af9a7148ac70cfb.jpg",
"https://cdn.bmf.kr/_data/product/H9881/ba2aba220a55924a00c668dd13c4cee1.jpg"
]
},
};

const StyledMenuDetail = styled.div`
display: flex;
flex-direction: column;
width: 700px;
height: 800px;
height: auto;
box-sizing: border-box;
background-color: #FFFFFF;
pointer-events: auto;
border-radius: 5px;
pointer-events: auto;
.upper-cont {
flex: 6.5;
display: flex;
padding: 20px;
}
.bottom-cont {
flex: 3.5;
}
`;

function MenuDetail({ hash, title }) {
const [data, setData] = useState(); // TODO: apply 'useFetch()'?

useEffect(() => {
// TODO: fetch data using 'hash'
setData(MOCK_DATA.data);
}, []);

function MenuDetail({ data }) {
return (
<StyledMenuDetail>
{data &&
<>
<div className="upper-cont">
<Preview imgs={[rvimg, bpimg]}/>
<OrderInfo title={title} data={data}/>
</div>
<div className="bottom-cont">
<RecommendSlider data={data.detail_section}/>
</div>
</>}
<>
<div className="upper-cont">
<Preview imgUrls={data.thumb_images}/>
<OrderInfo data={data}/>
</div>
<div className="bottom-cont">
<RecommendSlider data={data.detail_section}/>
</div>
</>}
</StyledMenuDetail>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ function Counter({ onChangeCount }) {
<div className="count">{count}</div>
<div className="btn-cont">
<ControlBtn onClick={handleClickUpBtn}>
<img src={UpBtnSvg} alt="image not found"/>
<img src={UpBtnSvg} alt="up button"/>
</ControlBtn>
<ControlBtn down disabled={count === 1} onClick={handleClickDownBtn}>
<img src={DownBtnSvg} alt="image not found"/>
<img src={DownBtnSvg} alt="down button"/>
</ControlBtn>
</div>
</StyledCounter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import Counter from './Counter.js';
const StyledOrderInfo = styled.div`
flex: 0 0 53%;
box-sizing: border-box;
padding-right: 16px;
text-align: left;
font-family: "Noto Sans KR";
& > * {
margin: 16px 0px;
& > :not(.title, .order-btn) {
margin: 16px auto;
}
.title {
Expand Down Expand Up @@ -87,7 +85,7 @@ const StyledOrderInfo = styled.div`
const OrderBtn = styled.button`
width: 90%;
height: 50px;
margin-left: 5%;
margin: 16px 0 16px 5%;
line-height: 26px;
font-size: 18px;
font-weight: 800;
Expand All @@ -97,7 +95,7 @@ const OrderBtn = styled.button`
background-color: #82D32D;
`;

function OrderInfo({ title, data }) {
function OrderInfo({ data }) {
const priceRef = useRef(data.prices[1].match(/[0-9]*/g).join(''));
const [totalPrice, setTotalPrice] = useState(data.prices[1]);

Expand All @@ -116,7 +114,7 @@ function OrderInfo({ title, data }) {

return (
<StyledOrderInfo>
<div className="title">{title}</div>
<div className="title">{data.title}</div>
<div className="product-desc">{data.product_description}</div>
<div className="price-cont">
<EventSpecialBadge/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useState, useEffect } from 'react';
import styled from 'styled-components'
import styled from 'styled-components';

const StyledPreview = styled.div`
flex: 0 0 47%;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 16px;
padding-right: 20px;
`;

const SelectedImg = styled.img`
Expand Down Expand Up @@ -35,6 +35,8 @@ const ImgListItem = styled.li`
height: 100%;
box-sizing: border-box;
border-radius: inherit;
pointer-events: none;
/* z-index: -1; */
}
&.no-img {
Expand All @@ -50,47 +52,40 @@ const ImgListItem = styled.li`
}
`;

function Preview({ imgs, defaultListSize = 5 }) {
function Preview({ imgUrls, defaultListSize = 5 }) {
const [selectedImgIdx, setSelectedImgIdx] = useState(0);
const [imgListData, setImgListData] = useState([]);

useEffect(() => {
// TODO: fetch img dat1a;
const res = imgs;
setImgListData(res);
}, []);

const handleClickImg = (newSelectedImgIdx) => {
// FIXME: fix not to use 'idx' when the 'id' is enable.
if (selectedImgIdx === newSelectedImgIdx)
const handleClickImg = ({ target }) => {
console.log(selectedImgIdx, target.dataset.idx);
if (!target.dataset.idx || selectedImgIdx === Number(target.dataset.idx))
return;

setSelectedImgIdx(newSelectedImgIdx);
setSelectedImgIdx(Number(target.dataset.idx));
};

const renderImgs = () => {
// FIXME: modify 'key' not to be 'idx'
const list = imgListData.map((img, idx) =>
const imgs = imgUrls.map((url, idx) =>
<ImgListItem
key={idx}
className={idx === selectedImgIdx ? "select" : ""}
onClick={() => handleClickImg(idx)}>
<img src={img}/>
data-idx={idx}
className={idx === selectedImgIdx ? 'select' : ''}>
<img src={url}/>
</ImgListItem>
);

let nextIdx = list.length;
let nextIdx = imgs.length;

while (list.length < defaultListSize)
list.push(<ImgListItem key={nextIdx++} className="no-img"/>)
while (imgs.length < defaultListSize)
imgs.push(<ImgListItem key={nextIdx++} className='no-img'/>)

return list;
return imgs;
};

return (
<StyledPreview>
<SelectedImg src={imgListData[selectedImgIdx]}/>
<ImgList onClickCapture={() => handleClickImg}>
<SelectedImg src={imgUrls[selectedImgIdx]}/>
<ImgList onClickCapture={handleClickImg}>
{renderImgs()}
</ImgList>
</StyledPreview>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,49 @@ import styled from 'styled-components';
import Slider from '../../../common/Slider.js';
// import MenuCard from '../../../MenuCard/MenuCard.js';

import leftBtnSvg from '../../../../rsc/svg/leftbtn.svg';
import rightBtnSvg from '../../../../rsc/svg/rightbtn.svg';
import leftBtnDisabledSvg from '../../../../rsc/svg/leftbtn_disabled.svg';
import rightBtnDisabledSvg from '../../../../rsc/svg/rightbtn_disabled.svg';

const StyledRecommendSlider = styled.div`
background-color: green; // FIXME
width: 100%;
height: 100%;
box-sizing: border-box;
/* padding: 20px; */
padding: 20px;
background: #F5F5F7;
.title {
float: left;
font-weight: 800;
font-size: 18px;
line-height: 26px;
color: #333333;
}
.btn-cont {
float: right;
margin-bottom: 20px;
font-size: 14px;
line-height: 20px;
color: #333333;
vertical-align: middle;
}
`;

const SlideBtn = styled.button`
width: 30px; // FIXME
height: 30px; // FIXME
padding: 0 6px;
border: none;
background-color: transparent;
&:not(:disabled):hover {
opacity: 0.7;
}
.img {
pointer-events: none;
z-index: -1;
}
`;

const TestItem = styled.div`
Expand All @@ -24,7 +56,6 @@ const TestItem = styled.div`
`;

function RecommendSlider({ data = [0, 1, 2, 3, 4, 5, 6] }) { // FIXME
// const [data, setData] = setState()
const sliderRef = useRef();
const [disableLeftBtn, setDisableLeftBtn] = useState();
const [disableRightBtn, setDisableRightBtn] = useState();
Expand All @@ -48,10 +79,14 @@ function RecommendSlider({ data = [0, 1, 2, 3, 4, 5, 6] }) { // FIXME

return (
<StyledRecommendSlider>
<div className="title">함께하면 더욱 맛있는 상품</div>
<div className="btn-cont">
<SlideBtn disabled={disableLeftBtn} onClick={handleClickLeftBtn}>
<img src={disableLeftBtn ? leftBtnDisabledSvg : leftBtnSvg} alt="left button"/>
</SlideBtn>
{sliderRef.current?.getCurrPage()}/{sliderRef.current?.getTotalPage()}
<SlideBtn disabled={disableRightBtn} onClick={handleClickRightBtn}>
<img src={disableRightBtn ? rightBtnDisabledSvg : rightBtnSvg} alt="right button"/>
</SlideBtn>
</div>
<Slider
Expand Down
43 changes: 38 additions & 5 deletions fe/sidedish-fe/src/components/MenuDetailModal/MenuDetailModal.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,49 @@
import React, { useState, useEffect } from 'react';
import useFetchData from '../../util/hooks/useFetchData.js';
import Global from '../../util/Global.js';
import Modal from '../common/Modal.js';
import MenuDetail from './MenuDetail/MenuDetail.js';

// FIXME
function MenuDetailModal({ hash, title = "[소중한식사] 경상도 한상차림" }) {
useEffect(() => {
// TODO: fetch img data
}, []);
function MenuDetailModal({ hash = "HDF4C", title = "[소중한식사] 경상도 한상차림" }) {
// const { response } = useFetchData(Global.getServerUrl() + '/detail/' + hash, {});
const response = {
"hash": "H9881",
"data": {
"top_image": "https://cdn.bmf.kr/_data/product/H9881/910a01a81c49cb75414edb759237501f.jpg",
"thumb_images": [
"https://cdn.bmf.kr/_data/product/H9881/910a01a81c49cb75414edb759237501f.jpg",
"https://cdn.bmf.kr/_data/product/H9881/fbf29077698ca16f8050e43476b47f38.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c96c6949efc3391148e9b280a2c5ed0b.jpg",
"https://cdn.bmf.kr/_data/product/H9881/71411e15d2d961df496f87f08648b345.jpg",
"https://cdn.bmf.kr/_data/product/H9881/437196dacf46b52b11d0bccbc4231558.jpg"
],
"product_description": "경상도 명물 요리 세 가지를 한 상에!",
"point": "312원",
"delivery_info": "서울 경기 새벽배송 / 전국택배 (제주 및 도서산간 불가) [화 · 수 · 목 · 금 · 토] 수령 가능한 상품입니다.",
"delivery_fee": "2,500원 (40,000원 이상 구매 시 무료)",
"prices": ["39,000원", "31,200원"],
"detail_section": [
"https://cdn.bmf.kr/_data/product/H9881/7fb1ddf1adeadc5410cecd79441f7b65.jpg",
"https://cdn.bmf.kr/_data/product/H9881/b776c59544b516a184d1363c2c802789.jpg",
"https://cdn.bmf.kr/_data/product/H9881/cc2b4a61db410096db0e3c497096d63f.jpg",
"https://cdn.bmf.kr/_data/product/H9881/77970960c8efe0992f9746c37062e1e4.jpg",
"https://cdn.bmf.kr/_data/product/H9881/aa56cec7d2fe4dde0b124c17a06ffda6.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c9fbe313767400ce21ea83bb2b9d8e96.jpg",
"https://cdn.bmf.kr/_data/product/H9881/320939f0d0fbe8e4846e20111f1aa4ce.jpg",
"https://cdn.bmf.kr/_data/product/H9881/5778ae933121c5d131889ecbf5e2874c.jpg",
"https://cdn.bmf.kr/_data/product/H9881/785291ed7fe3f2a8c7e06f443dea7553.jpg",
"https://cdn.bmf.kr/_data/product/H9881/92ef47f6efdd0286f6af7f712c3c838d.jpg",
"https://cdn.bmf.kr/_data/product/H9881/c0319354245ee2963ccb97d60943e8ff.jpg",
"https://cdn.bmf.kr/_data/product/H9881/07b1864a06f3b0b26af9a7148ac70cfb.jpg",
"https://cdn.bmf.kr/_data/product/H9881/ba2aba220a55924a00c668dd13c4cee1.jpg"
]
},
};

return (
<Modal>
<MenuDetail hash={hash} title={title}/>
{response && <MenuDetail data={{ ...response.data, title }}/>}
</Modal>
)
};
Expand Down
3 changes: 1 addition & 2 deletions fe/sidedish-fe/src/components/common/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import styled from 'styled-components';
const StyledSlider = styled.div`
display: inline-block;
width: 100%;
position: relative;
`;

const SliderList = styled.ul`
width: ${props => props.width + "px"};
display: flex;
justify-content: space-between;
position: absolute;
position: relative;
top: 0;
left: ${props => props.positionLeft + "px"};
transition: left 300ms linear;
Expand Down
3 changes: 3 additions & 0 deletions fe/sidedish-fe/src/rsc/svg/leftbtn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions fe/sidedish-fe/src/rsc/svg/leftbtn_disabled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f7a1621

Please sign in to comment.