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

FRDQ-116 - Configure RTK Query with RTK and Pagination component #138

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
5,159 changes: 2,739 additions & 2,420 deletions package-lock.json

Large diffs are not rendered by default.

59 changes: 35 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.21.0",
"@reduxjs/toolkit": "^1.4.0",
"@storybook/react": "^6.0.20",
"@storybook/react": "^6.0.20",
"@types/lodash": "^4.14.165",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
Expand All @@ -13,12 +14,12 @@
"@types/styled-components": "^5.1.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-hook-form": "^6.12.0",
"react-hook-form": "^6.12.0",
"react-redux": "^7.2.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"styled-components": "^5.1.1",
"typescript": "~4.0.2"
"styled-components": "^5.2.1",
"typescript": "^4.1.3"
},
"scripts": {
"start": "react-scripts start",
Expand Down Expand Up @@ -46,36 +47,46 @@
"devDependencies": {
"@babel/core": "^7.11.4",
"@commitlint/cli": "^9.1.2",
"@storybook/addon-actions": "^6.0.20",
"@storybook/addon-essentials": "^6.0.20",
"@storybook/addon-links": "^6.0.20",
"@storybook/node-logger": "^6.0.20",
"@storybook/preset-create-react-app": "^3.1.4",
"@reduxjs/toolkit": "^1.5.0",
"@rtk-incubator/rtk-query": "^0.1.0",
"@storybook/addon-actions": "^6.1.11",
"@storybook/addon-essentials": "^6.1.11",
"@storybook/addon-links": "^6.1.11",
"@storybook/node-logger": "^6.1.11",
"@storybook/preset-create-react-app": "^3.1.5",
"@storybook/react": "^6.1.11",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/react-hooks": "^3.4.2",
"@testing-library/react-hooks": "^3.7.0",
"@testing-library/user-event": "^7.2.1",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/lodash": "^4.14.165",
"@types/node": "^12.19.9",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
"@types/react-redux": "^7.1.12",
"@types/react-router-dom": "^5.1.6",
"@types/styled-components": "^5.1.7",
"@typescript-eslint/eslint-plugin": "^3.10.1",
"@typescript-eslint/parser": "^3.10.1",
"babel-loader": "^8.1.0",
"cross-env": "^7.0.2",
"babel-loader": "^8.2.2",
"cross-env": "^7.0.3",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.2.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-typescript": "^9.0.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^23.20.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.0.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^3.3.0",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "3.0.8",
"lint-staged": "^10.2.11",
"prettier": "^2.1.1",
"react-test-renderer": "^16.13.1",
"stylelint": "^13.7.1",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"react-redux": "^7.2.2",
"react-test-renderer": "^16.14.0",
"stylelint": "^13.8.0",
"stylelint-config-recommended": "^3.0.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-order": "^4.1.0",
Expand Down
4 changes: 4 additions & 0 deletions src/Routes/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Spinner from 'components/atoms/Spinner';
import { LoginPage } from 'Routes/helpers';
import PrivateRoute from 'Routes/PrivateRoute';
import ReduxTestComponent from 'redux/ReduxTestComponent/ReduxTestComponent';
import PaginationPage from 'pages/PaginationPage';

const Routes = (): JSX.Element => {
return (
Expand All @@ -25,6 +26,9 @@ const Routes = (): JSX.Element => {
<PrivateRoute path="/protected" exact>
<Spinner />
</PrivateRoute>
<Route path="/pagination" exact>
<PaginationPage />
</Route>
</Switch>
</>
);
Expand Down
17 changes: 17 additions & 0 deletions src/components/molecules/Pagination/Pagination.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export type IData = any[] | any;

export interface IRequest {
totalPassengers: number;
totalPages: number;
data: IData;
}

export interface IPagination {
page: number;
setPage: (v: number) => void;
isLoading: boolean;
isFetching: boolean;
courses: IRequest;
}

export type IVisibleButtons = Array<number>;
30 changes: 30 additions & 0 deletions src/components/molecules/Pagination/Pagination.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import styled from 'styled-components';
import colors from 'styles/colors';
import typography from 'styles/typography';

export const StyledList = styled.ul`
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 auto;
width: 100%;
height: 200px;
background-color: ${colors.background.Neutral80};
list-style: none;
`;

export const StyledButton = styled.button<{ isCurrent?: boolean }>`
width: 140px;
height: 60px;
${typography.body.bold.L}
border: 2px solid black;
background-color: ${colors.background.NeutralWhite};
background-color: ${({ disabled }) => disabled && `${colors.background.Neutral40}`};
background-color: ${({ isCurrent }) => isCurrent && `${colors.background.Primary40}`};
color: ${colors.background.Neutral40};
color: ${({ isCurrent }) => isCurrent && `${colors.background.NeutralWhite}`};
color: ${({ disabled }) => disabled && `${colors.background.Neutral80}`};
:hover:enabled {
background-color: burlywood;
}
`;
116 changes: 116 additions & 0 deletions src/components/molecules/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { useCallback, useEffect, useState } from 'react';
import usePaginationControl from 'hooks/usePaginationControl';
import { StyledList } from './Pagination.styled';
import PaginationButton from './PaginationButton';
import { IPagination, IVisibleButtons } from './Pagination.model';

const Pagination = ({
isLoading,
courses,
page,
setPage,
isFetching,
}: IPagination): JSX.Element => {
const [visibleButtonsOfNumbers, setVisibleButtonsOfNumbers] = useState<IVisibleButtons>([]);

// oddNumberOfButtons = temporary variable - in the future should be set by width of window
const oddNumberOfButtons = 5;

// immutable varialbe
const FIRST_PAGE = 1;

const { setFirstPage, setPrevPage, setNextPage, setLastPage } = usePaginationControl();

function createArrayOfButtons(currentPage: number, totalPages: number) {
const SCOPE = 1;
const DIVIDING_NUMBER = 2;
let start = currentPage;
let end = currentPage + oddNumberOfButtons;

if (start > SCOPE && oddNumberOfButtons > SCOPE) {
end -= Math.floor(oddNumberOfButtons / DIVIDING_NUMBER);
start -= Math.floor(oddNumberOfButtons / DIVIDING_NUMBER);
}

if (end > totalPages && !(oddNumberOfButtons <= SCOPE)) {
end = totalPages + SCOPE;
start = currentPage - oddNumberOfButtons + SCOPE;
}
// downlevelIteration
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html
// [...Array(end - start).keys()].map((i) => console.log(typeof i));
return [...Array(end - start).keys()].map((i) => i + start);
}

const createButtonsOfNumbers = useCallback(() => {
function doesArrayConsistNumber(oneOfVisibleNumbers: number) {
return visibleButtonsOfNumbers.includes(oneOfVisibleNumbers);
}
if (!isLoading && !doesArrayConsistNumber(page))
setVisibleButtonsOfNumbers(createArrayOfButtons(page, courses.totalPages));
}, [page, isLoading, courses, visibleButtonsOfNumbers]);

useEffect(() => {
createButtonsOfNumbers();
// if (isFetching) console.log('Use effect with isFetching');
// if (!isFetching) console.log('Use effect without isFetching');
}, [createButtonsOfNumbers, visibleButtonsOfNumbers, isFetching]);

function renderButtonsOfNumbers(currentPage: number) {
return visibleButtonsOfNumbers.map((numberOfButton: number) => {
const isCurrent = numberOfButton === currentPage;
const isDisable = numberOfButton > courses.totalPages;
return (
<li key={numberOfButton}>
<PaginationButton
type="button"
onClick={() => setPage(numberOfButton)}
disabled={isDisable}
isCurrent={isCurrent}
>
{numberOfButton}
</PaginationButton>
</li>
);
});
}

return (
<>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<StyledList>
<PaginationButton
type="button"
onClick={() => setPage(setFirstPage(FIRST_PAGE))}
disabled={page === 1}
>
First Page
</PaginationButton>
<PaginationButton
type="button"
onClick={() => setPage(setPrevPage(page))}
disabled={page === 1}
>
Previous Page
</PaginationButton>
{renderButtonsOfNumbers(page)}
<PaginationButton
type="button"
onClick={() => setPage(setNextPage(page))}
disabled={page === courses.totalPages}
>
Next Page
</PaginationButton>
<PaginationButton
type="button"
onClick={() => setPage(setLastPage(courses.totalPages))}
disabled={page === courses.totalPages}
>
Last Page
</PaginationButton>
</StyledList>
</div>
</>
);
};
export default Pagination;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface IPaginationButton {
isCurrent?: boolean;
disabled: boolean;
children: string | number;
type?: 'button';
className?: string;
onClick: () => void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { IPaginationButton } from './PagiantionButton.model';
import { StyledPaginationButton } from './PaginationButtonStyled';

const PaginationButton = ({
children,
onClick,
type,
className,
isCurrent,
disabled,
}: IPaginationButton): JSX.Element => {
return (
<StyledPaginationButton
onClick={onClick}
isCurrent={isCurrent}
disabled={disabled}
className={className}
type={type}
>
{children}
</StyledPaginationButton>
);
};

export default PaginationButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styled from 'styled-components';
import colors from 'styles/colors';
import typography from 'styles/typography';

export const StyledPaginationButton = styled.button<{ isCurrent?: boolean }>`
width: 100px;
height: 50px;
${typography.body.bold.L}
border: 2px solid black;
background-color: ${colors.background.NeutralWhite};
background-color: ${({ isCurrent }) => isCurrent && `${colors.background.Primary40}`};
background-color: ${({ disabled }) => disabled && `${colors.background.Neutral40}`};
color: ${colors.background.Neutral40};
color: ${({ isCurrent }) => isCurrent && `${colors.background.NeutralWhite}`};
color: ${({ disabled }) => disabled && `${colors.background.Neutral80}`};
:hover:enabled {
background-color: burlywood;
}
`;
3 changes: 3 additions & 0 deletions src/components/molecules/Pagination/PaginationButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import PaginationButton from './PaginationButton';

export default PaginationButton;
3 changes: 3 additions & 0 deletions src/components/molecules/Pagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Pagination from './Pagination';

export default Pagination;
3 changes: 3 additions & 0 deletions src/hooks/usePaginationControl/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import usePaginationControl from './usePaginationControl';

export default usePaginationControl;
30 changes: 30 additions & 0 deletions src/hooks/usePaginationControl/usePaginationControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface IReturnValues {
setFirstPage: (firstPage: number) => number;
setPrevPage: (currentPage: number) => number;
setNextPage: (currentPage: number) => number;
setLastPage: (lastPage: number) => number;
}

const usePaginationControl = (): IReturnValues => {
const SCOPE = 1;

function setFirstPage(firstPage: number) {
return firstPage;
}

function setPrevPage(currentPage: number) {
return currentPage - SCOPE;
}

function setNextPage(currentPage: number) {
return currentPage + SCOPE;
}

function setLastPage(lastPage: number) {
return lastPage;
}

return { setFirstPage, setPrevPage, setNextPage, setLastPage };
};

export default usePaginationControl;
6 changes: 6 additions & 0 deletions src/pages/PaginationPage/PaginationPage.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type ICurrentPage = number;

export interface ICourse {
id: string;
name: string;
}
Loading