/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* OpenCRVS is also distributed under the terms of the Civil Registration
* & Healthcare Disclaimer located at http://opencrvs.org/license.
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import * as React from 'react'
import styled from 'styled-components'
import { Button } from '../Button'
import { Icon } from '../Icon'
export type IPaginationVariant = 'small' | 'large' // small for desktop and large for mobile
export interface IPaginationProps {
currentPage: number
totalPages: number
onPageChange: (page: number) => void
siblingCount?: number
}
const PaginationWrapper = styled.div`
display: flex;
align-items: center;
`
const DesktopWrapper = styled.div`
display: flex;
float: left;
@media only screen and (max-width: 1023px) {
display: none;
}
`
const MobileWrapper = styled.div`
display: none;
@media only screen and (max-width: 1023px) {
display: inline-flex;
align-items: center;
margin-left: auto;
margin-right: auto;
}
`
const PaginationContainer = styled.div`
height: 40px;
padding: 8px;
display: flex;
align-items: center;
justify-content: center;
`
const StyledPagination = styled.div`
display: flex;
flex-direction: row;
align-items: center;
gap: 2px;
`
const PageNumberButton = styled(Button)`
height: 24px;
`
const DotsButton = styled(Button)`
height: 24px;
`
const StyledPageNumber = styled.span<{ isCurrentPage: boolean; size?: string }>`
${({ theme, size }) =>
size && size === 'large' ? theme.fonts.h4 : theme.fonts.bold12};
color: ${({ theme, isCurrentPage }) =>
isCurrentPage ? theme.colors.grey600 : theme.colors.grey400};
`
export const Pagination = ({
totalPages,
currentPage,
onPageChange
}: IPaginationProps) => {
const handleCurrentPage = () =>
totalPages > 0 ? (currentPage && currentPage > 0 ? currentPage : 1) : 0
const pageRange = (start: number, end: number) => {
const length = end - start + 1
return Array.from({ length }, (_, idx) => idx + start)
}
const paginationRow = (
currentPage: number,
totalPages: number,
siblingCount: number
) => {
if (totalPages <= 6) {
return pageRange(1, totalPages)
}
const DOTs = '...'
const leftRangeIndex = Math.max(currentPage - siblingCount, 1)
const rightRangeIndex = Math.min(currentPage + siblingCount, totalPages)
const showLeftDots = leftRangeIndex > 3
const showRightDots = rightRangeIndex < totalPages - 2
if (showLeftDots && showRightDots) {
const middleRange = pageRange(leftRangeIndex, rightRangeIndex)
return [1, DOTs, ...middleRange, DOTs, totalPages]
} else if (showLeftDots && !showRightDots) {
const rightItemsCount = 3 + 2 * siblingCount
const rightRange = pageRange(totalPages - rightItemsCount + 1, totalPages)
return [1, DOTs, ...rightRange]
} else if (!showLeftDots && showRightDots) {
const leftItemsCount = 3 + 2 * siblingCount
const leftRange = pageRange(1, leftItemsCount)
return [...leftRange, DOTs, totalPages]
}
return pageRange(1, totalPages)
}
const currentPageValue = handleCurrentPage()
const canGoToPreviousPage = currentPageValue > 1
const canGoToNextPage = currentPageValue + 1 <= totalPages
const changePage = (page: number | string) => {
if (typeof page === 'number') {
onPageChange(page)
}
}
const renderPages = (size: IPaginationVariant) => {
const currentPage = handleCurrentPage()
if (currentPage > totalPages) {
changePage(totalPages)
}
const pages = paginationRow(currentPage, totalPages, 1)
return (
)
}
return (
)
}