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 87eee2fd..c99f28ef 100644
--- a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
+++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
@@ -116,6 +116,7 @@ import UserReviews from '../ProductContentSection/UserReviews/UserReviews';
// import ViewAllReviewsButton from '../ProductContentSection/UserReviews/ViewAllReviewsButton';
import YouMayAlsoLike
from '../ProductContentSection/YouMayAlsoLike/YouMayAlsoLike';
+import SeeMoreProducts from '../ProductContentSection/SeeMoreProducts/SeeMoreProducts';
import QRCode from '../ProductInfoSection/QRCode/QRCode';
import ProductOverview from '../ProductOverview/ProductOverview';
// CSS imports
@@ -1005,6 +1006,7 @@ export default function ProductAllSection({
const [isShowUserReviewsFocused, setIsShowUserReviewsFocused] = useState(false);
// ๐ [251210] patnrId=21 SEE MORE PRODUCTS ๋ฒํผ ํ์ ์ฌ๋ถ
const [hasSeeMoreProducts, setHasSeeMoreProducts] = useState(false);
+ const [seeMoreProductsData, setSeeMoreProductsData] = useState([]);
const reviewTotalCount = stats.totalReviews;
@@ -1346,8 +1348,25 @@ export default function ProductAllSection({
console.log(` - Price: ${product.priceInfo}`);
console.log(` - Brand: ${product.brndNm || 'N/A'}`);
});
+
+ // ๐ SeeMoreProducts ์ปดํฌ๋ํธ๋ฅผ ์ํ ๋ฐ์ดํฐ ๋ณํ
+ const formattedProducts = otherProducts.map(product => ({
+ prdtId: product.prdtId,
+ prdtNm: product.prdtNm,
+ priceInfo: product.priceInfo,
+ patncNm: foundConts.patncNm,
+ patnrId: foundConts.patnrId,
+ brndNm: product.brndNm,
+ imgUrl: product.prdtImgUrl,
+ lgCatCd: product.lgCatCd,
+ offerInfo: product.offerInfo,
+ }));
+
+ // YouMayAlsoLike ๋ฐ์ดํฐ ํ์์ผ๋ก ๋ง์ถ๊ธฐ
+ setSeeMoreProductsData(formattedProducts);
} else {
console.log('[SEE MORE PRODUCTS] โ No other products in group - hiding button');
+ setSeeMoreProductsData([]);
}
} else {
console.log('[SEE MORE PRODUCTS] โ No group found for current product - hiding button');
@@ -2060,11 +2079,12 @@ export default function ProductAllSection({
- {/* TODO: ๋์ค์ ๊ทธ๋ฃน ์ํ ํ์ ์ปดํฌ๋ํธ ์ถ๊ฐ */}
-
-
SEE MORE PRODUCTS
-
๊ทธ๋ฃน ์ํ์ด ์ฌ๊ธฐ์ ํ์๋ ์์ ์
๋๋ค
-
+
handleButtonFocus('seemoreproducts')}
+ onBlur={handleButtonBlur}
+ />
)}
diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.jsx
new file mode 100644
index 00000000..ed5c7357
--- /dev/null
+++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.jsx
@@ -0,0 +1,197 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+
+import { useDispatch, useSelector } from 'react-redux';
+
+import { Job } from '@enact/core/util';
+import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
+import Spottable from '@enact/spotlight/Spottable';
+
+import { clearThemeDetail } from '../../../../actions/homeActions';
+import { finishModalMediaForce } from '../../../../actions/mediaActions';
+import { popPanel, pushPanel, updatePanel } from '../../../../actions/panelActions';
+import { finishVideoPreview } from '../../../../actions/playActions';
+import THeader from '../../../../components/THeader/THeader';
+import TItemCardNew from '../../../../components/TItemCard/TItemCard.new';
+import TVerticalPagenator from '../../../../components/TVerticalPagenator/TVerticalPagenator';
+import useScrollTo from '../../../../hooks/useScrollTo';
+import { LOG_CONTEXT_NAME, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config';
+import { $L } from '../../../../utils/helperMethods';
+import css from './SeeMoreProducts.module.less';
+
+const SpottableComponent = Spottable('div');
+
+const Container = SpotlightContainerDecorator(
+ {
+ enterTo: 'last-focused',
+ leaveFor: {
+ left: 'spotlight-product-info-section-container',
+ },
+ },
+ 'div'
+);
+
+export default function SeeMoreProducts({
+ groupProducts,
+ panelInfo,
+ onFocus,
+ onBlur,
+}) {
+ const { getScrollTo, scrollLeft } = useScrollTo();
+ const [newGroupProductData, setNewGroupProductData] = useState([]);
+ const dispatch = useDispatch();
+ const focusedContainerIdRef = useRef(null);
+
+ const panels = useSelector((state) => state.panels.panels);
+ const themeProductInfos = useSelector((state) => state.home.themeCurationDetailInfoData);
+
+ const launchedFromPlayer = useMemo(() => {
+ const detailPanelIndex = panels.findIndex(({ name }) => name === 'detailpanel');
+ const playerPanelIndex = panels.findIndex(({ name }) => name === 'playerpanel');
+
+ return detailPanelIndex - 1 === playerPanelIndex;
+ }, [panels]);
+
+ const onFocusedContainerId = useCallback((containerId) => {
+ focusedContainerIdRef.current = containerId;
+ }, []);
+
+ const _onFocus = useCallback(() => {
+ if (onFocus) {
+ onFocus();
+ }
+ }, [onFocus]);
+
+ const _onBlur = useCallback(() => {
+ if (onBlur) {
+ onBlur();
+ }
+ }, [onBlur]);
+
+ // ๊ทธ๋ฃน ์ํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ (YOU MAY ALSO LIKE์ ๋์ผ ๋ก์ง)
+ useEffect(() => {
+ console.log('[SeeMoreProducts] ๊ทธ๋ฃน ์ํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ:', {
+ originalData: groupProducts,
+ originalLength: groupProducts?.length || 0,
+ hasData: !!(groupProducts && groupProducts.length > 0)
+ });
+
+ if (groupProducts && groupProducts.length > 0) {
+ // ์ต๋ 9๊ฐ๋ก ์ ํ (YOU MAY ALSO LIKE์ ๋์ผ)
+ const processedData = groupProducts.length > 9
+ ? groupProducts.slice(0, groupProducts.length - 1)
+ : groupProducts;
+
+ console.log('[SeeMoreProducts] ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์ค์ :', {
+ processedLength: processedData.length,
+ processedData
+ });
+ setNewGroupProductData(processedData);
+ } else {
+ console.log('[SeeMoreProducts] ๋ฐ์ดํฐ ์์ - ๋น ๋ฐฐ์ด ์ค์ ');
+ setNewGroupProductData([]);
+ }
+ }, [groupProducts]);
+
+ const cursorOpen = useRef(new Job((func) => func(), 1000));
+
+ return (
+
+ {newGroupProductData && newGroupProductData.length > 0 && (
+
+
+
+
+ {newGroupProductData?.map((product, index) => {
+ const {
+ imgUrl: prdtImgUrl, // ์ด๋ฏธ์ง URL ๋ณ๊ฒฝ
+ patnrId,
+ prdtId,
+ prdtNm,
+ priceInfo,
+ offerInfo,
+ patncNm,
+ brndNm,
+ lgCatCd,
+ euEnrgLblInfos,
+ } = product;
+
+ const handleItemClick = () => {
+ console.log('[SeeMoreProducts] ์ํ ํด๋ฆญ:', product);
+
+ // Promise ์ฒด์ด๋์ผ๋ก ์์ ๋ณด์ฅ (YOU MAY ALSO LIKE์ ๋์ผ)
+ Promise.resolve()
+ .then(() => {
+ // 1. ๊ธฐ์กด ๋น๋์ค ๊ฐ์ ์ข
๋ฃ
+ dispatch(finishVideoPreview());
+ dispatch(finishModalMediaForce());
+
+ if (themeProductInfos && themeProductInfos.length > 0) {
+ dispatch(clearThemeDetail());
+ }
+ })
+ .then(() => {
+ // 2. ๋น๋์ค ์ข
๋ฃ ํ ์๋ก์ด ์ํ์ผ๋ก ์
๋ฐ์ดํธ
+ dispatch(
+ updatePanel({
+ name: panel_names.DETAIL_PANEL,
+ panelInfo: {
+ showNm: panelInfo?.showNm,
+ showId: panelInfo?.showId,
+ liveFlag: panelInfo?.liveFlag,
+ thumbnailUrl: panelInfo?.thumbnailUrl,
+ patnrId,
+ prdtId,
+ launchedFromPlayer: launchedFromPlayer,
+ fromPanel: {
+ fromSeeMoreProducts: true, // ๐ SeeMoreProducts์์ ์ ํ๋ ์ํ์์ ํ์
+ },
+ },
+ })
+ );
+ cursorOpen.current.stop();
+ });
+ };
+
+ // prdtId๊ฐ ์๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ ์์ ์ ์ธ key ์์ฑ
+ const itemKey = prdtId ? `${patnrId}-${prdtId}` : `see-more-product-${index}`;
+
+ // ๐ [251210] TItemCardNew์ spotlightId์ spottable ์ค์ ์ถ๊ฐ
+ return (
+
+ );
+ })}
+
+
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.module.less b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.module.less
new file mode 100644
index 00000000..fea0513d
--- /dev/null
+++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/SeeMoreProducts/SeeMoreProducts.module.less
@@ -0,0 +1,106 @@
+@import "../../../../style/CommonStyle.module.less";
+@import "../../../../style/utils.module.less";
+
+// .container {
+// .size(@w: 874px,@h:500px);
+
+// .itemWrapper {
+// .size(@w: 874px,@h:500px);
+// .item {
+// .size(@w: 300px,@h:300px);
+// }
+// }
+// }
+
+.tVerticalPagenator {
+ .size(@w: 1114px, @h: auto); // ๋ง์ง ํฌํจ ์ ์ฒด ํฌ๊ธฐ (1054px + 60px)
+ max-width: 1114px;
+ // padding-left: 30px; // ์ข์ธก 30px ๋ง์ง
+ // padding-right: 30px; // ์ฐ์ธก 30px ๋ง์ง
+ box-sizing: border-box;
+
+ // .sectionTitle {
+ // .font(@fontFamily: @baseFont, @fontSize: 30px);
+ // min-height: 56px;
+ // font-weight: 700;
+ // color: rgba(234, 234, 234, 1);
+ // // margin: 30px 0 20px 0;
+ // }
+ .tHeader {
+ background: transparent;
+ .size(@w: 1144px, @h: 36px); // ๋ง์ง ์ ์ธ ์ฝํ
์ธ ํฌ๊ธฐ
+ max-width: 1144px;
+ margin-bottom: 20px;
+
+ > div {
+ .size(@w:100%,@h:100%);
+ padding: 0;
+ }
+ .averageOverallRating {
+ .size(@w: 176px,@h:30px);
+ }
+
+ span {
+ font-size: 30px;
+ font-weight: 700;
+ height: 36px;
+ color: rgba(234, 234, 234, 1);
+ }
+ }
+
+ .container {
+ width: 100%;
+ .flex(@direction:column,@alignCenter:flex-start);
+ flex-wrap: wrap;
+ margin-top: 34px;
+ // > div {
+ // margin: 0 15px 15px 0;
+ // }
+
+ .renderCardContainer {
+ width: 1144px;
+ display: flex;
+ flex-wrap: wrap;
+ // margin-top: 34px;
+ > div.itemCardNew {
+ /* item card */
+ margin: 0 15px 15px 0;
+ .size(@w:360px,@h:494px);
+ background-color: rgba(51, 51, 51, 0.95);
+ border: none;
+
+ > div:nth-child(1) {
+ /* img wrapper*/
+ .size(@w:323px,@h:323px);
+
+ > img {
+ .size(@w:100%,@h:100%);
+ }
+ }
+
+ > div:nth-child(2) {
+ margin-top: 15px;
+ /* desc wrapper */
+ > div > div > h3 {
+ /* title */
+ color: rgba(234, 234, 234, 1);
+ .size(@w:100%,@h:64px);
+ line-height: 31px;
+ }
+ > p {
+ /* priceInfo */
+ height: 43px;
+ text-align: center;
+
+ > span {
+ font-size: 24px;
+ }
+ }
+ }
+ // width: 100%;
+ // padding-left: 60px;
+ // overflow: unset;
+ }
+ }
+ }
+}