[251123] fix: FavoriteButton , YouMayAlsoClickj

🕐 커밋 시간: 2025. 11. 23. 20:51:57

📊 변경 통계:
  • 총 파일: 2개
  • 추가: +64줄
  • 삭제: -28줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/components/FavoriteBtn.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/src/views/DetailPanel/components/FavoriteBtn.jsx (javascript):
    🔄 Modified: Spottable()

🔧 주요 변경 내용:
  • UI 컴포넌트 아키텍처 개선
This commit is contained in:
2025-11-23 20:51:57 +09:00
parent 52680e4802
commit 549f5caee7
2 changed files with 63 additions and 27 deletions

View File

@@ -141,13 +141,19 @@ export default function YouMayAlsoLike({
} = product; } = product;
const handleItemClick = () => { const handleItemClick = () => {
// Promise 체이닝으로 순서 보장 (Chrome 68, 87 호환성)
Promise.resolve()
.then(() => {
// 1. 기존 비디오 강제 종료
dispatch(finishVideoPreview()); dispatch(finishVideoPreview());
dispatch(finishModalMediaForce()); dispatch(finishModalMediaForce());
if (themeProductInfos && themeProductInfos.length > 0) { if (themeProductInfos && themeProductInfos.length > 0) {
dispatch(clearThemeDetail()); dispatch(clearThemeDetail());
} }
})
.then(() => {
// 2. 비디오 종료 후 새로운 상품으로 업데이트
// popPanel + pushPanel 대신 updatePanel 사용 // popPanel + pushPanel 대신 updatePanel 사용
// DetailPanel을 언마운트하지 않고 상품 정보만 업데이트 // DetailPanel을 언마운트하지 않고 상품 정보만 업데이트
// 이렇게 하면 백그라운드 비디오 제어 상태가 유지됨 // 이렇게 하면 백그라운드 비디오 제어 상태가 유지됨
@@ -167,6 +173,7 @@ export default function YouMayAlsoLike({
}) })
); );
cursorOpen.current.stop(); cursorOpen.current.stop();
});
}; };
// prdtId가 없는 경우를 대비한 안정적인 key 생성 // prdtId가 없는 경우를 대비한 안정적인 key 생성
const itemKey = prdtId ? `${patnrId}-${prdtId}` : `product-${index}`; const itemKey = prdtId ? `${patnrId}-${prdtId}` : `product-${index}`;

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useRef } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@@ -30,8 +30,12 @@ export default function FavoriteBtn({
}) { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { popupVisible, activePopup } = useSelector((state) => state.common.popup); const { popupVisible, activePopup } = useSelector((state) => state.common.popup);
const clickLockRef = useRef(false);
const handleFavoriteActivate = useCallback(() => {
if (clickLockRef.current) return;
clickLockRef.current = true;
const handleFavoriteClick = useCallback(() => {
dispatch( dispatch(
sendLogTotalRecommend({ sendLogTotalRecommend({
menu: logMenu, menu: logMenu,
@@ -61,10 +65,34 @@ export default function FavoriteBtn({
} }
}, [dispatch, favoriteFlag, selectedPatnrId, selectedPrdtId, logMenu]); }, [dispatch, favoriteFlag, selectedPatnrId, selectedPrdtId, logMenu]);
const handleMouseUp = useCallback(
(event) => {
// 실제 마우스 클릭(detail > 0)만 처리하고 키보드에서 전달된 mouse 이벤트(detail === 0)는 무시
if (event?.detail === 0) return;
if (event.button !== 0) return;
event.preventDefault();
event.stopPropagation();
handleFavoriteActivate();
},
[handleFavoriteActivate]
);
const handleClick = useCallback(
(event) => {
// 키보드(Enter)에서 발생하는 click(detail === 0)만 처리
if (event?.detail !== 0) return;
event.preventDefault();
event.stopPropagation();
handleFavoriteActivate();
},
[handleFavoriteActivate]
);
const PopUpOnClick = useCallback(() => { const PopUpOnClick = useCallback(() => {
setTimeout(() => Spotlight.focus('favoriteBtn')); setTimeout(() => Spotlight.focus('favoriteBtn'));
dispatch(setHidePopup()); dispatch(setHidePopup());
onFavoriteFlagChanged(favoriteFlag === 'Y' ? 'N' : 'Y'); onFavoriteFlagChanged(favoriteFlag === 'Y' ? 'N' : 'Y');
clickLockRef.current = false;
}, [dispatch, favoriteFlag, onFavoriteFlagChanged]); }, [dispatch, favoriteFlag, onFavoriteFlagChanged]);
const handleSpotlightDown = useCallback( const handleSpotlightDown = useCallback(
@@ -96,7 +124,8 @@ export default function FavoriteBtn({
role="button" role="button"
aria-label="Register in Favorites" aria-label="Register in Favorites"
tabIndex={0} tabIndex={0}
onClick={handleFavoriteClick} onMouseUp={handleMouseUp}
onClick={handleClick}
onSpotlightDown={handleSpotlightDown} onSpotlightDown={handleSpotlightDown}
data-spotlight-next-down={ data-spotlight-next-down={
kind === 'item_detail' ? nextDownId || 'product-details-button' : undefined kind === 'item_detail' ? nextDownId || 'product-details-button' : undefined