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
107 changes: 107 additions & 0 deletions apps/web/components/molecules/pagination/pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
import clsx from 'clsx';
import { VisuallyHidden } from 'ui';
import { useRouter } from 'next/router';

type PaginationProps = {
quantity: number;
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
};

export const Pagination = ({ quantity }: PaginationProps) => {
const router = useRouter();
const currentPage: number =
router.query.page && !isNaN(Number(router.query.page))
? Number(router.query.page)
: 1;
const perPage =
router.query.page && !isNaN(Number(router.query.limit))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

shouldn't that be check for router.query.limit? Just asking coz I don' really know 😅
Also I think it could be somehow extracted to some function as it is repeated two times here and kinda looks confusing even tho it just is some validation/parsing/default functionality.

? Number(router.query.limit)
: 11;
const totalPages = Math.ceil(quantity / perPage);

return (
<div className="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
<div className="flex flex-1 justify-between sm:hidden">
<a
href={`?page=${currentPage - 1}`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Kinda magic numbers

className="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
>
Previous
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
</a>
<a
href={`?page=${currentPage + 1}`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yerr a wizard Harry 😸

className="relative z-10 inline-flex items-center bg-blue-600 px-4 py-2 text-sm font-semibold text-white focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
>
{currentPage}
</a>
<a
href="#"
className="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
>
Next
</a>
</div>
<div className="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
<div>
<p className="text-sm text-gray-700">
<span className="font-medium">
{(currentPage - 1) * perPage + 1}
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
</span>
-
<span className="font-medium">
{currentPage !== totalPages ? currentPage * perPage : quantity}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What's that? 😮

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What is this comment? Explain your thoughts please, give others a chance to learn

</span>{' '}
z <span className="font-medium">{quantity}</span> wyników
</p>
</div>
<div>
<nav
className="isolate inline-flex -space-x-px rounded-md shadow-sm"
aria-label="Pagination"
>
{totalPages > 1 && (
<a
Comment thread
ssynowiec marked this conversation as resolved.
Outdated
href={currentPage > 1 ? `?page=${currentPage - 1}` : ''}
className="relative inline-flex items-center rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<VisuallyHidden>Poprzednia strona</VisuallyHidden>
<ChevronLeftIcon className="h-5 w-5" aria-hidden="true" />
</a>
)}
{Array.from({ length: totalPages }, (_, i) => (
<a
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Also a component candidate

key={i}
href={`?page=${i + 1}`}
className={clsx(
i + 1 === currentPage
? 'relative z-10 inline-flex items-center bg-blue-600 px-4 py-2 text-sm font-semibold text-white focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600'
: 'relative hidden items-center px-4 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 md:inline-flex',
)}
>
{i + 1}
</a>
))}
{totalPages > 5 && (
<span className="relative inline-flex items-center px-4 py-2 text-sm font-semibold text-gray-700 ring-1 ring-inset ring-gray-300 focus:outline-offset-0">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

component

...
</span>
)}
{totalPages > 1 && (
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This seems as repeated. Maybe it would be better to make a couple different components for different pagination scenarios instead of making so many cases here. It is kinda very hard to read.
It is okay to duplicate code sometimes or to make 2 or 3 similar components that are simpler, if they do differ than trying to make them one generic with higher complexity and less readability.
Don't be afraid to create smaller components 😉

<a
href={
currentPage <= totalPages - 1
? `?page=${currentPage + 1}`
: ''
}
className="relative inline-flex items-center rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<VisuallyHidden>Następna strona</VisuallyHidden>
<ChevronRightIcon className="h-5 w-5" aria-hidden="true" />
</a>
)}
</nav>
</div>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChallengeItem } from 'molecules/challengeItem/challengeItem';
import type { Challenge } from '../../../types/types';
import { Pagination } from 'molecules/pagination/pagination';

type TasksListProps = {
challenges: Challenge[];
Expand All @@ -13,9 +14,7 @@ export const ChallengesList = ({ challenges }: TasksListProps) => {
})}
</ul>

{/*<div className="h-96 rounded-lg border-4 border-dashed border-gray-200 lg:h-full">*/}
{/* Zadania*/}
{/*</div>*/}
<Pagination quantity={challenges.length} />
</div>
);
};