[251121] fix: JustForYouTestPanel Top Click
🕐 커밋 시간: 2025. 11. 21. 12:49:09 📊 변경 통계: • 총 파일: 5개 • 추가: +115줄 • 삭제: -23줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/components/FavoriteBtn.jsx ~ com.twin.app.shoptime/src/views/JustForYouPanel/JustForYouPanel.jsx ~ com.twin.app.shoptime/src/views/JustForYouPanel/JustForYouPanel.module.less ~ com.twin.app.shoptime/src/views/JustForYouTestPanel/JustForYouTestPanel.jsx 🔧 주요 변경 내용: • UI 컴포넌트 아키텍처 개선 • 테스트 커버리지 및 안정성 향상 • 중간 규모 기능 개선
This commit is contained in:
@@ -910,6 +910,10 @@ export default function ProductAllSection({
|
||||
Spotlight.focus('spotlightId_backBtn');
|
||||
}, []);
|
||||
|
||||
const handleSpotlightDown = useCallback((e) => {
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
const onFavoriteFlagChanged = useCallback(
|
||||
(newFavoriteFlag) => setFavoriteOverride(newFavoriteFlag),
|
||||
[]
|
||||
@@ -1265,7 +1269,7 @@ export default function ProductAllSection({
|
||||
|
||||
{promotions.map((promotion, idx) => {
|
||||
return(
|
||||
<HorizontalContainer className={css.couponContainer} key={idx}>
|
||||
<div className={css.couponContainer} key={idx}>
|
||||
<div className={css.couponTitleText}>
|
||||
<div className={css.firstTitle}>SPECIAL PROMOTION</div>
|
||||
<div className={css.secondTitle}>Coupon only applicable to this product!</div>
|
||||
@@ -1277,6 +1281,7 @@ export default function ProductAllSection({
|
||||
handleCouponClick(idx, promotion);
|
||||
}}
|
||||
onSpotlightUp={handleSpotlightUpFromCouponButtons}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
size="detail_very_small"
|
||||
>
|
||||
<div className={css.couponText}>
|
||||
@@ -1284,16 +1289,17 @@ export default function ProductAllSection({
|
||||
</div>
|
||||
<img className={css.buttonImg} src={couponImg} />
|
||||
</TButton>
|
||||
</HorizontalContainer>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{isBillingProductVisible && (
|
||||
<HorizontalContainer className={css.buyNowCartContainer}>
|
||||
<div className={css.buyNowCartContainer}>
|
||||
<TButton
|
||||
spotlightId="detail-buy-now-button"
|
||||
className={css.buyNowButton}
|
||||
onClick={handleBuyNowClick}
|
||||
onSpotlightUp={handleSpotlightUpFromBuyButtons}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
type="detail_small"
|
||||
>
|
||||
<div className={css.buyNowText}>{$L('BUY NOW')}</div>
|
||||
@@ -1304,14 +1310,15 @@ export default function ProductAllSection({
|
||||
// onClick={handleAddToCartClick}
|
||||
onClick={handleBuyNowClick}
|
||||
onSpotlightUp={handleSpotlightUpFromBuyButtons}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
type="detail_small"
|
||||
>
|
||||
<div className={css.addToCartText}>{$L('ADD TO CART')}</div>
|
||||
</TButton>
|
||||
</HorizontalContainer>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<HorizontalContainer
|
||||
<div
|
||||
className={classNames(
|
||||
css.buttonContainer,
|
||||
isBillingProductVisible && css.buttonHasNoCart
|
||||
@@ -1323,6 +1330,7 @@ export default function ProductAllSection({
|
||||
className={css.shopByMobileButton}
|
||||
onClick={handleShopByMobileOpen}
|
||||
onSpotlightUp={handleSpotlightUpToBackButton}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
>
|
||||
<div className={css.shopByMobileText}>{$L('SHOP BY MOBILE')}</div>
|
||||
</TButton>
|
||||
@@ -1338,7 +1346,7 @@ export default function ProductAllSection({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</HorizontalContainer>
|
||||
</div>
|
||||
|
||||
<div className={css.callToOrderSection}>
|
||||
{orderPhnNo && (
|
||||
|
||||
@@ -66,20 +66,33 @@ export default function FavoriteBtn({
|
||||
onFavoriteFlagChanged(favoriteFlag === 'Y' ? 'N' : 'Y');
|
||||
}, [dispatch, favoriteFlag, onFavoriteFlagChanged]);
|
||||
|
||||
const handleFavoriteKeyDown = useCallback((e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
handleFavoriteClick();
|
||||
}
|
||||
}, [handleFavoriteClick]);
|
||||
|
||||
const handleSpotlightDown = useCallback((e) => {
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SpottableDiv
|
||||
className={classNames(css.favorBtnContainer, kind === 'item_detail' ? css.smallSize : '')}
|
||||
spotlightId="favoriteBtn"
|
||||
onClick={handleFavoriteClick}
|
||||
className={classNames(css.favorBtnContainer, kind === 'item_detail' ? css.smallSize : '')}
|
||||
role="button"
|
||||
aria-label="Register in Favorites"
|
||||
tabIndex={0}
|
||||
onClick={handleFavoriteClick}
|
||||
onKeyDown={handleFavoriteKeyDown}
|
||||
onSpotlightDown={handleSpotlightDown}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
css.favoriteButton,
|
||||
favoriteFlag === 'N' ? css.favorBtn : css.favorUnableBtn
|
||||
)}
|
||||
aria-label="Register in Favorites"
|
||||
/>
|
||||
{activePopup === Config.ACTIVE_POPUP.favoritePopup && (
|
||||
<TPopUp
|
||||
|
||||
@@ -73,6 +73,21 @@ const JustForYouPanel = ({ panelInfo, isOnTop, ...rest }) => {
|
||||
const currentSentMenuRef = useRef(null);
|
||||
const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId);
|
||||
|
||||
// 마운트 로그
|
||||
useEffect(() => {
|
||||
console.log('[JustForYouPanel] 마운트됨', {
|
||||
isOnTop,
|
||||
recentItemsCount: recentItems?.length || 0,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
return () => {
|
||||
console.log('[JustForYouPanel] 언마운트됨', {
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleScroll = useCallback((e) => {
|
||||
setShowButton(e.scrollTop === 0);
|
||||
}, []);
|
||||
@@ -120,7 +135,24 @@ const JustForYouPanel = ({ panelInfo, isOnTop, ...rest }) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleWrapClickCapture = useCallback(() => {
|
||||
console.log("[JustForYouPanel] wrapper capture: 상위 div 통과");
|
||||
}, []);
|
||||
|
||||
const handlePanelClickCapture = useCallback(() => {
|
||||
console.log("[JustForYouPanel] TPanel capture: panel 통과");
|
||||
}, []);
|
||||
|
||||
const handleBodyClickCapture = useCallback(() => {
|
||||
console.log("[JustForYouPanel] TBody capture: body 통과");
|
||||
}, []);
|
||||
|
||||
const handleButtonWrapperClickCapture = useCallback(() => {
|
||||
console.log("[JustForYouPanel] 버튼 감싸는 div capture: 버튼 바로 위");
|
||||
}, []);
|
||||
|
||||
const handleTopButtonClick = useCallback(() => {
|
||||
console.log("[JustForYouPanel] TButton onClick: TOP 버튼 클릭");
|
||||
if (cbChangePageRef.current) {
|
||||
cbChangePageRef.current(0, true);
|
||||
}
|
||||
@@ -132,6 +164,10 @@ const JustForYouPanel = ({ panelInfo, isOnTop, ...rest }) => {
|
||||
}
|
||||
}, [recentItems]);
|
||||
|
||||
const handleTopButtonSpotlightDown = useCallback((e) => {
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
const renderItem = useCallback(
|
||||
(item) => {
|
||||
const {
|
||||
@@ -234,9 +270,15 @@ const JustForYouPanel = ({ panelInfo, isOnTop, ...rest }) => {
|
||||
// </TBody>
|
||||
// </TPanel>
|
||||
// </div>
|
||||
<div className={css.justForYouWrap}>
|
||||
<TPanel>
|
||||
<TBody className={css.justForYou}>
|
||||
<div
|
||||
className={css.justForYouWrap}
|
||||
onClickCapture={handleWrapClickCapture}
|
||||
>
|
||||
<TPanel onClickCapture={handlePanelClickCapture}>
|
||||
<TBody
|
||||
className={css.justForYou}
|
||||
onClickCapture={handleBodyClickCapture}
|
||||
>
|
||||
<div className={css.background}>
|
||||
<CustomImage src={background} animationSpeed="none" />
|
||||
</div>
|
||||
@@ -311,15 +353,23 @@ const JustForYouPanel = ({ panelInfo, isOnTop, ...rest }) => {
|
||||
)}
|
||||
|
||||
{recentItems && recentItems?.length > 10 && (
|
||||
<RecentSawContainer>
|
||||
<TButton
|
||||
onClick={handleTopButtonClick}
|
||||
size={null}
|
||||
spotlightId={SpotlightIds.JUST_FOR_YOU_TOP_BUTTON}
|
||||
ariaLabel="Move to Top"
|
||||
data-wheel-point
|
||||
type={TYPES.topButton}
|
||||
/>
|
||||
<RecentSawContainer onClickCapture={handleButtonWrapperClickCapture}>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
console.log("[JustForYouPanel] DIV onClick: TOP 버튼 DIV 클릭");
|
||||
handleTopButtonClick();
|
||||
}}
|
||||
>
|
||||
<TButton
|
||||
onClick={handleTopButtonClick}
|
||||
onSpotlightDown={handleTopButtonSpotlightDown}
|
||||
size={null}
|
||||
spotlightId={SpotlightIds.JUST_FOR_YOU_TOP_BUTTON}
|
||||
ariaLabel="Move to Top"
|
||||
data-wheel-point
|
||||
type={TYPES.topButton}
|
||||
/>
|
||||
</div>
|
||||
</RecentSawContainer>
|
||||
)}
|
||||
</TBody>
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.itemsContainer {
|
||||
|
||||
@@ -60,8 +60,17 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
||||
}, [dispatch]);
|
||||
|
||||
const handleTopButtonClick = useCallback(() => {
|
||||
console.log("[JustForYouTestPanel] TOP 버튼 클릭됨", {
|
||||
cbChangePageRefExists: !!cbChangePageRef.current,
|
||||
shelfInfosLength: shelfInfos?.length || 0,
|
||||
firstShelfProductCount: shelfInfos?.[0]?.productInfos?.length || 0,
|
||||
});
|
||||
|
||||
if (cbChangePageRef.current) {
|
||||
console.log("[JustForYouTestPanel] cbChangePageRef 호출");
|
||||
cbChangePageRef.current(0, true);
|
||||
} else {
|
||||
console.log("[JustForYouTestPanel] ⚠️ cbChangePageRef.current가 null");
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -69,10 +78,18 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
||||
shelfInfos.length > 0 &&
|
||||
shelfInfos[0].productInfos?.length > 0
|
||||
) {
|
||||
console.log("[JustForYouTestPanel] Spotlight.focus('justForYouList_1') 호출");
|
||||
Spotlight.focus("justForYouList_1");
|
||||
} else {
|
||||
console.log("[JustForYouTestPanel] ⚠️ shelfInfos 없음 또는 비어있음");
|
||||
}
|
||||
}, [shelfInfos]);
|
||||
|
||||
const handleTopButtonSpotlightDown = useCallback((e) => {
|
||||
console.log("[JustForYouTestPanel] TOP 버튼 SpotlightDown");
|
||||
e.stopPropagation();
|
||||
}, []);
|
||||
|
||||
const renderItem = useCallback(
|
||||
(shelfId, shelfExpsOrd, productInfos) =>
|
||||
({ index, ...rest }) => {
|
||||
@@ -138,6 +155,7 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
||||
className={css.tVerticalPagenator}
|
||||
spotlightId={"justforyouspotlight"}
|
||||
topMargin={470}
|
||||
cbChangePageRef={cbChangePageRef}
|
||||
>
|
||||
<div className={css.background}>
|
||||
<THeaderCustom
|
||||
@@ -204,6 +222,7 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
||||
<ListContainer>
|
||||
<TButton
|
||||
onClick={handleTopButtonClick}
|
||||
onSpotlightDown={handleTopButtonSpotlightDown}
|
||||
size={null}
|
||||
spotlightId={SpotlightIds.JUST_FOR_YOU_TOP_BUTTON}
|
||||
ariaLabel="Move to Top"
|
||||
|
||||
Reference in New Issue
Block a user