Skip to content

Commit cbbce25

Browse files
committed
페이지 위치 이동
1 parent 4c8dc50 commit cbbce25

2 files changed

Lines changed: 98 additions & 53 deletions

File tree

src/components/community/Community.css

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,17 +361,18 @@
361361

362362
.pagination-wrapper {
363363
display: flex;
364-
justify-content: space-between;
364+
justify-content: center;
365365
align-items: center;
366-
gap: 16px;
367-
padding-top: 28px;
366+
gap: 24px;
367+
padding-top: 32px;
368368
border-top: 1px solid var(--community-border);
369369
font-size: 14px;
370370
}
371371

372372
.page-numbers {
373-
display: flex;
373+
display: inline-flex;
374374
gap: 8px;
375+
align-items: center;
375376
}
376377

377378
.page-button {
@@ -385,6 +386,11 @@
385386
transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease;
386387
}
387388

389+
.page-button:disabled {
390+
cursor: not-allowed;
391+
opacity: 0.55;
392+
}
393+
388394
.page-button:hover {
389395
border-color: rgba(124, 92, 255, 0.45);
390396
color: var(--community-text);
@@ -410,7 +416,7 @@
410416
position: sticky;
411417
top: 96px;
412418
display: flex;
413-
flex-direction: column;
419+
border-radius: 12px;
414420
gap: 20px;
415421
align-self: start;
416422
}
@@ -423,8 +429,8 @@
423429

424430
.tag-list span {
425431
padding: 6px 10px;
426-
border-radius: 12px;
427-
background: var(--community-soft);
432+
flex-wrap: wrap;
433+
justify-content: center;
428434
color: var(--community-accent);
429435
font-size: 13px;
430436
font-weight: 600;
@@ -529,7 +535,8 @@
529535

530536
.pagination-wrapper {
531537
flex-direction: column;
532-
align-items: flex-start;
538+
align-items: center;
539+
gap: 16px;
533540
}
534541
}
535542

src/components/community/Community.jsx

Lines changed: 83 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ export default function Community() {
1212
const [posts, setPosts] = useState([]);
1313
const [loading, setLoading] = useState(true);
1414
const [error, setError] = useState("");
15-
1615
const [searchInput, setSearchInput] = useState("");
1716
const [tagInput, setTagInput] = useState("");
1817
const [keyword, setKeyword] = useState("");
1918
const [tagKeyword, setTagKeyword] = useState([]);
2019
const [currentPage, setCurrentPage] = useState(1);
21-
const ITEMS_PER_PAGE = 10;
20+
21+
const PAGE_SIZE = 10;
2222

2323
useEffect(() => {
2424
let ignore = false;
@@ -101,7 +101,7 @@ export default function Community() {
101101
return posts;
102102
}
103103

104-
const lowerKeyword = keyword.toLowerCase();
104+
const lowerKeyword = keyword.toLowerCase();
105105

106106
return posts.filter((post) => {
107107
const matchesKeyword = lowerKeyword
@@ -121,18 +121,6 @@ export default function Community() {
121121
});
122122
}, [keyword, tagKeyword, posts]);
123123

124-
useEffect(() => {
125-
setCurrentPage(1);
126-
}, [keyword, tagKeyword]);
127-
128-
useEffect(() => {
129-
const lastPage = Math.max(1, Math.ceil(filteredPosts.length / ITEMS_PER_PAGE));
130-
setCurrentPage((prev) => {
131-
const next = Math.min(prev, lastPage);
132-
return next === prev ? prev : next;
133-
});
134-
}, [filteredPosts.length, ITEMS_PER_PAGE]);
135-
136124
const handleSearchSubmit = (event) => {
137125
event?.preventDefault?.();
138126
const trimmedKeyword = searchInput.trim();
@@ -154,31 +142,43 @@ export default function Community() {
154142
setCurrentPage(1);
155143
};
156144

157-
const totalPages = Math.max(1, Math.ceil(filteredPosts.length / ITEMS_PER_PAGE));
158-
const hasResults = filteredPosts.length > 0;
159-
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
160-
const visiblePosts = useMemo(
161-
() => (hasResults ? filteredPosts.slice(startIndex, startIndex + ITEMS_PER_PAGE) : []),
162-
[filteredPosts, hasResults, startIndex, ITEMS_PER_PAGE]
163-
);
145+
const totalPages = useMemo(() => {
146+
const count = Math.ceil(filteredPosts.length / PAGE_SIZE);
147+
return count > 0 ? count : 1;
148+
}, [filteredPosts.length]);
149+
150+
useEffect(() => {
151+
if (currentPage > totalPages) {
152+
setCurrentPage(totalPages);
153+
}
154+
}, [currentPage, totalPages]);
155+
156+
const pageNumbers = useMemo(() => (
157+
Array.from({ length: totalPages }, (_, index) => index + 1)
158+
), [totalPages]);
159+
160+
const paginatedPosts = useMemo(() => {
161+
const start = (currentPage - 1) * PAGE_SIZE;
162+
const end = start + PAGE_SIZE;
163+
return filteredPosts.slice(start, end);
164+
}, [filteredPosts, currentPage]);
164165

166+
const jumpBy = 5;
165167
const goToPage = (page) => {
166-
const next = Math.min(Math.max(page, 1), Math.max(1, totalPages));
167-
setCurrentPage(next);
168+
if (page < 1 || page > totalPages) return;
169+
setCurrentPage(page);
168170
};
169171

170-
const goToFirst = () => goToPage(1);
171-
const goToLast = () => goToPage(totalPages);
172-
const goToPreviousGroup = () => goToPage(currentPage - 5);
173-
const goToNextGroup = () => goToPage(currentPage + 5);
174-
175-
const pageNumbers = useMemo(() => {
176-
const numbers = [];
177-
for (let i = 1; i <= totalPages; i += 1) {
178-
numbers.push(i);
172+
const handleChunkMove = (direction) => {
173+
const target = currentPage + direction * jumpBy;
174+
if (target < 1) {
175+
setCurrentPage(1);
176+
} else if (target > totalPages) {
177+
setCurrentPage(totalPages);
178+
} else {
179+
setCurrentPage(target);
179180
}
180-
return numbers;
181-
}, [totalPages]);
181+
};
182182

183183
return (
184184
<div className="community-wrapper">
@@ -266,7 +266,7 @@ export default function Community() {
266266

267267
{!loading && !error && filteredPosts.length > 0 && (
268268
<div className="post-list">
269-
{filteredPosts.map((post) => (
269+
{paginatedPosts.map((post) => (
270270
<div
271271
key={post.id}
272272
className="post-card"
@@ -304,16 +304,54 @@ export default function Community() {
304304
</div>
305305
)}
306306

307-
<div className="pagination-wrapper">
308-
<div className="page-numbers">
309-
<button className="page-button active">1</button>
310-
<button className="page-button">2</button>
311-
<button className="page-button">3</button>
312-
<button className="page-button">4</button>
313-
<button className="page-button">5</button>
307+
{filteredPosts.length > 0 && (
308+
<div className="pagination-wrapper">
309+
<div className="page-numbers">
310+
<button
311+
type="button"
312+
className="page-button"
313+
onClick={() => goToPage(1)}
314+
disabled={currentPage === 1}
315+
>
316+
처음
317+
</button>
318+
<button
319+
type="button"
320+
className="page-button"
321+
onClick={() => handleChunkMove(-1)}
322+
disabled={currentPage === 1}
323+
>
324+
-5쪽
325+
</button>
326+
{pageNumbers.map((page) => (
327+
<button
328+
key={page}
329+
type="button"
330+
className={`page-button${page === currentPage ? " active" : ""}`}
331+
onClick={() => goToPage(page)}
332+
>
333+
{page}
334+
</button>
335+
))}
336+
<button
337+
type="button"
338+
className="page-button"
339+
onClick={() => handleChunkMove(1)}
340+
disabled={currentPage === totalPages}
341+
>
342+
+5쪽
343+
</button>
344+
<button
345+
type="button"
346+
className="page-button"
347+
onClick={() => goToPage(totalPages)}
348+
disabled={currentPage === totalPages}
349+
>
350+
마지막
351+
</button>
352+
</div>
314353
</div>
315-
<button className="next-page">다음 페이지</button>
316-
</div>
354+
)}
317355
</main>
318356

319357
<aside className="sidebar-right">

0 commit comments

Comments
 (0)