-
Notifications
You must be signed in to change notification settings - Fork 1
✨ feat: 페이지네이션 구현 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
569f574
697f61e
112bcbe
17f2bce
8a282a1
c8738a4
752294b
5385973
f3b12ca
a313932
3bdfda4
124ae07
8ebe3c0
2e94368
212604e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Moon-ju-young marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,117 @@ | ||||||
| import ArrowLeft from '@/assets/icons/arrow-left.svg'; | ||||||
| import ArrowLeftGray from '@/assets/icons/arrow-left-gray.svg'; | ||||||
| import ArrowRight from '@/assets/icons/arrow-right.svg'; | ||||||
|
|
||||||
| interface Props { | ||||||
| totalPages: number; | ||||||
| currentPage: number; | ||||||
| setCurrentPage: React.Dispatch<React.SetStateAction<number>>; | ||||||
| } | ||||||
|
|
||||||
| export default function Pagination({ | ||||||
| totalPages, | ||||||
| currentPage, | ||||||
| setCurrentPage, | ||||||
| }: Props) { | ||||||
| const handleClick = (page: number) => { | ||||||
| setCurrentPage(page); | ||||||
| }; | ||||||
|
|
||||||
| const range = (start: number, end: number) => { | ||||||
| return Array.from({ length: end - start + 1 }, (_, i) => start + i); | ||||||
| }; | ||||||
|
|
||||||
| const renderButtons = () => { | ||||||
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| const buttons: React.ReactNode[] = []; | ||||||
|
|
||||||
| if (totalPages <= 7) { | ||||||
| for (let page = 1; page <= totalPages; page++) { | ||||||
| buttons.push( | ||||||
| <button | ||||||
| key={page} | ||||||
| type="button" | ||||||
| onClick={() => handleClick(page)} | ||||||
| className={`flex h-10 w-10 items-center justify-center rounded text-sm ${ | ||||||
|
||||||
| className={`flex h-10 w-10 items-center justify-center rounded text-sm ${ | |
| className={`flex size-10 items-center justify-center rounded text-body2 ${ |
💬 height와 width가 같은 경우 size로 쓸 수 있습니다~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 감사합니다!! tailwind가 익숙하지 않다보니...감사합니당
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ hover 스타일은 임의로 추가하신 건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ux적으로 저런 호버 있는 사이트들이 많아서 넣었는데 다시 보니까 그렇게 필요하지 않을 듯 합니다
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import ArrowLeft from '../../../assets/icons/arrow-left.svg'; | ||
| import ArrowLeftGray from '../../../assets/icons/arrow-left-gray.svg'; | ||
| import ArrowRight from '../../../assets/icons/arrow-right.svg'; | ||
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| interface Props { | ||
| totalPages: number; | ||
| currentPage: number; | ||
| onChangePage: (pageNumber: number) => void; | ||
Moon-ju-young marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| export default function Pagination({ | ||
| totalPages, | ||
| currentPage, | ||
| onChangePage, | ||
| }: Props) { | ||
| const groupSize = 7; | ||
| const currentGroup = Math.floor((currentPage - 1) / groupSize); | ||
| const groupStart = currentGroup * groupSize + 1; | ||
| const groupEnd = Math.min(groupStart + groupSize - 1, totalPages); | ||
|
|
||
| const renderPageNumbers = () => { | ||
| return Array.from( | ||
| { length: groupEnd - groupStart + 1 }, | ||
| (_, index) => groupStart + index, | ||
| ).map((pageNumber) => ( | ||
| <button | ||
| key={pageNumber} | ||
| type="button" | ||
| onClick={() => onChangePage(pageNumber)} | ||
| className={`w-10 h-10 rounded flex items-center justify-center text-sm ${ | ||
| currentPage === pageNumber | ||
| ? 'text-white font-bold' | ||
| : 'text-black hover:bg-gray-100' | ||
| }`} | ||
| style={{ | ||
| backgroundColor: currentPage === pageNumber ? '#FF8D72' : '#ffffff', | ||
| }} | ||
| > | ||
| {pageNumber} | ||
| </button> | ||
| )); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex items-center justify-center gap-4"> | ||
| {/* 이전 그룹 이동 */} | ||
| {totalPages > groupSize && groupStart > 1 && ( | ||
| <button type="button" onClick={() => onChangePage(groupStart - 1)}> | ||
| <img | ||
| src={groupStart - 1 === 1 ? ArrowLeftGray : ArrowLeft} | ||
| alt="이전 페이지 그룹" | ||
| className="w-5 h-5" | ||
| /> | ||
| </button> | ||
| )} | ||
|
|
||
| {/* 페이지 번호 */} | ||
| <div className="flex gap-1">{renderPageNumbers()}</div> | ||
|
|
||
| {/* 다음 그룹 이동 */} | ||
| {totalPages > groupSize && groupEnd < totalPages && ( | ||
| <button type="button" onClick={() => onChangePage(groupEnd + 1)}> | ||
| <img src={ArrowRight} alt="다음 페이지 그룹" className="w-5 h-5" /> | ||
| </button> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.