Skip to content

Commit 7170ed2

Browse files
authored
Merge pull request #50 from DeveloperBlog-Devflow/feature/til-manage-page
feat: 페이지네이션 추가
2 parents 5809b2e + e3e8263 commit 7170ed2

2 files changed

Lines changed: 131 additions & 1 deletion

File tree

app/(with-sidebar)/tils/page.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { fetchTilList } from '@/services/tils/tilListService.service';
1111
import { deleteTil } from '@/services/write/til.service';
1212

1313
import type { TilItem } from '@/types/til';
14+
import Pagination from '@/components/common/Pagination';
1415

1516
const Page = () => {
1617
const { user, authLoading } = useAuthUser();
@@ -23,6 +24,9 @@ const Page = () => {
2324

2425
const [searchTerm, setSearchTerm] = useState('');
2526

27+
const [currentPage, setCurrentPage] = useState(1);
28+
const itemsPerPage = 4;
29+
2630
// 데이터 가져오기
2731
useEffect(() => {
2832
if (!user) {
@@ -64,6 +68,27 @@ const Page = () => {
6468
setSortedItems(sorted);
6569
}, [items, sort, searchTerm]);
6670

71+
const totalPages = Math.ceil(sortedItems.length / itemsPerPage);
72+
73+
useEffect(() => {
74+
if (totalPages === 0) {
75+
if (currentPage !== 1) setCurrentPage(1);
76+
return;
77+
}
78+
if (currentPage > totalPages) {
79+
setCurrentPage(totalPages);
80+
}
81+
}, [totalPages, currentPage]);
82+
83+
const currentData = sortedItems.slice(
84+
(currentPage - 1) * itemsPerPage,
85+
currentPage * itemsPerPage
86+
);
87+
88+
const handlePageChange = (page: number) => {
89+
setCurrentPage(page);
90+
};
91+
6792
const handleDelete = async (id: string) => {
6893
if (!user) return;
6994

@@ -115,8 +140,14 @@ const Page = () => {
115140
{loading ? (
116141
<p className="text-sm text-slate-400">불러오는 중...</p>
117142
) : (
118-
<TilList items={sortedItems} onDelete={handleDelete} />
143+
<TilList items={currentData} onDelete={handleDelete} />
119144
)}
145+
146+
<Pagination
147+
currentPage={currentPage}
148+
totalPages={totalPages}
149+
onPageChange={handlePageChange}
150+
/>
120151
</div>
121152
);
122153
};

components/common/Pagination.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
type PaginationProps = {
2+
totalPages: number;
3+
currentPage: number;
4+
onPageChange: (page: number) => void;
5+
};
6+
7+
const Pagination = ({
8+
totalPages,
9+
currentPage,
10+
onPageChange,
11+
}: PaginationProps) => {
12+
const handleClick = (page: number) => {
13+
if (page < 1 || page > totalPages) return;
14+
onPageChange(page);
15+
};
16+
17+
const getPages = (): number[] => {
18+
const pages: number[] = [];
19+
const maxVisible = 5;
20+
21+
let start = Math.max(1, currentPage - Math.floor(maxVisible / 2));
22+
const end = Math.min(totalPages, start + maxVisible - 1);
23+
24+
if (end - start < maxVisible - 1) {
25+
start = Math.max(1, end - maxVisible + 1);
26+
}
27+
28+
for (let i = start; i <= end; i++) pages.push(i);
29+
return pages;
30+
};
31+
32+
const pages = getPages();
33+
34+
const baseBtn =
35+
'border-0 bg-transparent cursor-pointer text-[16px] font-medium text-[#616161] px-[10px] py-[6px] rounded-[6px] transition-all duration-200 ease-in-out';
36+
const activeBtn = '!bg-[#616161] text-white';
37+
const disabledBtn = 'disabled:text-[#ccc] disabled:cursor-not-allowed';
38+
39+
return (
40+
<div className="mt-7.5 flex items-center justify-center gap-1.5">
41+
<button
42+
className={`${baseBtn} ${disabledBtn}`}
43+
onClick={() => handleClick(currentPage - 1)}
44+
disabled={currentPage === 1}
45+
type="button"
46+
>
47+
&lt; 이전
48+
</button>
49+
50+
{pages[0] > 1 && (
51+
<>
52+
<button
53+
className={baseBtn}
54+
onClick={() => handleClick(1)}
55+
type="button"
56+
>
57+
1
58+
</button>
59+
{totalPages > 10 && <span className="px-1 text-[#888]">...</span>}
60+
</>
61+
)}
62+
63+
{pages.map((page) => (
64+
<button
65+
key={page}
66+
className={`${baseBtn} ${page === currentPage ? activeBtn : ''}`}
67+
onClick={() => handleClick(page)}
68+
type="button"
69+
>
70+
{page}
71+
</button>
72+
))}
73+
74+
{pages[pages.length - 1] < totalPages && (
75+
<>
76+
{totalPages > 10 && <span className="px-1 text-[#888]">...</span>}
77+
<button
78+
className={baseBtn}
79+
onClick={() => handleClick(totalPages)}
80+
type="button"
81+
>
82+
{totalPages}
83+
</button>
84+
</>
85+
)}
86+
87+
<button
88+
className={`${baseBtn} ${disabledBtn}`}
89+
onClick={() => handleClick(currentPage + 1)}
90+
disabled={currentPage === totalPages}
91+
type="button"
92+
>
93+
다음 &gt;
94+
</button>
95+
</div>
96+
);
97+
};
98+
99+
export default Pagination;

0 commit comments

Comments
 (0)