diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx index 1e6af9e7a2..a71ebecb59 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx @@ -33,7 +33,6 @@ import { CancellableOrder } from 'common/utils/isOrderCancellable' import { isOrderOffChainCancellable } from 'common/utils/isOrderOffChainCancellable' import { OrderRow } from './OrderRow' -import { OrdersTablePagination } from './OrdersTablePagination' import { TableGroup } from './TableGroup' import { getOrderParams } from './utils/getOrderParams' @@ -44,6 +43,7 @@ import { OrderTableItem, tableItemsToOrders, } from '../../utils/orderTableGroupUtils' +import { OrdersTablePagination } from '../OrdersTablePagination' // TODO: move elements to styled.jsx diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx deleted file mode 100644 index 926bc01d5f..0000000000 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { UI } from '@cowprotocol/ui' - -import { transparentize } from 'color2k' -import { Link } from 'react-router-dom' -import styled, { css } from 'styled-components/macro' - -export interface OrdersTablePaginationProps { - getPageUrl?(index: number): Partial<{ pathname: string; search: string }> - onPageChange?(index: number): void - pageSize: number - totalCount: number - currentPage: number - className?: string -} - -const PaginationBox = styled.div` - width: 100%; - display: flex; - overflow-x: auto; - text-align: center; - margin: 20px auto 0; - justify-content: center; - font-size: 14px; - font-weight: 500; - - ${({ theme }) => theme.mediaWidth.upToSmall` - justify-content: flex-start; - `}; -` - -const pageButtonStyles = css<{ $active?: boolean }>` - background: ${({ theme, $active }) => ($active ? transparentize(theme.text3, 0.9) : 'transparent')}; - color: ${({ $active }) => ($active ? `var(${UI.COLOR_TEXT})` : `var(${UI.COLOR_TEXT_OPACITY_25})`)}; - border: 0; - outline: 0; - padding: 5px 10px; - border-radius: 4px; - margin: 0 5px; - cursor: pointer; - transition: background var(${UI.ANIMATION_DURATION}) ease-in-out, color var(${UI.ANIMATION_DURATION}) ease-in-out; - text-decoration: none; - - &:hover { - background: var(${UI.COLOR_PAPER}); - color: inherit; - } -` - -const PageButtonLink = styled(Link)` - ${pageButtonStyles} -` - -const PageButton = styled.div` - ${pageButtonStyles} -` - -export function OrdersTablePagination({ - pageSize, - totalCount, - currentPage, - getPageUrl, - onPageChange, - className, -}: OrdersTablePaginationProps) { - const pagesCount = Math.ceil(totalCount / pageSize) - - return ( - - {[...new Array(pagesCount)].map((item, i) => { - const index = i + 1 - - if (onPageChange) { - return ( - onPageChange(index)}> - {index} - - ) - } - - if (getPageUrl) { - return ( - - {index} - - ) - } - - return null - })} - - ) -} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx index 1cfa94045d..5aaa3f5b23 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx @@ -13,12 +13,12 @@ import { BalancesAndAllowances } from 'modules/tokens' import { OrderRow } from './OrderRow' import * as styledEl from './OrderRow/styled' -import { OrdersTablePagination } from './OrdersTablePagination' import { OrderActions } from './types' import { getOrderParams } from './utils/getOrderParams' import { ORDERS_TABLE_PAGE_SIZE } from '../../const/tabs' import { OrderTableGroup } from '../../utils/orderTableGroupUtils' +import { OrdersTablePagination } from '../OrdersTablePagination' const GroupBox = styled.div`` diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/index.tsx new file mode 100644 index 0000000000..b3e81f2ecb --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/index.tsx @@ -0,0 +1,105 @@ +import { useCallback, useMemo } from 'react' + +import { ChevronLeft, ChevronRight } from 'react-feather' + +import { ArrowButton, BlankButton, PageButton, PageButtonLink, PaginationBox } from './styled' + +const PAGES_LIMIT = 14 + +export interface OrdersTablePaginationProps { + getPageUrl?(index: number): Partial<{ pathname: string; search: string }> + onPageChange?(index: number): void + pageSize: number + totalCount: number + currentPage: number + className?: string +} + +export function OrdersTablePagination({ + pageSize, + totalCount, + currentPage, + getPageUrl, + onPageChange, + className, +}: OrdersTablePaginationProps) { + const pagesCount = Math.ceil(totalCount / pageSize) + + const pagesArray = useMemo(() => [...new Array(pagesCount)].map((item, i) => i), [pagesCount]) + + const pageLimitMiddle = Math.ceil(PAGES_LIMIT / 2) + const batchOffset = currentPage > pageLimitMiddle ? currentPage - pageLimitMiddle : 0 + const isListBig = pagesCount > PAGES_LIMIT + const isFirstPagesBatch = currentPage <= pageLimitMiddle + const isLastPagesBatch = currentPage > pagesCount - pageLimitMiddle + + const batchStart = Math.min(batchOffset, pagesCount - PAGES_LIMIT) + const batchEnd = Math.min(PAGES_LIMIT + batchOffset, pagesCount) + + const goToPage = useCallback( + (page: number) => { + if (onPageChange) { + onPageChange(page) + return + } + + if (getPageUrl) { + getPageUrl(page) + return + } + }, + [onPageChange, getPageUrl] + ) + + return ( + + {isListBig && ( + <> + goToPage(Math.max(currentPage - 1, 1))}> + + + {!isFirstPagesBatch && ( + <> + goToPage(1)}>1 + ... + + )} + + )} + {pagesArray.slice(batchStart, batchEnd).map((i) => { + const index = i + 1 + + if (onPageChange) { + return ( + onPageChange(index)}> + {index} + + ) + } + + if (getPageUrl) { + return ( + + {index} + + ) + } + + return null + })} + {isListBig && ( + <> + {!isLastPagesBatch && ( + <> + ... + goToPage(pagesCount)}>{pagesCount} + + )} + goToPage(Math.min(currentPage + 1, pagesCount))}> + + + + )} + + ) +} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/styled.tsx new file mode 100644 index 0000000000..c38f31ddb5 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTablePagination/styled.tsx @@ -0,0 +1,62 @@ +import { UI } from '@cowprotocol/ui' + +import { transparentize } from 'color2k' +import { Link } from 'react-router-dom' +import styled, { css } from 'styled-components/macro' + +export const PaginationBox = styled.div` + width: 100%; + display: flex; + overflow-x: auto; + text-align: center; + margin: 20px auto 0; + justify-content: center; + font-size: 14px; + font-weight: 500; + + ${({ theme }) => theme.mediaWidth.upToSmall` + justify-content: flex-start; + `}; +` +const pageButtonStyles = css<{ $active?: boolean }>` + background: ${({ theme, $active }) => ($active ? transparentize(theme.text3, 0.9) : 'transparent')}; + color: ${({ $active }) => ($active ? `var(${UI.COLOR_TEXT})` : `var(${UI.COLOR_TEXT_OPACITY_25})`)}; + border: 0; + outline: 0; + padding: 5px 6px; + border-radius: 4px; + width: 34px; + margin: 0 5px; + cursor: pointer; + transition: background var(${UI.ANIMATION_DURATION}) ease-in-out, color var(${UI.ANIMATION_DURATION}) ease-in-out; + text-decoration: none; + + &:hover { + background: var(${UI.COLOR_PAPER}); + color: inherit; + } +` +export const PageButtonLink = styled(Link)` + ${pageButtonStyles} +` +export const PageButton = styled.div` + ${pageButtonStyles} +` +export const BlankButton = styled(PageButton)` + cursor: default; + + &:hover { + background: transparent !important; + color: var(${UI.COLOR_TEXT_OPACITY_25}) !important; + } +` +export const ArrowButton = styled.button` + ${pageButtonStyles}; + width: 30px; + height: 30px; + text-align: center; + margin: 0 5px; + padding: 0; + line-height: 0; + border: 1px solid var(${UI.COLOR_TEXT_OPACITY_25}); +`