From 519e27890860e22e337b447eec100477521b2fdb Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:36:02 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20=EC=84=B1=EB=8A=A5=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20:=20=EB=9E=9C=EB=94=A9=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A7=8C=ED=81=BC=EB=A7=8C=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EA=B8=B0=20(#774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: intersection api를 이용해서 특정 영역이 관측될 때 이미지 src를 채우는 hook 구현 * feat: useImageLazyLoading 훅 적용 * feat: 이미지 alt 값을 한국말로 변경 * fix: feature4,5 이미지를 4 불러올 때 한 번에 불러오는 방식으로 변경 * feat: threshold를 0.1에서 0.05로 조금 더 빨리 불러오도록 변경 * feat: alt 행댕이를 행댕이 - 행동대장 마스코트 라고 자세하게 설명 * feat: threshold default value 0.1 -> 0.05로 변경 * feat: 0.1 -> 0.05 놓친 부분 수정 --- client/src/hooks/useImageLazyLoading.ts | 49 +++++++++++++++++++ .../DescriptionSection/DescriptionSection.tsx | 16 +++++- .../AutoCalculate/AutoCalculate.tsx | 16 +++++- .../CheckDeposit/CheckDeposit.tsx | 16 +++++- .../Section/FeatureSection/FeatureSection.tsx | 8 ++- .../RecordMemoryWithPhoto.tsx | 18 ++++++- .../SimpleShare/SimpleShare.tsx | 16 +++++- .../SimpleTransfer/SimpleTransfer.tsx | 18 +++++-- 8 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 client/src/hooks/useImageLazyLoading.ts diff --git a/client/src/hooks/useImageLazyLoading.ts b/client/src/hooks/useImageLazyLoading.ts new file mode 100644 index 00000000..6b95c77a --- /dev/null +++ b/client/src/hooks/useImageLazyLoading.ts @@ -0,0 +1,49 @@ +import {useEffect, useState} from 'react'; + +type UseImageLazyLoadingProps = { + targetRef: React.RefObject; + src: string; + threshold?: number; +}; + +const useImageLazyLoading = ({ + targetRef, + src, + threshold = 0.05, +}: UseImageLazyLoadingProps) => { + const [imageSrc, setImageSrc] = useState(undefined); + + useEffect(() => { + if (targetRef && !imageSrc) { + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + setImageSrc(src); + if (targetRef.current) { + observer.unobserve(targetRef.current); + } + } + }, + {threshold}, + ); + + if (targetRef.current) { + observer.observe(targetRef.current); + } + + return () => { + if (targetRef.current) { + observer.unobserve(targetRef.current); + } + }; + } + + return; + }, [targetRef, src]); + + return { + imageSrc, + }; +}; + +export default useImageLazyLoading; diff --git a/client/src/pages/MainPage/Section/DescriptionSection/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection/DescriptionSection.tsx index 9b9cb37c..63ed09eb 100644 --- a/client/src/pages/MainPage/Section/DescriptionSection/DescriptionSection.tsx +++ b/client/src/pages/MainPage/Section/DescriptionSection/DescriptionSection.tsx @@ -1,11 +1,23 @@ +import {useRef} from 'react'; + import Text from '@HDesign/components/Text/Text'; +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {descriptionSectionStyle, imgStyle} from './DescriptionSection.style'; const DescriptionSection = () => { + const descriptionRef = useRef(null); + + const {imageSrc} = useImageLazyLoading({ + targetRef: descriptionRef, + src: `${process.env.IMAGE_URL}/standingDog.svg`, + threshold: 0.05, + }); + return ( -
- 행댕이 +
+ 행댕이 - 행동대장 마스코트 {`행동대장들을 위해 행동대장을 준비했어요 `} diff --git a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx index f3925e97..b090c471 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx @@ -1,12 +1,24 @@ +import {useRef} from 'react'; + +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {Text} from '@components/Design'; import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './AutoCalculate.style'; const AutoCalculate = () => { + const sectionRef = useRef(null); + + const {imageSrc} = useImageLazyLoading({ + targetRef: sectionRef, + src: `${process.env.IMAGE_URL}/feature2.svg`, + threshold: 0.05, + }); + return ( -
+
- + 차등 정산 계산을 쉽게 해주는 UI 이미지
계산은 저희가 알아서 해드려요 diff --git a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx index 3f9e06d5..73995dd1 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx @@ -1,10 +1,22 @@ +import {useRef} from 'react'; + +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {Text} from '@components/Design'; import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './CheckDeposit.style'; const CheckDeposit = () => { + const sectionRef = useRef(null); + + const {imageSrc} = useImageLazyLoading({ + targetRef: sectionRef, + src: `${process.env.IMAGE_URL}/feature3.svg`, + threshold: 0.05, + }); + return ( -
+
@@ -16,7 +28,7 @@ const CheckDeposit = () => { 간편하게 관리할 수 있어요.`}
- + 입금 확인 기능 UI 이미지
); diff --git a/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx b/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx index 4f2b3cac..60d34fd9 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx @@ -1,3 +1,5 @@ +import {useRef} from 'react'; + import {SimpleShare} from './SimpleShare'; import {AutoCalculate} from './AutoCalculate'; import {CheckDeposit} from './CheckDeposit'; @@ -5,13 +7,15 @@ import {SimpleTransfer} from './SimpleTransfer'; import {RecordMemoryWithPhoto} from './RecordMemoryWithPhoto'; const FeatureSection = () => { + const simpleTransferRef = useRef(null); + return ( <> - - + + ); }; diff --git a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx index 4af4b190..5ecaa823 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx @@ -1,8 +1,22 @@ +import {useRef} from 'react'; + +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {Text} from '@components/Design'; import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './RecordMemoryWithPhoto.style'; -const RecordMemoryWithPhoto = () => { +type RecordMemoryWithPhotoProps = { + targetRef: React.RefObject; +}; + +const RecordMemoryWithPhoto = ({targetRef}: RecordMemoryWithPhotoProps) => { + const {imageSrc} = useImageLazyLoading({ + targetRef, + src: `${process.env.IMAGE_URL}/feature5.svg`, + threshold: 0.05, + }); + return (
@@ -16,7 +30,7 @@ const RecordMemoryWithPhoto = () => { 정산은 투명하게, 추억은 오래오래 간직할 수 있어요.`}
- + 행사 사진을 저장할 수 있는 UI 이미지
); diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx index 472232da..5e40a8ed 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx @@ -1,10 +1,22 @@ +import {useRef} from 'react'; + +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {Text} from '@components/Design'; import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './SimpleShare.style'; const SimpleAccount = () => { + const sectionRef = useRef(null); + + const {imageSrc} = useImageLazyLoading({ + targetRef: sectionRef, + src: `${process.env.IMAGE_URL}/feature1.svg`, + threshold: 0.05, + }); + return ( -
+
@@ -16,7 +28,7 @@ const SimpleAccount = () => { 복잡한 절차 없이, 빠르게 정산을 마치세요.`}
- + 간편한 공유를 설명하는 UI 이미지
); diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx index e6bb9c27..380c3a80 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx @@ -1,12 +1,24 @@ +import useImageLazyLoading from '@hooks/useImageLazyLoading'; + import {Text} from '@components/Design'; import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './SimpleTransfer.style'; -const SimpleTransfer = () => { +type SimpleTransferProps = { + targetRef: React.RefObject; +}; + +const SimpleTransfer = ({targetRef}: SimpleTransferProps) => { + const {imageSrc} = useImageLazyLoading({ + targetRef, + src: `${process.env.IMAGE_URL}/feature4.svg`, + threshold: 0.05, + }); + return ( -
+
- + 간편 송금을 설명하는 UI 이미지
몇 번의 클릭으로 송금 완료! From fc44763d13b56e20658904dda7ce04613159bc8a Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:37:02 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20=EC=84=B1=EB=8A=A5=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20:=20Kakao=20script=EB=A5=BC=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B3=B3=EC=97=90=EC=84=9C=20=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EB=B0=9B=EA=B8=B0=20(#776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Kakao script 동적으로 불러올 수 있는 함수 작성 * feat: 드롭다운 버튼 베이스 onClick 메서드 추가 * feat: 모바일 환경에서 초대버튼 눌렀을 때 카카오 스크립트를 불러오도록 설정 * feat: KakaoInitializer 제거 --- client/index.html | 5 -- client/src/App.tsx | 5 +- .../Design/components/Dropdown/ButtonBase.tsx | 10 +++- .../Design/components/Dropdown/Dropdown.tsx | 3 +- .../components/Dropdown/Dropdown.type.ts | 1 + .../KakaoInitializer/KakaoInitializer.tsx | 15 ------ .../MobileShareEventButton.tsx | 4 +- client/src/utils/initKakao.ts | 46 +++++++++++++++++++ 8 files changed, 61 insertions(+), 28 deletions(-) delete mode 100644 client/src/components/KakaoInitializer/KakaoInitializer.tsx create mode 100644 client/src/utils/initKakao.ts diff --git a/client/index.html b/client/index.html index 610cb08a..179b7b46 100644 --- a/client/index.html +++ b/client/index.html @@ -35,11 +35,6 @@ -
diff --git a/client/src/App.tsx b/client/src/App.tsx index 99e09da8..2872860c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -5,7 +5,6 @@ import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; import ToastContainer from '@components/Toast/ToastContainer'; -import KakaoInitializer from '@components/KakaoInitializer/KakaoInitializer'; import AmplitudeInitializer from '@components/AmplitudeInitializer/AmplitudeInitializer'; import {HDesignProvider} from '@HDesign/index'; @@ -26,9 +25,7 @@ const App: React.FC = () => { - - - + diff --git a/client/src/components/Design/components/Dropdown/ButtonBase.tsx b/client/src/components/Design/components/Dropdown/ButtonBase.tsx index 8c1c553d..0d407293 100644 --- a/client/src/components/Design/components/Dropdown/ButtonBase.tsx +++ b/client/src/components/Design/components/Dropdown/ButtonBase.tsx @@ -12,14 +12,20 @@ type ButtonBaseProps = DropdownProps & { isOpen: boolean; setIsOpen: React.Dispatch>; dropdownRef: React.RefObject; + onBaseButtonClick?: () => void; }; -const ButtonBase = ({isOpen, setIsOpen, dropdownRef, baseButtonText, children}: ButtonBaseProps) => { +const ButtonBase = ({isOpen, setIsOpen, dropdownRef, baseButtonText, onBaseButtonClick, children}: ButtonBaseProps) => { const {theme} = useTheme(); + const onClick = () => { + if (onBaseButtonClick) onBaseButtonClick(); + setIsOpen(true); + }; + return ( <> - {isOpen && ( diff --git a/client/src/components/Design/components/Dropdown/Dropdown.tsx b/client/src/components/Design/components/Dropdown/Dropdown.tsx index ab5fe23e..17420ed8 100644 --- a/client/src/components/Design/components/Dropdown/Dropdown.tsx +++ b/client/src/components/Design/components/Dropdown/Dropdown.tsx @@ -7,7 +7,7 @@ import MeatballBase from './MeatballBase'; import ButtonBase from './ButtonBase'; import {dropdownBaseStyle} from './Dropdown.style'; -const Dropdown = ({base = 'meatballs', baseButtonText, children}: DropdownProps) => { +const Dropdown = ({base = 'meatballs', baseButtonText, onBaseButtonClick, children}: DropdownProps) => { const {isOpen, setIsOpen, baseRef, dropdownRef} = useDropdown(); const isDropdownOpen = isOpen && !!baseRef.current; @@ -21,6 +21,7 @@ const Dropdown = ({base = 'meatballs', baseButtonText, children}: DropdownProps) & { export type DropdownProps = { base?: DropdownBase; baseButtonText?: string; + onBaseButtonClick?: () => void; children: React.ReactElement[]; }; diff --git a/client/src/components/KakaoInitializer/KakaoInitializer.tsx b/client/src/components/KakaoInitializer/KakaoInitializer.tsx deleted file mode 100644 index d3ed82ba..00000000 --- a/client/src/components/KakaoInitializer/KakaoInitializer.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import {useEffect} from 'react'; - -const KakaoInitializer = ({children}: React.PropsWithChildren) => { - useEffect(() => { - if (!window.Kakao) return; - - if (!window.Kakao.isInitialized()) { - window.Kakao.init(process.env.KAKAO_JAVASCRIPT_KEY); - } - }, []); - - return children; -}; - -export default KakaoInitializer; diff --git a/client/src/components/ShareEventButton/MobileShareEventButton.tsx b/client/src/components/ShareEventButton/MobileShareEventButton.tsx index 368dd611..1c13f80e 100644 --- a/client/src/components/ShareEventButton/MobileShareEventButton.tsx +++ b/client/src/components/ShareEventButton/MobileShareEventButton.tsx @@ -2,6 +2,8 @@ import toast from '@hooks/useToast/toast'; import {Dropdown, DropdownButton} from '@components/Design'; +import initKakao from '@utils/initKakao'; + type MobileShareEventButtonProps = { copyShare: () => Promise; kakaoShare: () => void; @@ -18,7 +20,7 @@ const MobileShareEventButton = ({copyShare, kakaoShare}: MobileShareEventButtonP return (
- + diff --git a/client/src/utils/initKakao.ts b/client/src/utils/initKakao.ts new file mode 100644 index 00000000..508dc902 --- /dev/null +++ b/client/src/utils/initKakao.ts @@ -0,0 +1,46 @@ +const kakaoScript = { + url: 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.2/kakao.min.js', + integrity: 'sha384-TiCUE00h649CAMonG018J2ujOgDKW/kVWlChEuu4jK2vxfAAD0eZxzCKakxg55G4', + crossOrigin: 'anonymous', + loaded: false, +}; + +const loadKakaoScript = () => { + return new Promise((resolve, reject) => { + if (kakaoScript.loaded) { + resolve(null); + return; + } + + const script = document.createElement('script'); + script.src = kakaoScript.url; + script.integrity = kakaoScript.integrity; + script.crossOrigin = kakaoScript.crossOrigin; + script.async = true; + + script.onload = () => { + kakaoScript.loaded = true; + resolve(null); + }; + + script.onerror = error => { + reject(error); + }; + + document.head.appendChild(script); + }); +}; + +const initKakao = async () => { + try { + await loadKakaoScript(); + + if (window.Kakao && !window.Kakao.isInitialized()) { + window.Kakao.init(process.env.KAKAO_JAVASCRIPT_KEY); + } + } catch (error) { + console.error('Kakao SDK 로드 중 오류 발생:', error); + } +}; + +export default initKakao; From ccf83275c350a728b8b0516b0455b93fb542ded6 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:49:17 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20v2.1.1=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=ED=95=9C=20=EB=9E=9C=EB=94=A9=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B0=9C=EC=84=A0=20(#777)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 랜딩페이지 개선 * fix: 첫 스크롤이 이상하게 되던 오류 수정 * design: image가 꽉차게 보이도록 변경 * move: CreatorSection 파일 위치 변경 * fix: IOS 환경에서 svg 렌더를 위해 object tag 로 변경 * fix: import 잘못된 오류 수정 * style: lint 적용 * fix: `useMainPageYScroll.ts`를 FeatureSection 내부에서 호출하도록 변경 * refactor: avatar style 분ㄹ * fix: avatar를 button이 아니라 a태그로 감싸도록 변경 * style: lint 적용 및 사용하지 않는 주석과 코드 제거 * refactor: Avatar 부분 리스트 렌더링으로 변경 * style: fix 적용 * fix: object tag에 alt property 제거 --- client/src/GlobalStyle.ts | 1 + client/src/hooks/useMainPageYScroll.ts | 35 +++++++++ .../hooks/useMainSectionBackgroundScroll.ts | 28 ++++++++ client/src/pages/MainPage/MainPage.tsx | 3 + .../pages/MainPage/Section/CreatorSection.tsx | 72 ------------------- .../Section/CreatorSection/Avatar.style.ts | 17 +++++ .../Section/CreatorSection/Avatar.tsx | 24 +++++++ .../CreatorSection/CreatorSection.style.ts | 39 ++++++++++ .../Section/CreatorSection/CreatorSection.tsx | 59 +++++++++++++++ .../AutoCalculate/AutoCalculate.style.ts | 3 +- .../AutoCalculate/AutoCalculate.tsx | 2 +- .../CheckDeposit/CheckDeposit.style.ts | 3 +- .../CheckDeposit/CheckDeposit.tsx | 2 +- .../Section/FeatureSection/FeatureSection.tsx | 16 ++++- .../RecordMemoryWithPhoto.style.ts | 3 +- .../RecordMemoryWithPhoto.tsx | 2 +- .../SimpleShare/SimpleShare.style.ts | 3 +- .../SimpleShare/SimpleShare.tsx | 2 +- .../SimpleTransfer/SimpleTransfer.style.ts | 3 +- .../SimpleTransfer/SimpleTransfer.tsx | 2 +- .../Section/MainSection/MainSection.style.ts | 12 ++-- .../Section/MainSection/MainSection.tsx | 15 ++-- 22 files changed, 247 insertions(+), 99 deletions(-) create mode 100644 client/src/hooks/useMainPageYScroll.ts create mode 100644 client/src/hooks/useMainSectionBackgroundScroll.ts delete mode 100644 client/src/pages/MainPage/Section/CreatorSection.tsx create mode 100644 client/src/pages/MainPage/Section/CreatorSection/Avatar.style.ts create mode 100644 client/src/pages/MainPage/Section/CreatorSection/Avatar.tsx create mode 100644 client/src/pages/MainPage/Section/CreatorSection/CreatorSection.style.ts create mode 100644 client/src/pages/MainPage/Section/CreatorSection/CreatorSection.tsx diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index 460d50ca..f2f5c3cc 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -124,6 +124,7 @@ export const GlobalStyle = css` } body { + overflow-x: hidden; font-family: 'Pretendard', -apple-system, diff --git a/client/src/hooks/useMainPageYScroll.ts b/client/src/hooks/useMainPageYScroll.ts new file mode 100644 index 00000000..91289135 --- /dev/null +++ b/client/src/hooks/useMainPageYScroll.ts @@ -0,0 +1,35 @@ +import {useEffect, useRef} from 'react'; + +const useMainPageYScroll = () => { + const featureSectionRef = useRef(null); + const translateX = useRef(0); + + useEffect(() => { + const handleScroll = () => { + if (featureSectionRef.current) { + const featureSectionTop = featureSectionRef.current.offsetTop; + const scrollY = window.scrollY; + + if (scrollY >= featureSectionTop && translateX.current < window.innerWidth * 4) { + window.scrollTo(0, featureSectionTop); + translateX.current += scrollY - featureSectionTop; + const newTransform = `translateX(calc(200vw - ${translateX.current > 0 ? translateX.current : 0}px))`; + featureSectionRef.current.style.transform = newTransform; + } + if (scrollY <= featureSectionTop && translateX.current > 0) { + window.scrollTo(0, featureSectionTop); + translateX.current += scrollY - featureSectionTop; + const newTransform = `translateX(calc(200vw - ${translateX.current < window.innerWidth * 4 ? translateX.current : window.innerWidth * 4}px))`; + featureSectionRef.current.style.transform = newTransform; + } + } + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + + return {featureSectionRef}; +}; + +export default useMainPageYScroll; diff --git a/client/src/hooks/useMainSectionBackgroundScroll.ts b/client/src/hooks/useMainSectionBackgroundScroll.ts new file mode 100644 index 00000000..42ead493 --- /dev/null +++ b/client/src/hooks/useMainSectionBackgroundScroll.ts @@ -0,0 +1,28 @@ +import {useEffect, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const useMainSectionBackgroundScroll = (trackStartCreateEvent: () => void) => { + const navigate = useNavigate(); + + const handleClick = () => { + trackStartCreateEvent(); + navigate(ROUTER_URLS.createEvent); + }; + + const [isVisible, setIsVisible] = useState(true); + + useEffect(() => { + const handleScroll = () => { + setIsVisible(window.scrollY <= window.innerHeight); + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + + return {isVisible, handleClick}; +}; + +export default useMainSectionBackgroundScroll; diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 911f3245..f6663f61 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,10 +1,12 @@ import useAmplitude from '@hooks/useAmplitude'; +import useMainPageYScroll from '@hooks/useMainPageYScroll'; import Nav from './Nav/Nav'; import {MainSection} from './Section/MainSection'; import {DescriptionSection} from './Section/DescriptionSection'; import {FeatureSection} from './Section/FeatureSection'; import {mainContainer} from './MainPage.style'; +import CreatorSection from './Section/CreatorSection/CreatorSection'; const MainPage = () => { const {trackStartCreateEvent} = useAmplitude(); @@ -15,6 +17,7 @@ const MainPage = () => { +
); }; diff --git a/client/src/pages/MainPage/Section/CreatorSection.tsx b/client/src/pages/MainPage/Section/CreatorSection.tsx deleted file mode 100644 index fd1c8c2d..00000000 --- a/client/src/pages/MainPage/Section/CreatorSection.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import {css} from '@emotion/react'; - -import Text from '@components/Design/components/Text/Text'; - -const CreatorSection = () => { - return ( -
-
-
- - - 누구와도 간편하게 정산하세요 - -
-
-
- ); -}; - -export default CreatorSection; diff --git a/client/src/pages/MainPage/Section/CreatorSection/Avatar.style.ts b/client/src/pages/MainPage/Section/CreatorSection/Avatar.style.ts new file mode 100644 index 00000000..e03df7d0 --- /dev/null +++ b/client/src/pages/MainPage/Section/CreatorSection/Avatar.style.ts @@ -0,0 +1,17 @@ +import {css} from '@emotion/react'; + +export const avatarStyle = css({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '0.5rem', + '@media (min-width: 1200px)': { + gap: '1rem', + }, +}); + +export const avatarImageStyle = css({ + width: '100%', + height: '100%', + borderRadius: '25%', +}); diff --git a/client/src/pages/MainPage/Section/CreatorSection/Avatar.tsx b/client/src/pages/MainPage/Section/CreatorSection/Avatar.tsx new file mode 100644 index 00000000..d559325e --- /dev/null +++ b/client/src/pages/MainPage/Section/CreatorSection/Avatar.tsx @@ -0,0 +1,24 @@ +import {css} from '@emotion/react'; + +import {Text} from '@components/Design'; + +import {avatarImageStyle, avatarStyle} from './Avatar.style'; + +interface Props { + imagePath: string; + name: string; + navigateUrl: string; +} + +const Avatar = ({imagePath, name, navigateUrl}: Props) => { + return ( + + + + {name} + + + ); +}; + +export default Avatar; diff --git a/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.style.ts b/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.style.ts new file mode 100644 index 00000000..55ee71a5 --- /dev/null +++ b/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.style.ts @@ -0,0 +1,39 @@ +import {css} from '@emotion/react'; + +export const sectionStyle = css({ + display: 'flex', + padding: '4rem 0', + minHeight: '100vh', + width: '100vw', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#000000 ', + gap: '2rem', +}); + +export const partStyle = css({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '2rem', +}); + +export const avatarContainerStyle = css({ + display: 'grid', + gridTemplateColumns: 'repeat(2, 1fr)', + gridTemplateRows: 'repeat(2, 1fr)', + width: '100%', + padding: '0 4rem', + gap: '1rem', + maxWidth: '1200px', + '@media (min-width: 640px)': { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + gap: '2rem', + }, + '@media (min-width: 1024px)': { + gap: '6rem', + }, +}); diff --git a/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.tsx b/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.tsx new file mode 100644 index 00000000..6bd279fe --- /dev/null +++ b/client/src/pages/MainPage/Section/CreatorSection/CreatorSection.tsx @@ -0,0 +1,59 @@ +import {css} from '@emotion/react'; +import {useNavigate} from 'react-router-dom'; + +import Text from '@components/Design/components/Text/Text'; + +import Avatar from './Avatar'; +import {avatarContainerStyle, partStyle, sectionStyle} from './CreatorSection.style'; + +const CreatorSection = () => { + const frontEndDevelopers = [ + {imagePath: 'todari', name: '토다리', navigateUrl: 'https://github.com/Todari'}, + {imagePath: 'cookie', name: '쿠키', navigateUrl: 'https://github.com/jinhokim98'}, + {imagePath: 'soha', name: '소하', navigateUrl: 'https://github.com/soi-ha'}, + {imagePath: 'weadie', name: '웨디', navigateUrl: 'https://github.com/pakxe'}, + ]; + const backEndDevelopers = [ + {imagePath: '2sang', name: '이상', navigateUrl: 'https://github.com/kunsanglee'}, + {imagePath: 'baekho', name: '백호', navigateUrl: 'https://github.com/Arachneee'}, + {imagePath: 'mangcho', name: '망쵸', navigateUrl: 'https://github.com/3Juhwan'}, + {imagePath: 'gamja', name: '감자', navigateUrl: 'https://github.com/khabh'}, + ]; + + return ( +
+ + 행동대장을 만든 행동대장들 + +
+ + FRONTEND + +
+ {frontEndDevelopers.map(developer => ( + + ))} +
+
+
+ + BACKEND + +
+ {backEndDevelopers.map(developer => ( + + ))} +
+
+
+ ); +}; + +export default CreatorSection; diff --git a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.style.ts b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.style.ts index d847764e..41790116 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.style.ts +++ b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.style.ts @@ -7,7 +7,6 @@ export const sectionStyle = css({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - backgroundColor: '#ffffff', }); export const articleStyle = css({ @@ -28,6 +27,8 @@ export const articleStyle = css({ }); export const imageStyle = css({ + objectFit: 'cover', + aspectRatio: '1/1', minWidth: '15rem', maxWidth: '25rem', width: '100%', diff --git a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx index b090c471..697bffe7 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/AutoCalculate/AutoCalculate.tsx @@ -18,7 +18,7 @@ const AutoCalculate = () => { return (
- 차등 정산 계산을 쉽게 해주는 UI 이미지 +
계산은 저희가 알아서 해드려요 diff --git a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.style.ts b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.style.ts index 08e4619c..4cd328d8 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.style.ts +++ b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.style.ts @@ -7,7 +7,6 @@ export const sectionStyle = css({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - backgroundColor: '#DFC1FF', }); export const articleStyle = css({ @@ -36,6 +35,8 @@ export const textContainerStyle = css({ }); export const imageStyle = css({ + objectFit: 'cover', + aspectRatio: '1/1', minWidth: '20rem', maxWidth: '30rem', width: '100%', diff --git a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx index 73995dd1..2cc7c4fd 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/CheckDeposit/CheckDeposit.tsx @@ -28,7 +28,7 @@ const CheckDeposit = () => { 간편하게 관리할 수 있어요.`}
- 입금 확인 기능 UI 이미지 + ); diff --git a/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx b/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx index 60d34fd9..7c16517f 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/FeatureSection.tsx @@ -1,5 +1,8 @@ +import {css} from '@emotion/react'; import {useRef} from 'react'; +import useMainPageYScroll from '@hooks/useMainPageYScroll'; + import {SimpleShare} from './SimpleShare'; import {AutoCalculate} from './AutoCalculate'; import {CheckDeposit} from './CheckDeposit'; @@ -7,16 +10,25 @@ import {SimpleTransfer} from './SimpleTransfer'; import {RecordMemoryWithPhoto} from './RecordMemoryWithPhoto'; const FeatureSection = () => { + const {featureSectionRef} = useMainPageYScroll(); const simpleTransferRef = useRef(null); return ( - <> +
- +
); }; diff --git a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.style.ts b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.style.ts index 42f4781a..cac040ec 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.style.ts +++ b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.style.ts @@ -7,7 +7,6 @@ export const sectionStyle = css({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - backgroundColor: '#C1CFFF', }); export const articleStyle = css({ @@ -36,6 +35,8 @@ export const textContainerStyle = css({ }); export const imageStyle = css({ + objectFit: 'cover', + aspectRatio: '1/1', minWidth: '20rem', maxWidth: '25rem', width: '100%', diff --git a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx index 5ecaa823..7a3d7f44 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/RecordMemoryWithPhoto/RecordMemoryWithPhoto.tsx @@ -30,7 +30,7 @@ const RecordMemoryWithPhoto = ({targetRef}: RecordMemoryWithPhotoProps) => { 정산은 투명하게, 추억은 오래오래 간직할 수 있어요.`} - 행사 사진을 저장할 수 있는 UI 이미지 + ); diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.style.ts b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.style.ts index 9d362387..ad2279f7 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.style.ts +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.style.ts @@ -7,7 +7,6 @@ export const sectionStyle = css({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - backgroundColor: '#FFA5B8', }); export const articleStyle = css({ @@ -36,6 +35,8 @@ export const textContainerStyle = css({ }); export const imageStyle = css({ + objectFit: 'cover', + aspectRatio: '1/1', minWidth: '15rem', maxWidth: '25rem', width: '100%', diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx index 5e40a8ed..ae2b5b60 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleShare/SimpleShare.tsx @@ -28,7 +28,7 @@ const SimpleAccount = () => { 복잡한 절차 없이, 빠르게 정산을 마치세요.`} - 간편한 공유를 설명하는 UI 이미지 + ); diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.style.ts b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.style.ts index 36832804..5c996369 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.style.ts +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.style.ts @@ -7,7 +7,6 @@ export const sectionStyle = css({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - backgroundColor: '#ffffff', }); export const articleStyle = css({ @@ -36,6 +35,8 @@ export const textContainerStyle = css({ }); export const imageStyle = css({ + objectFit: 'cover', + aspectRatio: '1/1', minWidth: '20rem', maxWidth: '30rem', width: '100%', diff --git a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx index 380c3a80..dcb3cc42 100644 --- a/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx +++ b/client/src/pages/MainPage/Section/FeatureSection/SimpleTransfer/SimpleTransfer.tsx @@ -18,7 +18,7 @@ const SimpleTransfer = ({targetRef}: SimpleTransferProps) => { return (
- 간편 송금을 설명하는 UI 이미지 +
몇 번의 클릭으로 송금 완료! diff --git a/client/src/pages/MainPage/Section/MainSection/MainSection.style.ts b/client/src/pages/MainPage/Section/MainSection/MainSection.style.ts index 8db38b97..4afea6c8 100644 --- a/client/src/pages/MainPage/Section/MainSection/MainSection.style.ts +++ b/client/src/pages/MainPage/Section/MainSection/MainSection.style.ts @@ -47,12 +47,16 @@ export const backgroundStyle = css({ height: '100vh', top: 0, zIndex: -1, + backgroundColor: '#000000', }); -export const backgroundImageStyle = css({ - height: '100vh', - objectFit: 'cover', -}); +export const backgroundImageStyle = (isVisible: boolean) => + css({ + objectFit: 'cover', + height: '100vh', + width: '100vw', + opacity: isVisible ? 1 : 0, + }); export const sectionStyle = css({ display: 'flex', diff --git a/client/src/pages/MainPage/Section/MainSection/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection/MainSection.tsx index e6e47633..8b2491e6 100644 --- a/client/src/pages/MainPage/Section/MainSection/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection/MainSection.tsx @@ -1,11 +1,9 @@ -import {useNavigate} from 'react-router-dom'; - import Button from '@HDesign/components/Button/Button'; import Text from '@HDesign/components/Text/Text'; -import {Icon} from '@components/Design'; +import useMainSectionBackgroundScroll from '@hooks/useMainSectionBackgroundScroll'; -import {ROUTER_URLS} from '@constants/routerUrls'; +import {Icon} from '@components/Design'; import { animateWithDelay, @@ -21,17 +19,12 @@ type MainSectionProps = { }; const MainSection = ({trackStartCreateEvent}: MainSectionProps) => { - const navigate = useNavigate(); - - const handleClick = () => { - trackStartCreateEvent(); - navigate(ROUTER_URLS.createEvent); - }; + const {isVisible, handleClick} = useMainSectionBackgroundScroll(trackStartCreateEvent); return (
- +
{`행동대장으로 From 86b36ca4903c9570814c9f7172c8d894437c1f9d Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:49:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=99=88=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20=EC=9E=88?= =?UTF-8?q?=EC=9D=84=20=EB=95=90=20=ED=86=A0=ED=81=B0=EC=9D=B4=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EB=8F=84=20=EC=A7=80=EC=B6=9C=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=91=EA=B7=BC=20=EB=B6=88=EA=B0=80=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#781)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/StepList/Step.tsx | 2 +- client/src/pages/EventPage/HomePage/HomePage.tsx | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index aead2f37..b8c0813b 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource @emotion/react */ -import {useNavigate} from 'react-router-dom'; +import {useMatch, useNavigate} from 'react-router-dom'; import {css} from '@emotion/react'; import Amount from '@components/Design/components/Amount/Amount'; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 4314d959..f8a205ef 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,6 +1,6 @@ import type {EventPageContextProps} from '../EventPageLayout'; -import {useNavigate, useOutletContext} from 'react-router-dom'; +import {useMatch, useNavigate, useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/Steps'; import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; @@ -13,10 +13,14 @@ import {Icon, Tab, Tabs, Title} from '@HDesign/index'; import getEventIdByUrl from '@utils/getEventIdByUrl'; +import {ROUTER_URLS} from '@constants/routerUrls'; + import {receiptStyle} from './HomePage.style'; const HomePage = () => { const {isAdmin, eventName} = useOutletContext(); + const isInHomePage = useMatch(ROUTER_URLS.home) !== null; + const {steps} = useRequestGetSteps(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); const {images} = useRequestGetImages(); @@ -38,7 +42,7 @@ const HomePage = () => { /> } /> - } /> + } />
);