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
Binary file added frontend/src/assets/images/scrollDown.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/serviceGuide-1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/serviceGuide-2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/serviceGuide-3.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/serviceGuide-4.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/serviceGuide-5.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 35 additions & 1 deletion frontend/src/pages/LandingPage/LandingPage.constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { CarouselItemType } from './LandingPage.types';
import { CarouselItemType, ServiceGuideStepType } from './LandingPage.types';

import guide1 from '@/assets/images/serviceGuide-1.webp';
import guide2 from '@/assets/images/serviceGuide-2.webp';
import guide3 from '@/assets/images/serviceGuide-3.webp';
import guide4 from '@/assets/images/serviceGuide-4.webp';
import guide5 from '@/assets/images/serviceGuide-5.webp';

export const CAROUSEL_ITEMS: CarouselItemType[] = [
{ icon: 'Reading', text: '오디오북 듣기' },
Expand All @@ -10,3 +16,31 @@ export const CAROUSEL_ITEMS: CarouselItemType[] = [
];

export const CAROUSEL_TIMEOUT = 1500;

export const SERVICE_GUIDE_STEPS: ServiceGuideStepType[] = [
{
step: 1,
description: '매일 반복되는 통학 시간,\n무의미하게 흘려보내고\n있진 않나요?',
image: guide1,
},
{
step: 2,
description: '두리번으로 자투리 시간을\n알차게 활용해\n목표를 달성해보세요',
image: guide2,
},
{
step: 3,
description: '이동 경로와 나만의 목표를 고려해\n이동 시간에 할 일을\n관리할 수 있어요',
image: guide3,
},
{
step: 4,
description: '주변의 다른 통학생은\n어떤 목표를 향해\n가고 있는지 알아보세요',
image: guide4,
},
{
step: 5,
description: '내가 보낸 이동 시간,\n얼마나 의미 있었는지\n한눈에 확인하세요',
image: guide5,
},
];
16 changes: 8 additions & 8 deletions frontend/src/pages/LandingPage/LandingPage.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ export const LandingPageLayout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
height: 100%;
padding: 2rem 0;
`;
overflow-y: scroll;
scroll-snap-type: y mandatory;
scroll-behavior: smooth;

export const MainContent = styled.main`
display: flex;
flex-direction: column;
align-items: center;
gap: 3.2rem;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
`;
10 changes: 10 additions & 0 deletions frontend/src/pages/LandingPage/LandingPage.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ export interface CarouselItemType {
}

export type CarouselItemStatusType = 'focus' | 'blur';

export interface ServiceGuideStepType {
step: number;
description: string;
image: string;
}

export interface ServiceGuideCarouselProps {
steps: ServiceGuideStepType[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const ListLayout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
height: 18rem;
height: 15rem;
overflow: hidden;
position: relative;
`;
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import styled from 'styled-components';

export const ButtonContainer = styled.div`
position: relative;
width: 100%;
display: flex;
justify-content: center;
z-index: 10;
`;

export const ButtonLayout = styled.button`
display: flex;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ const KakaoLoginButton = () => {
};

return (
<S.ButtonLayout onClick={handleKakaoLogin}>
<S.ButtonContent>
<Icon icon="Kakao" />
<span>카카오 로그인</span>
</S.ButtonContent>
</S.ButtonLayout>
<S.ButtonContainer>
<S.ButtonLayout onClick={handleKakaoLogin}>
<S.ButtonContent>
<Icon icon="Kakao" />
<span>카카오 로그인</span>
</S.ButtonContent>
</S.ButtonLayout>
</S.ButtonContainer>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import styled from 'styled-components';

export const GuideIntroLayout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
width: 100%;
height: 100%;
scroll-snap-align: start;
scroll-snap-stop: always;
flex-shrink: 0;
background: linear-gradient(
0deg,
${({ theme }) => theme.colors.green100} 0%,
${({ theme }) => theme.colors.white} 56.28%
);
`;

export const ScrollDownContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
`;

export const ScrollDownText = styled.div`
${({ theme }) => theme.fonts.label14Reg};
color: ${({ theme }) => theme.colors.green800};
`;

export const ScrollDownImage = styled.img`
width: 4.4rem;
height: 6.4rem;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as S from './GuideIntro.styled';
import CarouselList from '../../CarouselList';
import KakaoLoginButton from '../../KakaoLoginButton';
import LandingHeader from '../../LandingHeader';
import LandingMessage from '../../LandingMessage';

import scrollDownImage from '@/assets/images/scrollDown.webp';

const GuideIntro = () => {
return (
<S.GuideIntroLayout>
<LandingHeader />
<LandingMessage />
<CarouselList />
<KakaoLoginButton />
<S.ScrollDownContainer>
<S.ScrollDownText>아래로 스크롤하면 서비스 소개를 볼 수 있어요</S.ScrollDownText>
<S.ScrollDownImage src={scrollDownImage} alt="scrollDown" />
</S.ScrollDownContainer>
</S.GuideIntroLayout>
);
};

export default GuideIntro;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import styled from 'styled-components';

export const GuideOutroLayout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
width: 100%;
height: 100%;
scroll-snap-align: start;
scroll-snap-stop: always;
flex-shrink: 0;
box-sizing: border-box;
background: linear-gradient(
0deg,
${({ theme }) => theme.colors.green100} 0%,
${({ theme }) => theme.colors.white} 56.28%
);
`;

export const ContentContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
`;

export const ScrollDownText = styled.div`
${({ theme }) => theme.fonts.label14Reg};
color: ${({ theme }) => theme.colors.green800};
`;

export const ButtonContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as S from './GuideOutro.styled';
import CarouselList from '../../CarouselList';
import KakaoLoginButton from '../../KakaoLoginButton';
import LandingHeader from '../../LandingHeader';
import LandingMessage from '../../LandingMessage';

const GuideOutro = () => {
return (
<S.GuideOutroLayout>
<LandingHeader />
<LandingMessage />
<CarouselList />
<S.ButtonContainer>
<S.ScrollDownText>로그인하여 두리번을 시작해보세요</S.ScrollDownText>
<KakaoLoginButton />
</S.ButtonContainer>
</S.GuideOutroLayout>
);
};

export default GuideOutro;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import styled from 'styled-components';

export const GuideSlideLayout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: ; */
width: 100%;
height: 100%;
padding: 5rem 0;
position: relative;
scroll-snap-align: start;
scroll-snap-stop: always;
flex-shrink: 0;
overflow: hidden;
gap: 5rem;
`;

export const Description = styled.div`
${({ theme }) => theme.fonts.heading20};
line-height: 2.8rem;
white-space: pre-line;
text-align: center;
`;

export const Image = styled.img`
max-width: 260px;
z-index: 1;
position: relative;
bottom: 0;
`;
Comment on lines +26 to +31
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

bottom: 0 on a position: relative element is a no-op
Offset properties have no effect with position: relative unless you intend to nudge the element. Use position: absolute inside a relative parent or drop the offset.

-export const Image = styled.img`
-  max-width: 260px;
-  z-index: 1;
-  position: relative;
-  bottom: 0;
-`;
+export const Image = styled.img`
+  max-width: 260px;
+  z-index: 1;
+  /* Removed ineffective positioning; parent handles layout */
+`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const Image = styled.img`
max-width: 260px;
z-index: 1;
position: relative;
bottom: 0;
`;
export const Image = styled.img`
max-width: 260px;
z-index: 1;
/* Removed ineffective positioning; parent handles layout */
`;
🤖 Prompt for AI Agents
In
frontend/src/pages/LandingPage/components/ServiceGuide/GuideSlide/GuideSlide.styled.ts
between lines 26 and 31, the CSS rule 'bottom: 0' on a 'position: relative'
element has no effect. To fix this, either remove the 'bottom: 0' property if no
offset is needed, or change the position to 'absolute' if you intend to position
the element relative to its nearest positioned ancestor.


export const IndexContainer = styled.div`
display: flex;
flex-direction: column;
gap: 1.2rem;
position: absolute;
right: 2.4rem;
top: 50%;
transform: translateY(-50%);
z-index: 10;
`;

export const IndexCircle = styled.div<{ $isActive: boolean }>`
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
background-color: ${({ theme, $isActive }) =>
$isActive ? theme.colors.green600 : theme.colors.gray300};
`;

export const ButtonContainer = styled.div`
position: absolute;
bottom: 3rem;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as S from './GuideSlide.styled';
import { ServiceGuideStepType } from '../../../LandingPage.types';
import KakaoLoginButton from '../../KakaoLoginButton';
import LandingHeader from '../../LandingHeader';

interface ServiceGuideProps {
step: ServiceGuideStepType;
totalSteps: number;
}

const GuideSlide = ({ step, totalSteps }: ServiceGuideProps) => {
return (
<S.GuideSlideLayout>
<LandingHeader />
<S.Description>{step.description}</S.Description>

<S.IndexContainer>
{Array.from({ length: totalSteps }).map((_, index) => (
<S.IndexCircle key={index} $isActive={index + 1 === step.step} />
))}
</S.IndexContainer>
<S.Image src={step.image} alt="service guide" />

<S.ButtonContainer>
<KakaoLoginButton />
</S.ButtonContainer>
</S.GuideSlideLayout>
);
};

export default GuideSlide;
19 changes: 9 additions & 10 deletions frontend/src/pages/LandingPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import CarouselList from './components/CarouselList';
import KakaoLoginButton from './components/KakaoLoginButton';
import LandingHeader from './components/LandingHeader';
import LandingMessage from './components/LandingMessage';
import GuideIntro from './components/ServiceGuide/GuideIntro';
import GuideOutro from './components/ServiceGuide/GuideOutro';
import GuideSlide from './components/ServiceGuide/GuideSlide';
import { SERVICE_GUIDE_STEPS } from './LandingPage.constants';
import * as S from './LandingPage.styled';

const LandingPage = () => {
return (
<S.LandingPageLayout>
<LandingHeader />
<S.MainContent>
<LandingMessage />
<CarouselList />
</S.MainContent>
<KakaoLoginButton />
<GuideIntro />
{SERVICE_GUIDE_STEPS.map((step) => (
<GuideSlide key={step.step} step={step} totalSteps={SERVICE_GUIDE_STEPS.length} />
))}
<GuideOutro />
</S.LandingPageLayout>
);
};
Expand Down