diff --git a/package-lock.json b/package-lock.json index 731893c..a5c9c64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "embla-carousel-react": "^8.0.0-rc14", "eslint": "8.43.0", "eslint-config-next": "13.4.7", + "gsap": "^3.12.4", "loadsh": "^0.0.4", "lodash": "^4.17.21", "lowlight": "2.4", @@ -8026,6 +8027,11 @@ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, + "node_modules/gsap": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.4.tgz", + "integrity": "sha512-1ByAq8dD0W4aBZ/JArgaQvc0gyUfkGkP8mgAQa0qZGdpOKlSOhOf+WNXjoLimKaKG3Z4Iu6DKZtnyszqQeyqWQ==" + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", diff --git a/package.json b/package.json index fb66dd8..15ada55 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "embla-carousel-react": "^8.0.0-rc14", "eslint": "8.43.0", "eslint-config-next": "13.4.7", + "gsap": "^3.12.4", "loadsh": "^0.0.4", "lodash": "^4.17.21", "lowlight": "2.4", diff --git a/src/app/page.tsx b/src/app/page.tsx index 98b0b58..7f460d1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,9 +1,19 @@ -import LandingContainer from '@/components/landing/LandingContainer'; -import EventHeader from '@/components/shared/EventHeader'; import { checkUser } from '@/service/auth'; import { ACCESS_TOKEN, MAIN_PATH, REFRESH_TOKEN } from '@/utils/const'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; +import LandingMain from '@/components/landing/LandingMain'; +import DescriptionBox from '@/components/landing/DescriptionBox'; +import LastNaigator from '@/components/landing/LastNaigator'; +import Footer from '@/components/shared/Footer'; +import autocomplete from '@/assets/autocomplete.gif'; +import mypage from '@/assets/mypage.gif'; +import editing from '@/assets/edit-memo.gif'; +import hire from '@/assets/hire.gif'; +import editUnderline from '@/assets/icons/edit_underline.svg'; +import speechBubble from '@/assets/icons/speech_bubble.svg'; +import infinity from '@/assets/icons/rank/infinity_1.svg'; +import wheel from '@/assets/icons/wheel_icon.svg'; export default async function LandingPage() { const accessToken = cookies().get(ACCESS_TOKEN)?.value; @@ -14,5 +24,55 @@ export default async function LandingPage() { isLogin && redirect(MAIN_PATH); - return ; + return ( +
+ +
+ + + + +
+ +
+
+ ); } diff --git a/src/components/landing/DescriptionBox.tsx b/src/components/landing/DescriptionBox.tsx new file mode 100644 index 0000000..76eabfd --- /dev/null +++ b/src/components/landing/DescriptionBox.tsx @@ -0,0 +1,80 @@ +'use client'; + +import Image, { StaticImageData } from 'next/image'; +import { useEffect, useRef } from 'react'; +import { gsap } from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; +type Props = { + title1: string; + title2: string; + description1: string; + description2: string; + subImg: string | StaticImageData; + mainImg: string | StaticImageData; + subImgAlt: string; + mainImgAlt: string; + reverse?: boolean; +}; + +gsap.registerPlugin(ScrollTrigger); + +export default function DescriptionBox({ + title1, + title2, + description1, + description2, + subImg, + mainImg, + subImgAlt, + mainImgAlt, + reverse = false, +}: Props) { + const ref = useRef(null); + + useEffect(() => { + if (ref.current) { + const element = ref.current; + gsap.fromTo( + element, + { opacity: 0, y: 400 }, + { + scrollTrigger: { + trigger: element, + start: 'top bottom', + }, + y: 0, + opacity: 1, + duration: 1, + } + ); + } + }, []); + + return ( +
+ {mainImgAlt} +
+ {subImgAlt} +

+ {title1} +
+ {title2} +

+

+ {description1} +
+ {description2} +

+
+
+ ); +} diff --git a/src/components/landing/LandingContainer.tsx b/src/components/landing/LandingContainer.tsx deleted file mode 100644 index 87d291e..0000000 --- a/src/components/landing/LandingContainer.tsx +++ /dev/null @@ -1,230 +0,0 @@ -'use client'; - -import Image from 'next/image'; -import Link from 'next/link'; -import { useRef, useState } from 'react'; -import TypeIt from 'typeit-react'; -import autocomplete from '@/assets/autocomplete.gif'; -import mypage from '@/assets/mypage.gif'; -import editing from '@/assets/edit-memo.gif'; -import logo from '@/assets/inforum_logo.png'; -import editUnderline from '@/assets/icons/edit_underline.svg'; -import speechBubble from '@/assets/icons/speech_bubble.svg'; -import Footer from '@/components/shared/Footer'; -import down from '@/assets/icons/down.svg'; -import { MAIN_PATH } from '@/utils/const'; -import { useRouter } from 'next/navigation'; -import infinity from '@/assets/icons/rank/infinity_1.svg'; -import wheel from '@/assets/icons/wheel_icon.svg'; -import hire from '@/assets/hire.gif'; -import EventHeader from '../shared/EventHeader'; - -export default function LandingContainer() { - const [readyState, setReadyState] = useState(false); - const firstScreenRef = useRef(null); - const router = useRouter(); - - return ( -
- {/* */} -
- logo -

- { - setReadyState(true); - }, - }} - > - 무한한 개발 이야기 공간 - -

-
-

- 다양한 개발 컨텐츠를 쉽고 간편하게 만들어 보세요 -
- 인포럼과 함께 긍정적인 개발 생태계를 만들어봐요 -

- -
- down -
- -
- autocomplete -
- speech-bubble -

- 생성형 AI를 활용한 -
- 텍스트 자동 생성 기능 -

-

- ++ 명령어를 입력해 텍스트를 자동 생성해보세요! -
- 글을 다 작성하면 자동생성된 요약과 태그를 제공합니다! - {/*
- 검색보다 빠르고 간편하게 정보를 제공합니다. */} -

-
-
- -
-
- edit-underline -

- 블럭 기반 에디터를 활용한 -
- 간편한 에디팅 기능 -

-

- / 키와 드래그를 이용하여 다양한 편집 기능을 사용해보세요! -
- 바로 반영되는 마크다운 문법을 사용해보세요! -

-
- landing -
- -
- mypage -
- infinity -

- 즐겁고, 꾸준하게 -
- Post Motivation -

-

- Post History 기능으로 꾸준하게 작성해보세요! -
- 메모 작성, 답변 채택 등 다양한 활동을 통해 등급을 올려보세요! -

-
-
-
-
- wheel -

- 신속하고 편리한 -
- 채용 도우미 서비스 -

-

- 원하는 직무의 개발자를 인포럼에서 찾아보세요! -
- 키워드에 맞는 질문을 자동 생성해 미니면접을 진행해보세요! -

-
- hire -
- -
-

- 인포럼과 함께 -
- 토론하며 성장하는 -
- 긍정적인 개발공간을 만들어보세요. -

- - -
- -
- - {/*
-

지원 예정

-
-
    -
  • - series 기능 -
  • -
  • - 스마트 드래그 기능 -
  • -
  • - 등급 제도 -
  • -
  • - 사용자 log 기반
    - 나만의 포트폴리오 -
  • -
- -
*/} -
- ); -} diff --git a/src/components/landing/LandingMain.tsx b/src/components/landing/LandingMain.tsx new file mode 100644 index 0000000..d4e4654 --- /dev/null +++ b/src/components/landing/LandingMain.tsx @@ -0,0 +1,68 @@ +'use client'; + +import { MAIN_PATH } from '@/utils/const'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useRef, useState } from 'react'; +import TypeIt from 'typeit-react'; +import down from '@/assets/icons/down.svg'; +import logo from '@/assets/inforum_logo.png'; + +export default function LandingMain() { + const [readyState, setReadyState] = useState(false); + const firstScreenRef = useRef(null); + + return ( +
+ logo +

+ { + setReadyState(true); + }, + }} + > + 무한한 개발 이야기 공간 + +

+
+

+ 다양한 개발 컨텐츠를 쉽고 간편하게 만들어 보세요 +
+ 인포럼과 함께 긍정적인 개발 생태계를 만들어봐요 +

+ +
+ 시작하기 +
+ +
+ down +
+ ); +} diff --git a/src/components/landing/LastNaigator.tsx b/src/components/landing/LastNaigator.tsx new file mode 100644 index 0000000..dd57536 --- /dev/null +++ b/src/components/landing/LastNaigator.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { MAIN_PATH } from '@/utils/const'; +import Link from 'next/link'; +import { useEffect, useRef } from 'react'; +import { gsap } from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; + +gsap.registerPlugin(ScrollTrigger); + +export default function LastNaigator() { + const ref = useRef(null); + + useEffect(() => { + if (ref.current) { + const element = ref.current; + gsap.fromTo( + element, + { opacity: 0 }, + { + scrollTrigger: { + trigger: element, + start: 'top center', + }, + opacity: 1, + duration: 1, + } + ); + } + }, []); + return ( +
+
+

+ 인포럼과 함께 +
+ 토론하며 성장하는 +
+ 긍정적인 개발공간을 만들어보세요. +

+ + +
+ 시작하기 +
+ +
+
+ ); +} diff --git a/src/components/shared/MoreOptions.tsx b/src/components/shared/MoreOptions.tsx index d2837db..e1845d5 100644 --- a/src/components/shared/MoreOptions.tsx +++ b/src/components/shared/MoreOptions.tsx @@ -20,7 +20,7 @@ export default function MoreOptions({ more