import Image from 'next/image';
import React, {
Dispatch,
HTMLAttributes,
SetStateAction,
useCallback,
useEffect,
useMemo,
} from 'react';
import iconArrowRight from 'assets/images/iconArrowRight.png';
import iconArrowLeft from 'assets/images/iconArrowLeft.png';
interface PaginationProps {
dataLength: number;
showItemLength: number;
blockLength: number;
setPage: Dispatch<SetStateAction<number>>;
currentPage: number;
container?: HTMLAttributes<HTMLDivElement>;
}
function Pagination({
dataLength,
showItemLength,
blockLength,
currentPage,
setPage,
container,
}: PaginationProps) {
const getPageStates = useCallback(
(paramsCurrentPage: number) => {
const totalCount = dataLength;
let pageCount =
totalCount / showItemLength + (showItemLength % totalCount > 0 ? 1 : 0);
pageCount = Math.floor(pageCount);
if (pageCount === 0) pageCount++;
if (totalCount % showItemLength === 0 && totalCount > showItemLength) {
pageCount--;
}
const start =
paramsCurrentPage === 1 ? 0 : (paramsCurrentPage - 1) * showItemLength;
const number = totalCount - (paramsCurrentPage - 1) * showItemLength;
let startPage = Math.floor(paramsCurrentPage / blockLength);
startPage = startPage * blockLength + 1;
if (paramsCurrentPage % blockLength === 0) startPage -= blockLength;
let endPage = startPage + blockLength - 1;
if (endPage > pageCount) endPage = pageCount;
endPage = Math.floor(endPage);
const pageBlocks: number[] = [];
for (let i = startPage; i <= endPage; i++) {
pageBlocks.push(i);
}
return {
endPage,
number,
pageCount,
start,
startPage,
totalCount,
pageBlocks,
};
},
[blockLength, dataLength, showItemLength]
);
const pagingState = useMemo(
() => getPageStates(currentPage),
[currentPage, getPageStates]
);
const pageHandler = (
where:
| 'first'
| 'last'
| 'plus'
| 'minus'
| 'switchPage'
| 'prevBlock'
| 'nextBlock',
pageNum?: number
) => {
if (where === 'first') {
setPage(1);
} else if (where === 'last') {
setPage(pagingState.pageCount);
} else if (where === 'plus') {
currentPage !== pagingState.pageCount && setPage(currentPage + 1);
} else if (where === 'minus') {
currentPage > 1 && pagingState.pageCount && setPage(currentPage - 1);
} else if (where === 'switchPage') {
if (pageNum) setPage(pageNum);
} else if (where === 'prevBlock') {
if (currentPage - blockLength < 1) {
setPage(1);
} else {
const getForwardPagingState = getPageStates(currentPage - blockLength);
setPage(getForwardPagingState.pageBlocks[0]);
}
} else if (where === 'nextBlock') {
const getForwardPagingState = getPageStates(currentPage + blockLength);
if (getForwardPagingState.pageBlocks[0] > pagingState.pageCount) {
setPage(pagingState.pageCount);
} else {
setPage(getForwardPagingState.pageBlocks[0]);
}
}
};
const isShowFirst = pagingState.pageBlocks.indexOf(1) !== -1;
const isShowLast =
pagingState.pageBlocks.indexOf(pagingState.pageCount) !== -1;
return (
<div {...container}>
<div
className="
flex flex-row items-center
justify-center py-[20px]"
>
<button
className="paginationButton pr-[8px]"
onClick={() => pageHandler('prevBlock')}
disabled={isShowFirst}
>
<Image src={iconArrowLeft} alt="arrowLeft" />
이전
</button>
<div className="ml-[7px] mr-[12px] h-[12px] w-[1px] bg-[#eee]"></div>
<div className="flex items-center">
<div className={`${isShowFirst && 'hidden'}`}>
<button
className="px-[10px] text-[0.875rem] text-txtHint"
onClick={() => pageHandler('first')}
>
1
</button>
<span className="text-txtHint">...</span>
</div>
<div className="flex items-center justify-center">
{pagingState.pageBlocks.map((item) => {
return (
<div
key={item}
className={`
${
item === currentPage
? 'font-bold text-txtBasic'
: 'text-txtHint'
}
flex cursor-pointer items-center justify-center
px-[10px] text-[0.875rem]`}
onClick={() => pageHandler('switchPage', item)}
>
{item}
</div>
);
})}
</div>
<div className={`${isShowLast && 'hidden'}`}>
<span className="text-txtHint">...</span>
<button
className="px-[10px] text-[0.875rem] text-txtHint"
onClick={() => pageHandler('last')}
>
{pagingState.pageCount}
</button>
</div>
</div>
<div className="mr-[7px] ml-[12px] h-[12px] w-[1px] bg-[#eee]"></div>
<button
className="paginationButton pl-[8px]"
onClick={() => pageHandler('nextBlock')}
disabled={isShowLast}
>
다음
<Image src={iconArrowRight} alt="arrowRight" />
</button>
</div>
</div>
);
}
export default Pagination;