[251209] feat: ShopByShow-8

🕐 커밋 시간: 2025. 12. 09. 17:49:58

📊 변경 통계:
  • 총 파일: 5개
  • 추가: +69줄
  • 삭제: -22줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/FeaturedBrandsPanel.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/ShopByShow/ShopByShow.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/ShopByShow/ShopByShowList/ShopByShowContents/ShopByShowContents.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/ShopByShow/ShopByShowList/ShopByShowContents/ShopByShowProductList/ShopByShowProductList.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/ShopByShow/ShopByShowList/ShopByShowNav/ShopByShowNav.jsx

🔧 주요 변경 내용:
  • 소규모 기능 개선
This commit is contained in:
2025-12-09 17:49:58 +09:00
parent 407b4c7751
commit aa1f9630e6
5 changed files with 69 additions and 22 deletions

View File

@@ -773,15 +773,20 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
// effect: set selectedPatnrId and selectedPatncNm // effect: set selectedPatnrId and selectedPatncNm
useEffect(() => { useEffect(() => {
if (brandInfo) { if (brandInfo && panelInfo?.patnrId) {
const patnrId = panelInfo?.patnrId; const patnrId = panelInfo.patnrId;
const patncNm = brandInfo.find((b) => b?.patnrId === patnrId).patncNm; const patncNm = brandInfo.find((b) => b?.patnrId === patnrId)?.patncNm;
if (patncNm) {
setSelectedPatncNm(patncNm); setSelectedPatncNm(patncNm);
if (!fromDetail) setSelectedPatnrId(patnrId);
} }
}, [brandInfo, panelInfo?.patnrId]);
// Detail에서 돌아와도 patnrId가 비어 있으면 다시 설정해 API 호출이 정상 동작하도록 보완
if (!fromDetail || !selectedPatnrId) {
setSelectedPatnrId(patnrId);
}
}
}, [brandInfo, panelInfo?.patnrId, selectedPatnrId, fromDetail]);
// effect: data fetching based on brandLayoutInfo and selectedPatnrId // effect: data fetching based on brandLayoutInfo and selectedPatnrId
useEffect(() => { useEffect(() => {
@@ -791,6 +796,16 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
Object.entries(DISPATCH_MAP) // Object.entries(DISPATCH_MAP) //
.forEach(([templateCode, action]) => { .forEach(([templateCode, action]) => {
if (hasTemplateCodeWithValue(sortedBrandLayoutInfo, templateCode)) { if (hasTemplateCodeWithValue(sortedBrandLayoutInfo, templateCode)) {
// Detail 복귀 시 ShopByShow 데이터가 이미 있으면 재호출을 건너뛰어 선택 상태가 초기화되는 것을 방지
if (
templateCode === TEMPLATE_CODE_CONF.NBCU &&
fromDetail &&
shouldRenderComponent(brandShopByShowContsList)
) {
console.log("[FeaturedBrandsPanel] Skip re-fetch ShopByShow on return from detail");
return;
}
console.log("[FeaturedBrandsPanel] Fetching data for template:", templateCode, "patnrId:", selectedPatnrId); console.log("[FeaturedBrandsPanel] Fetching data for template:", templateCode, "patnrId:", selectedPatnrId);
dispatch(action({ patnrId: selectedPatnrId })); dispatch(action({ patnrId: selectedPatnrId }));
} }

View File

@@ -11,9 +11,11 @@ import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDeco
import useScrollTo from "../../../hooks/useScrollTo"; import useScrollTo from "../../../hooks/useScrollTo";
import SectionTitle from "../../../components/SectionTitle/SectionTitle"; import SectionTitle from "../../../components/SectionTitle/SectionTitle";
import { $L } from "../../../utils/helperMethods"; import { $L } from "../../../utils/helperMethods";
import { panel_names } from "../../../utils/Config";
import css from "./ShopByShow.module.less"; import css from "./ShopByShow.module.less";
import ShopByShowNav from "./ShopByShowList/ShopByShowNav/ShopByShowNav"; import ShopByShowNav from "./ShopByShowList/ShopByShowNav/ShopByShowNav";
import ShopByShowContents from "./ShopByShowList/ShopByShowContents/ShopByShowContents"; import ShopByShowContents from "./ShopByShowList/ShopByShowContents/ShopByShowContents";
import { updatePanel } from "../../../actions/panelActions";
const STRING_CONF = { const STRING_CONF = {
SHOP_BY_SHOW: "SHOP BY SHOW", SHOP_BY_SHOW: "SHOP BY SHOW",
@@ -43,16 +45,40 @@ const ShopByShow = ({
const brandShopByShowClctInfos = brandShopByShowContsInfo?.brandShopByShowClctInfos || []; const brandShopByShowClctInfos = brandShopByShowContsInfo?.brandShopByShowClctInfos || [];
const handleContsIdChange = useCallback((contsId) => { // DetailPanel 복귀 시 panelInfo에 저장된 contsId로 네비게이션 선택을 복구
useEffect(() => {
if (panelInfo?.contsId && panelInfo.contsId !== selectedContsId) {
setSelectedContsId(panelInfo.contsId);
}
}, [panelInfo?.contsId, selectedContsId]);
const handleContsIdChange = useCallback(
(contsId) => {
// patnrId가 없으면 Detail 복귀 직후라 정상 호출 불가
if (!selectedPatnrId) return;
setSelectedContsId(contsId); setSelectedContsId(contsId);
// 현재 선택된 contsId를 패널 상태에 저장해 복귀 시 복원
dispatch(
updatePanel({
name: panel_names.FEATURED_BRANDS_PANEL,
panelInfo: {
...(panelInfo || {}),
contsId,
},
})
);
// 'ALL' 버튼 클릭 시 (contsId === null) 첫 번째 contents 로드 // 'ALL' 버튼 클릭 시 (contsId === null) 첫 번째 contents 로드
const targetContsId = contsId || (brandShopByShowContsList?.[0]?.contsId); const targetContsId = contsId || brandShopByShowContsList?.[0]?.contsId;
if (targetContsId) { if (targetContsId) {
dispatch(getBrandShopByShow({ patnrId: selectedPatnrId, contsId: targetContsId })); dispatch(getBrandShopByShow({ patnrId: selectedPatnrId, contsId: targetContsId }));
} }
}, [selectedPatnrId, brandShopByShowContsList, dispatch]); },
[selectedPatnrId, brandShopByShowContsList, dispatch]
);
useEffect(() => { useEffect(() => {
if (panelInfo?.section !== "shop-by-show" || !panelInfo?.x) { if (panelInfo?.section !== "shop-by-show" || !panelInfo?.x) {
@@ -127,6 +153,7 @@ const ShopByShow = ({
handleItemFocus={_handleItemFocus} handleItemFocus={_handleItemFocus}
clctNm={collection.clctNm} clctNm={collection.clctNm}
clctImgUrl={collection.clctImgUrl} clctImgUrl={collection.clctImgUrl}
contsId={brandShopByShowContsInfo?.contsId || selectedContsId}
patnrId={selectedPatnrId} patnrId={selectedPatnrId}
selectedPatnrId={selectedPatnrId} selectedPatnrId={selectedPatnrId}
shelfOrder={shelfOrder} shelfOrder={shelfOrder}

View File

@@ -17,6 +17,7 @@ export default memo(function ShopByShowContents({
handleItemFocus, handleItemFocus,
clctNm, clctNm,
clctImgUrl, clctImgUrl,
contsId,
patnrId, patnrId,
selectedPatnrId, selectedPatnrId,
shelfOrder, shelfOrder,
@@ -50,6 +51,7 @@ export default memo(function ShopByShowContents({
brandProductInfos={brandProductInfos} brandProductInfos={brandProductInfos}
contentsIndex={contentsIndex} contentsIndex={contentsIndex}
handleFocus={handleFocus} handleFocus={handleFocus}
contsId={contsId}
patnrId={patnrId} patnrId={patnrId}
selectedPatnrId={selectedPatnrId} selectedPatnrId={selectedPatnrId}
clctNm={clctNm} clctNm={clctNm}

View File

@@ -23,6 +23,7 @@ export default function ShopByShowProductList({
brandProductInfos, brandProductInfos,
contentsIndex, contentsIndex,
handleFocus, handleFocus,
contsId,
patnrId, patnrId,
selectedPatnrId, selectedPatnrId,
clctNm, clctNm,
@@ -85,6 +86,7 @@ export default function ShopByShowProductList({
lastFocusedTargetId, lastFocusedTargetId,
patnrId: effectivePatnrId, patnrId: effectivePatnrId,
section, section,
contsId,
x, x,
}, },
}) })
@@ -94,11 +96,11 @@ export default function ShopByShowProductList({
dispatch( dispatch(
pushPanel({ pushPanel({
name: panel_names.DETAIL_PANEL, name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId: effectivePatnrId, prdtId }, panelInfo: { patnrId: effectivePatnrId, prdtId, contsId },
}) })
); );
}, },
[dispatch, patnrId] [dispatch, patnrId, contsId]
); );
const renderItem = useCallback( const renderItem = useCallback(

View File

@@ -25,6 +25,7 @@ export default memo(function ShopByShowNav({
selectedContsId, selectedContsId,
}) { }) {
const { getScrollTo, scrollLeft } = useScrollTo(); const { getScrollTo, scrollLeft } = useScrollTo();
const activeContsId = selectedContsId ?? brandShopByShowContsInfo?.contsId;
const handleClick = useCallback( const handleClick = useCallback(
(contsId) => () => { (contsId) => () => {
@@ -39,7 +40,7 @@ export default memo(function ShopByShowNav({
} }
}, [handleItemFocus]); }, [handleItemFocus]);
const selectedText = !selectedContsId ? "Selected " : ""; const selectedText = !activeContsId ? "Selected " : "";
const allLabeltext = selectedText + "ALL 1 of " + (brandShopByShowContsList.length + 1); const allLabeltext = selectedText + "ALL 1 of " + (brandShopByShowContsList.length + 1);
return ( return (
@@ -63,13 +64,13 @@ export default memo(function ShopByShowNav({
brandShopByShowContsList.map(({ contsId, contsNm }, index) => ( brandShopByShowContsList.map(({ contsId, contsNm }, index) => (
<li key={"shop-by-show-conts-" + index}> <li key={"shop-by-show-conts-" + index}>
<TButton <TButton
className={brandShopByShowContsInfo?.contsId === contsId && css.selected} className={activeContsId === contsId && css.selected}
onClick={handleClick(contsId)} onClick={handleClick(contsId)}
onFocus={handleFocus} onFocus={handleFocus}
selected={brandShopByShowContsInfo?.contsId === contsId} selected={activeContsId === contsId}
type={TYPES.oneDepthCategory} type={TYPES.oneDepthCategory}
ariaLabel={ ariaLabel={
brandShopByShowContsInfo?.contsId === contsId activeContsId === contsId
? "Selected " + contsNm + " " + (index * 1 + 1) + " of " + brandShopByShowContsList.length ? "Selected " + contsNm + " " + (index * 1 + 1) + " of " + brandShopByShowContsList.length
: "" + contsNm + " " + (index * 1 + 1) + " of " + brandShopByShowContsList.length : "" + contsNm + " " + (index * 1 + 1) + " of " + brandShopByShowContsList.length
} }