diff --git a/src/assets/images/banner_roll.png b/src/assets/images/banner_roll.png
new file mode 100644
index 00000000..21e0994a
Binary files /dev/null and b/src/assets/images/banner_roll.png differ
diff --git a/src/pages/main/Main.tsx b/src/pages/main/Main.tsx
index 1f672879..4fa23d8e 100644
--- a/src/pages/main/Main.tsx
+++ b/src/pages/main/Main.tsx
@@ -1,12 +1,14 @@
import { useState } from "react";
import * as S from "./Main.styled";
-import Performance from "./components/performance/Performance";
+import Carousel from "./components/carousel/Carousel";
import Chips from "./components/chips/Chips";
+import Performance from "./components/performance/Performance";
import Footer from "./components/footer/Footer";
+import { dummyData } from "./constants/dummyData";
+
const Main = () => {
- // chips 클릭하면 seGenre 달라지게!
const [genre, setGenre] = useState("ALL");
const handleGenre = (value: string) => {
@@ -15,8 +17,9 @@ const Main = () => {
return (
+
-
+
);
diff --git a/src/pages/main/components/carousel/Carousel.styled.ts b/src/pages/main/components/carousel/Carousel.styled.ts
new file mode 100644
index 00000000..3bc60b2e
--- /dev/null
+++ b/src/pages/main/components/carousel/Carousel.styled.ts
@@ -0,0 +1,30 @@
+import styled from "styled-components";
+
+export const CarouselWarpper = styled.div`
+ width: 100%;
+ overflow: hidden;
+`;
+
+export const CarouselLayout = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+`;
+
+export const CarouselContainer = styled.ul`
+ display: flex;
+ width: 100%;
+`;
+
+export const CarouselItem = styled.button`
+ flex-shrink: 0;
+ width: 100%;
+
+ list-style: none;
+
+ img {
+ width: 100%;
+ height: auto;
+ }
+`;
diff --git a/src/pages/main/components/carousel/Carousel.tsx b/src/pages/main/components/carousel/Carousel.tsx
new file mode 100644
index 00000000..55c07e12
--- /dev/null
+++ b/src/pages/main/components/carousel/Carousel.tsx
@@ -0,0 +1,102 @@
+import { useState, useEffect, useRef } from "react";
+import { useNavigate } from "react-router-dom";
+import * as S from "./Carousel.styled";
+
+import carouselImg from "../../../../assets/images/banner_roll.png";
+interface PromotionProps {
+ promotionId: number;
+ promotionPhoto: string;
+ performanceId: number;
+}
+
+interface PromotionComponentProps {
+ promotionList: PromotionProps[];
+}
+
+// 서버에서 이미지 url 받아오기
+const ImgList = [carouselImg, carouselImg, carouselImg, carouselImg, carouselImg];
+
+const Carousel = ({ promotionList }: PromotionComponentProps) => {
+ const navigate = useNavigate();
+
+ const carouselList = ImgList;
+ const [currIndex, setCurrIndex] = useState(1);
+ const [currList, setCurrList] = useState();
+
+ const carouselRef = useRef(null);
+
+ // 인덱스 번호 변경
+ const moveToNthSlide = (index: number) => {
+ setTimeout(() => {
+ setCurrIndex(index);
+ if (carouselRef.current !== null) {
+ carouselRef.current.style.transition = "";
+ }
+ }, 500);
+ };
+
+ // 슬라이드 이동할 때 무한 + 어색하지 않도록 처음과 끝 반복
+ useEffect(() => {
+ if (carouselList.length !== 0) {
+ const startData = carouselList[0];
+ const endData = carouselList[carouselList.length - 1];
+ const newList = [endData, ...carouselList, startData];
+
+ setCurrList(newList);
+ }
+ }, [carouselList]);
+
+ // idx 변경되면 위치 이동
+ useEffect(() => {
+ if (carouselRef.current !== null) {
+ carouselRef.current.style.transform = `translateX(-${currIndex}00%)`;
+ }
+ }, [currIndex]);
+
+ // 5초마다 타이머 실행 -> 5초에 한 번씩 idx 변경
+ useEffect(() => {
+ const time = setTimeout(() => {
+ const newIndex = currIndex + 1;
+
+ if (newIndex === carouselList.length + 1) {
+ moveToNthSlide(1);
+ } else if (newIndex === 0) {
+ moveToNthSlide(carouselList.length);
+ }
+
+ setCurrIndex((prev) => prev + 1);
+ if (carouselRef.current !== null) {
+ carouselRef.current.style.transition = "all 0.5s ease-in-out";
+ }
+ }, 3000);
+ return () => {
+ clearInterval(time);
+ };
+ }, [currIndex]);
+
+ return (
+
+
+
+ {currList?.map((image, idx) => {
+ const key = `${image}-${idx}`;
+
+ return (
+ {
+ // id값 줘서 클릭하면 해당 공연으로 넘어갈 수 있도록
+ navigate("/lookup");
+ }}
+ >
+
+
+ );
+ })}
+
+
+
+ );
+};
+
+export default Carousel;
diff --git a/src/pages/main/components/performance/Performance.tsx b/src/pages/main/components/performance/Performance.tsx
index df65f258..e1b69baa 100644
--- a/src/pages/main/components/performance/Performance.tsx
+++ b/src/pages/main/components/performance/Performance.tsx
@@ -5,19 +5,29 @@ import Spacing from "@components/commons/spacing/Spacing";
import PerformnaceCard from "./PerformnaceCard";
import BannerImg from "../../../../assets/images/banner_basic.png";
-import { dummyData } from "./dummyData";
-
-const Performance = ({ genre }: { genre: string }) => {
+interface PerfonmanceProps {
+ performanceId: number;
+ performanceTitle: string;
+ performancePeriod: string;
+ ticketPrice: number;
+ dueDate: number;
+ genre: string;
+ posterImage: string;
+}
+interface PerformanceComponentProps {
+ genre: string;
+ performanceList: PerfonmanceProps[];
+}
+
+const Performance = ({ genre, performanceList }: PerformanceComponentProps) => {
const navigate = useNavigate();
const handleNavigate = () => {
navigate("/register");
};
- // 이 위치에 API로 불러온 배열 넣기
- const data = dummyData.performanceList;
-
- const filteredData = genre === "ALL" ? data : data.filter((item) => item.genre === genre);
+ const filteredData =
+ genre === "ALL" ? performanceList : performanceList.filter((item) => item.genre === genre);
const sortData = filteredData
.filter((item) => item.dueDate >= 1)
@@ -30,7 +40,7 @@ const Performance = ({ genre }: { genre: string }) => {
{data1.map((item) => (
-
+
))}
@@ -40,7 +50,7 @@ const Performance = ({ genre }: { genre: string }) => {
{data2.map((item) => (
-
+
))}
diff --git a/src/pages/main/components/performance/dummyData.ts b/src/pages/main/constants/dummyData.ts
similarity index 100%
rename from src/pages/main/components/performance/dummyData.ts
rename to src/pages/main/constants/dummyData.ts