From 8d060288406b9ccdd488ff477579a02f9fdc3c45 Mon Sep 17 00:00:00 2001 From: IvanHoncharenko Date: Wed, 17 May 2023 10:11:30 +0300 Subject: [PATCH] Pagination implemented --- src/components/Button/interfaces/IButton.ts | 6 +- src/components/Icons/ArrowLeftIcon.tsx | 16 ++++++ src/components/Icons/ArrowRightIcon.tsx | 18 ++++++ src/components/Icons/Vector.svg | 3 - src/components/Icons/index.tsx | 4 ++ src/components/Pagination/Pagination.tsx | 57 +++++++++++++++++++ .../Pagination/components/PaginationList.tsx | 45 +++++++++++++++ .../Pagination/interfaces/IPagination.ts | 7 +++ .../Pagination/interfaces/IPaginationPage.ts | 7 +++ .../Pagination/sass/Pagination.module.scss | 14 +++++ .../sass/PaginationList.module.scss | 7 +++ src/constants/values.ts | 5 ++ src/stories/Pagination.stories.tsx | 19 +++++++ src/utils/pagination.ts | 26 +++++++++ 14 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/components/Icons/ArrowLeftIcon.tsx create mode 100644 src/components/Icons/ArrowRightIcon.tsx delete mode 100644 src/components/Icons/Vector.svg create mode 100644 src/components/Pagination/Pagination.tsx create mode 100644 src/components/Pagination/components/PaginationList.tsx create mode 100644 src/components/Pagination/interfaces/IPagination.ts create mode 100644 src/components/Pagination/interfaces/IPaginationPage.ts create mode 100644 src/components/Pagination/sass/Pagination.module.scss create mode 100644 src/components/Pagination/sass/PaginationList.module.scss create mode 100644 src/constants/values.ts create mode 100644 src/stories/Pagination.stories.tsx create mode 100644 src/utils/pagination.ts diff --git a/src/components/Button/interfaces/IButton.ts b/src/components/Button/interfaces/IButton.ts index 142e2b8..4946cc9 100644 --- a/src/components/Button/interfaces/IButton.ts +++ b/src/components/Button/interfaces/IButton.ts @@ -4,9 +4,9 @@ import { Colors, Variants, ButtonSizes } from '../../../constants/general'; export interface IButtonProps extends ComponentPropsWithRef<'button'> { text?: string, isLoading?: boolean, - variant: Variants, - color: Colors, - size: ButtonSizes, + variant?: Variants, + color?: Colors, + size?: ButtonSizes, iconLeft?: string, iconRight?: string, } diff --git a/src/components/Icons/ArrowLeftIcon.tsx b/src/components/Icons/ArrowLeftIcon.tsx new file mode 100644 index 0000000..82eb59c --- /dev/null +++ b/src/components/Icons/ArrowLeftIcon.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +const ArrowLeftIcon = () => ( + + + + +); + +export default ArrowLeftIcon; diff --git a/src/components/Icons/ArrowRightIcon.tsx b/src/components/Icons/ArrowRightIcon.tsx new file mode 100644 index 0000000..3340609 --- /dev/null +++ b/src/components/Icons/ArrowRightIcon.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +const ArrowLeftIcon = () => ( + + + + + + +); + +export default ArrowLeftIcon; diff --git a/src/components/Icons/Vector.svg b/src/components/Icons/Vector.svg deleted file mode 100644 index 9890292..0000000 --- a/src/components/Icons/Vector.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/components/Icons/index.tsx b/src/components/Icons/index.tsx index ed8dae1..da5119e 100644 --- a/src/components/Icons/index.tsx +++ b/src/components/Icons/index.tsx @@ -40,6 +40,8 @@ import BriefcaseIcon from './BriefcaseIcon'; import PencilIcon from './PencilIcon'; import CpuIcon from './CpuIcon'; import TrashCanIcon from './TrashCanIcon'; +import ArrowRightIcon from './ArrowRightIcon'; +import ArrowLeftIcon from './ArrowLeftIcon'; export { CloseIcon, @@ -84,4 +86,6 @@ export { PencilIcon, CpuIcon, TrashCanIcon, + ArrowRightIcon, + ArrowLeftIcon, }; diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx new file mode 100644 index 0000000..20a3c18 --- /dev/null +++ b/src/components/Pagination/Pagination.tsx @@ -0,0 +1,57 @@ +import React, { FC, useEffect } from 'react'; +import IconButton from '../IconButton/IconButton'; +import PaginationList from './components/PaginationList'; +import { ArrowRightIcon, ArrowLeftIcon } from '../Icons'; +import { IPagination } from './interfaces/IPagination'; +import styles from './sass/Pagination.module.scss'; + +const Pagination: FC = ({ + currentPage, lastPage, total, setPage, perPage, +}) => { + const prevPage = currentPage - 1; + const prevPageActive = prevPage < 1; + const nextPage = currentPage + 1; + const nextPageActive = nextPage > lastPage; + + const handleSetPage = (page: number) => { + setPage(page); + window.scrollTo({ + top: 0, + behavior: 'smooth', + }); + }; + + useEffect(() => { + if (currentPage > lastPage) { + setPage(lastPage); + } + }, [setPage, currentPage, lastPage]); + + return ( + perPage < total ? ( +
+ handleSetPage(prevPage)} + icon={} + /> + handleSetPage(page)} + /> + handleSetPage(nextPage)} + icon={} + /> +
+ ) : ( +
+ ) + ); +}; + +export default Pagination; diff --git a/src/components/Pagination/components/PaginationList.tsx b/src/components/Pagination/components/PaginationList.tsx new file mode 100644 index 0000000..a4907a2 --- /dev/null +++ b/src/components/Pagination/components/PaginationList.tsx @@ -0,0 +1,45 @@ +import React, { FC } from 'react'; +import { IPaginationPage } from '../interfaces/IPaginationPage'; +import Button from '../../Button/Button'; +import { + ONE_PAGE, PAGE_DELIMITER, THREE_PAGES_DELIMITER, ENTRY_DELIMITER, +} from '../../../constants/values'; +import { + calcPage, add, lesser, reduce, bigger, +} from '../../../utils/pagination'; +import styles from '../sass/PaginationList.module.scss'; + +const PaginationList: FC = ({ + currentPage, lastPage, perPage, total, setPage, +}) => { + let firstPaginationPage = calcPage(currentPage, perPage, ONE_PAGE, perPage, reduce, bigger); + let lastPaginationPage = calcPage(currentPage, perPage, ENTRY_DELIMITER, total, add, lesser); + if (currentPage === PAGE_DELIMITER) { + firstPaginationPage = calcPage(currentPage, perPage, PAGE_DELIMITER, perPage, reduce, bigger); + lastPaginationPage = calcPage(currentPage, perPage, THREE_PAGES_DELIMITER, total, add, lesser); + } else if (currentPage > PAGE_DELIMITER && currentPage <= lastPage - PAGE_DELIMITER) { + firstPaginationPage = calcPage(currentPage, perPage, PAGE_DELIMITER, perPage, reduce, bigger); + lastPaginationPage = calcPage(currentPage, perPage, PAGE_DELIMITER, total, add, lesser); + } else if (currentPage > lastPage - PAGE_DELIMITER) { + firstPaginationPage = calcPage(lastPage, perPage, ENTRY_DELIMITER, perPage, reduce, bigger); + lastPaginationPage = lastPage; + } + + const links = new Array(lastPaginationPage - firstPaginationPage + 1).fill(null); + + return ( + <> + {links.map((item, index) => ( +