-
Notifications
You must be signed in to change notification settings - Fork 1.7k
solution #1474
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
base: master
Are you sure you want to change the base?
solution #1474
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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}`); | ||
| const total = 42; | ||
| //const perPage = 5; | ||
|
|
||
| export const App: React.FC = () => { | ||
| const [perPage, setPerPage] = useState(5); | ||
| const [currentPage, setCurrentPage] = useState(1); | ||
| const startIndex = (currentPage - 1) * perPage; | ||
| const visibleItems = items.slice(startIndex, startIndex + perPage); | ||
|
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. potential bug here, if currentPage > max pages → the array will be empty, need clamp: |
||
|
|
||
| const handlePerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const newValue = Number(event.target.value); | ||
|
|
||
| setPerPage(newValue); | ||
| 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 ${(currentPage - 1) * perPage + 1} - ${Math.min(currentPage * perPage, total)} of 42)`} | ||
| </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> | ||
|
|
@@ -33,77 +51,18 @@ 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={page => setCurrentPage(page)} | ||
| /> | ||
| <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> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,82 @@ | ||
| export const Pagination = () => {}; | ||
| type Props = { | ||
| total: number; | ||
| perPage: number; | ||
| currentPage: number; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the task description, the |
||
| onPageChange: (page: number) => void; | ||
| }; | ||
|
|
||
| export const Pagination: React.FC<Props> = ({ | ||
| total, | ||
| perPage, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no validation — user can pass any value via URL. |
||
| currentPage = 1, | ||
| onPageChange, | ||
| }) => { | ||
| const totalPages = Math.ceil(total / perPage); | ||
|
|
||
| if (totalPages <= 1) { | ||
| return null; | ||
| } | ||
|
|
||
| const pages = Array.from({ length: totalPages }, (_, i) => i + 1); | ||
|
|
||
| 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 => { | ||
| e.preventDefault(); | ||
| if (currentPage > 1) { | ||
| onPageChange(currentPage - 1); | ||
| } | ||
| }} | ||
| > | ||
| « | ||
| </a> | ||
| </li> | ||
|
|
||
| {pages.map(page => { | ||
| return ( | ||
| <li | ||
| key={page} | ||
| className={`page-item ${currentPage === page ? 'active' : ''}`} | ||
| > | ||
| <a | ||
| data-cy="pageLink" | ||
| className="page-link" | ||
| href={`#${page}`} | ||
| onClick={e => { | ||
| e.preventDefault(); | ||
| onPageChange(page); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The requirements state that the |
||
| }} | ||
| > | ||
| {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 => { | ||
| e.preventDefault(); | ||
| if (currentPage < totalPages) { | ||
| onPageChange(currentPage + 1); | ||
| } | ||
| }} | ||
| > | ||
| » | ||
| </a> | ||
| </li> | ||
| </ul> | ||
| ); | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This component is missing the requirement to integrate with React Router. The task specifies that
pageandperPageshould be stored in the URL as query parameters (e.g.,?page=2&perPage=7) and used to initialize the state when the page loads.