@@ -219,6 +219,57 @@ export default function Community() {
219219 return sortedPosts . slice ( start , end ) ;
220220 } , [ sortedPosts , currentPage ] ) ;
221221
222+ const topWriters = useMemo ( ( ) => {
223+ if ( ! posts . length ) return [ ] ;
224+
225+ const counts = posts . reduce ( ( acc , post ) => {
226+ const author = ( post . author || "익명" ) . trim ( ) ;
227+ if ( ! author ) return acc ;
228+ acc [ author ] = ( acc [ author ] ?? 0 ) + 1 ;
229+ return acc ;
230+ } , { } ) ;
231+
232+ return Object . entries ( counts )
233+ . sort ( ( a , b ) => {
234+ const countDiff = b [ 1 ] - a [ 1 ] ;
235+ if ( countDiff !== 0 ) return countDiff ;
236+ return a [ 0 ] . localeCompare ( b [ 0 ] ) ;
237+ } )
238+ . slice ( 0 , 7 )
239+ . map ( ( [ name , count ] ) => ( { name, count } ) ) ;
240+ } , [ posts ] ) ;
241+
242+ const weeklyPopular = useMemo ( ( ) => {
243+ if ( ! posts . length ) return [ ] ;
244+
245+ const oneWeekAgo = Date . now ( ) - 7 * 24 * 60 * 60 * 1000 ;
246+ const withinWeek = posts . filter ( ( post ) =>
247+ Number . isFinite ( post . createdAtMs ) && post . createdAtMs >= oneWeekAgo
248+ ) ;
249+
250+ const source = withinWeek . length ? withinWeek : posts ;
251+
252+ return [ ...source ]
253+ . sort ( ( a , b ) => {
254+ const likeDiff = ( b . likes ?? 0 ) - ( a . likes ?? 0 ) ;
255+ if ( likeDiff !== 0 ) return likeDiff ;
256+ const commentDiff = ( b . comments ?? 0 ) - ( a . comments ?? 0 ) ;
257+ if ( commentDiff !== 0 ) return commentDiff ;
258+ const timeA = Number . isFinite ( a . createdAtMs ) ? a . createdAtMs : 0 ;
259+ const timeB = Number . isFinite ( b . createdAtMs ) ? b . createdAtMs : 0 ;
260+ if ( timeA !== timeB ) return timeB - timeA ;
261+ return ( b . id ?? 0 ) - ( a . id ?? 0 ) ;
262+ } )
263+ . slice ( 0 , 5 )
264+ . map ( ( post ) => ( {
265+ id : post . id ,
266+ title : post . title ,
267+ author : post . author ,
268+ likes : post . likes ?? 0 ,
269+ createdAt : post . date ,
270+ } ) ) ;
271+ } , [ posts ] ) ;
272+
222273 const jumpBy = 5 ;
223274 const goToPage = ( page ) => {
224275 if ( page < 1 || page > totalPages ) return ;
@@ -250,15 +301,18 @@ export default function Community() {
250301 </ ul >
251302 < div className = "top-writers" >
252303 < h4 > Zivorp TOP Writers</ h4 >
253- < ol >
254- < li > < span > y2gcoder</ span > < span > 10</ span > </ li >
255- < li > < span > durams</ span > < span > 8</ span > </ li >
256- < li > < span > David</ span > < span > 7</ span > </ li >
257- < li > < span > 식빵</ span > < span > 10</ span > </ li >
258- < li > < span > 이선희</ span > < span > 10</ span > </ li >
259- < li > < span > 찹찹이</ span > < span > 10</ span > </ li >
260- < li > < span > Rio song</ span > < span > 10</ span > </ li >
261- </ ol >
304+ { topWriters . length ? (
305+ < ol >
306+ { topWriters . map ( ( { name, count } ) => (
307+ < li key = { name } >
308+ < span > { name } </ span >
309+ < span > { count } </ span >
310+ </ li >
311+ ) ) }
312+ </ ol >
313+ ) : (
314+ < p className = "top-writers-empty" > 아직 활동 기록이 없어요.</ p >
315+ ) }
262316 </ div >
263317 </ aside >
264318
@@ -435,13 +489,26 @@ export default function Community() {
435489 </ div >
436490 < div className = "popular-posts" >
437491 < h4 > 주간 인기글</ h4 >
438- < ul >
439- < li > < div className = "post-title" > 버블 정렬 시각화 프로젝트 공유합니다</ div > < div className = "post-author" > 김코딩</ div > </ li >
440- < li > < div className = "post-title" > 그래프 탐색 알고리즘 비교: BFS vs DFS</ div > < div className = "post-author" > 이알고</ div > </ li >
441- < li > < div className = "post-title" > 동적 프로그래밍 문제 해결 가이드</ div > < div className = "post-author" > 박코딩</ div > </ li >
442- < li > < div className = "post-title" > 백엔드 신입 CS 스터디 3기 모집</ div > < div className = "post-author" > 김지훈</ div > </ li >
443- < li > < div className = "post-title" > AI 실전 활용을 위한 4주 집중 스터디, 애사모!</ div > < div className = "post-author" > Edun</ div > </ li >
444- </ ul >
492+ { weeklyPopular . length ? (
493+ < ul >
494+ { weeklyPopular . map ( ( post ) => (
495+ < li key = { post . id } >
496+ < button
497+ type = "button"
498+ onClick = { ( ) => navigate ( `/community/post/${ post . id } ` ) }
499+ >
500+ < div className = "post-title" > { post . title } </ div >
501+ < div className = "post-author" > { post . author || "익명" } </ div >
502+ { typeof post . likes === "number" && (
503+ < div className = "post-likes" > 좋아요 { post . likes } </ div >
504+ ) }
505+ </ button >
506+ </ li >
507+ ) ) }
508+ </ ul >
509+ ) : (
510+ < p className = "popular-posts-empty" > 인기 게시글을 불러오는 중입니다.</ p >
511+ ) }
445512 </ div >
446513 </ aside >
447514 </ div >
0 commit comments