Skip to content
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
102 changes: 29 additions & 73 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import React from 'react';
import './App.css';
import { getNumbers } from './utils';
import { useState } from 'react';
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 [perPage, setPerPage] = useState(Number('5'));
const [currentPage, setCurrentPage] = useState(1);
const lastItems = perPage * currentPage;
const firstItem = lastItems - perPage;

const newItems = items.slice(firstItem, lastItems);

return (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant .map(n => n) - this creates a new array with the same values. Use getNumbers(1, pageCount) directly, or use .map with a meaningful transformation if needed.

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

<p className="lead" data-cy="info">
Page 1 (items 1 - 5 of 42)
Page {currentPage} (items {firstItem + 1} -{' '}
Comment on lines 22 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded 42 should be replaced with total prop to properly display the actual total count when it changes.

{lastItems > items.length ? items.length : lastItems} of {items.length})
</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">
value={perPage}
onChange={event => {
setPerPage(Number(event.target.value));
setCurrentPage(1);
}}
className="form-control"
>
<option value="3">3</option>
<option value="5">5</option>
<option value="10">10</option>
Expand All @@ -32,78 +48,18 @@ export const App: React.FC = () => {
</label>
</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={items.length}
perPage={perPage}
currentPage={currentPage}
Comment on lines 50 to +54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as prev button - onPageChange is called on every click, including when disabled. Clicking the disabled next button on the last page still triggers the callback with the same page number.

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>
{newItems.map(item => (
<li data-cy="item" key={item}>
{item}
</li>
))}
</ul>
</div>
);
Expand Down
73 changes: 72 additions & 1 deletion src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,72 @@
export const Pagination = () => {};
import cn from 'classnames';
import React from 'react';
import { getNumbers } from '../../utils';

type Props = {
total: number;
perPage: number;
currentPage: number;
onPageChange: (page: number) => void;
};
export const Pagination: React.FC<Props> = ({
total,
perPage,
currentPage = 1,
onPageChange,
}) => {
const pageCount = Math.ceil(total / perPage);
const listItems = getNumbers(1, pageCount).map(n => n);

const handlePageChange = (page: number) => {
if (page !== currentPage && page >= 1 && page <= pageCount) {
onPageChange(page);
}
};

return (
<ul className="pagination">
<li
className={cn('page-item', { disabled: currentPage === 1 })}

>
<a
data-cy="prevLink"
className="page-link"
href="#prev"
aria-disabled={currentPage === 1}
onClick={() => handlePageChange(currentPage - 1)}
>
«
</a>
</li>
{listItems.map(count => (
<li
key={count}
className={cn('page-item ', { active: currentPage === count })}
>
<a
data-cy="pageLink"
className="page-link"
onClick={() => handlePageChange(count)}
href={`#${count}`}
>
{count}
</a>
</li>
))}
<li
className={cn('page-item', { disabled: currentPage === pageCount })}
>
<a
data-cy="nextLink"
className="page-link"
href="#next"
aria-disabled={currentPage === pageCount}
onClick={() => handlePageChange(currentPage + 1)}
>
»
</a>
</li>
</ul>
);
};
Loading