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

[Feat/#120] 메인 페이지 Carousel 기능 추가 #121

Merged
merged 5 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
Binary file added src/assets/images/banner_roll.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions src/pages/main/Main.tsx
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -15,8 +17,9 @@ const Main = () => {

return (
<S.MainWrapper>
<Carousel promotionList={dummyData.promotionList} />
<Chips handleGenre={handleGenre} />
<Performance genre={genre} />
<Performance genre={genre} performanceList={dummyData.performanceList} />
<Footer />
</S.MainWrapper>
);
Expand Down
30 changes: 30 additions & 0 deletions src/pages/main/components/carousel/Carousel.styled.ts
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 까먹고 있었는데 button 요소 의 하위 요소로 img 요소가 왔을 떄의 스타일 정의 방식은 오랜만에 보내요!
딱히 코드의 내용이 없을 때 활용하면 좋긴 하겠네요 ~!

width: 100%;
height: auto;
}
`;
102 changes: 102 additions & 0 deletions src/pages/main/components/carousel/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Comment on lines +4 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 파일 경로 이렇게 작성하신 이유가 있을까여??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버에서 보내주는 이미지를 삽입해야 해서 임시로 넣은 이미지입니다!

promotionId: number;
promotionPhoto: string;
performanceId: number;
}

interface PromotionComponentProps {
promotionList: PromotionProps[];
}

// 서버에서 이미지 url 받아오기
const ImgList = [carouselImg, carouselImg, carouselImg, carouselImg, carouselImg];

const Carousel = (promotionList: PromotionComponentProps) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const Carousel = (promotionList: PromotionComponentProps) => {
const Carousel = ({ promotionList }: PromotionComponentProps) => {

const navigate = useNavigate();

const carouselList = ImgList;
const [currIndex, setCurrIndex] = useState(1);
const [currList, setCurrList] = useState<string[]>();

const carouselRef = useRef<HTMLUListElement>(null);

// 인덱스 번호 변경
const moveToNthSlide = (index: number) => {
setTimeout(() => {
setCurrIndex(index);
if (carouselRef.current !== null) {
carouselRef.current.style.transition = "";
}
}, 500);
};
Comment on lines +29 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 일정 시간을 준 뒤에 우선 인덱스를 옮겨보고, 해당 인덱스의 위치가 존재하지 않으면 이동하는 애니메이션을 존재하지 않도록 하는 센스 좋아요 ~~!


// 슬라이드 이동할 때 무한 + 어색하지 않도록 처음과 끝 반복
useEffect(() => {
if (carouselList.length !== 0) {
const startData = carouselList[0];
const endData = carouselList[carouselList.length - 1];
const newList = [endData, ...carouselList, startData];

setCurrList(newList);
}
}, [carouselList]);
Comment on lines +39 to +47
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 새로운 배열을 연결하는 방식을 채택하셨네요! 그걸 위해 마지막 데이터와 시작 데이터를 양쪽에 추가해줘서 좀 더 자연스럽게 만들어준 것도 좋아요 ~!


// idx 변경되면 위치 이동
useEffect(() => {
if (carouselRef.current !== null) {
carouselRef.current.style.transform = `translateX(-${currIndex}00%)`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) ${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);
Comment on lines +72 to +73
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5) 언마운트될 때 클린업 함수 작성하는 센스 좋은데요? 사이드 이펙트 방지하는 것 같고 좋네요!

};
}, [currIndex]);

return (
<S.CarouselWarpper>
<S.CarouselLayout>
<S.CarouselContainer ref={carouselRef}>
{currList?.map((image, idx) => {
const key = `${image}-${idx}`;

return (
<S.CarouselItem
key={key}
onClick={() => {
// id값 줘서 클릭하면 해당 공연으로 넘어갈 수 있도록
navigate("/lookup");
}}
>
<img src={image} alt="carousel-img" />
</S.CarouselItem>
);
})}
</S.CarouselContainer>
</S.CarouselLayout>
</S.CarouselWarpper>
);
};

export default Carousel;
28 changes: 19 additions & 9 deletions src/pages/main/components/performance/Performance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -30,7 +40,7 @@ const Performance = ({ genre }: { genre: string }) => {
<S.PerformanceWrapper>
<S.PerformanceLayout>
{data1.map((item) => (
<PerformnaceCard {...item} />
<PerformnaceCard key={item.performanceId} {...item} />
))}
</S.PerformanceLayout>
<Spacing marginBottom="1.5" />
Expand All @@ -40,7 +50,7 @@ const Performance = ({ genre }: { genre: string }) => {
<Spacing marginBottom="3.2" />
<S.PerformanceLayout>
{data2.map((item) => (
<PerformnaceCard {...item} />
<PerformnaceCard key={item.performanceId} {...item} />
))}
</S.PerformanceLayout>
<Spacing marginBottom="1.6" />
Expand Down
Loading