Skip to content

Commit 16a7342

Browse files
authored
Merge pull request #29 from DguFarmSystem/Feature/#27
Feature/#27
2 parents b70dee1 + 9450e42 commit 16a7342

File tree

7 files changed

+221
-15
lines changed

7 files changed

+221
-15
lines changed

package-lock.json

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dependencies": {
1414
"@types/styled-components": "^5.1.34",
1515
"axios": "^1.7.9",
16+
"framer-motion": "^12.4.3",
1617
"react": "^18.3.1",
1718
"react-dom": "^18.3.1",
1819
"react-responsive": "^10.0.0",

src/assets/Icons/FarmLogo1.png

69.4 KB
Loading

src/assets/Icons/IntroLogo.svg

Lines changed: 10 additions & 0 deletions
Loading

src/hooks/useMediaQueries.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ const useMediaQueries = () => {
55
* Union 작업중 콘텐츠 박스에서 767보다 더 작은 크기 조절이 필요해서 isTiny를 추가했습니다.
66
* 반응형 작업하실 때 한번더 봐주시고 고쳐주시면 좋을거 같습니다.
77
*/
8-
const isTiny = useMediaQuery({ query: "(max-width: 385px)" })
8+
const isTiny = useMediaQuery({ query: "(max-width: 385px)" });
9+
const isApp = useMediaQuery({ query: "(max-width: 440px)"});
910
const isMobile = useMediaQuery({ query: "(max-width: 767px)" });
1011
const isTablet = useMediaQuery({
1112
query: "(min-width: 768px) and (max-width: 1023px)",
1213
});
14+
const isIpadPro = useMediaQuery({
15+
query: "(min-width: 700px) and (max-width: 1400px)",
16+
});
1317
const isDesktop = useMediaQuery({
1418
query: "(min-width: 1024px)"
1519
});
1620

17-
return { isTiny, isMobile, isTablet, isDesktop };
21+
return { isTiny, isApp, isMobile, isTablet, isDesktop, isIpadPro };
1822
};
1923

2024
export default useMediaQueries;

src/pages/Main/Intro/Intro.styled.tsx

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,87 @@
11
import styled from 'styled-components';
22

3-
export const Container = styled.div<{ $isMobile: boolean; $isTablet: boolean }>`
3+
export const AppContainer = styled.div`
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
justify-content: space-between;
8+
height: 160vh;
9+
background: linear-gradient(90deg, #102C19, #194326);
10+
color: white;
11+
text-align: center;
12+
padding: 0 20px;
13+
`;
14+
15+
export const TopSection = styled.div`
16+
display: flex;
17+
flex-direction: column;
18+
align-items: center;
19+
justify-content: center;
20+
flex: 1;
21+
margin-top: 5vh;
22+
`;
23+
24+
export const BottomSection = styled.div`
25+
display: flex;
26+
flex-direction: column;
27+
align-items: center;
28+
justify-content: center;
29+
flex: 1;
30+
margin-bottom: 15vh;
31+
`;
32+
33+
export const IntroPhrase = styled.p`
34+
color: white;
35+
font-size: 18px;
36+
font-weight: 600;
37+
text-align: center;
38+
padding-top: 10px;
39+
padding-bottom: 10px;
40+
`;
41+
42+
export const IntroDescription = styled.p`
43+
font-size: 14px;
44+
font-weight: 500;
45+
text-align: center;
46+
padding-top: 5px;
47+
padding-bottom: 5px;
48+
color: #333; // 기본적으로 어두운 회색
49+
`;
50+
51+
export const AppApplyButton = styled.div`
52+
width: 110px;
53+
height: 35px;
54+
background-color: #28723F;
55+
display: flex;
56+
align-items: center;
57+
justify-content: center;
58+
border-radius: 12px;
59+
color: white;
60+
font-size: 13px;
61+
font-weight: 500;
62+
margin-top: 20px;
63+
`;
64+
65+
export const Container = styled.div<{ $isMobile: boolean; $isTablet: boolean; $isApp: boolean, $isIpadPro: boolean }>`
466
display: flex;
567
flex-direction: column;
668
align-items: flex-start;
769
justify-content: center;
8-
height: ${({ $isMobile, $isTablet }) => ($isMobile ? "80vh" : $isTablet ? "100vh" : "110vh")};
9-
background: ${({ $isMobile }) => (
10-
$isMobile ? "linear-gradient(90deg, #28723F, #75e298)"
11-
: "linear-gradient(90deg, #28723F, #A2E9B8)"
70+
height: ${({ $isMobile, $isTablet, $isApp, $isIpadPro }) =>
71+
$isMobile ? "75vh" : $isTablet ? "80vh" : $isApp ? "90vh" : $isIpadPro ? "105h" : "120vh"};
72+
73+
background: ${({ $isMobile, $isTablet, $isApp }) => (
74+
$isApp ? "linear-gradient(90deg, #102C19, #194326)" :
75+
$isMobile ? "linear-gradient(90deg, #28723F, #75e298)" :
76+
$isTablet ? "linear-gradient(90deg, #28723F, #A2E9B8)" :
77+
"linear-gradient(90deg, #28723F, #A2E9B8)"
1278
)};
79+
1380
padding: ${({ $isMobile }) => ($isMobile ? "0px" : "50px")};
1481
color: white;
1582
`;
1683

84+
1785
/* 추가된 네비게이션 정렬용 스타일 */
1886
export const NavWrapper = styled.div`
1987
width: 100%;

src/pages/Main/Intro/Intro.tsx

Lines changed: 91 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,98 @@
1-
import * as S from './Intro.styled.tsx';
2-
import logo from '../../../assets/FarmLogo.png';
1+
import * as S from './Intro.styled';
2+
import logo from '../../../assets/Icons/FarmLogo1.png';
33
import { useState } from 'react';
4-
import Popup from '@/components/Popup/Popup.tsx';
5-
import useMediaQueries from '@/hooks/useMediaQueries.ts';
4+
import Popup from '@/components/Popup/Popup';
5+
import useMediaQueries from '@/hooks/useMediaQueries';
6+
import IntroLogo from '../../../assets/Icons/IntroLogo.svg';
7+
import { motion } from 'framer-motion';
68

79
const Intro = () => {
810
const [isPopupOpen, setPopupOpen] = useState(false);
9-
const { isTiny, isMobile, isTablet } = useMediaQueries();
10-
11+
const { isTiny, isApp, isMobile, isTablet, isIpadPro } = useMediaQueries();
12+
13+
const fadeInUp = {
14+
hidden: { opacity: 0, y: 30 },
15+
visible: (i = 1) => ({
16+
opacity: 1,
17+
y: 0,
18+
transition: { delay: i * 0.3, duration: 0.6, ease: "easeOut" }
19+
}),
20+
};
21+
22+
if (isApp) {
23+
return (
24+
<S.AppContainer>
25+
<S.TopSection>
26+
<motion.img
27+
src={IntroLogo}
28+
alt=""
29+
initial="hidden"
30+
animate="visible"
31+
variants={fadeInUp}
32+
custom={0}
33+
/>
34+
35+
{["미래를 준비하고 성장하는 여정,", "Farm System에서 함께하세요."].map((text, index) => (
36+
<S.IntroPhrase
37+
as={motion.div}
38+
key={index}
39+
variants={fadeInUp}
40+
initial="hidden"
41+
animate="visible"
42+
custom={index + 2}
43+
>
44+
{text}
45+
</S.IntroPhrase>
46+
))}
47+
</S.TopSection>
48+
49+
{/* 2/3 지점: Description - 화면에 들어올 때 애니메이션 적용 */}
50+
<S.BottomSection>
51+
{[
52+
"Farm System은 SW/AI 분야에 관심있는",
53+
"학생들로 구성된 자율 학습 동아리로,",
54+
"Union · 게임/영상 · 보안/웹 ·",
55+
"사물인터넷/로봇 · 인공지능 · 빅데이터의",
56+
"5가지 신기술 트랙을 제공하여",
57+
"학습 경험을 통해 SW/AI 역량을 배양합니다."
58+
].map((text, index) => (
59+
<S.IntroDescription
60+
as={motion.p}
61+
key={index}
62+
initial={{ color: "#333", clipPath: "inset(0 100% 0 0)" }}
63+
whileInView={{ color: "#ffffff", clipPath: "inset(0 0 0 0)" }}
64+
transition={{ duration: 1.2, delay: index * 0.5, ease: "easeOut" }}
65+
viewport={{ once: true }}
66+
>
67+
{text}
68+
</S.IntroDescription>
69+
))}
70+
71+
<motion.div
72+
initial={{ opacity: 0, y: 30 }}
73+
whileInView={{ opacity: 1, y: 0 }}
74+
transition={{ duration: 0.8, delay: 3.5, ease: "easeOut" }} // description 마지막보다 살짝 더 늦게 실행
75+
viewport={{ once: true }} // 한 번만 실행
76+
>
77+
<S.AppApplyButton onClick={() => setPopupOpen(true)}>
78+
지원하기
79+
</S.AppApplyButton>
80+
</motion.div>
81+
</S.BottomSection>
82+
83+
84+
<Popup
85+
isOpen={isPopupOpen}
86+
onClose={() => setPopupOpen(false)}
87+
title={"지금은 모집 기간이 아닙니다."}
88+
content={"공개 모집 예정: 2025년 2월월"}
89+
/>
90+
</S.AppContainer>
91+
);
92+
}
93+
1194
return (
12-
<S.Container id="about" $isMobile={isMobile} $isTablet={isTablet}>
95+
<S.Container id="about" $isApp={isApp} $isMobile={isMobile} $isTablet={isTablet} $isIpadPro={isIpadPro}>
1396
<S.Bud $isMobile={isMobile} $isTablet={isTablet}>🌱</S.Bud>
1497
<S.Description $isMobile={isMobile} $isTablet={isTablet}>
1598
미래를 준비하고 성장하는 여정, <br />
@@ -41,4 +124,4 @@ const Intro = () => {
41124
);
42125
};
43126

44-
export default Intro;
127+
export default Intro;

0 commit comments

Comments
 (0)