Skip to content

Commit 4b324ac

Browse files
authored
Merge pull request #139 from Podo-Store/dev
랜딩페이지 3p 개편
2 parents 0a64df0 + 997da6d commit 4b324ac

File tree

9 files changed

+227
-111
lines changed

9 files changed

+227
-111
lines changed
Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use "./../../styles/_responsive.scss" as r;
2+
13
@keyframes fade-in {
24
0% {
35
opacity: 0;
@@ -40,11 +42,6 @@
4042
background: var(--purple-purple-8-line, #caabff);
4143
}
4244

43-
.cards-wrap .margin {
44-
width: 50px;
45-
height: 100%;
46-
}
47-
4845
.cards-content#opened {
4946
position: relative;
5047

@@ -53,6 +50,10 @@
5350
width: 700px;
5451

5552
box-sizing: border-box;
53+
@include r.media-tablet {
54+
width: 585px;
55+
height: 300px;
56+
}
5657
}
5758

5859
.cards-content .background-image {
@@ -85,6 +86,9 @@
8586
row-gap: 8px;
8687

8788
width: 60%;
89+
@include r.media-tablet {
90+
width: 73%;
91+
}
8892
}
8993

9094
.cards-content#opened .cards-top .label {
@@ -127,6 +131,10 @@
127131
width: 85px;
128132

129133
box-sizing: border-box;
134+
@include r.media-tablet {
135+
width: 585px;
136+
height: 85px;
137+
}
130138
}
131139

132140
.cards-content .mou-logo {
@@ -141,6 +149,10 @@
141149
box-sizing: border-box;
142150
border-radius: 50%;
143151
background-color: var(--ect-white, #fff);
152+
@include r.media-tablet {
153+
right: 23px;
154+
bottom: 17.5px;
155+
}
144156
}
145157

146158
.cards-content .mou-logo img {
@@ -153,4 +165,8 @@
153165

154166
width: max-content;
155167
transform: rotate(-90deg);
168+
@include r.media-tablet {
169+
top: 50%;
170+
transform: translate(0, -50%) rotate(0deg);
171+
}
156172
}
Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,76 @@
11
import React, { Fragment, useState, useEffect } from "react";
2-
import { organizationsExport } from "../../constants/organizations.ts";
3-
import "./CardsContent.css";
2+
3+
import useWindowDimensions from "@/hooks/useWindowDimensions";
4+
5+
import { organizationsExport } from "../../constants/organizations";
6+
7+
import "./CardsContent.scss";
48

59
/**
610
*
711
* @param {*} props - Component properties
812
* @param {number} props.pageNum - 페이지 번호
913
* @param {Object} props.isOpened - 카드 오픈 여부
1014
* @param {function} props.setIsOpened - 카드 오픈 여부 설정 함수
11-
* @param {boolean} [props.rightMargin=true] - 오른쪽 여백 여부
1215
* @returns
1316
*/
14-
const CardsContent = ({ pageNum, isOpened, setIsOpened, rightMargin = true }) => {
17+
18+
interface CardsContentProps {
19+
pageNum: number;
20+
isOpened: boolean;
21+
setIsOpened: React.Dispatch<React.SetStateAction<{ [key: number]: boolean }>>;
22+
}
23+
24+
const CardsContent: React.FC<CardsContentProps> = ({ pageNum, isOpened, setIsOpened }) => {
1525
// MOU 키워드 보이지 않게 처리
1626
const [isKeywordVisible, setIsKeywordVisible] = useState(false);
1727
// MOU 키워드 등장 애니메이션
1828
const [isKeywordAnimating, setIsKeywordAnimating] = useState(false);
1929
// 배경 단체 사진
2030
const [showPhoto, setShowPhoto] = useState(false);
2131

32+
// for responsive design
33+
const { widthConditions } = useWindowDimensions();
34+
const isTablet = widthConditions.isTablet || widthConditions.isMobile;
35+
2236
useEffect(() => {
2337
setShowPhoto(false);
24-
let timer1, timer2, timer3;
38+
let timers: NodeJS.Timeout[] = new Array(3);
39+
2540
if (isOpened) {
2641
setIsKeywordVisible(false);
27-
timer1 = setTimeout(() => {
42+
timers[0] = setTimeout(() => {
2843
setIsKeywordVisible(true);
2944
setIsKeywordAnimating(true);
30-
timer2 = setTimeout(() => {
45+
timers[1] = setTimeout(() => {
3146
setShowPhoto(true);
32-
timer3 = setTimeout(() => {
47+
timers[2] = setTimeout(() => {
3348
setIsKeywordAnimating(false);
3449
}, 1000);
3550
}, 500);
3651
}, 300);
3752
}
3853
return () => {
39-
clearTimeout(timer1);
40-
clearTimeout(timer2);
41-
clearTimeout(timer3);
54+
clearTimeout(timers[0]);
55+
clearTimeout(timers[1]);
56+
clearTimeout(timers[2]);
4257
};
4358
}, [isOpened]);
4459

4560
const onMouseEnter = () => {
4661
// setIsOpened((prev) => ({ ...prev, [pageNum]: true }));
4762
// 선택된 카드만 열기, 나머진 닫기
48-
setIsOpened((prev) => ({ [pageNum]: true }));
63+
if (!isTablet) {
64+
// 기본: mouse hover 시 카드 열기
65+
setIsOpened((prev) => ({ [pageNum]: true }));
66+
}
67+
};
68+
const onClick = () => {
69+
// 선택된 카드만 열기, 나머진 닫기
70+
if (isTablet) {
71+
// responsive: 클릭 시 카드 열기
72+
setIsOpened((prev) => ({ [pageNum]: true }));
73+
}
4974
};
5075

5176
const onMouseLeave = () => {
@@ -95,10 +120,14 @@ const CardsContent = ({ pageNum, isOpened, setIsOpened, rightMargin = true }) =>
95120
</div>
96121
</div>
97122
</div>
98-
{rightMargin && <div className="margin"></div>}
99123
</div>
100124
) : (
101-
<div className="cards-wrap d-flex" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
125+
<div
126+
className="cards-wrap d-flex"
127+
onClick={onClick}
128+
onMouseEnter={onMouseEnter}
129+
onMouseLeave={onMouseLeave}
130+
>
102131
<div id="closed" className="cards-content f-dir-column f-center">
103132
<p className="fade-in p-large-medium c-white t-center">
104133
{organizationsExport[pageNum]?.name || ""}
@@ -111,7 +140,6 @@ const CardsContent = ({ pageNum, isOpened, setIsOpened, rightMargin = true }) =>
111140
/>
112141
</div>
113142
</div>
114-
{rightMargin && <div className="margin"></div>}
115143
</div>
116144
);
117145
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
@use "./../../styles/_responsive.scss" as r;
2+
13
/* Page3 기본 스타일 */
24
.main-ver2 .page3 {
35
background: linear-gradient(180deg, #fff 0%, #f5f0ff 100%);
46
}
57

68
.main-ver2 .page3.page-size {
79
overflow-x: auto;
10+
@include r.media-tablet {
11+
min-height: 1056px;
12+
}
813
}
914

1015
.main-ver2 .page3 > .title_64px {
@@ -21,16 +26,33 @@
2126
max-width: 1520px; /* Page3Cards의 너비와 동일 */
2227

2328
overflow: hidden;
29+
@include r.media-tablet {
30+
max-height: 800px;
31+
}
2432
}
2533

2634
.page3 .slider {
2735
display: flex;
2836
overflow-x: hidden;
2937
scroll-snap-type: x mandatory;
3038
scroll-behavior: smooth;
39+
@include r.media-tablet {
40+
flex-direction: column;
41+
align-items: center;
42+
43+
// 이거 안하니까 상하 슬라이드 작동 안하더라..
44+
height: 100%; // slider-wrapper의 전체 높이
45+
46+
overflow-x: unset;
47+
overflow-y: hidden;
48+
scroll-snap-type: y mandatory;
49+
}
3150
}
3251

3352
.page3 .slide {
3453
flex: 1 0 100%;
3554
scroll-snap-align: start;
55+
@include r.media-tablet {
56+
scroll-snap-align: start;
57+
}
3658
}

src/components/landing/Page3.tsx

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,70 @@ import { useRef, useState } from "react";
22

33
import Page3Cards from "./Page3Cards";
44

5-
import "./Page3.css";
5+
import useWindowDimensions from "@/hooks/useWindowDimensions";
6+
7+
import { organizationsLength } from "@/constants/organizations";
8+
9+
import "./Page3.scss";
610

711
// THX to Skillthrive: https://youtu.be/McPdzhLRzCg?si=swwfYJhFEB-4bOsl
812
const Page3 = () => {
913
// 슬라이드 총 개수
1014
const [currentSlide, setCurrentSlide] = useState(0);
11-
const totalSlides = 2;
15+
16+
// for responsive design
17+
const { widthConditions } = useWindowDimensions();
18+
const isTablet = widthConditions.isTablet || widthConditions.isMobile;
19+
// const isMobile = widthConditions.isMobile;
20+
21+
const slidesPerPage = !isTablet ? 5 : 3;
22+
const totalSlides = Math.ceil(organizationsLength / slidesPerPage);
1223

1324
const sliderRef = useRef<HTMLDivElement>(null);
1425

15-
const onPrevSlide = () => {
16-
const newSlide = currentSlide !== 0 ? currentSlide - 1 : currentSlide;
17-
setCurrentSlide(newSlide);
26+
const handleSlide = (direction: "prev" | "next") => {
27+
let newSlide;
28+
if (direction === "prev") {
29+
newSlide = currentSlide !== 0 ? currentSlide - 1 : currentSlide;
30+
setCurrentSlide(newSlide);
31+
} else {
32+
newSlide = currentSlide !== totalSlides - 1 ? currentSlide + 1 : currentSlide;
33+
setCurrentSlide(newSlide);
34+
}
35+
1836
if (sliderRef.current) {
19-
sliderRef.current.scrollTo({
20-
left: sliderRef.current.offsetWidth * newSlide,
21-
behavior: "smooth",
22-
});
37+
if (!isTablet) {
38+
// 기본: 좌우 슬라이드
39+
sliderRef.current.scrollTo({
40+
left: sliderRef.current.offsetWidth * newSlide,
41+
behavior: "smooth",
42+
});
43+
} else {
44+
// responsive: 상하 슬라이드
45+
sliderRef.current.scrollTo({
46+
top: sliderRef.current.offsetHeight * newSlide,
47+
behavior: "smooth",
48+
});
49+
}
2350
}
2451
};
2552

26-
const onNextSlide = () => {
27-
const newSlide = currentSlide !== totalSlides - 1 ? currentSlide + 1 : currentSlide;
28-
setCurrentSlide(newSlide);
29-
if (sliderRef.current) {
30-
sliderRef.current.scrollTo({
31-
left: sliderRef.current.offsetWidth * newSlide,
32-
behavior: "smooth",
33-
});
53+
const renderPage3Cards = () => {
54+
const cards = [];
55+
for (let i = 0; i < totalSlides; i++) {
56+
cards.push(
57+
<div className="slide" key={i}>
58+
<Page3Cards
59+
pageStartNum={i * slidesPerPage}
60+
onPrevSlide={() => handleSlide("prev")}
61+
onNextSlide={() => handleSlide("next")}
62+
setLeftArrowDisappear={currentSlide === 0}
63+
setRightArrowDisappear={currentSlide === totalSlides - 1}
64+
/>
65+
</div>
66+
);
3467
}
68+
return cards;
3569
};
3670

3771
return (
@@ -42,22 +76,7 @@ const Page3 = () => {
4276
<div className="j-content-center">
4377
<div className="slider-wrapper">
4478
<div className="slider" ref={sliderRef}>
45-
<div className="slide">
46-
<Page3Cards
47-
pageStartNum={0}
48-
onPrevSlide={onPrevSlide}
49-
onNextSlide={onNextSlide}
50-
setLeftArrowDisappear={currentSlide === 0}
51-
/>
52-
</div>
53-
<div className="slide">
54-
<Page3Cards
55-
pageStartNum={5}
56-
onPrevSlide={onPrevSlide}
57-
onNextSlide={onNextSlide}
58-
setRightArrowDisappear={currentSlide === totalSlides - 1}
59-
/>
60-
</div>
79+
{renderPage3Cards()}
6180
</div>
6281
</div>
6382
</div>

src/components/landing/Page3Cards.css

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)