Skip to content

Commit 5426260

Browse files
authored
Merge pull request #38 from CodeItBoost3/feature/group-detail-api
그룹 상세 API 연동
2 parents b0f16c8 + d94aefc commit 5426260

7 files changed

Lines changed: 132 additions & 67 deletions

File tree

.github/build.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
cd ../
3+
mkdir output
4+
cp -R ./CodeItBoost3_FE/* ./output
5+
cp -R ./output ./CodeItBoost3_FE/

.github/vercel.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 2,
3+
"routes": [
4+
{
5+
"handle": "filesystem"
6+
},
7+
{
8+
"src": "/.*",
9+
"dest": "/index.html"
10+
}
11+
]
12+
}

.github/workflows/sync-to-fork.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Sync Fork with Upstream
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
8+
jobs:
9+
sync:
10+
if: github.repository == 'CodeItBoost3/CodeItBoost3_FE'
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Check out the repository
15+
uses: actions/checkout@v3
16+
with:
17+
persist-credentials: false
18+
19+
- name: Set up Git
20+
run: |
21+
git config user.name "Dubabbi"
22+
git config user.email "thdms3160@naver.com"
23+
24+
- name: Add Fork as Remote
25+
run: git remote add fork https://github.com/Dubabbi/CodeItBoost3_FE.git
26+
27+
- name: Push changes to Fork
28+
env:
29+
GITHUB_USERNAME: Dubabbi
30+
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
31+
run: |
32+
git push -f https://Dubabbi:$GITHUB_TOKEN@github.com/Dubabbi/CodeItBoost3_FE.git develop
33+

src/assets/image/readme.png

2.51 MB
Loading

src/pages/Group.jsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ export default function Group() {
3030
const [currentPage, setCurrentPage] = useState(1);
3131
const [searchTerm, setSearchTerm] = useState("");
3232
const [groupData, setGroupData] = useState([]);
33+
const [totalPages, setTotalPages] = useState(1);
3334
const [searchParams, setSearchParams] = useSearchParams();
3435
const [sortBy, setSortBy] = useState(searchParams.get("sortBy") || "mostLiked");
3536
const tabName = searchParams.get(GROUP_PARAMS) || "Public";
3637
const isPublic = tabName === "Public";
3738
const addToast = useToast();
38-
const totalPages = 10;
3939

4040
useEffect(() => {
4141
const fetchGroupList = async () => {
@@ -44,16 +44,19 @@ export default function Group() {
4444
type: isPublic ? "public" : "private",
4545
sortBy,
4646
keyword: searchTerm,
47+
page: currentPage,
4748
});
4849

4950
setGroupData(data.data || []);
51+
setCurrentPage(currentPage);
52+
setTotalPages(totalPages);
5053
} catch {
5154
addToast("그룹 목록 조회에 실패했습니다.");
5255
}
5356
};
5457

5558
fetchGroupList();
56-
}, [isPublic, searchTerm, sortBy]);
59+
}, [isPublic, searchTerm, sortBy, currentPage]);
5760

5861
useEffect(() => {
5962
setSortBy(searchParams.get("sortBy") || "mostLiked");
@@ -62,11 +65,7 @@ export default function Group() {
6265
const handleSearch = () => {
6366
console.log("검색어:", searchTerm);
6467
};
65-
66-
const handlePageChange = (page) => {
67-
setCurrentPage(page);
68-
};
69-
68+
7069
const handleSelect = (selectedValue) => {
7170
if (selectedValue !== sortBy) {
7271
setSortBy(selectedValue);
@@ -147,7 +146,11 @@ export default function Group() {
147146
</div>
148147

149148
<div className="p-4">
150-
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} />
149+
<Pagination
150+
currentPage={currentPage}
151+
totalPages={totalPages}
152+
onPageChange={setCurrentPage}
153+
/>
151154
</div>
152155
</div>
153156
);

src/pages/GroupDetail.jsx

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useToast } from "@/hooks/useToast";
33
import { useSearchParams, useParams } from 'react-router-dom';
44

55
import groupService from '@/services/group/groupService';
6-
import GroupTab from '@/components/group/GroupTab';
76
import SearchBar from "@/components/common/SearchBar";
87
import SearchButton from "@/components/common/SearchButton";
98
import Select from '@/components/common/Select';
@@ -22,8 +21,6 @@ export default function GroupDetail() {
2221
const { groupId } = useParams();
2322
const addToast = useToast();
2423
const [searchTerm, setSearchTerm] = useState("");
25-
// eslint-disable-next-line
26-
const [groupData, setGroupData] = useState("");
2724
const [searchParams, setSearchParams] = useSearchParams();
2825
const [sortBy, setSortBy] = useState(searchParams.get("sortBy") || "mostLiked");
2926
const [currentPage, setCurrentPage] = useState(1);
@@ -32,11 +29,13 @@ export default function GroupDetail() {
3229
const [morePosition, setMorePosition] = useState({ x: 0, y: 0 });
3330
const [showEditGroup, setShowEditGroup] = useState(false);
3431
const [group, setGroup] = useState(null);
32+
const [publicMemories, setPublicMemories] = useState([]);
33+
const [privateMemories, setPrivateMemories] = useState([]);
34+
3535
const totalPages = 10;
3636
const GROUP_PARAMS = 'group';
3737
const tabName = searchParams.get(GROUP_PARAMS) || 'Public';
38-
// eslint-disable-next-line
39-
const [isPublic, setIsPublic] = useState('true');
38+
4039
const options = [
4140
{ label: "최신순", value: "latest" },
4241
{ label: "추억 많은 순", value: "mostPosted" },
@@ -48,30 +47,57 @@ export default function GroupDetail() {
4847
const fetchGroupDetail = async () => {
4948
try {
5049
const data = await groupService.getGroupDetail(groupId);
51-
50+
5251
if (!data) {
5352
addToast("해당 그룹을 찾을 수 없습니다.");
5453
return;
5554
}
56-
55+
5756
setGroup(data);
58-
setIsPublic(data.isPublic);
57+
58+
setPublicMemories(
59+
data.publicPosts
60+
? data.publicPosts.map(post => ({
61+
author: post.author?.nickname || "알 수 없음",
62+
visibility: "공개",
63+
title: post.title || "제목 없음",
64+
location: data.groupName || "알 수 없음",
65+
date: post.createdAt ? new Date(post.createdAt).toLocaleDateString("ko-KR") : "날짜 없음",
66+
tags: post.tags || [],
67+
likes: post.likeCount || 0,
68+
comments: post.commentCount || 0,
69+
}))
70+
: []
71+
);
72+
73+
setPrivateMemories(
74+
data.privatePosts
75+
? data.privatePosts.map(post => ({
76+
author: post.author?.nickname || "알 수 없음",
77+
visibility: "비공개",
78+
title: post.title || "제목 없음",
79+
date: post.createdAt ? new Date(post.createdAt).toLocaleDateString("ko-KR") : "날짜 없음",
80+
likes: post.likeCount || 0,
81+
comments: post.commentCount || 0,
82+
}))
83+
: []
84+
);
5985
} catch {
6086
addToast("그룹 상세 조회에 실패했습니다.");
6187
}
6288
};
63-
89+
6490
if (groupId) fetchGroupDetail();
6591
}, [groupId]);
66-
92+
6793
useEffect(() => {
6894
setSortBy(searchParams.get("sortBy") || "mostLiked");
6995
}, [searchParams]);
7096

7197
const handleSearch = async () => {
7298
try {
7399
const data = await groupService.searchGroups(searchTerm);
74-
setGroupData(data.data || []);
100+
setGroup(data.data || []);
75101
} catch {
76102
addToast("그룹 검색에 실패했습니다.");
77103
}
@@ -88,16 +114,6 @@ export default function GroupDetail() {
88114
setCurrentPage(page);
89115
};
90116

91-
const publicMemories = [
92-
{ author: "달봉이아들", visibility: "공개", title: '추억 글 제목', location: '인천 앞바다', date: '24.01.19', tags: ["태그", "길면", "두줄", "낚시", "인천"], likes: 120, comments: 8 },
93-
{ author: "달봉이아들", visibility: "공개", title: '추억 글 제목', location: '인천 앞바다', date: '24.02.01', tags: ["여행", "추억", "가족", "사진"], likes: 98, comments: 12 },
94-
];
95-
96-
const privateMemories = [
97-
{ author: "달봉이아들", visibility: "비공개", title: '추억 글 제목', date: '24.01.19', likes: 120, comments: 8 },
98-
{ author: "달봉이아들", visibility: "비공개", title: '추억 글 제목', date: '24.02.01', likes: 98, comments: 12 },
99-
];
100-
101117
const handleMoreClick = (event) => {
102118
event.preventDefault();
103119
setIsMoreOpen(true);
@@ -111,51 +127,56 @@ export default function GroupDetail() {
111127
return (
112128
<div className="w-full max-w-[1200px] mx-auto py-3">
113129
<div className="flex flex-col md:flex-row p-6 relative">
114-
<img className="w-[180px] h-[180px] rounded-lg object-cover" src="https://placehold.co/180x180" alt="그룹 이미지" />
130+
<img
131+
className="w-[180px] h-[180px] rounded-lg object-cover"
132+
src={group?.imageUrl ? `https://${group.imageUrl}` : "https://placehold.co/180x180"}
133+
alt="그룹 이미지"
134+
/>
115135

116136
<div className="flex-1 ml-6 space-y-4">
117137
<div className="flex items-center space-x-2">
118-
<span className="text-sm text-black">D+265</span>
119-
<span className="text-sm text-darkGray-active">| 공개</span>
138+
<span className="text-sm text-black">{group?.dday || "D+0"}</span>
139+
<span className="text-sm text-darkGray-active">| {group?.isPublic ? "공개" : "비공개"}</span>
120140
</div>
121141
<div className="space-y-2">
122142
<h1 className="text-2xl font-bold text-black">{group?.groupName || "그룹 이름"}</h1>
123143
<p className="text-sm text-darkerGray">{group?.groupDescription || "그룹 설명이 없습니다."}</p>
124-
</div>
144+
</div>
125145

126-
<div className="space-y-2">
127-
<h1 className="mt-5 font-semibold text-base text-darkerGray ml-1">획득배지</h1>
128-
<div className="mt-1 flex flex-col md:flex-row justify-between items-center">
129-
<div className="flex flex-wrap gap-2">
130-
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">👾 7일 연속 추억 등록</span>
131-
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">🌼 그룹 공감 1만 개 이상 받기</span>
132-
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">💖 추억 공감 1만 개 이상 받기</span>
146+
<div className="space-y-2">
147+
<h1 className="mt-5 font-semibold text-base text-darkerGray ml-1">획득배지</h1>
148+
<div className="mt-1 flex flex-col md:flex-row justify-between items-center">
149+
<div className="flex flex-wrap gap-2">
150+
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">👾 7일 연속 추억 등록</span>
151+
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">🌼 그룹 공감 1만 개 이상 받기</span>
152+
<span className="bg-darkWhite text-sm px-3 py-1 rounded-full">💖 추억 공감 1만 개 이상 받기</span>
153+
</div>
154+
155+
<div className="flex space-x-4 mt-3 md:mt-0">
156+
<button className="px-5 py-2 whitespace-nowrap w-[110px] text-white bg-black hover:bg-black-hover active:bg-black-active rounded-lg">참여하기</button>
157+
<button className="flex items-center w-[150px] whitespace-nowrap px-5 py-2 bg-white hover:bg-background active:bg-darkWhite border rounded-lg">
158+
<img src={LogoImage} alt="공감 아이콘" className="w-5 h-5 mr-2" />
159+
공감 보내기
160+
</button>
161+
</div>
133162
</div>
134-
135-
<div className="flex space-x-4 mt-3 md:mt-0">
136-
<button className="px-5 py-2 whitespace-nowrap w-[110px] text-white bg-black hover:bg-black-hover active:bg-black-active rounded-lg">참여하기</button>
137-
<button className="flex items-center w-[150px] whitespace-nowrap px-5 py-2 bg-white hover:bg-background active:bg-darkWhite border rounded-lg">
138-
<img src={LogoImage} alt="공감 아이콘" className="w-5 h-5 mr-2" />
139-
공감 보내기
140-
</button>
141-
</div>
142163
</div>
143-
</div>
144164
</div>
145165

146166
<button className="absolute top-4 right-4" onClick={handleMoreClick}>
147167
<img src={MoreIcon} alt="더보기" />
148168
</button>
149169
</div>
170+
150171
{isModalOpen && <CreateMemory onClose={() => setIsModalOpen(false)} />}
151172
{isMoreOpen && <MoreOptionsModal position={{ x: morePosition.x - 40, y: morePosition.y }} onClose={handleCloseMore} onEdit={() => setShowEditGroup(true)} />}
152173
{showEditGroup && <EditGroup onClose={() => setShowEditGroup(false)} />}
153174

154175
<div className="my-[70px] border-t border-gray-200"></div>
155176

156177
<div>
157-
158-
<div className="flex gap-3 justify-start items-center mb-3">
178+
179+
<div className="flex gap-3 justify-start items-center mb-3">
159180
<h2 className="text-2xl font-semibold text-black">
160181
<span className="text-darkViolet">달봉이네 가족</span>의 추억 목록
161182
</h2>
@@ -164,7 +185,6 @@ export default function GroupDetail() {
164185
</button>
165186

166187
</div>
167-
<GroupTab />
168188

169189
<div className="flex mt-4 items-center gap-5">
170190
<Select options={options} onSelect={handleSelect} value={sortBy} />
@@ -188,23 +208,15 @@ export default function GroupDetail() {
188208
<div className="mt-6 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
189209
{tabName === "Public"
190210
? publicMemories.map((memory, index) =>
191-
<PublicPostCard
192-
key={index}
193-
id={index + 1}
194-
groupId={1}
195-
{...memory}
196-
/>)
211+
<PublicPostCard key={index} id={index + 1} groupId={groupId} {...memory} />
212+
)
197213
: privateMemories.map((memory, index) =>
198-
<PrivatePostCard
199-
key={index}
200-
id={index + 1}
201-
groupId={1}
202-
{...memory}
203-
/>)}
214+
<PrivatePostCard key={index} id={index + 1} groupId={groupId} {...memory} />
215+
)}
204216
</div>
205217

206218
<div className="p-6">
207-
<Pagination
219+
<Pagination
208220
currentPage={currentPage}
209221
totalPages={totalPages}
210222
onPageChange={handlePageChange}

src/services/group/groupService.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ export const createGroup = async (formData) => {
1818
};
1919

2020
/** 그룹 목록 조회 */
21-
export const getGroupList = async ({ type = "", sortBy = "", keyword = "" }) => {
21+
export const getGroupList = async ({ type = "", sortBy = "", keyword = "", page = 1 }) => {
2222
try {
23-
const params = { sortBy };
23+
const params = { sortBy, page };
2424

2525
if (type) {
2626
params.type = type;

0 commit comments

Comments
 (0)