Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions components/common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { Hamburger, YappLogo } from 'public/assets/icons';
import { ReactElement, useEffect, useRef } from 'react';
import styled from 'styled-components';
import media from 'styles/media';
import Button from '../Button';
import { NEXT_GENERATION_RECRUIT_LINK } from 'database/recruit';

function Header(): ReactElement {
const { asPath } = useRouter();
Expand Down Expand Up @@ -46,6 +48,17 @@ function Header(): ReactElement {
<MenuText active={asPath === path}>{name}</MenuText>
</Link>
))}
<Button
buttonColor={'blue_100'}
width={129}
height={39}
borderRadius={150}
onClick={() =>
(window.location.href = NEXT_GENERATION_RECRUIT_LINK)
}
>
<ButtonText>알림 신청하기</ButtonText>
</Button>
</HeaderMenu>
<MobileHeaderMenu onClick={handleToggleMenu} />
</HeaderInner>
Expand Down Expand Up @@ -109,5 +122,9 @@ const MobileHeaderMenu = styled(Hamburger)`
cursor: pointer;
}
`;
const ButtonText = styled.span`
color: white;
font-size: 1.6rem;
`;

export default Header;
138 changes: 138 additions & 0 deletions components/home/Dday/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { Box } from 'components/common';
import { ReactElement, useEffect, useState } from 'react';
import styled from 'styled-components';
import media from 'styles/media';

function Dday(): ReactElement {
const [timeLeft, setTimeLeft] = useState({
days: 0,
hours: 0,
mins: 0,
secs: 0,
});
useEffect(() => {
const interval = setInterval(() => {
const today = new Date();
const targetDate = new Date('2025-04-10'); // 채용 시작 날짜
const diffTime = targetDate.getTime() - today.getTime();

const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
const diffHours = Math.floor(
(diffTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
);
const diffMinutes = Math.floor(
(diffTime % (1000 * 60 * 60)) / (1000 * 60),
);
const diffSeconds = Math.floor((diffTime % (1000 * 60)) / 1000);

setTimeLeft({
days: diffDays,
hours: diffHours,
mins: diffMinutes,
secs: diffSeconds,
});

if (diffTime <= 0) {
clearInterval(interval);
}
}, 1000);

return () => clearInterval(interval);
}, []);

return (
<DdayContainer>
<StyledBox
width={164.5}
height={147}
backgroundColor="white"
borderRadius={18}
>
<TimeSpan>{timeLeft.days}</TimeSpan>
<TimeText>DAYS</TimeText>
</StyledBox>
<Dot>:</Dot>

<StyledBox
width={164.5}
height={147}
backgroundColor="white"
borderRadius={18}
>
<TimeSpan>{timeLeft.hours}</TimeSpan>
<TimeText>HOURS</TimeText>
</StyledBox>
<Dot>:</Dot>

<StyledBox
width={164.5}
height={147}
backgroundColor="white"
borderRadius={18}
>
<TimeSpan>{timeLeft.mins}</TimeSpan>
<TimeText>MINS</TimeText>
</StyledBox>
<Dot>:</Dot>
<StyledBox
width={164.5}
height={147}
backgroundColor="white"
borderRadius={18}
>
<TimeSpan>{timeLeft.secs}</TimeSpan>
<TimeText>SECS</TimeText>
</StyledBox>
</DdayContainer>
);
}

const DdayContainer = styled.div`
position: relative;
display: flex;
gap: 12px;
`;
const StyledBox = styled(Box)`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
${media.tablet} {
width: 151.75px;
height: 147px;
}
${media.mobile} {
width: 64.75px;
height: 81px;
}
`;
const TimeSpan = styled.span`
color: ${({ theme }) => theme.palette.blue_100};
font-weight: 700;
font-size: 6rem;
${media.mobile} {
font-size: 2.4rem;
}
`;
const TimeText = styled.span`
color: ${({ theme }) => theme.palette.grey_400};
font-weight: 600;
font-size: 2.6rem;
${media.mobile} {
font-size: 1.5rem;
}
`;
const Dot = styled.div`
width: 17px;
color: ${({ theme }) => theme.palette.white};
font-size: 6rem;
font-weight: 600;
line-height: 160%;
display: flex;
align-items: center;
margin: 0 0.4rem;
${media.mobile} {
font-size: 2.4rem;
}
`;
export default Dday;
172 changes: 172 additions & 0 deletions components/home/IntroSection/Banner26th.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { Box, Button } from 'components/common';
import { useEffect, useState } from 'react';
import styled from 'styled-components';
import media from 'styles/media';
import Dday from '../Dday';
import YappuLogo from 'public/assets/images/26th/illust_mini.svg';
import { NEXT_GENERATION_RECRUIT_LINK } from 'database/recruit';

const Banner26th = () => {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);

return (
<>
<Banner25thTextContentBox className={mounted ? 'appear' : ''}>
<BannerTitleBox>
<YappuLogoBox />
<YappSubTitleBox>탐색을 넘어 세상을 넓혀가는</YappSubTitleBox>
<h3>
<BannerTitleSpan>26기의 주인공</BannerTitleSpan>이
<br />
되어주세요
</h3>
<BannerRecruitDateBox>4.10 (목) - 4.20 (일)</BannerRecruitDateBox>
</BannerTitleBox>
<Dday />
<StyledButton
width={265}
height={72}
borderRadius={20}
buttonColor={'blue_100'}
fontColor={'white'}
onClick={() => (window.location.href = NEXT_GENERATION_RECRUIT_LINK)}
>
⏰ 26기 모집 알림 신청하기
</StyledButton>
</Banner25thTextContentBox>
<BannerBackgroundInner className={mounted ? 'appear' : ''} />;
</>
);
};
export default Banner26th;

const BannerBackgroundInner = styled.div`
width: 100%;
height: 100%;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
background: url('/assets/images/26th/banner-pc.png'),
linear-gradient(#bdeaff, #67b2ff);
transform: scale(0.8);
opacity: 0;
transition: transform 2s ease, opacity 2s ease;

&.appear {
transform: scale(1);
opacity: 1;
}

background-size: cover;
background-repeat: no-repeat;
background-position: center center;

${media.mobile} {
background: url('/assets/images/26th/banner-tablet.png'),
linear-gradient(#bdeaff, #67b2ff);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}

${media.small} {
background: url('/assets/images/26th/banner-mobile.png'),
linear-gradient(#bdeaff, #67b2ff);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
`;

const Banner25thTextContentBox = styled.div`
position: absolute;
top: 10%;
left: 50%;
z-index: 20;
flex: 1;
display: flex;
height: fit-content;
flex-direction: column;
justify-content: center;
align-items: center;
white-space: nowrap;
gap: 8rem;
transition: transform 2s ease, opacity 2s ease;
transform: translate3d(-50%, -2rem, 0);
opacity: 0;

&.appear {
transform: translate3d(-50%, 0, 0);
opacity: 1;
}
`;

const BannerTitleBox = styled.div`
display: flex;
gap: 1rem;
height: fit-content;
flex-direction: column;
justify-content: center;
align-items: center;

& > h3 {
margin: 0;
text-align: center;
font-size: 6.8rem;
font-weight: 700;
line-height: 125%;
letter-spacing: -0.07rem;
color: ${({ theme }) => theme.palette.black};
}
${media.mobile} {
& > h3 {
font-size: 3.6rem;
letter-spacing: -0.032rem;
}
}
${media.small} {
top: 20%;
gap: 1rem;

& > h3 {
font-size: 2rem;
letter-spacing: -0.032rem;
}
}

${media.small} {
gap: 0.8rem;
}
`;
const BannerTitleSpan = styled.span`
color: ${({ theme }) => theme.palette.blue_100};
font-weight: 600;
`;
const BannerRecruitDateBox = styled.div`
color: ${({ theme }) => theme.palette.grey_700};
font-weight: 600;
font-size: 2.6rem;
margin-top: 4rem;
`;

const YappuLogoBox = styled(YappuLogo)``;

const YappSubTitleBox = styled.div`
font-size: 2.8rem;
color: ${({ theme }) => theme.palette.grey_700};
margin-top: 1.4rem;

${media.small} {
}
`;

const StyledButton = styled(Button)`
${media.mobile} {
width: 229px;
height: 59px;
}
`;
9 changes: 6 additions & 3 deletions components/home/IntroSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { MouseEvent, ReactElement } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
import media from 'styles/media';
import Banner25th from './Banner25th';
import Banner26th from './Banner26th';

function IntroSection(): ReactElement {
const [isHover, setIsHover] = useState(false);
Expand All @@ -24,21 +24,24 @@ function IntroSection(): ReactElement {
onMouseLeave={handleEnter}
onMouseMove={handleMove}
>
<Banner25th />
<Banner26th />
<FloatingArrow />
</IntroSectionContainer>
);
}

const IntroSectionContainer = styled.div`
background-color: black;
background: linear-gradient(#bdeaff, #67b2ff);
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: calc(100vh - 70px);
@media (max-height: 874px) {
height: 110vh;
}
${media.mobile} {
height: calc(100vh - 64px);
}
Expand Down
Loading