Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagination implemented #16

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/Button/interfaces/IButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
16 changes: 16 additions & 0 deletions src/components/Icons/ArrowLeftIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

const ArrowLeftIcon = () => (
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d={'M6.71047 0.710469C6.32047 0.320469 5.69047 0.320469 5.30047 0.710469L0.710469 5.30047C0.320469 5.69047'
+ ' 0.320469 6.32047 0.710469 6.71047L5.30047 11.3005C5.69047 11.6905 6.32047 11.6905 6.71047 11.3005C7.10047'
+ ' 10.9105 7.10047 10.2805 6.71047 9.89047L2.83047 6.00047L6.71047 2.12047C7.10047 1.73047 7.09047 1.09047 '
+ '6.71047 0.710469Z'}
fill="#8891A3"
/>
</svg>

);

export default ArrowLeftIcon;
18 changes: 18 additions & 0 deletions src/components/Icons/ArrowRightIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

const ArrowLeftIcon = () => (
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d={'M1.28953 11.2895C1.67953 11.6795 2.30953 11.6795 2.69953 11.2895L7.28953 6.69953C7.67953 6.30953'
+ ' 7.67953 5.67953 7.28953 5.28953L2.69953 0.699532C2.30953 0.309531 1.67953 0.309531 1.28953'
+ ' 0.699532C0.899531 1.08953 0.899531 1.71953 1.28953 2.10953L5.16953 5.99953L1.28953 9.87953C0.899531'
+ ' 10.2695 0.909531 10.9095 1.28953 11.2895Z'}
fill="#8891A3"
/>
</svg>
</svg>

);

export default ArrowLeftIcon;
3 changes: 0 additions & 3 deletions src/components/Icons/Vector.svg

This file was deleted.

4 changes: 4 additions & 0 deletions src/components/Icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -84,4 +86,6 @@ export {
PencilIcon,
CpuIcon,
TrashCanIcon,
ArrowRightIcon,
ArrowLeftIcon,
};
57 changes: 57 additions & 0 deletions src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -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<IPagination> = ({
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 ? (
<div className={styles.container}>
<IconButton
disabled={prevPageActive}
onClick={() => handleSetPage(prevPage)}
icon={<ArrowLeftIcon />}
/>
<PaginationList
currentPage={currentPage}
lastPage={lastPage}
perPage={perPage}
total={total}
setPage={(page) => handleSetPage(page)}
/>
<IconButton
disabled={nextPageActive}
onClick={() => handleSetPage(nextPage)}
icon={<ArrowRightIcon />}
/>
</div>
) : (
<div />
)
);
};

export default Pagination;
45 changes: 45 additions & 0 deletions src/components/Pagination/components/PaginationList.tsx
Original file line number Diff line number Diff line change
@@ -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<IPaginationPage> = ({
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) => (
<Button
className={styles.button}
key={[firstPaginationPage, index].join('_')}
text={`${firstPaginationPage + index}`}
disabled={firstPaginationPage + index === currentPage}
onClick={() => setPage(firstPaginationPage + index)}
/>
))}
</>
);
};

export default PaginationList;
7 changes: 7 additions & 0 deletions src/components/Pagination/interfaces/IPagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface IPagination {
currentPage: number
lastPage: number
total: number
setPage: (pageNumber: number) => void
perPage: number
}
7 changes: 7 additions & 0 deletions src/components/Pagination/interfaces/IPaginationPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface IPaginationPage {
currentPage: number
lastPage: number
perPage: number
total: number
setPage: (pageNumber: number) => void
}
14 changes: 14 additions & 0 deletions src/components/Pagination/sass/Pagination.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.container {
display: flex;
justify-content: center;
align-items: center;
padding: 24px 0;

button:first-child {
margin-right: 4px;
}

button:last-child {
margin-left: 4px;
}
}
7 changes: 7 additions & 0 deletions src/components/Pagination/sass/PaginationList.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.button {
padding: 0;
width: 24px;
min-width: initial;
height: 24px;
margin: 0 4px;
}
5 changes: 5 additions & 0 deletions src/constants/values.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const ONE_PAGE = 1;
export const PAGE_DELIMITER = 2;
export const THREE_PAGES_DELIMITER = 3;

export const ENTRY_DELIMITER = 4;
19 changes: 19 additions & 0 deletions src/stories/Pagination.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Pagination from '../components/Pagination/Pagination';

export default {
title: 'Example/Pagination',
component: Pagination,
} as ComponentMeta<typeof Pagination>;

const Template: ComponentStory<typeof Pagination> = ({ ...args }) => <Pagination {...args} />;

export const Default = Template.bind({});
Default.args = {
currentPage: 3,
perPage: 2,
lastPage: 8,
total: 8,
setPage: () => {},
};
26 changes: 26 additions & 0 deletions src/utils/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ONE_PAGE } from '../constants/values';

export const reduce = (argFirst: number, argSecond: number) => argFirst - argSecond;

export const add = (argFirst: number, argSecond: number) => argFirst + argSecond;

export const bigger = (argFirst: number, argSecond: number) => argFirst > argSecond;

export const lesser = (argFirst: number, argSecond: number) => argFirst < argSecond;

export const calcPage = (
page: number,
perPage: number,
delimiter: number,
max: number,
calcFunc: (argFirst: number, argSecond: number) => number,
boolFunc: (argFirst: number, argSecond: number) => boolean,
) => {
let firstPage = page;

while (boolFunc(firstPage * perPage, max) && boolFunc(firstPage, calcFunc(page, delimiter))) {
firstPage = calcFunc(firstPage, ONE_PAGE);
}

return firstPage;
};