Skip to content

Commit 41c663e

Browse files
committed
feat(community): 정렬 추가
1 parent ff466cc commit 41c663e

File tree

5 files changed

+75
-48
lines changed

5 files changed

+75
-48
lines changed

front/src/app/(dashboard)/analysis/[id]/page.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,10 @@ export default function ResultsPage() {
4242
</div>
4343

4444
{/* 🌐 공개 설정 및 커뮤니티 섹션 */}
45-
<RepositoryPublicSection
46-
userId={history.repository.ownerId}
47-
repoId={repoId}
48-
initialPublic={history.repository.publicRepository}
49-
/>
45+
<RepositoryPublicSection
46+
userId={history.repository.ownerId}
47+
repoId={repoId}
48+
initialPublic={history.repository.publicRepository} />
5049
</div>
5150
</div>
5251
)

front/src/app/community/page.tsx

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,11 @@ import RepositoryList from '@/components/community/RepoList';
55
export default function HomePage() {
66
return (
77
<main className="max-w-3xl mx-auto p-6">
8-
<h1 className="text-3xl font-bold mb-2 text-blue-600">Portfol.ioQ</h1>
9-
<p className="text-gray-500 text-sm mb-6">커뮤니티 레포지토리 피드</p>
8+
<div className="mb-8">
9+
<h1 className="mb-2 text-3xl font-bold">커뮤니티</h1>
10+
<p className="text-muted-foreground">다른 사용자의 분석 결과를 둘러보세요.</p>
11+
</div>
1012
<RepositoryList />
1113
</main>
1214
);
13-
}
14-
15-
// "use client"
16-
17-
// import { useState } from "react"
18-
// import { CommentList } from "@/components/community/CommentList"
19-
// import { CommentForm } from "@/components/community/CommentForm"
20-
21-
// export default function CommunityPage() {
22-
// const [refreshKey, setRefreshKey] = useState(0)
23-
24-
// return (
25-
// <main className="max-w-2xl mx-auto py-10">
26-
// <h1 className="text-2xl font-bold mb-6">💬 댓글 테스트 페이지</h1>
27-
28-
// {/* ✅ 댓글 작성 폼을 위로 이동 */}
29-
// <section className="mb-8">
30-
// <h2 className="text-lg font-semibold mb-3">댓글 작성</h2>
31-
// <CommentForm
32-
// analysisResultId="1"
33-
// memberId={1} // 로그인 후 실제 유저 ID로 대체
34-
// onCommentAdded={() => setRefreshKey((k) => k + 1)} // 작성 후 목록 새로고침
35-
// />
36-
// </section>
37-
38-
// {/* ✅ 댓글 목록은 아래쪽에 표시 */}
39-
// <section className="border-t border-border pt-6">
40-
// <h2 className="text-lg font-semibold mb-3">댓글 목록</h2>
41-
// <CommentList key={refreshKey} analysisResultId="1" />
42-
// </section>
43-
// </main>
44-
// )
45-
// }
15+
}

front/src/components/community/RepoCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
import type { RepositoryItem } from '@/types/community';
44
import { useRouter } from 'next/navigation'
5+
import { formatRelativeTimeKST } from '@/lib/utils/formatDate'
56

67
export default function RepositoryCard({ item }: { item: RepositoryItem }) {
7-
88
const router = useRouter();
9+
const relativeTime = formatRelativeTimeKST(item.createDate);
910

1011
return (
1112
<article className="bg-white border border-gray-200 rounded-2xl shadow-sm p-5 hover:shadow-md transition-all duration-200">
@@ -30,7 +31,7 @@ export default function RepositoryCard({ item }: { item: RepositoryItem }) {
3031
<p className="font-semibold text-sm">{item.userName}</p>
3132
<p className="text-gray-500 text-xs">@{item.userName.toLowerCase()}</p>
3233
</div>
33-
<span className="ml-auto text-gray-400 text-xs">2시간 전</span>
34+
<span className="ml-auto text-gray-400 text-xs">{relativeTime}</span>
3435
</div>
3536

3637
{/* 레포지토리 링크 */}

front/src/components/community/RepoList.tsx

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,49 @@
22

33
import { useRepositories } from '@/hooks/community/useCommunity';
44
import RepositoryCard from './RepoCard';
5+
import { Button } from '@/components/ui/Button'
56

67
export default function RepositoryList() {
7-
const { data, loading, error } = useRepositories();
8+
const {
9+
repositories,
10+
loading,
11+
error,
12+
sortType,
13+
setSortType,
14+
} = useRepositories()
815

916
if (loading) return <p>로딩 중...</p>;
1017
if (error) return <p className="text-red-500">에러 발생: {error}</p>;
1118

1219
return (
1320
<section className="flex flex-col gap-6 mt-6">
14-
{data.map((item, i) => (
15-
<RepositoryCard key={i} item={item} />
16-
))}
21+
{/* ✅ 정렬 버튼 */}
22+
<div className="flex justify-end gap-2">
23+
<Button
24+
variant={sortType === 'latest' ? 'default' : 'outline'}
25+
size="sm"
26+
onClick={() => setSortType('latest')}
27+
>
28+
최신순
29+
</Button>
30+
<Button
31+
variant={sortType === 'score' ? 'default' : 'outline'}
32+
size="sm"
33+
onClick={() => setSortType('score')}
34+
>
35+
점수순
36+
</Button>
37+
</div>
38+
39+
{repositories.length === 0 ? (
40+
<p className="text-center text-muted-foreground">아직 공개된 분석이 없습니다.</p>
41+
) : (
42+
<div className="flex flex-col gap-6">
43+
{repositories.map((item) => (
44+
<RepositoryCard key={item.repositoryId} item={item} />
45+
))}
46+
</div>
47+
)}
1748
</section>
1849
);
1950
}

front/src/hooks/community/useCommunity.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use client';
22

3-
import { useEffect, useState } from 'react';
3+
import { useEffect, useState, useMemo } from 'react';
44
import { fetchRepositories } from '@/lib/api/community';
55
import type { RepositoryItem } from '@/types/community';
66

77
export function useRepositories() {
88
const [data, setData] = useState<RepositoryItem[]>([]);
99
const [loading, setLoading] = useState(true);
1010
const [error, setError] = useState<string | null>(null);
11+
const [sortType, setSortType] = useState<'latest' | 'score'>('latest')
1112

1213
useEffect(() => {
1314
(async () => {
@@ -22,5 +23,30 @@ export function useRepositories() {
2223
})();
2324
}, []);
2425

25-
return { data, loading, error };
26+
const sortedData = useMemo(() => {
27+
if (sortType === 'score') {
28+
return data
29+
.slice()
30+
.sort((a, b) => (b.totalScore ?? 0) - (a.totalScore ?? 0))
31+
}
32+
33+
// 최신순
34+
const parseDate = (d?: string) => {
35+
if (!d) return 0
36+
// 백엔드 LocalDateTime 형식 → JS Date 변환 (마이크로초 제거 + UTC 보정)
37+
return Date.parse(d.split('.')[0] + 'Z')
38+
}
39+
40+
return data
41+
.slice()
42+
.sort((a, b) => parseDate(b.createDate) - parseDate(a.createDate))
43+
}, [data, sortType])
44+
45+
return {
46+
repositories: sortedData,
47+
loading,
48+
error,
49+
sortType,
50+
setSortType,
51+
}
2652
}

0 commit comments

Comments
 (0)