From fb2b6a91c8eaf663e9f67f285133b40b4e9e6169 Mon Sep 17 00:00:00 2001 From: kiyeong Date: Wed, 27 Nov 2024 23:21:47 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=8B=9C=EC=B2=AD?= =?UTF-8?q?=20=ED=9A=9F=EC=88=98=20top10,=20=EC=A0=84=EC=B2=B4=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EC=88=98=20top10=20=EC=B6=94=EC=B2=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Main/components/RecommendedContents.tsx | 283 ++++++++++++-------- 1 file changed, 164 insertions(+), 119 deletions(-) diff --git a/src/Main/components/RecommendedContents.tsx b/src/Main/components/RecommendedContents.tsx index ca0a207..1feaf43 100644 --- a/src/Main/components/RecommendedContents.tsx +++ b/src/Main/components/RecommendedContents.tsx @@ -18,6 +18,8 @@ interface Content { listedIn: string; description: string; posterPath?: string; + watchCount?: number; + likeCount?: number; } interface CategoryContent { @@ -26,6 +28,12 @@ interface CategoryContent { } function RecommendedContents(): JSX.Element { + const [watchTop, setWatchTop] = useState< + { content: Content; watchCount: number }[] + >([]); + const [likeTop, setLikeTop] = useState< + { content: Content; likeCount: number }[] + >([]); const [categories, setCategories] = useState([]); const [isLoading, setIsLoading] = useState(true); const [selectedContent, setSelectedContent] = useState(null); @@ -44,28 +52,37 @@ function RecommendedContents(): JSX.Element { }; useEffect(() => { - const fetchRecommendedContents = async () => { + const fetchAllContents = async () => { setIsLoading(true); try { - const response = await api.get("/api/recommend/10"); + // 많이 시청한 콘텐츠 TOP 10 가져오기 + const watchResponse = await api.get("/api/watch/top"); + setWatchTop(watchResponse.data || []); + + // 좋아요한 콘텐츠 TOP 10 가져오기 + const likeResponse = await api.get("/api/like/top"); + setLikeTop(likeResponse.data || []); + + // 추천 콘텐츠 가져오기 + const recommendResponse = await api.get("/api/recommend/10"); const fetchedCategories = Object.keys(categoryLabels).map( (category) => ({ category, contents: - response.data[category]?.map( + recommendResponse.data[category]?.map( (item: { content: Content }) => item.content ) || [], }) ); setCategories(fetchedCategories); } catch (error) { - console.error("추천 콘텐츠를 가져오는 중 오류 발생:", error); + console.error("콘텐츠를 가져오는 중 오류 발생:", error); } finally { setIsLoading(false); } }; - fetchRecommendedContents(); + fetchAllContents(); }, []); const handleCardClick = (content: Content) => { @@ -78,6 +95,126 @@ function RecommendedContents(): JSX.Element { setIsModalOpen(false); }; + const renderContentGrid = ( + items: { content: Content; count?: number }[], + label: string, + countLabel?: string + ) => ( + + + {label} + + {items.length > 0 ? ( + + + {items.map(({ content, count }) => ( + handleCardClick(content)} + > + {content.posterPath ? ( + {`${content.title} + ) : ( + + + 포스터가 없습니다. + + + )} + + {content.title} + + {countLabel && ( + + {`${countLabel}: ${count}`} + + )} + + ))} + + + ) : ( + + 충분한 데이터가 쌓이지 않았습니다. + + )} + + ); + + const renderCategoryGrids = () => + categories.map(({ category, contents }) => + renderContentGrid( + contents.map((content) => ({ content })), + categoryLabels[category] || category + ) + ); + if (isLoading) { return ( - {categories.map(({ category, contents }) => ( - - {/* 카테고리 제목 */} - - {categoryLabels[category]} - - {contents.length > 0 ? ( - - - - {contents.map((content) => ( - handleCardClick(content)} - > - {content.posterPath ? ( - {`${content.title} - ) : ( - - - 해당 콘텐츠는 - - - 포스터가 없습니다. - - - )} - - {content.title} - - - ))} - - - - ) : ( - - 충분한 데이터가 쌓이지 않았습니다. - - )} - - ))} + {/* 많이 시청한 콘텐츠 TOP 10 */} + {renderContentGrid( + watchTop.map((item) => ({ + content: item.content, + count: item.watchCount, + })), + "🔥 서비스 이용자들이 많이 시청한 콘텐츠 TOP 10", + "시청 횟수" + )} + + {/* 좋아요한 콘텐츠 TOP 10 */} + {renderContentGrid( + likeTop.map((item) => ({ + content: item.content, + count: item.likeCount, + })), + "❤️ 서비스 이용자들이 좋아한 콘텐츠 TOP 10", + "좋아요 수" + )} + + {/* 기존 추천 콘텐츠 */} + {renderCategoryGrids()} {/* DetailModal */} {selectedContent && (