From cbdf1b89f8f40883f9588dfe4455a08b0bde608e Mon Sep 17 00:00:00 2001 From: optrader Date: Wed, 10 Dec 2025 17:30:18 +0900 Subject: [PATCH] =?UTF-8?q?[251210]=20fix:=20DetailPanel,ProductAllSection?= =?UTF-8?q?=20API=EC=B5=9C=EC=A0=81=ED=99=94-2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ• ์ปค๋ฐ‹ ์‹œ๊ฐ„: 2025. 12. 10. 17:30:18 ๐Ÿ“Š ๋ณ€๊ฒฝ ํ†ต๊ณ„: โ€ข ์ด ํŒŒ์ผ: 1๊ฐœ โ€ข ์ถ”๊ฐ€: +85์ค„ โ€ข ์‚ญ์ œ: -52์ค„ ๐Ÿ“ ์ˆ˜์ •๋œ ํŒŒ์ผ: ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ๐Ÿ”ง ์ฃผ์š” ๋ณ€๊ฒฝ ๋‚ด์šฉ: โ€ข ์†Œ๊ทœ๋ชจ ๊ธฐ๋Šฅ ๊ฐœ์„  โ€ข ์ฝ”๋“œ ์ •๋ฆฌ ๋ฐ ์ตœ์ ํ™” --- .../ProductAllSection/ProductAllSection.jsx | 139 +++++++++++------- 1 file changed, 86 insertions(+), 53 deletions(-) diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx index 837ffdc2..92008749 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx @@ -274,7 +274,6 @@ export default function ProductAllSection({ // const [currentHeight, setCurrentHeight] = useState(0); //ํ•˜๋‹จ๋ถ€๋ถ„๊นŒ์ง€ ๊ฐ”์„๋•Œ ์ฒดํฌ์šฉ - const [documentHeight, setDocumentHeight] = useState(0); const [isBottom, setIsBottom] = useState(false); //qr์ฝ”๋“œ ๋…ธ์ถœ์šฉ @@ -283,6 +282,8 @@ export default function ProductAllSection({ // sendLogGNB์šฉ entryMenu const entryMenuRef = useRef(null); + const lastProductDetailLogKeyRef = useRef(null); + const lastGnbLogKeyRef = useRef(null); // ์ถœ์ฒ˜ ์ •๋ณด ํ†ตํ•ฉ (ํ–ฅํ›„ ํ™•์žฅ์„ฑ ๋Œ€๋น„) // YouMayLike ์ƒํ’ˆ์ด ์•„๋‹ ๊ฒฝ์šฐ fromPanel์„ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ์˜ค๊ธฐ ๋ฐฉ์ง€ @@ -298,6 +299,7 @@ export default function ProductAllSection({ // ๋ชจ๋“  timeout/timer๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ref const timersRef = useRef([]); + const contentHeightRef = useRef(0); // handleScrollToImages์˜ timeout์„ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ref const scrollToImagesTimeoutRef = useRef(null); @@ -733,6 +735,7 @@ export default function ProductAllSection({ // sendLogGNB ๋กœ๊น… - Source์˜ DetailPanel ์ปดํฌ๋„ŒํŠธ๋“ค๊ณผ ๋™์ผํ•œ ํŒจํ„ด useEffect(() => { + if (!productData?.prdtId) return; if (!entryMenuRef.current) entryMenuRef.current = nowMenu; // BUY NOW ๋ฒ„ํŠผ ํ™œ์„ฑํ™” ์ƒํƒœ์— ๋”ฐ๋ฅธ ๋ฉ”๋‰ด ๊ฒฐ์ • (Source SingleProduct vs UnableProduct ํŒจํ„ด) @@ -754,8 +757,22 @@ export default function ProductAllSection({ ? `${baseMenu}/${Config.LOG_MENU.DETAIL_PAGE_YOU_MAY_LIKE}` : baseMenu; + const logKey = `${productData?.patnrId || ''}-${productData?.prdtId || ''}`; + if (lastGnbLogKeyRef.current === logKey) { + return; + } + lastGnbLogKeyRef.current = logKey; + dispatch(sendLogGNB(menu)); - }, [isBillingProductVisible, isGroupProductVisible, isTravelProductVisible, fromPanel?.fromYouMayLike]); + }, [ + isBillingProductVisible, + isGroupProductVisible, + isTravelProductVisible, + fromPanel?.fromYouMayLike, + productData?.patnrId, + productData?.prdtId, + nowMenu, + ]); // sendLogGNB ์ „์†ก ํ›„ ํ”Œ๋ž˜๊ทธ ์ดˆ๊ธฐํ™” (1ํšŒ ์‚ฌ์šฉ ํ›„ ๋น„ํ™œ์„ฑํ™”) useEffect(() => { @@ -774,37 +791,54 @@ export default function ProductAllSection({ // sendLogProductDetail ๋กœ๊น… - Source์˜ productData ๋ณ€๊ฒฝ ๊ฐ์ง€์™€ ๋™์ผํ•œ ํŒจํ„ด useEffect(() => { - if (productData && Object.keys(productData).length > 0) { - const params = { - befPrice: productData?.priceInfo?.split("|")[0], - curationId: productData?.curationId ?? "", - curationNm: productData?.curationNm ?? "", - entryMenu: entryMenuRef.current, - expsOrd: "1", - inDt: formatGMTString(new Date()), - lastPrice: productData?.priceInfo?.split("|")[1], - lgCatCd: productData?.catCd ?? "", - lgCatNm: productData?.catNm ?? "", - linkTpCd: panelInfo?.linkTpCd ?? "", - logTpNo: isTravelProductVisible - ? Config.LOG_TP_NO.PRODUCT.TRAVEL_DETAIL - : isGroupProductVisible - ? Config.LOG_TP_NO.PRODUCT.GROUP_DETAIL - : isBillingProductVisible - ? Config.LOG_TP_NO.PRODUCT.BILLING_PRODUCT_DETAIL - : Config.LOG_TP_NO.PRODUCT.PRODUCT_DETAIL, - patncNm: productData?.patncNm ?? "", - patnrId: productData?.patnrId ?? "", - prdtId: productData?.prdtId ?? "", - prdtNm: productData?.prdtNm ?? "", - revwGrd: productData?.revwGrd ?? "", - rewdAplyFlag: productData.priceInfo?.split("|")[2], - tsvFlag: productData?.todaySpclFlag ?? "", - }; - - dispatch(sendLogProductDetail(params)); + if (!productData || Object.keys(productData).length === 0) { + return; } - }, [productData, panelInfo?.linkTpCd, isBillingProductVisible, isGroupProductVisible, isTravelProductVisible, dispatch]); // productData ๋ณ€๊ฒฝ ์‹œ ์žฌ์‹คํ–‰ + + const logTpNo = isTravelProductVisible + ? Config.LOG_TP_NO.PRODUCT.TRAVEL_DETAIL + : isGroupProductVisible + ? Config.LOG_TP_NO.PRODUCT.GROUP_DETAIL + : isBillingProductVisible + ? Config.LOG_TP_NO.PRODUCT.BILLING_PRODUCT_DETAIL + : Config.LOG_TP_NO.PRODUCT.PRODUCT_DETAIL; + + const logKey = `${productData?.patnrId || ''}-${productData?.prdtId || ''}-${panelInfo?.linkTpCd || ''}-${logTpNo}`; + if (lastProductDetailLogKeyRef.current === logKey) { + return; + } + lastProductDetailLogKeyRef.current = logKey; + + const params = { + befPrice: productData?.priceInfo?.split("|")[0], + curationId: productData?.curationId ?? "", + curationNm: productData?.curationNm ?? "", + entryMenu: entryMenuRef.current, + expsOrd: "1", + inDt: formatGMTString(new Date()), + lastPrice: productData?.priceInfo?.split("|")[1], + lgCatCd: productData?.catCd ?? "", + lgCatNm: productData?.catNm ?? "", + linkTpCd: panelInfo?.linkTpCd ?? "", + logTpNo, + patncNm: productData?.patncNm ?? "", + patnrId: productData?.patnrId ?? "", + prdtId: productData?.prdtId ?? "", + prdtNm: productData?.prdtNm ?? "", + revwGrd: productData?.revwGrd ?? "", + rewdAplyFlag: productData.priceInfo?.split("|")[2], + tsvFlag: productData?.todaySpclFlag ?? "", + }; + + dispatch(sendLogProductDetail(params)); + }, [ + productData, + panelInfo?.linkTpCd, + isBillingProductVisible, + isGroupProductVisible, + isTravelProductVisible, + dispatch, + ]); // productData ๋ณ€๊ฒฝ ์‹œ ์žฌ์‹คํ–‰ // [251115] ์ฃผ์„ ์ฒ˜๋ฆฌ: MediaPanel์—์„œ ์ด๋ฏธ ํฌ์ปค์Šค ์ด๋™์„ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ // ProductAllSection์˜ ์ž๋™ ํฌ์ปค์Šค๋Š” ํฌ์ปค์Šค ํƒˆ์ทจ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Œ @@ -1246,6 +1280,13 @@ export default function ProductAllSection({ const prevScrollTopRef = useRef(0); // HomePanel ์Šคํƒ€์ผ ์Šคํฌ๋กค ์œ„์น˜ ์ถ”์  const scrollExpandTimerRef = useRef(null); // ์Šคํฌ๋กค ํ™•์žฅ ํƒ€์ด๋จธ const mediaMinimizedRef = useRef(false); + const getTotalContentHeight = useCallback(() => { + const measuredHeight = + contentHeightRef.current || + scrollContainerRef.current?.scrollHeight || + 0; + return measuredHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0); + }, []); const handleArrowClickAlternative = useCallback(() => { dispatch(minimizeModalMedia()); @@ -1258,14 +1299,14 @@ export default function ProductAllSection({ animate: true, }); - // documentHeight๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ˜๋ณต ๊ณ„์‚ฐ ์ œ๊ฑฐ - const totalHeight = documentHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0); + // ์บ์‹œ๋œ ์ฝ˜ํ…์ธ  ๋†’์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ˜๋ณต ๊ณ„์‚ฐ ์ตœ์†Œํ™” + const totalHeight = getTotalContentHeight(); const isAtBottom = scrollPositionRef.current + 1100 >= totalHeight; if (isAtBottom) { setIsBottom(isAtBottom); } - }, [documentHeight, scrollTop, dispatch]); + }, [scrollTop, dispatch, getTotalContentHeight]); const handleScroll = useCallback( (e) => { @@ -1276,12 +1317,12 @@ export default function ProductAllSection({ const prevScrollTop = prevScrollTopRef.current; scrollPositionRef.current = currentScrollTop; + contentHeightRef.current = e?.scrollHeight || contentHeightRef.current || 0; // ๊ธฐ์กด bottom ์ฒดํฌ ๋กœ์ง ์œ ์ง€ - if (documentHeight) { - const isAtBottom = - scrollPositionRef.current + 944 >= - documentHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0); + const totalHeight = getTotalContentHeight(); + if (totalHeight) { + const isAtBottom = scrollPositionRef.current + 944 >= totalHeight; if (isAtBottom !== isBottom) { setIsBottom(isAtBottom); } @@ -1334,7 +1375,7 @@ export default function ProductAllSection({ } // v2: onScrollStop์—์„œ ์ฒ˜๋ฆฌ (๊ธฐ์กด ๋กœ์ง ์œ ์ง€) }, - [documentHeight, isBottom, productVideoVersion, isVideoPlaying, dispatch] + [isBottom, productVideoVersion, isVideoPlaying, dispatch, getTotalContentHeight] ); // ์Šคํฌ๋กค ๋ฉˆ์ถ”์—ˆ์„ ๋•Œ๋งŒ ํ˜ธ์ถœ (์„ฑ๋Šฅ ์ตœ์ ํ™”) @@ -1342,10 +1383,10 @@ export default function ProductAllSection({ (e) => { const currentScrollTop = e.scrollTop; scrollPositionRef.current = currentScrollTop; - if (documentHeight) { - const isAtBottom = - currentScrollTop + 944 >= - documentHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0); + contentHeightRef.current = e?.scrollHeight || contentHeightRef.current || 0; + const totalHeight = getTotalContentHeight(); + if (totalHeight) { + const isAtBottom = currentScrollTop + 944 >= totalHeight; if (isAtBottom !== isBottom) { setIsBottom(isAtBottom); } @@ -1360,7 +1401,7 @@ export default function ProductAllSection({ return shouldMinimize; }); }, - [documentHeight] + [getTotalContentHeight] ); useEffect(() => { @@ -1385,14 +1426,6 @@ export default function ProductAllSection({ setActiveButton(null); }, []); - useEffect(() => { - setDocumentHeight( - (productDetailRef.current?.scrollHeight || 0) + - (descriptionRef.current?.scrollHeight || 0) + - (reviewRef.current?.scrollHeight || 0) - ); - }, [productDetailRef.current, descriptionRef.current, reviewRef.current]); - // ์Šคํฌ๋กค ์œ„์น˜์— ๋”ฐ๋ฅธ MediaPanel ์ œ์–ด (๋น„๋””์˜ค ์žฌ์ƒ ์ค‘์—๋Š” ์ž๋™ ์ œ์–ด ์•ˆํ•จ - unmount ์‹œ์—๋งŒ ์ •๋ฆฌ) // useEffect(() => { // console.log('๐Ÿ“ [ProductAllSection] useEffect ์‹คํ–‰ - shouldMinimizeMedia:', shouldMinimizeMedia);