Skip to content

E. Pagination

components/Pagination.tsx
import React, { ChangeEvent, ReactNode } from "react";
import Select from "./Select";
import clsx from "clsx";

interface PaginationProps {
  handlePageSize: (e: ChangeEvent<any>) => void;
  handlePage: (page : number) => void;

  page: number | string;
  pageSize: number | string;

  pagination:
    | {
        page: number;
        pageSize: number;
        total: number;
        total_page: number;
      }
    | undefined;
}

export const Pagination: React.FC<PaginationProps> = ({
  handlePageSize,
  handlePage,
  pagination,
  page,
  pageSize,
}) => {
  function getPage(totalItems: number, currentPage: number, pageSize: number) {
    currentPage = currentPage;

    pageSize = pageSize;

    // calculate total pages
    let totalPages = Math.ceil(totalItems / pageSize);

    let startPage: number, endPage: number;
    if (totalPages <= 10) {
      // less than 10 total pages so show all
      startPage = 1;
      endPage = totalPages;
    } else {
      // more than 10 total pages so calculate start and end pages
      if (currentPage <= 6) {
        startPage = 1;
        endPage = 10;
      } else if (currentPage + 4 >= totalPages) {
        startPage = totalPages - 9;
        endPage = totalPages;
      } else {
        startPage = currentPage - 5;
        endPage = currentPage + 4;
      }
    }

    // calculate start and end item indexes
    let startIndex = (currentPage - 1) * pageSize;
    let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);

    // create an array of pages to ng-repeat in the pager control
    const pages = Array.from(
      { length: endPage + 1 - startPage },
      (_, i) => startPage + i
    );

    // return object with all pager properties required by the view
    return {
      totalItems: totalItems,
      currentPage: currentPage,
      pageSize: pageSize,
      totalPages: totalPages,
      startPage: startPage,
      endPage: endPage,
      startIndex: startIndex,
      endIndex: endIndex,
      pages: pages,
    };
  }
  let pages = getPage(
    pagination?.total || 0,
    pagination?.page || 1,
    pagination?.pageSize || 10
  );

  return (
    <div className="flex items-center justify-between mt-6">
      <div>
        <select
          value={pageSize}
          onChange={handlePageSize}
          className="px-2 py-1 text-sm text-blue-500 rounded-md  border"
        >
          <option value={1}>1</option>
          <option value={5}>5</option>
          <option value={10}>10</option>
          <option value={25}>25</option>
          <option value={50}>50</option>
          <option value={100}>100</option>
        </select>
      </div>

      <div className="items-center hidden md:flex gap-x-3">
        {pages.pages.map((pageItem, index) => (
          <button
            key={index}
            onClick={()=> {
              handlePage(pageItem)
            }}
            className={clsx(
              `px-4 py-2 rounded-full text-sm `,
              {
                "text-blue-500   bg-blue-100/60": page === pageItem,
                "text-blue-500  border  border-blue-100/60": page !== pageItem,
              },
              {}
            )}
          >
            {pageItem}
          </button>
        ))}
      </div>
    </div>
  );
};