Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> Here is the [working version](https://mate-academy.github.io/react_pagination/)

You a given a list of items and markup for the `Pagination`. Implement the
You a given a list of items and markup for the `Pagination`. Implement the
`Pagination` as a stateless component to show only the items for a current page.

1. The `Pagination` should be used with the next props:
Expand Down Expand Up @@ -32,4 +32,4 @@ You a given a list of items and markup for the `Pagination`. Implement the
- Implement a solution following the [React task guideline](https://github.com/mate-academy/react_task-guideline#react-tasks-guideline).
- Use the [React TypeScript cheat sheet](https://mate-academy.github.io/fe-program/js/extra/react-typescript).
- Open one more terminal and run tests with `npm test` to ensure your solution is correct.
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://<your_account>.github.io/react_pagination/) and add it to the PR description.
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://jk-npc.github.io/react_pagination/) and add it to the PR description.
110 changes: 34 additions & 76 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
import React from 'react';
import React, { useState } from 'react';
import './App.css';
import { getNumbers } from './utils';
import { Pagination } from './components/Pagination';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const items = getNumbers(1, 42).map(n => `Item ${n}`);

export const App: React.FC = () => {
const [currentPage, setCurrentPage] = useState(1);
const [perPage, setPerPage] = useState(5);

const total = items.length;

const startItem = (currentPage - 1) * perPage + 1;
const endItem = Math.min(currentPage * perPage, total);

const visibleItems = items.slice(startItem - 1, endItem);

const handlePerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setPerPage(+event.target.value);
setCurrentPage(1);
};

return (
<div className="container">
<h1>Items with Pagination</h1>

<p className="lead" data-cy="info">
Page 1 (items 1 - 5 of 42)
{`Page ${currentPage} (items ${startItem} - ${endItem} of ${total})`}
</p>

<div className="form-group row">
<div className="col-3 col-sm-2 col-xl-1">
<select
data-cy="perPageSelector"
id="perPageSelector"
className="form-control">
className="form-control"
value={perPage}
onChange={handlePerPageChange}
>
<option value="3">3</option>
<option value="5">5</option>
<option value="10">10</option>
Expand All @@ -33,80 +51,20 @@ export const App: React.FC = () => {
</div>

{/* Move this markup to Pagination */}
<ul className="pagination">
<li className="page-item disabled">
<a
data-cy="prevLink"
className="page-link"
href="#prev"
aria-disabled="true">
«
</a>
</li>
<li className="page-item active">
<a data-cy="pageLink" className="page-link" href="#1">
1
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#2">
2
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#3">
3
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#4">
4
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#5">
5
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#6">
6
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#7">
7
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#8">
8
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#9">
9
</a>
</li>
<li className="page-item">
<a
data-cy="nextLink"
className="page-link"
href="#next"
aria-disabled="false">
»
</a>
</li>
</ul>
<Pagination
total={total}
perPage={perPage}
currentPage={currentPage}
onPageChange={setCurrentPage}
/>

<ul>
<li data-cy="item">Item 1</li>
<li data-cy="item">Item 2</li>
<li data-cy="item">Item 3</li>
<li data-cy="item">Item 4</li>
<li data-cy="item">Item 5</li>
{visibleItems.map(item => (
<li key={item} data-cy="item">
{item}
</li>
))}
</ul>
</div>
);
};

export default App;
78 changes: 77 additions & 1 deletion src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,77 @@
export const Pagination = () => {};
import React from 'react';

type Props = {
total: number;
perPage: number;
currentPage?: number;
onPageChange: (page: number) => void;
};

export const Pagination: React.FC<Props> = ({
total,
perPage,
currentPage = 1,
onPageChange,
}) => {
const totalPages = Math.ceil(total / perPage);

const handlePageChange = (page: number, event: React.MouseEvent) => {
event.preventDefault();

if (page >= 1 && page <= totalPages && page !== currentPage) {
onPageChange(page);
}
};

const pages = [];

for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}

return (
<ul className="pagination">
<li className={`page-item ${currentPage === 1 ? 'disabled' : ''}`}>
<a
data-cy="prevLink"
className="page-link"
href="#prev"
aria-disabled={currentPage === 1}
onClick={e => handlePageChange(currentPage - 1, e)}
>
«
</a>
</li>

{pages.map(page => (
<li
key={page}
className={`page-item ${page === currentPage ? 'active' : ''}`}
>
<a
data-cy="pageLink"
className="page-link"
href={`#${page}`}
onClick={e => handlePageChange(page, e)}
>
{page}
</a>
</li>
))}

<li
className={`page-item ${currentPage === totalPages ? 'disabled' : ''}`}
>
<a
data-cy="nextLink"
className="page-link"
href="#next"
aria-disabled={currentPage === totalPages}
onClick={e => handlePageChange(currentPage + 1, e)}
>
»
</a>
</li>
</ul>
);
};
Loading