[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:
2025-11-21 12:49:10 +09:00
parent 2c99ab559c
commit 9c5de90098
5 changed files with 115 additions and 23 deletions

View File

@@ -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,11 +1269,11 @@ 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>
</div>
</div>
<TButton
spotlightId="detail-coupon-button"
className={css.couponButton}
@@ -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 && (

View File

@@ -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

View File

@@ -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>

View File

@@ -15,6 +15,8 @@
left: 0;
top: 0;
width: 100%;
z-index: -1;
pointer-events: none;
}
.itemsContainer {

View File

@@ -60,19 +60,36 @@ 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 (
shelfInfos &&
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"