pageNation 스닙팻

악음·2022년 4월 11일
0

기능구현

목록 보기
1/4
// base
// base
import Image from 'next/image';
import React, {
  Dispatch,
  HTMLAttributes,
  SetStateAction,
  useCallback,
  useEffect,
  useMemo,
} from 'react';

// images
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 {
        // 페이지 블록만큼 감소
        // setPage(currentPage - blockLength);

        // 이전블록의 첫번째
        const getForwardPagingState = getPageStates(currentPage - blockLength);
        setPage(getForwardPagingState.pageBlocks[0]);
      }
    } else if (where === 'nextBlock') {
      const getForwardPagingState = getPageStates(currentPage + blockLength);

      // 패이지 불록만큼 증가.
      // if (currentPage + blockLength > pagingState.pageCount) {
      //   return setPage(pagingState.pageCount);
      // } else {
      //   setPage(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;


profile
RN/react.js개발자이며 배운것들을 제가 보기위해서 정리하기 때문에 비속어 오타가 있을수있습니다.

0개의 댓글