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

fix: 랜딩페이지 UI 수정 #61

Merged
merged 19 commits into from
Jan 20, 2025
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
24 changes: 24 additions & 0 deletions src/assets/icon/firstLandingPage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/assets/icon/lastLanding.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions src/assets/icon/secondLanding.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions src/components/home/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import MatchIcon from '@/assets/icon/matchIcon.svg?react';
import FriendIcon from '@/assets/icon/friendsIcon.svg?react';
import NotificationIcon from '@/assets/icon/notificationIcon.svg?react';
import BasicProfileIcon from '@/assets/icon/basicProfileIcon.svg?react';
import { Link } from 'react-router-dom';

interface NavbarProps {
modalContent: {
Expand Down Expand Up @@ -76,15 +77,15 @@ const Navbar = ({ modalContent, setModalContent }: NavbarProps) => {
<NotificationIcon />
<span className={`text-[10px] text-textDarkGray`}>알림</span>
</Button>
<Button
variant="icon"
<Link
to="/mypage"
className="flex flex-col items-center justify-center gap-1"
>
<div className="flex items-center rounded-full bg-textDarkGray w-[24px] h-[24px]">
<BasicProfileIcon className="text-[#AEAEAE]" />
</div>
<span className={`text-[10px] text-textDarkGray`}>프로필</span>
</Button>
<span className="text-[10px] text-textDarkGray">프로필</span>
</Link>
</nav>
);
};
Expand Down
21 changes: 8 additions & 13 deletions src/components/landing/LandingHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
//slide 구현이 되었을때, 공통으로 사용이 될 경우를 대비해서 일단 구현만
// interface HeaderProps {
// tite: string;
// subtitle: string;
// }
interface HeaderProps {
title: string;
subtitle: React.ReactNode;
}

const Header = () => {
const Header = ({ title, subtitle }: HeaderProps) => {
return (
<div className="text-left ml-8 mt-[15%]">
<h1 className="text-[60px] font-bold leading-[1.3]">
Gachi <br /> Taxi
</h1>
<p className="text-[20px] mt-[13%] mb-[20%] leading-[1.5]">
가천대학교 <br /> 택시 동승 서비스
</p>
<div className="items-center mt-[15%] h-[82px]">
<h1 className="text-[24px] font-bold mb-[8px]">{title}</h1>
<p className="text-body text-textLightGray">{subtitle}</p>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './routes.constant';
export * from './timeOptions.constant';
export * from './styles.constant';
export * from './menuItems.constant';
export * from './landingText.constant';
10 changes: 10 additions & 0 deletions src/constants/landingText.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const LANDING_TEXTS = {
FIRST_TITLE: '지금 바로 매칭하기',
FIRST_SUBTITLE: ['자동 매칭 기능을 통해', '현재 위치에서 매칭하기'],

SECOND_TITLE: '매칭 미리 예약하기',
SECOND_SUBTITLE: ['수동 매칭 기능을 통해', '매칭을 미리 예약하기'],

LAST_TITLE: '키워드로 매칭하기',
LAST_SUBTITLE: ['키워드 기능을 통해', '매칭 상대 고르기'],
} as const;
31 changes: 17 additions & 14 deletions src/pages/landing/FirstLanding.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import LandingHeader from '@/components/landing/LandingHeader';
import KakaoLoginButton from '@/components/landing/KakaoLoginButton';
import GachiTaxi from '@/assets/icon/gachiTaxi.svg?react';
import GoogleLoginButton from '@/components/landing/GoogleLoginButton';
import { GoogleOAuthProvider } from '@react-oauth/google';
import FirstSvg from '@/assets/icon/firstLandingPage.svg?react';
import { LANDING_TEXTS } from '@/constants';

const FirstLanding = () => {
const CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;

return (
<>
<LandingHeader />
<GachiTaxi className="float-right mb-[70px]" />
<KakaoLoginButton />
<GoogleOAuthProvider clientId={CLIENT_ID}>
<GoogleLoginButton />
</GoogleOAuthProvider>
</>
<section className="w-full flex-1 flex flex-col items-center h-screen gap-8">
<div className="text-center">
<LandingHeader
title={LANDING_TEXTS.FIRST_TITLE}
subtitle={
<>
{LANDING_TEXTS.FIRST_SUBTITLE.map((line, index) => (
<p key={index}>{line}</p>
))}
</>
}
/>
</div>
<FirstSvg />
</section>
);
};

Expand Down
25 changes: 25 additions & 0 deletions src/pages/landing/LastLanding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import LandingHeader from '@/components/landing/LandingHeader';
import LastSvg from '@/assets/icon/lastLanding.svg?react';
import { LANDING_TEXTS } from '@/constants';

const LastLanding = () => {
return (
<section className="w-full flex-1 flex flex-col items-center h-screen gap-8 z-10">
<div className="text-center">
<LandingHeader
title={LANDING_TEXTS.LAST_TITLE}
subtitle={
<>
{LANDING_TEXTS.LAST_SUBTITLE.map((line, index) => (
<p key={index}>{line}</p>
))}
</>
}
/>
</div>
<LastSvg />
</section>
);
};

export default LastLanding;
25 changes: 25 additions & 0 deletions src/pages/landing/SecondLanding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import LandingHeader from '@/components/landing/LandingHeader';
import SecondSvg from '@/assets/icon/secondLanding.svg?react';
import { LANDING_TEXTS } from '@/constants';

const SecondLanding = () => {
return (
<section className="w-full flex-1 flex flex-col items-center h-screen gap-8 z-10">
<div className="text-center">
<LandingHeader
title={LANDING_TEXTS.SECOND_TITLE}
subtitle={
<>
{LANDING_TEXTS.SECOND_SUBTITLE.map((line, index) => (
<p key={index}>{line}</p>
))}
</>
}
/>
</div>
<SecondSvg className="items-cemter mt-[10px]" />
</section>
);
};

export default SecondLanding;
92 changes: 87 additions & 5 deletions src/pages/landing/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,93 @@
//추후에 두번째, 세번째 슬라이드 디자인이 구현될 경우 추가할 예정
import FirstLanding from '@/pages/landing/FirstLanding';
import { useState, useRef, useEffect } from 'react';
import { motion } from 'framer-motion';
import FirstLanding from './FirstLanding';
import SecondLanding from './SecondLanding';
import LastLanding from './LastLanding';
import KakaoLoginButton from '@/components/landing/KakaoLoginButton';
import GoogleLoginButton from '@/components/landing/GoogleLoginButton';
import { GoogleOAuthProvider } from '@react-oauth/google';

const slides = [<FirstLanding />, <SecondLanding />, <LastLanding />];

const LandingPage = () => {
const CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
const [currentIndex, setCurrentIndex] = useState(0);
const sliderRef = useRef<HTMLDivElement>(null);

const handleScroll = () => {
if (sliderRef.current) {
const scrollLeft = sliderRef.current.scrollLeft || 0;
const slideWidth = sliderRef.current.clientWidth || 1;
const newIndex = Math.round(scrollLeft / slideWidth);
setCurrentIndex(newIndex);
}
};

const goToSlide = (index: number) => {
if (sliderRef.current) {
sliderRef.current.scrollTo({
left: index * (sliderRef.current.clientWidth || 1),
behavior: 'smooth',
});
}
};

useEffect(() => {
const slider = sliderRef.current;
if (slider) {
slider.addEventListener('scroll', handleScroll);
}
return () => {
if (slider) {
slider.removeEventListener('scroll', handleScroll);
}
};
}, []);

return (
<section className="flex-1 w-full p-horizontal">
<FirstLanding />
</section>
<div className="relative w-full flex flex-col items-center justify-around overflow-x-hidden">
<motion.div
ref={sliderRef}
className="flex w-full overflow-x-auto overflow-y-hidden snap-mandatory snap-x scroll-smooth scroll-hidden"
drag="x"
dragConstraints={{ left: 0, right: 0 }}
onDragEnd={(_, info) => {
if (info.offset.x < -50) {
goToSlide(Math.min(currentIndex + 1, slides.length - 1));
} else if (info.offset.x > 50) {
goToSlide(Math.max(currentIndex - 1, 0));
}
}}
>
{slides.map((slide, index) => (
<div
key={index}
className="min-w-full flex justify-center items-center snap-center"
>
{slide}
</div>
))}
</motion.div>

<div className="absolute bottom-[27%] flex justify-center gap-2 z-30">
{slides.map((_, index) => (
<div
key={index}
onClick={() => goToSlide(index)}
className={`w-3 h-3 rounded-full cursor-pointer transition-all ${
index === currentIndex ? 'bg-primary' : 'bg-textDarkGray'
}`}
></div>
))}
</div>

<div className="absolute w-[85%] bottom-10 flex flex-col max-w-[430px]">
<KakaoLoginButton />
<GoogleOAuthProvider clientId={CLIENT_ID}>
<GoogleLoginButton />
</GoogleOAuthProvider>
</div>
</div>
);
};

Expand Down
Loading