Skip to content

Commit 62d67cd

Browse files
authored
feat : 재사용 가능한 페이지네이션 구현 (#92)
1 parent ae17500 commit 62d67cd

File tree

2 files changed

+111
-40
lines changed

2 files changed

+111
-40
lines changed

src/pages/Admin/Report.tsx

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AlarmIcon } from '@/assets/icons';
55

66
import AdminPageTitle from './components/AdminPageTitle';
77
import ListHeaderFrame from './components/ListHeaderFrame';
8+
import PagenationNavigation from './components/PagenationNavigation';
89
import ReportDetailModal from './components/ReportDetailModal';
910
import ReportHandlingModal from './components/ReportHandlingModal';
1011
import ReportListItem from './components/ReportListItem';
@@ -19,28 +20,33 @@ export default function ReportManage() {
1920
currentPage: '1',
2021
totalPages: '0',
2122
});
23+
2224
const [selectedReport, setSelectReport] = useState<Report | null>(null);
2325
const [selectedReportId, setSelectedReportId] = useState<number | null>(null);
2426

25-
// const [allReports, setAllReports] = useState();
26-
2727
const [reportQueryString, setReportQueryString] = useState<ReportQueryString>({
2828
reportType: null,
2929
status: 'PENDING',
3030
page: '1',
31-
size: '3',
31+
size: '2',
3232
});
33+
3334
const handleGetReports = async (reportQueryString: ReportQueryString) => {
3435
const res = await getReports(reportQueryString);
3536
if (res?.status === 200) {
36-
console.log(res.data.data.content);
37-
setReports(res.data.data.content);
37+
const data = res.data.data;
38+
setReports(data.content);
3839
setReportPages(() => ({
39-
currentPage: res.data.data.currentPage,
40-
totalPages: res.data.data.totalPages,
40+
currentPage: data.currentPage,
41+
totalPages: data.totalPages,
4142
}));
4243
}
4344
};
45+
46+
const handleNowPage = (page: string) => {
47+
setReportQueryString((cur) => ({ ...cur, page: page }));
48+
};
49+
4450
useEffect(() => {
4551
handleGetReports(reportQueryString);
4652
}, [reportQueryString]);
@@ -68,39 +74,11 @@ export default function ReportManage() {
6874
setSelectReport={setSelectReport}
6975
/>
7076
))}
71-
<div className="bg-accent-1 mt-5 flex h-10 w-full items-center justify-center">
72-
<div className="flex gap-2">
73-
<button
74-
className="h-full w-10 rounded-2xl border bg-white"
75-
onClick={() => {
76-
const nowPage = Number(reportQueryString.page);
77-
if (nowPage > 1) {
78-
const newPage = (nowPage - 1).toString();
79-
setReportQueryString((cur) => ({ ...cur, page: newPage }));
80-
}
81-
}}
82-
>
83-
84-
</button>
85-
<span>
86-
{reportPages.currentPage}/{reportPages.totalPages}
87-
</span>
88-
<button
89-
className="h-full w-10 rounded-2xl border bg-white"
90-
onClick={() => {
91-
const nowPage = Number(reportQueryString.page);
92-
const totalPage = Number(reportPages.totalPages);
93-
if (nowPage < totalPage) {
94-
const newPage = (nowPage + 1).toString();
95-
console.log(newPage);
96-
setReportQueryString((cur) => ({ ...cur, page: newPage }));
97-
}
98-
}}
99-
>
100-
101-
</button>
102-
</div>
103-
</div>
77+
<PagenationNavigation
78+
totalPage={Number(reportPages.totalPages)}
79+
buttonLength={3}
80+
handlePageNumberButtonClick={handleNowPage}
81+
/>
10482
</section>
10583
{detailModalOpen && (
10684
<ReportDetailModal selectedReport={selectedReport} closeEvent={setDetailModalOpen} />
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { useState } from 'react';
2+
import { twMerge } from 'tailwind-merge';
3+
4+
interface PagenationNavigation {
5+
totalPage: number;
6+
buttonLength: number;
7+
handlePageNumberButtonClick: (page: string) => void;
8+
}
9+
export default function PagenationNavigation({
10+
totalPage,
11+
buttonLength,
12+
handlePageNumberButtonClick,
13+
}: PagenationNavigation) {
14+
const totalSection = Math.ceil(totalPage / buttonLength) - 1;
15+
const [nowSection, setNowSection] = useState<number>(0);
16+
const [nowPageNumberAt, setNowPageNumberAt] = useState(1);
17+
18+
// 네비게이션 시작점, 끝점
19+
const navigationRange = {
20+
start: nowSection * buttonLength + 1,
21+
end: nowSection * buttonLength + buttonLength,
22+
};
23+
24+
// 페이지 버튼 배열
25+
const pageNumberButtonArray = Array.from(
26+
{ length: navigationRange.end - navigationRange.start + 1 },
27+
(_, index) => navigationRange.start + index,
28+
);
29+
30+
// 페이지 버튼 클릭시 해당 번호값이 파라미터에 담김
31+
const handlePageButtonClick = (page: number) => {
32+
const pageString = page.toString();
33+
handlePageNumberButtonClick(pageString);
34+
setNowPageNumberAt(page);
35+
};
36+
37+
const handlePrevButtonClick = () => {
38+
if (nowSection > 0) {
39+
const prev = (nowSection - 1) * buttonLength + buttonLength;
40+
setNowSection((cur) => cur - 1);
41+
handlePageButtonClick(prev);
42+
}
43+
};
44+
45+
const handleNextButtonClick = () => {
46+
if (nowSection < totalSection) {
47+
const next = (nowSection + 1) * buttonLength + 1;
48+
setNowSection((cur) => cur + 1);
49+
handlePageButtonClick(next);
50+
}
51+
};
52+
53+
const buttonStyle = 'border bg-white px-2 py-1 disabled:bg-gray-20';
54+
55+
return (
56+
<div className="mt-5 flex h-10 w-full items-center justify-center">
57+
<div className="flex items-center">
58+
<button
59+
className={twMerge(buttonStyle)}
60+
disabled={nowSection <= 0}
61+
onClick={() => {
62+
handlePrevButtonClick();
63+
}}
64+
>
65+
prev
66+
</button>
67+
{pageNumberButtonArray.map((num) => {
68+
if (totalPage < num) return null;
69+
return (
70+
<button
71+
key={num}
72+
className={twMerge(buttonStyle, nowPageNumberAt === num && 'bg-accent-3')}
73+
onClick={() => {
74+
handlePageButtonClick(num);
75+
}}
76+
>
77+
{num}
78+
</button>
79+
);
80+
})}
81+
<button
82+
className={twMerge(buttonStyle)}
83+
disabled={nowSection >= totalSection}
84+
onClick={() => {
85+
handleNextButtonClick();
86+
}}
87+
>
88+
next
89+
</button>
90+
</div>
91+
</div>
92+
);
93+
}

0 commit comments

Comments
 (0)