diff --git a/sidedish/src/component/Carousel/Carousel.jsx b/sidedish/src/component/Carousel/Carousel.jsx index 7d00c76ff..230538ab1 100644 --- a/sidedish/src/component/Carousel/Carousel.jsx +++ b/sidedish/src/component/Carousel/Carousel.jsx @@ -1,11 +1,14 @@ -import React, { useRef, useState } from 'react'; +import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react'; import styled from 'styled-components'; -import { IoChevronBackSharp, IoChevronForwardSharp } from 'react-icons/io5'; +import CarouselItem from 'component/Carousel/CarouselItem'; -const Carousel = ({ children, itemWidth, maxItem, skipItem, animationTime }) => { +const Carousel = forwardRef(({ children, skipItem, animationTime }, ref) => { + const currRef = useRef(); const [locationX, setLocationX] = useState(0); const [currIdx, setCurrIdx] = useState(0); const [leftItem, setLeftItem] = useState(); + const [itemWidth, setItemWidth] = useState(0); + const maxItem = currRef.current && Math.floor(currRef.current.offsetWidth / itemWidth) + 1; const handleClickPrev = () => { const possibleMove = currIdx >= skipItem ? skipItem : currIdx; @@ -16,6 +19,7 @@ const Carousel = ({ children, itemWidth, maxItem, skipItem, animationTime }) => const handleClickNext = () => { const totalItemCount = children.length; + console.log(currIdx); const newLeftItem = totalItemCount - (currIdx + maxItem); const possibleMove = newLeftItem >= skipItem ? skipItem : newLeftItem; setLocationX(locationX - itemWidth * possibleMove); @@ -23,6 +27,21 @@ const Carousel = ({ children, itemWidth, maxItem, skipItem, animationTime }) => setLeftItem(newLeftItem - possibleMove); }; + useImperativeHandle( + ref, + () => ({ + handleClickPrev, + handleClickNext, + }), + [handleClickPrev, handleClickNext] + ); + + const carouselItems = + children && + children.map((child) => { + return ; + }); + return ( currIdx={currIdx} leftItem={leftItem} > - -
-
{children}
+
+ {carouselItems}
- ); -}; +}); export default Carousel; export const StyledCarousel = styled.div` position: relative; + overflow: hidden; - .carouselWrapper { - overflow: hidden; - } - .carouselList { + .container { display: flex; transition: ${({ animationTime }) => `transform ${animationTime}s`}; transform: ${({ locationX }) => `translateX(${locationX}px)`}; } - .arrow { - position: absolute; - font-size: 2rem; - top: 40%; - } - .leftArrow { - left: -50px; - opacity: ${({ currIdx }) => (currIdx === 0 ? '0.3' : '1')}; - } - .leftArrow:hover { - color: ${({ currIdx }) => currIdx !== 0 && 'red'}; - } - .rightArrow { - right: -50px; - opacity: ${({ leftItem }) => (leftItem === 0 ? '0.3' : '1')}; - } - .rightArrow :hover { - color: ${({ leftItem }) => leftItem !== 0 && 'red'}; - } `; diff --git a/sidedish/src/component/Carousel/CarouselItem.jsx b/sidedish/src/component/Carousel/CarouselItem.jsx new file mode 100644 index 000000000..4b46ad045 --- /dev/null +++ b/sidedish/src/component/Carousel/CarouselItem.jsx @@ -0,0 +1,18 @@ +import React, { useRef, forwardRef, useEffect, useState, useImperativeHandle } from 'react'; +// import styled from 'styled-components'; + +const CarouselItem = ({ item, setItemWidth }) => { + const targetRef = useRef(); + + useEffect(() => { + setItemWidth(targetRef.current.offsetWidth); + }, []); + + return ( + <> +
{item}
+ + ); +}; + +export default CarouselItem; diff --git a/sidedish/src/component/DishItem/DishItem.jsx b/sidedish/src/component/DishItem/DishItem.jsx index baad4763d..ed0c76177 100644 --- a/sidedish/src/component/DishItem/DishItem.jsx +++ b/sidedish/src/component/DishItem/DishItem.jsx @@ -17,7 +17,6 @@ const DishItem = ({ const toggleModal = () => { setShowDetail((showDetail) => !showDetail); - console.log('modal is toggled'); }; const handleMouseEnter = () => setIsHover(true); @@ -69,7 +68,7 @@ export default DishItem; const StyledDishItem = styled.div` width: ${({ size }) => (size === 'L' ? '384px' : '308px')}; height: ${({ size }) => (size === 'L' ? '540px' : '456px')}; - margin-right: ${({ size }) => size === 'M' && '16px'}; + margin-right: ${({ size }) => size === 'M' && '16px'}; // 얘를 지우고 캐로셀 안에서 작동이 되게 .imgContainer { position: relative; } diff --git a/sidedish/src/component/ItemDetail/DetailModal.jsx b/sidedish/src/component/ItemDetail/DetailModal.jsx index 78835b095..158bbab8f 100644 --- a/sidedish/src/component/ItemDetail/DetailModal.jsx +++ b/sidedish/src/component/ItemDetail/DetailModal.jsx @@ -109,11 +109,16 @@ const DetailModal = ({ detailData, loading, title, badge }) => { export default DetailModal; export const ModalStyle = styled.div` - width: 70%; + width: 50%; height: 95%; background-color: white; display: flex; flex-direction: column; + + .error_center { + justify-content: center; + align-items: center; + } `; const Top = styled.div` diff --git a/sidedish/src/component/ItemDetail/ItemDetail.jsx b/sidedish/src/component/ItemDetail/ItemDetail.jsx index 2df1f8822..5da778781 100644 --- a/sidedish/src/component/ItemDetail/ItemDetail.jsx +++ b/sidedish/src/component/ItemDetail/ItemDetail.jsx @@ -24,7 +24,9 @@ const ItemDetail = ({ id, toggleModal, title, badge }) => { {detailData ? ( ) : ( - 데이터가 없습니다. + + 😢불러올 데이터가 없습니다😢 + )}
X @@ -36,6 +38,15 @@ const ItemDetail = ({ id, toggleModal, title, badge }) => { export default ItemDetail; +const ErrorStyle = styled.div` + height: 100%; + display: flex; + justify-content: center; + align-items: center; + font-size: 32px; + font-weight: bold; +`; + const StyleModal = styled.div` position: fixed; display: flex; @@ -49,9 +60,9 @@ const StyleModal = styled.div` .closeBtn { position: fixed; - left: 86%; + left: 76%; font-size: 24px; - top: 36px; + top: 20px; color: white; } `; diff --git a/sidedish/src/component/Main/Main.jsx b/sidedish/src/component/Main/Main.jsx index 3995e334a..9b3447619 100644 --- a/sidedish/src/component/Main/Main.jsx +++ b/sidedish/src/component/Main/Main.jsx @@ -5,7 +5,12 @@ import MoreButton from 'component/atoms/MoreButton'; const Main = () => { const [slideDishCount, setSlideDishCount] = useState(1); - const slideDishes = ['main', 'soup', 'side']; + const slideDishes = [ + { path: 'main', title: '모두가 좋아하는 든든한 메인요리' }, + { path: 'soup', title: '정성이 담긴 뜨끈한 국물요리' }, + { path: 'side', title: '식탁을 풍성하게 하는 정갈한 밑반찬' }, + ]; + const slideDishList = slideDishes .slice(0, slideDishCount) .map((category, idx) => ); diff --git a/sidedish/src/component/SlideDish/SlideDish.jsx b/sidedish/src/component/SlideDish/SlideDish.jsx index a5b8332b3..8325f4f3a 100644 --- a/sidedish/src/component/SlideDish/SlideDish.jsx +++ b/sidedish/src/component/SlideDish/SlideDish.jsx @@ -1,31 +1,41 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useLayoutEffect, useRef } from 'react'; import styled from 'styled-components'; import DishItem from 'component/DishItem/DishItem'; import { URL } from 'util/data'; import useFetch from 'hooks/useFetch'; import Carousel from 'component/Carousel/Carousel'; +import { IoChevronBackSharp, IoChevronForwardSharp } from 'react-icons/io5'; -const SlideDish = ({ category }) => { - const { data: slideData, loading, error } = useFetch({ url: URL[category]() }); +const SlideDish = ({ category: { path, title } }) => { + const ref = useRef(); + + const { data: slideData, loading, error } = useFetch({ url: URL[path]() }); const slideCategory = slideData && slideData.body.map((item) => ); + const settings = { + ref: ref, + skipItem: 2, + animationTime: 0.5, + }; + if (error) throw Error(error); return loading ? (
Loading...
) : ( -
모두가 좋아하는 든든한 메인요리
- - {slideCategory} - +
{title}
+ ref.current.handleClickPrev()} + className="leftArrow arrow" + /> + {slideCategory} + + ref.current.handleClickNext()} + className="rightArrow arrow" + />
); }; @@ -35,9 +45,28 @@ export default SlideDish; const SlideContainer = styled.div` min-width: 1280px; position: relative; + + .arrow { + position: absolute; + font-size: 2rem; + top: 40%; + } + .carouselWrapper { min-width: 1280px; } + .leftArrow { + left: -50px; + } + .leftArrow:hover { + color: red; + } + .rightArrow { + right: -50px; + } + .rightArrow :hover { + color: red; + } `; const Header = styled.div`