import { useContext } from 'react';
import { store } from '../../store/store';
import styleSheet from './SelectPage.styleSheet';
import { cx } from '../../utils/style/emotion';
/**
* @namespace SelectPage
*/
/**
* The SelectPage component, contain a bunch of buttons to select the page to display : previous x, x, ,x , next.
* If there are more than 5 pages, there is one or two cuts in order to have small amount of buttons.
* Buttons being useless are disabled (current page, or previous when 1st page is selected for exemples).
* @memberof SelectPage
* @function
* @return {React.ReactElement} jsx to be injected in the html.
*/
export const SelectPage = (): React.ReactElement => {
const { currentPage, filteredData, itemsPerPage, width, style, dispatch } =
useContext(store);
const numberOfPages: number =
filteredData.length === 0
? 1
: Math.ceil(filteredData.length / itemsPerPage);
const buttonList: (number | string)[] = ['Previous'];
if (numberOfPages <= 7) {
let i = 1;
while (i <= numberOfPages) {
buttonList.push(i);
i++;
}
} else {
//no more than 7 total page buttons, cut with '...' at one or two position depending on currentPage.
if (currentPage <= 4) buttonList.push(1, 2, 3, 4, 5, '...', numberOfPages);
else if (currentPage >= numberOfPages - 3)
buttonList.push(
1,
'...',
numberOfPages - 4,
numberOfPages - 3,
numberOfPages - 2,
numberOfPages - 1,
numberOfPages
);
else
buttonList.push(
1,
'...',
currentPage - 1,
currentPage,
currentPage + 1,
'...',
numberOfPages
);
}
buttonList.push('Next');
/**
* Dispatch the selected page to the store.
* @memberof SelectPage
* @param {object} event - the event object from the click event.
* @function
*/
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
dispatch({ type: 'setCurrentPage', payload: event.currentTarget.value });
};
/**
* Check if a button should have disabled attribute.
* @memberof SelectPage
* @param {number|string} page - the event object from the click event.
* @function
*/
const isDisabled = (page: number | string) =>
page === currentPage ||
page === '...' ||
(page === 'Previous' && currentPage === 1) ||
(page === 'Next' && currentPage === numberOfPages);
/**
* Check if the button should have the hidden class (previous and next button on small screen if there is lot of page ).
* @memberof SelectPage
* @param {object} event - the event object from the click event.
* @function
*/
const hiddenIfNeeded = (page: number | string) =>
width < 480 && numberOfPages > 5 && (page === 'Previous' || page === 'Next')
? true
: undefined;
/**
* An object containing the classnames generated from the stylesheet made with emotion and using the style state of the store
* @memberof SelectPage
*/
const classNames: { [Class: string]: string } = styleSheet(style);
return (
<div
className={cx(classNames.wrapper, width > 800 && classNames.wrapperLarge)}
>
{buttonList.map((page, i) => (
<button
key={i}
type="button"
disabled={isDisabled(page)}
onClick={handleClick}
data-active={page === currentPage ? true : undefined}
data-hidden={hiddenIfNeeded(page)}
value={page}
className={classNames.button}
>
{page}
</button>
))}
</div>
);
};
Source