From d3117351c0dedce50c5f7c89d417a7d02ca13555 Mon Sep 17 00:00:00 2001 From: optrader Date: Sat, 11 Oct 2025 22:04:25 +0900 Subject: [PATCH] =?UTF-8?q?[251011]=20fix:=20ProudctAllSection=20scroller?= =?UTF-8?q?=20=EB=A6=AC=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=B5=9C=EC=A0=81?= =?UTF-8?q?=ED=99=94-3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ• ์ปค๋ฐ‹ ์‹œ๊ฐ„: 2025. 10. 11. 22:04:23 ๐Ÿ“Š ๋ณ€๊ฒฝ ํ†ต๊ณ„: โ€ข ์ด ํŒŒ์ผ: 5๊ฐœ โ€ข ์ถ”๊ฐ€: +123์ค„ โ€ข ์‚ญ์ œ: -102์ค„ ๐Ÿ“ ์ˆ˜์ •๋œ ํŒŒ์ผ: ~ com.twin.app.shoptime/src/actions/playActions.js ~ com.twin.app.shoptime/src/hooks/useReviews/useReviews.js ~ com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx ~ com.twin.app.shoptime/src/views/UserReview/components/UserReviewItem.jsx ๐Ÿ”ง ํ•จ์ˆ˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ: ๐Ÿ“„ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx (javascript): ๐Ÿ”„ Modified: Spottable() ๐Ÿ”ง ์ฃผ์š” ๋ณ€๊ฒฝ ๋‚ด์šฉ: โ€ข ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ฐœ์„  โ€ข UI ์ปดํฌ๋„ŒํŠธ ์•„ํ‚คํ…์ฒ˜ ๊ฐœ์„  --- .../src/actions/playActions.js | 3 +- .../src/hooks/useReviews/useReviews.js | 408 +++++++++++------- .../src/views/DetailPanel/DetailPanel.jsx | 230 ++++------ .../ProductVideo/ProductVideo.jsx | 38 +- .../UserReview/components/UserReviewItem.jsx | 86 ++-- 5 files changed, 393 insertions(+), 372 deletions(-) diff --git a/com.twin.app.shoptime/src/actions/playActions.js b/com.twin.app.shoptime/src/actions/playActions.js index 564a3485..0c6524fd 100644 --- a/com.twin.app.shoptime/src/actions/playActions.js +++ b/com.twin.app.shoptime/src/actions/playActions.js @@ -31,7 +31,8 @@ export const startVideoPlayer = const topPanel = panels[panels.length - 1]; let panelWorkingAction = pushPanel; - const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL; + // const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL; + const panelName = panel_names.PLAYER_PANEL; if (topPanel && topPanel.name === panelName) { panelWorkingAction = updatePanel; diff --git a/com.twin.app.shoptime/src/hooks/useReviews/useReviews.js b/com.twin.app.shoptime/src/hooks/useReviews/useReviews.js index 5dc0a7d1..7eec359c 100644 --- a/com.twin.app.shoptime/src/hooks/useReviews/useReviews.js +++ b/com.twin.app.shoptime/src/hooks/useReviews/useReviews.js @@ -4,17 +4,17 @@ import { getUserReviews } from '../../actions/productActions'; import fp from '../../utils/fp'; const DISPLAY_SIZE = 3; // ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ -const STEP_SIZE = 1; // ํŽ˜์ด์ง• ์‹œ ์ด๋™ํ•  ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ +const STEP_SIZE = 1; // ํŽ˜์ด์ง• ์‹œ ์ด๋™ํ•  ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ const useReviews = (prdtId, patnrId) => { const dispatch = useDispatch(); // Redux ์ƒํƒœ์—์„œ ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ - CustomerImages์™€ ๋™์ผํ•œ ๋ฐฉ์‹ - const reviewData = useSelector(state => state.product.reviewData); - const loadedPrdtId = useSelector(state => state.product.loadedPrdtId); + const reviewData = useSelector((state) => state.product.reviewData); + const loadedPrdtId = useSelector((state) => state.product.loadedPrdtId); // ๋นˆ ๋‚ด์šฉ ๋ฆฌ๋ทฐ ํ•„ํ„ฐ๋ง - ์˜๋ฏธ์žˆ๋Š” ๋ฆฌ๋ทฐ๋งŒ ํ‘œ์‹œ - const allReviews = (reviewData?.reviewList || []).filter(review => { + const allReviews = (reviewData?.reviewList || []).filter((review) => { const content = review.rvwCtnt?.trim(); return content && content.length > 0; }); @@ -22,21 +22,21 @@ const useReviews = (prdtId, patnrId) => { const reviewDetail = reviewData?.reviewDetail || {}; // [useReviews] Redux ์ƒํƒœ ํ™•์ธ ๋กœ๊ทธ - console.log('[useReviews] Redux ์ƒํƒœ ํ™•์ธ:', { - prdtId, - patnrId, - hasReviewData: !!reviewData, - reviewDataKeys: reviewData ? Object.keys(reviewData) : [], - reviewListLength: (reviewData && reviewData.reviewList) ? reviewData.reviewList.length : 0, - reviewDetail: reviewData ? reviewData.reviewDetail : null, - fullReviewData: reviewData - }); + // console.log('[useReviews] Redux ์ƒํƒœ ํ™•์ธ:', { + // prdtId, + // patnrId, + // hasReviewData: !!reviewData, + // reviewDataKeys: reviewData ? Object.keys(reviewData) : [], + // reviewListLength: (reviewData && reviewData.reviewList) ? reviewData.reviewList.length : 0, + // reviewDetail: reviewData ? reviewData.reviewDetail : null, + // fullReviewData: reviewData + // }); // ๋กœ์ปฌ ์ƒํƒœ ๊ด€๋ฆฌ const [currentPage, setCurrentPage] = useState(0); const [currentFilter, setCurrentFilter] = useState({ - type: 'rating', // 'rating', 'keyword', 'sentiment' - value: 'all' // 'all', 1-5, 'positive', 'negative', 'aroma' ๋“ฑ + type: 'rating', // 'rating', 'keyword', 'sentiment' + value: 'all', // 'all', 1-5, 'positive', 'negative', 'aroma' ๋“ฑ }); const [isLoading, setIsLoading] = useState(false); const [hasLoadedData, setHasLoadedData] = useState(false); @@ -59,14 +59,14 @@ const useReviews = (prdtId, patnrId) => { return; } - console.log('[useReviews] loadReviews ์‹œ์ž‘:', { prdtId, patnrId }); + // console.log('[useReviews] loadReviews ์‹œ์ž‘:', { prdtId, patnrId }); setIsLoading(true); try { // Redux action์„ ํ†ตํ•ด API ํ˜ธ์ถœ - patnrId ์ถ”๊ฐ€ await dispatch(getUserReviews({ prdtId, patnrId })); setHasLoadedData(true); - console.log('[useReviews] loadReviews ์™„๋ฃŒ'); + // console.log('[useReviews] loadReviews ์™„๋ฃŒ'); } catch (error) { console.error('[useReviews] loadReviews ์‹คํŒจ:', error); } finally { @@ -77,17 +77,17 @@ const useReviews = (prdtId, patnrId) => { // prdtId๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์ž๋™์œผ๋กœ ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ (์‹ฑ๊ธ€ํ†ค ํŒจํ„ด) useEffect(() => { if (prdtId && patnrId && prdtId !== loadedPrdtId) { - console.log('[useReviews] prdtId changed, loading new data:', { - from: loadedPrdtId, - to: prdtId, - patnrId - }); + // console.log('[useReviews] prdtId changed, loading new data:', { + // from: loadedPrdtId, + // to: prdtId, + // patnrId + // }); // prdtId ๋ณ€๊ฒฝ ์‹œ ๋กœ๋”ฉ ์ƒํƒœ ์ฆ‰์‹œ ์„ค์ •์œผ๋กœ UI ๊นœ๋นก์ž„ ๋ฐฉ์ง€ setIsLoading(true); setHasLoadedData(false); loadReviews(); } else if (prdtId === loadedPrdtId) { - console.log('[useReviews] Using cached data for same prdtId:', { prdtId, patnrId }); + // console.log('[useReviews] Using cached data for same prdtId:', { prdtId, patnrId }); setHasLoadedData(true); // ์บ์‹œ๋œ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ ์‹œ ๋กœ๋“œ ์™„๋ฃŒ ์ƒํƒœ๋กœ ์„ค์ • } }, [prdtId, patnrId, loadedPrdtId, loadReviews]); @@ -112,35 +112,103 @@ const useReviews = (prdtId, patnrId) => { if (!sentiment) return true; const positiveWords = new Set([ - 'good', 'great', 'excellent', 'amazing', 'love', 'perfect', 'best', - 'wonderful', 'fantastic', 'awesome', 'outstanding', 'superb', 'brilliant', - 'positive', 'happy', 'satisfied', 'pleased', 'delightful', 'enjoyed', - 'recommend', 'nice', 'helpful', 'valuable', 'impressive', 'remarkable', - 'favorite', 'friendly', 'comfortable', 'smooth', 'reliable', 'incredible', - 'lovely', 'beautiful', 'fun', 'worthwhile', 'useful' + 'good', + 'great', + 'excellent', + 'amazing', + 'love', + 'perfect', + 'best', + 'wonderful', + 'fantastic', + 'awesome', + 'outstanding', + 'superb', + 'brilliant', + 'positive', + 'happy', + 'satisfied', + 'pleased', + 'delightful', + 'enjoyed', + 'recommend', + 'nice', + 'helpful', + 'valuable', + 'impressive', + 'remarkable', + 'favorite', + 'friendly', + 'comfortable', + 'smooth', + 'reliable', + 'incredible', + 'lovely', + 'beautiful', + 'fun', + 'worthwhile', + 'useful', ]); const negativeWords = new Set([ - 'bad', 'terrible', 'awful', 'hate', 'worst', 'horrible', 'poor', - 'disappointing', 'useless', 'waste', 'cheap', 'broken', 'defective', - 'unhappy', 'unsatisfied', 'frustrating', 'annoying', 'regret', 'slow', - 'ugly', 'overpriced', 'boring', 'uncomfortable', 'noisy', 'buggy', - 'dirty', 'smelly', 'difficult', 'complicated', 'fake', 'flimsy' + 'bad', + 'terrible', + 'awful', + 'hate', + 'worst', + 'horrible', + 'poor', + 'disappointing', + 'useless', + 'waste', + 'cheap', + 'broken', + 'defective', + 'unhappy', + 'unsatisfied', + 'frustrating', + 'annoying', + 'regret', + 'slow', + 'ugly', + 'overpriced', + 'boring', + 'uncomfortable', + 'noisy', + 'buggy', + 'dirty', + 'smelly', + 'difficult', + 'complicated', + 'fake', + 'flimsy', ]); - const negationWords = new Set(['not', 'no', 'never', "isn't", "wasn't", "don't", "doesn't", "didn't"]); + const negationWords = new Set([ + 'not', + 'no', + 'never', + "isn't", + "wasn't", + "don't", + "doesn't", + "didn't", + ]); const content = (review.rvwCtnt || '').toLowerCase(); if (!content) return false; - const tokens = content.replace(/[^a-z0-9\s'-]/g, ' ').split(/\s+/).filter(Boolean); + const tokens = content + .replace(/[^a-z0-9\s'-]/g, ' ') + .split(/\s+/) + .filter(Boolean); const hasWordWithoutNegation = (wordSet) => { return tokens.some((token, index) => { if (!wordSet.has(token)) return false; const prevTokens = tokens.slice(Math.max(0, index - 3), index); - return !prevTokens.some(prevToken => negationWords.has(prevToken)); + return !prevTokens.some((prevToken) => negationWords.has(prevToken)); }); }; @@ -160,19 +228,19 @@ const useReviews = (prdtId, patnrId) => { return { rating: { all: 0 }, keyword: {}, - sentiment: {} + sentiment: {}, }; } const counts = { rating: { all: allReviews.length }, keyword: {}, - sentiment: {} + sentiment: {}, }; // ๋ณ„์ ๋ณ„ ์นด์šดํŠธ - ์†Œ์ˆ˜์  ๋ณ„์ ์„ ์ •์ˆ˜๋กœ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์นด์šดํŒ… for (let i = 1; i <= 5; i++) { - counts.rating[i] = allReviews.filter(review => { + counts.rating[i] = allReviews.filter((review) => { const rating = review.rvwScr || review.rvwRtng || review.rating || 0; return Math.round(rating) === i; }).length; @@ -180,34 +248,34 @@ const useReviews = (prdtId, patnrId) => { // ํ‚ค์›Œ๋“œ๋ณ„ ์นด์šดํŠธ const keywords = ['aroma', 'vanilla', 'cinnamon', 'quality']; - keywords.forEach(keyword => { - counts.keyword[keyword] = allReviews.filter(review => + keywords.forEach((keyword) => { + counts.keyword[keyword] = allReviews.filter((review) => matchesKeyword(review, keyword) ).length; }); // ๊ฐ์ •๋ณ„ ์นด์šดํŠธ - counts.sentiment.positive = allReviews.filter(review => + counts.sentiment.positive = allReviews.filter((review) => matchesSentiment(review, 'positive') ).length; - counts.sentiment.negative = allReviews.filter(review => + counts.sentiment.negative = allReviews.filter((review) => matchesSentiment(review, 'negative') ).length; // ๋””๋ฒ„๊น…: filterCounts ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ํ™•์ธ - console.log('[useReviews] filterCounts ๊ณ„์‚ฐ ์™„๋ฃŒ:', { - totalReviews: allReviews.length, - ratingCounts: counts.rating, - keywordCounts: counts.keyword, - sentimentCounts: counts.sentiment, - sampleReviews: allReviews.slice(0, 3).map(review => ({ - rvwId: review.rvwId, - rvwScr: review.rvwScr, - rvwRtng: review.rvwRtng, - rating: review.rating, - roundedRating: Math.round(review.rvwScr || review.rvwRtng || review.rating || 0) - })) - }); + // console.log('[useReviews] filterCounts ๊ณ„์‚ฐ ์™„๋ฃŒ:', { + // totalReviews: allReviews.length, + // ratingCounts: counts.rating, + // keywordCounts: counts.keyword, + // sentimentCounts: counts.sentiment, + // sampleReviews: allReviews.slice(0, 3).map(review => ({ + // rvwId: review.rvwId, + // rvwScr: review.rvwScr, + // rvwRtng: review.rvwRtng, + // rating: review.rating, + // roundedRating: Math.round(review.rvwScr || review.rvwRtng || review.rating || 0) + // })) + // }); return counts; }, [allReviews, matchesKeyword, matchesSentiment]); @@ -224,7 +292,7 @@ const useReviews = (prdtId, patnrId) => { if (currentFilter.value === 'all' || currentFilter.value === null) { result = [...allReviews]; // ์ „์ฒด ํ‘œ์‹œ } else { - result = allReviews.filter(review => { + result = allReviews.filter((review) => { const rating = review.rvwScr || review.rvwRtng || review.rating || 0; return Math.round(rating) === currentFilter.value; }); @@ -232,15 +300,11 @@ const useReviews = (prdtId, patnrId) => { break; case 'sentiment': - result = allReviews.filter(review => - matchesSentiment(review, currentFilter.value) - ); + result = allReviews.filter((review) => matchesSentiment(review, currentFilter.value)); break; case 'keyword': - result = allReviews.filter(review => - matchesKeyword(review, currentFilter.value) - ); + result = allReviews.filter((review) => matchesKeyword(review, currentFilter.value)); break; default: @@ -282,44 +346,50 @@ const useReviews = (prdtId, patnrId) => { // ๋‹ค์Œ ์ฒญํฌ ๋กœ๋“œ (ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ํŽ˜์ด์ง€๋งŒ ์ฆ๊ฐ€) const loadMore = useCallback(() => { if (hasMore) { - console.log('[useReviews] loadMore: ๋‹ค์Œ ์ฒญํฌ ๋กœ๋“œ', { - currentPage, - nextPage: currentPage + 1, - currentDisplayCount: displayReviews.length, - totalFilteredCount: filteredReviews.length - }); - setCurrentPage(prev => prev + 1); + // console.log('[useReviews] loadMore: ๋‹ค์Œ ์ฒญํฌ ๋กœ๋“œ', { + // currentPage, + // nextPage: currentPage + 1, + // currentDisplayCount: displayReviews.length, + // totalFilteredCount: filteredReviews.length + // }); + setCurrentPage((prev) => prev + 1); } }, [hasMore, currentPage, displayReviews.length, filteredReviews.length]); // UserReviewPanel ์ „์šฉ ํŽ˜์ด์ง• ํ•จ์ˆ˜๋“ค const goToNextUserReviewPage = useCallback(() => { if (userReviewPanelHasNext) { - console.log('[useReviews] UserReviewPanel ๋‹ค์Œ ํŽ˜์ด์ง€:', { - currentPage: userReviewPanelPage, - nextPage: userReviewPanelPage + 1, - totalPages: userReviewPanelTotalPages, - filteredCount: filteredReviews.length - }); - setUserReviewPanelPage(fp.pipe( - (prev) => prev + 1 - )); + // console.log('[useReviews] UserReviewPanel ๋‹ค์Œ ํŽ˜์ด์ง€:', { + // currentPage: userReviewPanelPage, + // nextPage: userReviewPanelPage + 1, + // totalPages: userReviewPanelTotalPages, + // filteredCount: filteredReviews.length + // }); + setUserReviewPanelPage(fp.pipe((prev) => prev + 1)); } - }, [userReviewPanelHasNext, userReviewPanelPage, userReviewPanelTotalPages, filteredReviews.length]); + }, [ + userReviewPanelHasNext, + userReviewPanelPage, + userReviewPanelTotalPages, + filteredReviews.length, + ]); const goToPrevUserReviewPage = useCallback(() => { if (userReviewPanelHasPrev) { - console.log('[useReviews] UserReviewPanel ์ด์ „ ํŽ˜์ด์ง€:', { - currentPage: userReviewPanelPage, - prevPage: userReviewPanelPage - 1, - totalPages: userReviewPanelTotalPages, - filteredCount: filteredReviews.length - }); - setUserReviewPanelPage(fp.pipe( - (prev) => prev - 1 - )); + // console.log('[useReviews] UserReviewPanel ์ด์ „ ํŽ˜์ด์ง€:', { + // currentPage: userReviewPanelPage, + // prevPage: userReviewPanelPage - 1, + // totalPages: userReviewPanelTotalPages, + // filteredCount: filteredReviews.length + // }); + setUserReviewPanelPage(fp.pipe((prev) => prev - 1)); } - }, [userReviewPanelHasPrev, userReviewPanelPage, userReviewPanelTotalPages, filteredReviews.length]); + }, [ + userReviewPanelHasPrev, + userReviewPanelPage, + userReviewPanelTotalPages, + filteredReviews.length, + ]); // ํ•„ํ„ฐ ๋ณ€๊ฒฝ ์‹œ UserReviewPanel ํŽ˜์ด์ง€๋„ ์ดˆ๊ธฐํ™” useEffect(() => { @@ -328,7 +398,7 @@ const useReviews = (prdtId, patnrId) => { // Single Filter ์ ์šฉ ํ•จ์ˆ˜ const applyFilter = useCallback((type, value) => { - console.log('[useReviews] ํ•„ํ„ฐ ์ ์šฉ:', { type, value }); + // console.log('[useReviews] ํ•„ํ„ฐ ์ ์šฉ:', { type, value }); // ์ด์ „ ํ•„ํ„ฐ ๊ฒฐ๊ณผ ํ•ด์ œ setCurrentFilter({ type, value }); @@ -336,38 +406,48 @@ const useReviews = (prdtId, patnrId) => { }, []); // ํŽธ์˜ ํ•จ์ˆ˜๋“ค (๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค ํ˜ธํ™˜์„ฑ) - const applyRatingFilter = useCallback((rating) => { - console.log('[useReviews] applyRatingFilter called with:', rating); - applyFilter('rating', rating); - }, [applyFilter]); + const applyRatingFilter = useCallback( + (rating) => { + // console.log('[useReviews] applyRatingFilter called with:', rating); + applyFilter('rating', rating); + }, + [applyFilter] + ); - const applySentimentFilter = useCallback((sentiment) => { - applyFilter('sentiment', sentiment); - }, [applyFilter]); + const applySentimentFilter = useCallback( + (sentiment) => { + applyFilter('sentiment', sentiment); + }, + [applyFilter] + ); - const applyKeywordFilter = useCallback((keyword) => { - applyFilter('keyword', keyword); - }, [applyFilter]); + const applyKeywordFilter = useCallback( + (keyword) => { + applyFilter('keyword', keyword); + }, + [applyFilter] + ); // ํ•„ํ„ฐ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ const clearAllFilters = useCallback(() => { - console.log('[useReviews] ๋ชจ๋“  ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”'); + // console.log('[useReviews] ๋ชจ๋“  ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”'); applyFilter('rating', 'all'); }, [applyFilter]); // ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๋ฆฌ๋ทฐ๋“ค๋งŒ ์ถ”๋ ค๋‚ด๋Š” ํ•จ์ˆ˜ const getReviewsWithImages = useMemo(() => { const reviewsWithImages = allReviews.filter( - (review) => review.reviewImageList && - Array.isArray(review.reviewImageList) && - review.reviewImageList.length > 0 + (review) => + review.reviewImageList && + Array.isArray(review.reviewImageList) && + review.reviewImageList.length > 0 ); - console.log('[useReviews] ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๋ฆฌ๋ทฐ ํ•„ํ„ฐ๋ง:', { - totalReviews: allReviews.length, - reviewsWithImages: reviewsWithImages.length, - imageReviews: reviewsWithImages.slice(0, 3) // ์ฒ˜์Œ 3๊ฐœ๋งŒ ๋กœ๊ทธ - }); + // console.log('[useReviews] ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๋ฆฌ๋ทฐ ํ•„ํ„ฐ๋ง:', { + // totalReviews: allReviews.length, + // reviewsWithImages: reviewsWithImages.length, + // imageReviews: reviewsWithImages.slice(0, 3) // ์ฒ˜์Œ 3๊ฐœ๋งŒ ๋กœ๊ทธ + // }); return reviewsWithImages; }, [allReviews]); @@ -387,50 +467,56 @@ const useReviews = (prdtId, patnrId) => { imgUrl, imgSeq: imgSeq || imgIndex + 1, reviewId: review.rvwId, - reviewData: review // ์ „์ฒด ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ๋„ ํฌํ•จ + reviewData: review, // ์ „์ฒด ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ๋„ ํฌํ•จ }); } }); } }); - console.log('[useReviews] ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ์™„๋ฃŒ:', { - totalImages: images.length, - sampleImages: images.slice(0, 3) - }); + // console.log('[useReviews] ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ ์ถ”์ถœ ์™„๋ฃŒ:', { + // totalImages: images.length, + // sampleImages: images.slice(0, 3) + // }); return images; }, [getReviewsWithImages]); // DetailPanel์šฉ - ์ฒ˜์Œ 5๊ฐœ๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ (ํ•„ํ„ฐ๋ง ์•ˆ๋œ ์›๋ณธ์—์„œ) const previewReviews = useMemo(() => { - console.log('[useReviews] previewReviews ๊ณ„์‚ฐ:', { - allReviewsLength: allReviews.length, - previewCount: Math.min(allReviews.length, 5), - prdtId, - hasLoadedData, - isLoading, - reviewData, - allReviews: allReviews.slice(0, 3) - }); + // console.log('[useReviews] previewReviews ๊ณ„์‚ฐ:', { + // allReviewsLength: allReviews.length, + // previewCount: Math.min(allReviews.length, 5), + // prdtId, + // hasLoadedData, + // isLoading, + // reviewData, + // allReviews: allReviews.slice(0, 3) + // }); return allReviews.slice(0, 5); }, [allReviews, prdtId, hasLoadedData, isLoading, reviewData]); // ํ†ต๊ณ„ ์ •๋ณด const stats = useMemo(() => { return { - totalReviews: (reviewDetail && reviewDetail.totRvwCnt) ? reviewDetail.totRvwCnt : allReviews.length, // ์ „์ฒด ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ - filteredCount: filteredReviews.length, // ํ•„ํ„ฐ๋ง๋œ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ - displayedCount: displayReviews.length, // ํ˜„์žฌ ํ‘œ์‹œ ์ค‘์ธ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ - averageRating: (reviewDetail && reviewDetail.totRvwAvg) ? reviewDetail.totRvwAvg : - (reviewDetail && reviewDetail.avgRvwScr) ? reviewDetail.avgRvwScr : 0, - totalRatingCount: (reviewDetail && reviewDetail.totRvwCnt) ? reviewDetail.totRvwCnt : allReviews.length + totalReviews: + reviewDetail && reviewDetail.totRvwCnt ? reviewDetail.totRvwCnt : allReviews.length, // ์ „์ฒด ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ + filteredCount: filteredReviews.length, // ํ•„ํ„ฐ๋ง๋œ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ + displayedCount: displayReviews.length, // ํ˜„์žฌ ํ‘œ์‹œ ์ค‘์ธ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ + averageRating: + reviewDetail && reviewDetail.totRvwAvg + ? reviewDetail.totRvwAvg + : reviewDetail && reviewDetail.avgRvwScr + ? reviewDetail.avgRvwScr + : 0, + totalRatingCount: + reviewDetail && reviewDetail.totRvwCnt ? reviewDetail.totRvwCnt : allReviews.length, }; }, [allReviews.length, filteredReviews.length, displayReviews.length, reviewDetail]); // ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ - ๊ฐ•์ œ๋กœ ๋‹ค์‹œ ๋กœ๋“œ const refreshData = useCallback(() => { - console.log('[useReviews] ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ ์‹œ์ž‘'); + // console.log('[useReviews] ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ ์‹œ์ž‘'); setHasLoadedData(false); // ๊ฐ•์ œ๋กœ ๋‹ค์‹œ ๋กœ๋“œํ•˜๋„๋ก setCurrentPage(0); setCurrentFilter({ type: 'rating', value: 'all' }); // ๊ธฐ๋ณธ ํ•„ํ„ฐ๋กœ ์ดˆ๊ธฐํ™” @@ -439,47 +525,47 @@ const useReviews = (prdtId, patnrId) => { return { // ๐Ÿ”ฅ ํ•ต์‹ฌ API ํ•จ์ˆ˜ - useReviews๊ฐ€ ๋ชจ๋“  API ํ˜ธ์ถœ ๋‹ด๋‹น - loadReviews, // ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ (prdtId ๊ธฐ๋ฐ˜) - refreshData, // ๋ฐ์ดํ„ฐ ๊ฐ•์ œ ์ƒˆ๋กœ๊ณ ์นจ + loadReviews, // ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ (prdtId ๊ธฐ๋ฐ˜) + refreshData, // ๋ฐ์ดํ„ฐ ๊ฐ•์ œ ์ƒˆ๋กœ๊ณ ์นจ // ๐Ÿ“Š ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ - displayReviews, // ํ˜„์žฌ ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๋ฆฌ๋ทฐ๋“ค (์ฒญํ‚น๋œ) - ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ์šฉ - previewReviews, // DetailPanel์šฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ฆฌ๋ทฐ (์ฒซ 5๊ฐœ) - allReviews, // ์ „์ฒด ์›๋ณธ ๋ฆฌ๋ทฐ (ํ•„ํ„ฐ๋ง ์•ˆ๋œ, ๋นˆ ๋‚ด์šฉ ์ œ์™ธ) - filteredReviews, // ํ•„ํ„ฐ๋ง๋œ ์ „์ฒด ๋ฆฌ๋ทฐ + displayReviews, // ํ˜„์žฌ ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๋ฆฌ๋ทฐ๋“ค (์ฒญํ‚น๋œ) - ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ์šฉ + previewReviews, // DetailPanel์šฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ฆฌ๋ทฐ (์ฒซ 5๊ฐœ) + allReviews, // ์ „์ฒด ์›๋ณธ ๋ฆฌ๋ทฐ (ํ•„ํ„ฐ๋ง ์•ˆ๋œ, ๋นˆ ๋‚ด์šฉ ์ œ์™ธ) + filteredReviews, // ํ•„ํ„ฐ๋ง๋œ ์ „์ฒด ๋ฆฌ๋ทฐ hasReviews: allReviews.length > 0 && hasLoadedData && !isLoading && isCurrentProductLoaded, // ๋ฆฌ๋ทฐ ์กด์žฌ ์—ฌ๋ถ€ (ํ˜„์žฌ ์ œํ’ˆ์ด ๋กœ๋“œ๋œ ๊ฒฝ์šฐ์—๋งŒ true) // ๐Ÿ”„ UserReviewPanel ์ „์šฉ ํŽ˜์ด์ง• ๋ฐ์ดํ„ฐ - userReviewPanelReviews, // UserReviewPanel์šฉ ํŽ˜์ด์ง•๋œ ๋ฆฌ๋ทฐ๋“ค (3๊ฐœ ํ‘œ์‹œ, 1๊ฐœ์”ฉ ์ด๋™) - userReviewPanelPage, // ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘) - userReviewPanelHasNext, // ๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€ - userReviewPanelHasPrev, // ์ด์ „ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€ + userReviewPanelReviews, // UserReviewPanel์šฉ ํŽ˜์ด์ง•๋œ ๋ฆฌ๋ทฐ๋“ค (3๊ฐœ ํ‘œ์‹œ, 1๊ฐœ์”ฉ ์ด๋™) + userReviewPanelPage, // ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘) + userReviewPanelHasNext, // ๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€ + userReviewPanelHasPrev, // ์ด์ „ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€ userReviewPanelTotalPages, // ์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜ - goToNextUserReviewPage, // ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ - goToPrevUserReviewPage, // ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ + goToNextUserReviewPage, // ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ + goToPrevUserReviewPage, // ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ // ๐Ÿ–ผ๏ธ ์ด๋ฏธ์ง€ ๊ด€๋ จ ๋ฐ์ดํ„ฐ - CustomerImages ์ „์šฉ - getReviewsWithImages, // ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๋ฆฌ๋ทฐ๋“ค๋งŒ ํ•„ํ„ฐ๋ง + getReviewsWithImages, // ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๋ฆฌ๋ทฐ๋“ค๋งŒ ํ•„ํ„ฐ๋ง extractImagesFromReviews, // ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœ (reviewData ํฌํ•จ) // ๐Ÿ“„ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ํŽ˜์ด์ง€๋„ค์ด์…˜ - hasMore, // ๋” ๋กœ๋“œํ•  ๋ฆฌ๋ทฐ๊ฐ€ ์žˆ๋Š”์ง€ - loadMore, // ๋‹ค์Œ ์ฒญํฌ ํ‘œ์‹œ (ํด๋ผ์ด์–ธํŠธ์—์„œ ์Šฌ๋ผ์ด์‹ฑ) - currentPage, // ํ˜„์žฌ ํŽ˜์ด์ง€ (0๋ถ€ํ„ฐ ์‹œ์ž‘) + hasMore, // ๋” ๋กœ๋“œํ•  ๋ฆฌ๋ทฐ๊ฐ€ ์žˆ๋Š”์ง€ + loadMore, // ๋‹ค์Œ ์ฒญํฌ ํ‘œ์‹œ (ํด๋ผ์ด์–ธํŠธ์—์„œ ์Šฌ๋ผ์ด์‹ฑ) + currentPage, // ํ˜„์žฌ ํŽ˜์ด์ง€ (0๋ถ€ํ„ฐ ์‹œ์ž‘) // ๐Ÿ” ํ•„ํ„ฐ๋ง ์‹œ์Šคํ…œ - currentFilter, // ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํ•„ํ„ฐ { type, value } - filterCounts, // ๊ฐ ํ•„ํ„ฐ๋ณ„ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ (์‹ค์‹œ๊ฐ„ ๊ณ„์‚ฐ) - applyFilter, // ํ†ตํ•ฉ ํ•„ํ„ฐ ์ ์šฉ ํ•จ์ˆ˜ - applyRatingFilter, // ๋ณ„์  ํ•„ํ„ฐ ์ ์šฉ - applyKeywordFilter, // ํ‚ค์›Œ๋“œ ํ•„ํ„ฐ ์ ์šฉ - applySentimentFilter, // ๊ฐ์ • ํ•„ํ„ฐ ์ ์šฉ - clearAllFilters, // ๋ชจ๋“  ํ•„ํ„ฐ ์ดˆ๊ธฐํ™” + currentFilter, // ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํ•„ํ„ฐ { type, value } + filterCounts, // ๊ฐ ํ•„ํ„ฐ๋ณ„ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ (์‹ค์‹œ๊ฐ„ ๊ณ„์‚ฐ) + applyFilter, // ํ†ตํ•ฉ ํ•„ํ„ฐ ์ ์šฉ ํ•จ์ˆ˜ + applyRatingFilter, // ๋ณ„์  ํ•„ํ„ฐ ์ ์šฉ + applyKeywordFilter, // ํ‚ค์›Œ๋“œ ํ•„ํ„ฐ ์ ์šฉ + applySentimentFilter, // ๊ฐ์ • ํ•„ํ„ฐ ์ ์šฉ + clearAllFilters, // ๋ชจ๋“  ํ•„ํ„ฐ ์ดˆ๊ธฐํ™” // โšก ์ƒํƒœ ๊ด€๋ฆฌ - isLoading, // API ๋กœ๋”ฉ ์ƒํƒœ - hasLoadedData, // ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์™„๋ฃŒ ์—ฌ๋ถ€ - stats, // ํ†ต๊ณ„ ์ •๋ณด + isLoading, // API ๋กœ๋”ฉ ์ƒํƒœ + hasLoadedData, // ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์™„๋ฃŒ ์—ฌ๋ถ€ + stats, // ํ†ต๊ณ„ ์ •๋ณด // ๐Ÿ› ๋””๋ฒ„๊ทธ ์ •๋ณด _debug: { @@ -492,9 +578,9 @@ const useReviews = (prdtId, patnrId) => { currentPage, hasMore, isLoading, - hasLoadedData - } + hasLoadedData, + }, }; }; -export default useReviews; \ No newline at end of file +export default useReviews; diff --git a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx index e1068b02..9764f561 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx @@ -1,47 +1,24 @@ // src/views/DetailPanel/DetailPanel.new.jsx -import React, { - useCallback, - useEffect, - useLayoutEffect, - useMemo, - useRef, - useState, -} from 'react'; +import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; -import { - useDispatch, - useSelector, -} from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import Spinner from '@enact/sandstone/Spinner'; import Spotlight from '@enact/spotlight'; import { setContainerLastFocusedElement } from '@enact/spotlight/src/container'; -import indicatorDefaultImage - from '../../../assets/images/img-thumb-empty-144@3x.png'; +import indicatorDefaultImage from '../../../assets/images/img-thumb-empty-144@3x.png'; import { getDeviceAdditionInfo } from '../../actions/deviceActions'; import { getThemeCurationDetailInfo } from '../../actions/homeActions'; -import { - getMainCategoryDetail, - getMainYouMayLike, -} from '../../actions/mainActions'; -import { - popPanel, - updatePanel, -} from '../../actions/panelActions'; +import { getMainCategoryDetail, getMainYouMayLike } from '../../actions/mainActions'; +import { popPanel, updatePanel } from '../../actions/panelActions'; import { finishVideoPreview } from '../../actions/playActions'; -import { - clearProductDetail, - getProductOptionId, -} from '../../actions/productActions'; +import { clearProductDetail, getProductOptionId } from '../../actions/productActions'; import TBody from '../../components/TBody/TBody'; import TPanel from '../../components/TPanel/TPanel'; import { panel_names } from '../../utils/Config'; import fp from '../../utils/fp'; -import { - $L, - getQRCodeUrl, -} from '../../utils/helperMethods'; +import { $L, getQRCodeUrl } from '../../utils/helperMethods'; import { SpotlightIds } from '../../utils/SpotlightIds'; import DetailPanelBackground from './components/DetailPanelBackground'; import THeaderCustom from './components/THeaderCustom'; @@ -55,68 +32,49 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { const productData = useSelector((state) => state.main.productData); const youmaylikeData = useSelector((state) => state.main.youmaylikeData); - const themeProductInfos = useSelector( - (state) => state.home.themeCurationDetailInfoData - ); + const themeProductInfos = useSelector((state) => state.home.themeCurationDetailInfoData); const isLoading = useSelector((state) => - fp.pipe(() => state, fp.get("common.appStatus.showLoadingPanel.show"))() + fp.pipe(() => state, fp.get('common.appStatus.showLoadingPanel.show'))() ); const themeData = useSelector((state) => fp.pipe( () => state, - fp.get("home.productData.themeInfo"), + fp.get('home.productData.themeInfo'), (list) => list && list[0] )() ); - const webOSVersion = useSelector( - (state) => state.common.appStatus.webOSVersion - ); + const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion); const panels = useSelector((state) => state.panels.panels); - // FP ๋ฐฉ์‹์œผ๋กœ ์ƒํƒœ ๊ด€๋ฆฌ const [selectedIndex, setSelectedIndex] = useState(0); const localRecentItems = useSelector((state) => - fp.pipe(() => state, fp.get("localSettings.recentItems"))() + fp.pipe(() => state, fp.get('localSettings.recentItems'))() ); const { httpHeader } = useSelector((state) => state.common); - const { popupVisible, activePopup } = useSelector( - (state) => state.common.popup - ); - const [lgCatCd, setLgCatCd] = useState(""); + const { popupVisible, activePopup } = useSelector((state) => state.common.popup); + const [lgCatCd, setLgCatCd] = useState(''); const [themeProductInfo, setThemeProductInfo] = useState(null); const containerRef = useRef(null); - const panelType = useMemo( - () => fp.pipe(() => panelInfo, fp.get("type"))(), - [panelInfo] - ); + const panelType = useMemo(() => fp.pipe(() => panelInfo, fp.get('type'))(), [panelInfo]); const panelCurationId = useMemo( - () => fp.pipe(() => panelInfo, fp.get("curationId"))(), - [panelInfo] - ); - const panelPatnrId = useMemo( - () => fp.pipe(() => panelInfo, fp.get("patnrId"))(), - [panelInfo] - ); - const panelPrdtId = useMemo( - () => fp.pipe(() => panelInfo, fp.get("prdtId"))(), + () => fp.pipe(() => panelInfo, fp.get('curationId'))(), [panelInfo] ); + const panelPatnrId = useMemo(() => fp.pipe(() => panelInfo, fp.get('patnrId'))(), [panelInfo]); + const panelPrdtId = useMemo(() => fp.pipe(() => panelInfo, fp.get('prdtId'))(), [panelInfo]); const panelLiveReqFlag = useMemo( - () => fp.pipe(() => panelInfo, fp.get("liveReqFlag"))(), - [panelInfo] - ); - const panelBgImgNo = useMemo( - () => fp.pipe(() => panelInfo, fp.get("bgImgNo"))(), + () => fp.pipe(() => panelInfo, fp.get('liveReqFlag'))(), [panelInfo] ); + const panelBgImgNo = useMemo(() => fp.pipe(() => panelInfo, fp.get('bgImgNo'))(), [panelInfo]); const productPmtSuptYn = useMemo( - () => fp.pipe(() => productData, fp.get("pmtSuptYn"))(), + () => fp.pipe(() => productData, fp.get('pmtSuptYn'))(), [productData] ); const productGrPrdtProcYn = useMemo( - () => fp.pipe(() => productData, fp.get("grPrdtProcYn"))(), + () => fp.pipe(() => productData, fp.get('grPrdtProcYn'))(), [productData] ); @@ -124,7 +82,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { () => fp.pipe( () => panelType, - (type) => (type === "theme" ? themeData : productData) + (type) => (type === 'theme' ? themeData : productData) )(), [panelType, themeData, productData] ); @@ -132,11 +90,9 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { const [productType, setProductType] = useState(null); const [openThemeItemOverlay, setOpenThemeItemOverlay] = useState(false); - // FP ๋ฐฉ์‹์œผ๋กœ ์Šคํฌ๋กค ์ƒํƒœ ๊ด€๋ฆฌ const [scrollToSection, setScrollToSection] = useState(null); const [pendingScrollSection, setPendingScrollSection] = useState(null); - // FP ๋ฐฉ์‹์œผ๋กœ ์ƒํƒœ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜๋“ค const updateSelectedIndex = useCallback((newIndex) => { setSelectedIndex( fp.pipe( @@ -150,15 +106,13 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { setOpenThemeItemOverlay(fp.pipe(() => isOpen, Boolean)()); }, []); - // FP ๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ •์˜ const onSpotlightUpTButton = useCallback((e) => { e.stopPropagation(); - Spotlight.focus("spotlightId_backBtn"); + Spotlight.focus('spotlightId_backBtn'); }, []); const onClick = useCallback( (isCancelClick) => (ev) => { - // FP ๋ฐฉ์‹์œผ๋กœ ์•ก์…˜ ๋””์ŠคํŒจ์น˜ ์ฒด์ด๋‹ fp.pipe( () => { dispatch(finishVideoPreview()); @@ -169,12 +123,12 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { const shouldUpdatePanel = fp.pipe( () => panels, - fp.get("length"), + fp.get('length'), (length) => length === 4 )() && fp.pipe( () => panels, - fp.get("1.name"), + fp.get('1.name'), (name) => name === panel_names.PLAYER_PANEL )(); @@ -183,7 +137,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { updatePanel({ name: panel_names.PLAYER_PANEL, panelInfo: { - thumbnail: fp.pipe(() => panelInfo, fp.get("thumbnailUrl"))(), + thumbnail: fp.pipe(() => panelInfo, fp.get('thumbnailUrl'))(), }, }) ); @@ -198,35 +152,31 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { [dispatch, panelInfo, panels] ); - // FP ๋ฐฉ์‹์œผ๋กœ ์Šคํฌ๋กค ํ•จ์ˆ˜ ํ•ธ๋“ค๋Ÿฌ const handleScrollToSection = useCallback( (sectionId) => { - console.log("DetailPanel: handleScrollToSection called with:", sectionId); - console.log("DetailPanel: scrollToSection function:", scrollToSection); + console.log('DetailPanel: handleScrollToSection called with:', sectionId); + console.log('DetailPanel: scrollToSection function:', scrollToSection); - // FP ๋ฐฉ์‹์œผ๋กœ ์Šคํฌ๋กค ์ฒ˜๋ฆฌ ๋กœ์ง const scrollAction = fp.pipe( () => ({ scrollToSection, sectionId }), ({ scrollToSection, sectionId }) => { if (fp.isNotNil(scrollToSection)) { return { - action: "execute", + action: 'execute', scrollFunction: scrollToSection, sectionId, }; } else { - return { action: "store", sectionId }; + return { action: 'store', sectionId }; } } )(); // ์•ก์…˜์— ๋”ฐ๋ฅธ ์ฒ˜๋ฆฌ - if (scrollAction.action === "execute") { + if (scrollAction.action === 'execute') { scrollAction.scrollFunction(scrollAction.sectionId); } else { - console.log( - "DetailPanel: scrollToSection function is null, storing pending scroll" - ); + console.log('DetailPanel: scrollToSection function is null, storing pending scroll'); setPendingScrollSection(scrollAction.sectionId); } }, @@ -236,7 +186,6 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // ===== ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์„ค์ • (์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด useEffect ๋ถˆํ•„์š”) ===== // DetailPanelBackground ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐฐ๊ฒฝ ๋ Œ๋”๋ง - // FP ๋ฐฉ์‹์œผ๋กœ pending scroll ์ฒ˜๋ฆฌ (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) useEffect(() => { const shouldExecutePendingScroll = fp.pipe( () => ({ scrollToSection, pendingScrollSection }), @@ -245,10 +194,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { )(); if (shouldExecutePendingScroll) { - console.log( - "DetailPanel: executing pending scroll to:", - pendingScrollSection - ); + console.log('DetailPanel: executing pending scroll to:', pendingScrollSection); // ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ cleanup ํ•จ์ˆ˜ const timeoutId = setTimeout(() => { @@ -265,9 +211,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { } }, [scrollToSection, pendingScrollSection]); - // FP ๋ฐฉ์‹์œผ๋กœ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์ฒ˜๋ฆฌ (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) useEffect(() => { - // FP ๋ฐฉ์‹์œผ๋กœ ์•ก์…˜ ๋””์ŠคํŒจ์น˜ ์ฒด์ด๋‹ const loadInitialData = fp.pipe( () => { // ๊ธฐ๋ณธ ์•ก์…˜ ๋””์ŠคํŒจ์น˜ @@ -276,7 +220,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }, () => { // ํ…Œ๋งˆ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ - const isThemeType = panelType === "theme"; + const isThemeType = panelType === 'theme'; if (isThemeType) { dispatch( @@ -298,7 +242,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { getMainCategoryDetail({ patnrId: panelPatnrId, prdtId: panelPrdtId, - liveReqFlag: panelLiveReqFlag || "N", + liveReqFlag: panelLiveReqFlag || 'N', }) ); } @@ -319,7 +263,6 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { panelBgImgNo, ]); - // FP ๋ฐฉ์‹์œผ๋กœ ์ถ”์ฒœ ์ƒํ’ˆ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) useEffect(() => { const shouldLoadRecommendations = fp.pipe(() => lgCatCd, fp.isNotEmpty)(); @@ -345,7 +288,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { setLgCatCd(productData.catCd); } else if ( themeProductInfos && - themeProductInfos[selectedIndex]?.pmtSuptYn === "N" && + themeProductInfos[selectedIndex]?.pmtSuptYn === 'N' && panelInfo?.curationId ) { const themeCatCd = themeProductInfos[selectedIndex]?.catCd; @@ -359,7 +302,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // selectedIndex, // themeProductPmtSuptYn: themeProductInfos?.[selectedIndex]?.pmtSuptYn // }); - setLgCatCd(""); + setLgCatCd(''); } }, [productData, themeProductInfos, selectedIndex, panelInfo?.curationId]); @@ -389,16 +332,14 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // - ์ˆœ์ˆ˜ ์œ ํ‹ธ๋กœ ๋นŒ๋“œ/์—…์„œํŠธ ํ•จ์ˆ˜ ์ž‘์„ฑ ํ›„, ์ ์ ˆํ•œ useEffect์—์„œ ํ˜ธ์ถœํ•˜์„ธ์š”. // ์˜ˆ) saveRecentItem(panelInfo, selectedIndex) - // FP ๋ฐฉ์‹์œผ๋กœ cleanup ์ฒ˜๋ฆฌ (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) useEffect(() => { return () => { - // FP ๋ฐฉ์‹์œผ๋กœ cleanup ์•ก์…˜ ์‹คํ–‰ fp.pipe( () => { dispatch(clearProductDetail()); }, () => { - setContainerLastFocusedElement(null, ["indicator-GridListContainer"]); + setContainerLastFocusedElement(null, ['indicator-GridListContainer']); } )(); }; @@ -411,9 +352,6 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // } // }, [panelInfo, selectedIndex]) - // ํ…Œ๋งˆ/ํ˜ธํ…” ๊ธฐ๋ฐ˜ ์ธ๋ฑ์Šค ์ดˆ๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•˜๋ฉด: - // - findIndex ์œ ํ‹ธ์„ ๋งŒ๋“ค์–ด ๋งค์นญ ์ธ๋ฑ์Šค๋ฅผ ๊ณ„์‚ฐ ํ›„ setSelectedIndex์— ๋ฐ˜์˜ํ•˜์„ธ์š”. - // FP ๋ฐฉ์‹์œผ๋กœ ๋ฒ„์ „ ๋น„๊ต ํ—ฌํผ ํ•จ์ˆ˜ (curry ์ ์šฉ) const versionComparators = useMemo( () => ({ isVersionGTE: fp.curry((target, version) => version >= target), @@ -422,12 +360,9 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { [] ); - // FP ๋ฐฉ์‹์œผ๋กœ ์กฐ๊ฑด ์ฒดํฌ ํ—ฌํผ ํ•จ์ˆ˜๋“ค (curry ์ ์šฉ) const conditionCheckers = useMemo( () => ({ - hasDataAndCondition: fp.curry( - (conditionFn, data) => fp.isNotNil(data) && conditionFn(data) - ), + hasDataAndCondition: fp.curry((conditionFn, data) => fp.isNotNil(data) && conditionFn(data)), equalTo: fp.curry((expected, actual) => actual === expected), checkAllConditions: fp.curry((conditions, data) => fp.reduce( @@ -441,7 +376,6 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { ); const getProductType = useCallback(() => { - // FP ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ๋ฐ ํƒ€์ž… ๊ฒฐ์ • - curry ์ ์šฉ์œผ๋กœ ๋” ํ•จ์ˆ˜ํ˜• ๊ฐœ์„  const createTypeChecker = fp.curry((type, conditions, sideEffect) => fp.pipe( () => conditions(), @@ -459,7 +393,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // ํ…Œ๋งˆ ํƒ€์ž… ์ฒดํฌ () => createTypeChecker( - "theme", + 'theme', () => fp.pipe( () => ({ panelCurationId, themeData }), @@ -469,10 +403,10 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { () => { const themeProduct = fp.pipe( () => themeData, - fp.get("productInfos"), + fp.get('productInfos'), fp.get(selectedIndex.toString()) )(); - setProductType("theme"); + setProductType('theme'); setThemeProductInfo(themeProduct); } ), @@ -480,7 +414,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // Buy Now ํƒ€์ž… ์ฒดํฌ (curry ํ™œ์šฉ) () => createTypeChecker( - "buyNow", + 'buyNow', () => fp.pipe( () => ({ @@ -499,21 +433,21 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }) => { const conditions = [ () => fp.isNotNil(productData), - () => conditionCheckers.equalTo("Y")(productPmtSuptYn), - () => conditionCheckers.equalTo("N")(productGrPrdtProcYn), + () => conditionCheckers.equalTo('Y')(productPmtSuptYn), + () => conditionCheckers.equalTo('N')(productGrPrdtProcYn), () => fp.isNotNil(panelPrdtId), - () => versionComparators.isVersionGTE("6.0")(webOSVersion), + () => versionComparators.isVersionGTE('6.0')(webOSVersion), ]; return conditionCheckers.checkAllConditions(conditions)({}); } )(), - () => setProductType("buyNow") + () => setProductType('buyNow') ), // Shop By Mobile ํƒ€์ž… ์ฒดํฌ (curry ํ™œ์šฉ) () => createTypeChecker( - "shopByMobile", + 'shopByMobile', () => fp.pipe( () => ({ @@ -532,27 +466,24 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }) => { if (!productData) return false; - const isDirectMobile = - conditionCheckers.equalTo("N")(productPmtSuptYn); + const isDirectMobile = conditionCheckers.equalTo('N')(productPmtSuptYn); const conditionalMobileConditions = [ - () => conditionCheckers.equalTo("Y")(productPmtSuptYn), - () => conditionCheckers.equalTo("N")(productGrPrdtProcYn), - () => versionComparators.isVersionLT("6.0")(webOSVersion), + () => conditionCheckers.equalTo('Y')(productPmtSuptYn), + () => conditionCheckers.equalTo('N')(productGrPrdtProcYn), + () => versionComparators.isVersionLT('6.0')(webOSVersion), () => fp.isNotNil(panelPrdtId), ]; - const isConditionalMobile = - conditionCheckers.checkAllConditions( - conditionalMobileConditions - )({}); + const isConditionalMobile = conditionCheckers.checkAllConditions( + conditionalMobileConditions + )({}); return isDirectMobile || isConditionalMobile; } )(), - () => setProductType("shopByMobile") + () => setProductType('shopByMobile') ), ]; - // FP ๋ฐฉ์‹์œผ๋กœ ์ˆœ์ฐจ์  ํƒ€์ž… ์ฒดํฌ const matchedRule = fp.reduce( (result, rule) => (result.matched ? result : rule()), { matched: false }, @@ -569,13 +500,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { productGrPrdtProcYn, webOSVersion, }), - ({ - productData, - panelPrdtId, - productPmtSuptYn, - productGrPrdtProcYn, - webOSVersion, - }) => ({ + ({ productData, panelPrdtId, productPmtSuptYn, productGrPrdtProcYn, webOSVersion }) => ({ pmtSuptYn: productPmtSuptYn, grPrdtProcYn: productGrPrdtProcYn, prdtId: panelPrdtId, @@ -583,8 +508,8 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }) )(); - console.warn("Unknown product type:", productData); - console.warn("Product data properties:", debugInfo); + console.warn('Unknown product type:', productData); + console.warn('Product data properties:', debugInfo); } }, [ panelCurationId, @@ -600,7 +525,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { useEffect(() => { // productData๊ฐ€ ๋กœ๋“œ๋œ ํ›„์—๋งŒ getProductType ์‹คํ–‰ - if (productData || (panelType === "theme" && themeData)) { + if (productData || (panelType === 'theme' && themeData)) { getProductType(); } }, [getProductType, productData, themeData, panelType]); @@ -614,11 +539,11 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }, [themeData, selectedIndex]); const imageUrl = useMemo( - () => fp.pipe(() => productData, fp.get("thumbnailUrl960"))(), + () => fp.pipe(() => productData, fp.get('thumbnailUrl960'))(), [productData] ); - // FP ๋ฐฉ์‹์œผ๋กœ ํƒ€์ดํ‹€๊ณผ aria-label ๋ฉ”๋ชจ์ด์ œ์ด์…˜ (์„ฑ๋Šฅ ์ตœ์ ํ™”) + // ํƒ€์ดํ‹€๊ณผ aria-label ๋ฉ”๋ชจ์ด์ œ์ด์…˜ (์„ฑ๋Šฅ ์ตœ์ ํ™”) const headerTitle = useMemo( () => fp.pipe( @@ -628,21 +553,20 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { () => ({ panelPrdtId, productData }), ({ panelPrdtId, productData }) => fp.isNotNil(panelPrdtId) && - fp.pipe(() => productData, fp.get("prdtNm"), fp.isNotNil)() - ? fp.pipe(() => productData, fp.get("prdtNm"))() + fp.pipe(() => productData, fp.get('prdtNm'), fp.isNotNil)() + ? fp.pipe(() => productData, fp.get('prdtNm'))() : null )(); const themeTitle = fp.pipe( () => ({ panelType, themeData }), ({ panelType, themeData }) => - panelType === "theme" && - fp.pipe(() => themeData, fp.get("curationNm"), fp.isNotNil)() - ? fp.pipe(() => themeData, fp.get("curationNm"))() + panelType === 'theme' && fp.pipe(() => themeData, fp.get('curationNm'), fp.isNotNil)() + ? fp.pipe(() => themeData, fp.get('curationNm'))() : null )(); - return productTitle || themeTitle || ""; + return productTitle || themeTitle || ''; } )(), [panelPrdtId, productData, panelType, themeData] @@ -653,10 +577,9 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { fp.pipe( () => ({ panelPrdtId, productData }), ({ panelPrdtId, productData }) => - fp.isNotNil(panelPrdtId) && - fp.pipe(() => productData, fp.get("prdtNm"), fp.isNotNil)() - ? fp.pipe(() => productData, fp.get("prdtNm"))() - : "" + fp.isNotNil(panelPrdtId) && fp.pipe(() => productData, fp.get('prdtNm'), fp.isNotNil)() + ? fp.pipe(() => productData, fp.get('prdtNm'))() + : '' )(), [panelPrdtId, productData] ); @@ -666,7 +589,6 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { // Pink Pong ๋“ฑ ํŠน์ • ํŒŒํŠธ๋„ˆ์‚ฌ์—์„œ๋งŒ thumbnailUrl960 ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์–ด์„œ ๋ฐฐ๊ฒฝ์ด ๋ณ€๊ฒฝ๋จ // ํ˜„์žฌ๋Š” ๊ณ ์ • ๋ฐฐ๊ฒฝ(detailPanelBg)๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ์„ ์ฒ˜๋ฆฌ - // FP ๋ฐฉ์‹์œผ๋กœ ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์„ค์ • (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€) /* useLayoutEffect(() => { const shouldSetBackground = fp.pipe( @@ -681,7 +603,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { }, [imageUrl]); */ - console.log("productDataSource :", productDataSource); + console.log('productDataSource :', productDataSource); // ์–ธ๋งˆ์šดํŠธ ์‹œ ์ธ๋ฑ์Šค ์ดˆ๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•˜๋ฉด: // useEffect(() => () => setSelectedIndex(0), []) @@ -725,18 +647,12 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { isDefaultContainer > {useMemo(() => { - // FP ๋ฐฉ์‹์œผ๋กœ ๋ Œ๋”๋ง ์กฐ๊ฑด ๊ฒฐ์ • (๋ฉ”๋ชจ์ด์ œ์ด์…˜์œผ๋กœ ์ตœ์ ํ™”) const renderStates = fp.pipe( () => ({ isLoading, panelInfo, productDataSource, productType }), ({ isLoading, panelInfo, productDataSource, productType }) => { const hasRequiredData = fp.pipe( () => [panelInfo, productDataSource, productType], - (data) => - fp.reduce( - (acc, item) => acc && fp.isNotNil(item), - true, - data - ) + (data) => fp.reduce((acc, item) => acc && fp.isNotNil(item), true, data) )(); return { diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx index 2a9677e6..1f8d9fdc 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.jsx @@ -2,6 +2,7 @@ import React, { useCallback, useMemo, useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import Spottable from '@enact/spotlight/Spottable'; import { startVideoPlayer, finishVideoPreview } from '../../../../actions/playActions'; +import { startMediaPlayer, finishMediaPreview } from '../../../../actions/mediaActions'; import CustomImage from '../../../../components/CustomImage/CustomImage'; import { panel_names } from '../../../../utils/Config'; import playImg from '../../../../../assets/images/btn/btn-play-thumb-nor.png'; @@ -78,8 +79,33 @@ export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl }) { // modal=true๋กœ ์žฌ์ƒ ์ค‘์ด๋ฉด modal=false(์ „์ฒดํ™”๋ฉด)๋กœ ๋ณ€๊ฒฝ const newModalState = isCurrentlyPlayingModal ? false : modalState; + // dispatch( + // startVideoPlayer({ + // qrCurrentItem: productInfo, + // showUrl: productInfo?.prdtMediaUrl, + // showNm: productInfo?.prdtNm, + // patnrNm: productInfo?.patncNm, + // patncLogoPath: productInfo?.patncLogoPath, + // orderPhnNo: productInfo?.orderPhnNo, + // disclaimer: productInfo?.disclaimer, + // subtitle: productInfo?.prdtMediaSubtitlUrl, + // lgCatCd: productInfo?.catCd, + // patnrId: productInfo?.patnrId, + // lgCatNm: productInfo?.catNm, + // prdtId: productInfo?.prdtId, + // patncNm: productInfo?.patncNm, + // prdtNm: productInfo?.prdtNm, + // thumbnailUrl: productInfo?.thumbnailUrl960, + // shptmBanrTpNm: 'MEDIA', + // modal: newModalState, + // modalContainerId: 'product-video-player', + // modalClassName: modalClassNameChange(), + // spotlightDisable: true, + // }) + // ); + dispatch( - startVideoPlayer({ + startMediaPlayer({ qrCurrentItem: productInfo, showUrl: productInfo?.prdtMediaUrl, showNm: productInfo?.prdtNm, @@ -112,7 +138,15 @@ export default function ProductVideo({ productInfo, videoUrl, thumbnailUrl }) { if (isLaunchedFromPlayer) { setIsLaunchedFromPlayer(false); } - }, [dispatch, productInfo, canPlayVideo, isLaunchedFromPlayer, modalClassNameChange, panels, modalState]); + }, [ + dispatch, + productInfo, + canPlayVideo, + isLaunchedFromPlayer, + modalClassNameChange, + panels, + modalState, + ]); if (!canPlayVideo) return null; diff --git a/com.twin.app.shoptime/src/views/UserReview/components/UserReviewItem.jsx b/com.twin.app.shoptime/src/views/UserReview/components/UserReviewItem.jsx index 5276f211..f4023d7c 100644 --- a/com.twin.app.shoptime/src/views/UserReview/components/UserReviewItem.jsx +++ b/com.twin.app.shoptime/src/views/UserReview/components/UserReviewItem.jsx @@ -1,11 +1,11 @@ // Light theme ๊ฐœ๋ณ„ ๋ฆฌ๋ทฐ ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ -import React, { useCallback } from "react"; -import Spottable from "@enact/spotlight/Spottable"; -import classNames from "classnames"; -import StarRating from "../../DetailPanel/components/StarRating"; -import css from "./UserReviewItem.module.less"; +import React, { useCallback } from 'react'; +import Spottable from '@enact/spotlight/Spottable'; +import classNames from 'classnames'; +import StarRating from '../../DetailPanel/components/StarRating'; +import css from './UserReviewItem.module.less'; -const SpottableComponent = Spottable("div"); +const SpottableComponent = Spottable('div'); /** * UserReviewPanel์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ณ„ ๋ฆฌ๋ทฐ ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ @@ -20,7 +20,7 @@ const UserReviewItem = ({ onNextPage, onPrevPage, onClick, - isPaging = false + isPaging = false, }) => { const handleReviewClick = useCallback(() => { if (onClick) { @@ -29,50 +29,45 @@ const UserReviewItem = ({ }, [onClick, review, index]); // ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ - ์กฐ๊ฑด๋ถ€ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ - const handleKeyDown = useCallback((event) => { - // ์ฒซ๋ฒˆ์งธ ๋ฆฌ๋ทฐ(index 0)์—์„œ ์œ„ ํ™”์‚ดํ‘œ ์ฒ˜๋ฆฌ - if (event.key === 'ArrowUp' && index === 0) { - if (hasPrev && onPrevPage) { - console.log('[UserReviewItem] ์ฒซ๋ฒˆ์งธ ๋ฆฌ๋ทฐ์—์„œ ์œ„ ํ™”์‚ดํ‘œ - ์ด์ „ ํŽ˜์ด์ง€'); - onPrevPage(); + const handleKeyDown = useCallback( + (event) => { + // ์ฒซ๋ฒˆ์งธ ๋ฆฌ๋ทฐ(index 0)์—์„œ ์œ„ ํ™”์‚ดํ‘œ ์ฒ˜๋ฆฌ + if (event.key === 'ArrowUp' && index === 0) { + if (hasPrev && onPrevPage) { + // console.log('[UserReviewItem] ์ฒซ๋ฒˆ์งธ ๋ฆฌ๋ทฐ์—์„œ ์œ„ ํ™”์‚ดํ‘œ - ์ด์ „ ํŽ˜์ด์ง€'); + onPrevPage(); + } + event.preventDefault(); // ํŽ˜์ด์ง• ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํฌ์ปค์Šค ์‚ฌ๋ผ์ง ๋ฐฉ์ง€ + event.stopPropagation(); } - event.preventDefault(); // ํŽ˜์ด์ง• ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํฌ์ปค์Šค ์‚ฌ๋ผ์ง ๋ฐฉ์ง€ - event.stopPropagation(); - } - // ์„ธ๋ฒˆ์งธ ๋ฆฌ๋ทฐ(index 2)์—์„œ ์•„๋ž˜ ํ™”์‚ดํ‘œ ์ฒ˜๋ฆฌ - else if (event.key === 'ArrowDown' && index === 2) { - if (hasNext && onNextPage) { - console.log('[UserReviewItem] ์„ธ๋ฒˆ์งธ ๋ฆฌ๋ทฐ์—์„œ ์•„๋ž˜ ํ™”์‚ดํ‘œ - ๋‹ค์Œ ํŽ˜์ด์ง€'); - onNextPage(); + // ์„ธ๋ฒˆ์งธ ๋ฆฌ๋ทฐ(index 2)์—์„œ ์•„๋ž˜ ํ™”์‚ดํ‘œ ์ฒ˜๋ฆฌ + else if (event.key === 'ArrowDown' && index === 2) { + if (hasNext && onNextPage) { + // console.log('[UserReviewItem] ์„ธ๋ฒˆ์งธ ๋ฆฌ๋ทฐ์—์„œ ์•„๋ž˜ ํ™”์‚ดํ‘œ - ๋‹ค์Œ ํŽ˜์ด์ง€'); + onNextPage(); + } + event.preventDefault(); // ํŽ˜์ด์ง• ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํฌ์ปค์Šค ์‚ฌ๋ผ์ง ๋ฐฉ์ง€ + event.stopPropagation(); } - event.preventDefault(); // ํŽ˜์ด์ง• ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํฌ์ปค์Šค ์‚ฌ๋ผ์ง ๋ฐฉ์ง€ - event.stopPropagation(); - } - }, [index, hasNext, hasPrev, onNextPage, onPrevPage]); + }, + [index, hasNext, hasPrev, onNextPage, onPrevPage] + ); // ๋‚ ์งœ ํฌ๋งทํŒ… ํ•จ์ˆ˜ const formatToYYMMDD = (dateStr) => { const date = new Date(dateStr); const iso = date.toISOString().slice(2, 10); - return iso.replace(/-/g, "."); + return iso.replace(/-/g, '.'); }; - const { - reviewImageList, - rvwRtng, - rvwRgstDtt, - rvwCtnt, - rvwId, - wrtrNknm, - rvwWrtrId - } = review; + const { reviewImageList, rvwRtng, rvwRgstDtt, rvwCtnt, rvwId, wrtrNknm, rvwWrtrId } = review; return ( {rvwRtng && ( - + )} {(wrtrNknm || rvwWrtrId) && ( - - {wrtrNknm || rvwWrtrId} - - )} - {rvwRgstDtt && ( - - {formatToYYMMDD(rvwRgstDtt)} - + {wrtrNknm || rvwWrtrId} )} + {rvwRgstDtt && {formatToYYMMDD(rvwRgstDtt)}} {/* ๋ฆฌ๋ทฐ ํ…์ŠคํŠธ */} - {rvwCtnt && ( -
{rvwCtnt}
- )} + {rvwCtnt &&
{rvwCtnt}
}
);