From dd352743927d5f99a97fbc395a9b9b5051b1c5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=80=EB=82=98?= Date: Tue, 13 Feb 2024 20:57:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feature-031:=20=ED=91=B8=ED=84=B0=20?= =?UTF-8?q?=EC=9C=84=20=ED=95=98=EB=8B=A8=20=ED=99=94=EB=A9=B4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 ++ src/components/Home/InsightVideos.tsx | 48 ++++++++++++++++++++++++++- src/styles/HomepageStyle.ts | 19 +++++++++++ yarn.lock | 10 ++++++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d60688..da23877 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/node": "^20.11.9", "@types/react-modal": "^3.16.3", "axios": "^1.6.4", + "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-modal": "^3.16.1", @@ -24,6 +25,7 @@ "styled-reset": "^4.5.2" }, "devDependencies": { + "@types/lodash": "^4.14.202", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", diff --git a/src/components/Home/InsightVideos.tsx b/src/components/Home/InsightVideos.tsx index 6075a38..2ca9c2f 100644 --- a/src/components/Home/InsightVideos.tsx +++ b/src/components/Home/InsightVideos.tsx @@ -1,7 +1,9 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; +import { throttle } from 'lodash'; import { InsightVideosContainer } from '@/styles/HomepageStyle'; import Card from '../category/Card'; import { cardDummy } from '../category/Card'; +import successImg from '@/assets/success.png'; interface InsightVideosProps { username: string; @@ -15,6 +17,41 @@ const InsightVideos: React.FC = ({ const formattedHashtags = popularHashtags.map((tag) => '#' + tag); const [categoryItems] = useState([]); const [checkedItems, setCheckedItems] = useState([]); + const [isEndOfPage, setIsEndOfPage] = useState(false); + + const timerId = useRef(null); + + useEffect(() => { + if (isEndOfPage) { + timerId.current = setTimeout(() => { + window.scroll(0, 1000); + setIsEndOfPage(false); + }, 3000); + } + + return () => { + if (timerId.current !== null) { + clearTimeout(timerId.current); + } + }; + }, [isEndOfPage]); + + + const checkScrollPosition = useCallback(() => { + if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { + setIsEndOfPage(true); + } else { + setIsEndOfPage(false); + } + }, []); + + useEffect(() => { + window.addEventListener('scroll', checkScrollPosition); + + return () => { + window.removeEventListener('scroll', checkScrollPosition); + } + }, [checkScrollPosition]); return ( @@ -33,6 +70,15 @@ const InsightVideos: React.FC = ({ setCheckedVideos={setCheckedItems} /> + {isEndOfPage && +
+
+ successImg +

+ 마지막 영상이에요!
더 많은 영상 변환하러 가볼까요? +

+
+
}
); diff --git a/src/styles/HomepageStyle.ts b/src/styles/HomepageStyle.ts index ec1ebb4..5d5450e 100644 --- a/src/styles/HomepageStyle.ts +++ b/src/styles/HomepageStyle.ts @@ -233,6 +233,25 @@ export const InsightVideosContainer = styled.div` margin-bottom: 40px; } + .end-message { + margin-top: 120px; + display: flex; + justify-content: center; + text-align: center; + } + + .end-wrapper { + width: 255px; + height: 171.11px; + } + + .end-text { + margin-top: 20px; + color: ${theme.color.gray400}; + font-size: 20px; + line-height: 1.6em; + } + .category-container { width: 250px; height: 38px; diff --git a/yarn.lock b/yarn.lock index 420cd38..302e992 100644 --- a/yarn.lock +++ b/yarn.lock @@ -730,6 +730,11 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/lodash@^4.14.202": + version "4.14.202" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" + integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== + "@types/node@*", "@types/node@^20.11.9": version "20.11.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.9.tgz#959d436f20ce2ee3df897c3eaa0617c98fa70efb" @@ -1788,6 +1793,11 @@ lodash.merge@^4.6.2: resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" From e09bc26615c0e3aa8b7538c500693f09b1d9024a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=80=EB=82=98?= Date: Wed, 14 Feb 2024 23:47:10 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feature-031:=20=ED=91=B8=ED=84=B0=20?= =?UTF-8?q?=EC=9C=84=20=ED=99=94=EB=A9=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Home/InsightVideos.tsx | 71 +++++++++++++-------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/components/Home/InsightVideos.tsx b/src/components/Home/InsightVideos.tsx index 406767f..c95f959 100644 --- a/src/components/Home/InsightVideos.tsx +++ b/src/components/Home/InsightVideos.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { InsightVideosContainer } from '@/styles/HomepageStyle'; import Card from '../category/Card'; import { IVideoProps } from 'types/videos'; @@ -17,46 +17,42 @@ const InsightVideos: React.FC = ({ const formattedHashtags = popularHashtags.map((tag) => '#' + tag); const [categoryItems] = useState([]); const [checkedItems, setCheckedItems] = useState([]); + const [showEndMessage, setShowEndMessage] = useState(false); + + const endBox = useRef(null); const onFileClick = (e: React.MouseEvent) => { e.stopPropagation(); // 비디오 카테고리로 저장 API 호출 후 이런 인사이트는 어때요 API 재호출로 최신화하기 }; - const [isEndOfPage, setIsEndOfPage] = useState(false); - - const timerId = useRef(null); useEffect(() => { - if (isEndOfPage) { - timerId.current = setTimeout(() => { - window.scroll(0, 1000); - setIsEndOfPage(false); - }, 3000); - } - - return () => { - if (timerId.current !== null) { - clearTimeout(timerId.current); - } + const handleIntersect = (entries: IntersectionObserverEntry[]) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setShowEndMessage(true); + setTimeout(() => { + setShowEndMessage(false); + }, 2000); + } + }); }; - }, [isEndOfPage]); - - const checkScrollPosition = useCallback(() => { - if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { - setIsEndOfPage(true); - } else { - setIsEndOfPage(false); - } - }, []); + const observer = new IntersectionObserver(handleIntersect, { + threshold: 1.0, + }); - useEffect(() => { - window.addEventListener('scroll', checkScrollPosition); + const endBoxElement = endBox.current; + if (endBoxElement) { + observer.observe(endBoxElement); + } return () => { - window.removeEventListener('scroll', checkScrollPosition); - } - }, [checkScrollPosition]); + if (endBoxElement) { + observer.unobserve(endBoxElement); + } + }; + }, []); return ( @@ -82,15 +78,14 @@ const InsightVideos: React.FC = ({ ))} - {isEndOfPage && -
-
- successImg -

- 마지막 영상이에요!
더 많은 영상 변환하러 가볼까요? -

-
-
} +
+
+ successImg +

+ 마지막 영상이에요!
더 많은 영상 변환하러 가볼까요? +

+
+
);