mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 05:22:02 +00:00
325 lines
10 KiB
TypeScript
325 lines
10 KiB
TypeScript
'use client';
|
|
|
|
import { ReactNode } from 'react';
|
|
import { Icon } from '@iconify/react';
|
|
|
|
import { cn } from '@/lib/helper';
|
|
|
|
const range = (start: number, end: number) =>
|
|
Array.from({ length: end - start + 1 }, (_, i) => i + start);
|
|
|
|
const PaginationButton = ({
|
|
content = '',
|
|
disabled = false,
|
|
onClick = () => {},
|
|
}: {
|
|
content?: ReactNode;
|
|
disabled?: boolean;
|
|
onClick?: () => void;
|
|
}) => (
|
|
<button
|
|
className={cn(
|
|
'join-item btn btn-ghost p-2.5 rounded-lg text-sm font-medium text-gray-500 aspect-square',
|
|
'disabled:text-gray-700 disabled:pointer-events-auto! disabled:cursor-not-allowed! disabled:bg-gray-50 disabled:active:translate-y-0'
|
|
)}
|
|
disabled={disabled}
|
|
onClick={onClick}
|
|
>
|
|
{content}
|
|
</button>
|
|
);
|
|
|
|
const EtcPaginationButton = ({
|
|
startPage = 0,
|
|
endPage = 0,
|
|
onPageItemClick = (pageNumber: number) => {},
|
|
}) => {
|
|
const pages = range(startPage, endPage);
|
|
|
|
return (
|
|
<>
|
|
{startPage > 0 && endPage >= startPage && (
|
|
<div className='dropdown dropdown-top dropdown-center'>
|
|
<button
|
|
tabIndex={0}
|
|
role='button'
|
|
className={cn(
|
|
'join-item btn btn-ghost p-2.5 rounded-lg text-sm font-medium text-gray-500 aspect-square'
|
|
)}
|
|
>
|
|
...
|
|
</button>
|
|
|
|
<div className='dropdown-content'>
|
|
<ul
|
|
tabIndex={0}
|
|
className='menu bg-base-100 rounded-lg z-1 w-fit min-w-max max-h-64 p-1 shadow-sm mb-2 overflow-y-auto flex-nowrap'
|
|
>
|
|
{pages.map((pageNumber) => (
|
|
<li key={pageNumber}>
|
|
<PaginationButton
|
|
content={pageNumber}
|
|
onClick={() => onPageItemClick(pageNumber)}
|
|
/>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{(startPage === 0 || endPage < startPage) && (
|
|
<button
|
|
disabled
|
|
className={cn(
|
|
'join-item btn btn-ghost p-2.5 rounded-lg text-sm font-medium text-gray-500 aspect-square'
|
|
)}
|
|
>
|
|
...
|
|
</button>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const Pagination = ({
|
|
currentPage = 1,
|
|
totalItems = 0,
|
|
itemsPerPage = 10,
|
|
onPageChange = (pageNumber: number) => {},
|
|
onPrevPage = () => {},
|
|
onNextPage = () => {},
|
|
}) => {
|
|
const totalPages =
|
|
Math.ceil(totalItems / itemsPerPage) === 0
|
|
? 1
|
|
: Math.ceil(totalItems / itemsPerPage);
|
|
|
|
const pageChangeHandler = (pageNumber: number) => onPageChange(pageNumber);
|
|
|
|
return (
|
|
<div>
|
|
<div className='join w-full justify-between items-center gap-3'>
|
|
<button
|
|
disabled={currentPage === 1}
|
|
onClick={onPrevPage}
|
|
className={cn(
|
|
'join-item btn btn-outline group px-3 py-2 text-sm font-semibold rounded-lg border border-gray-300 shadow-xs hidden sm:flex justify-center items-center gap-1.5',
|
|
'disabled:bg-[initial]! disabled:text-gray-400 disabled:pointer-events-auto! disabled:cursor-not-allowed disabled:active:translate-y-0'
|
|
)}
|
|
>
|
|
<Icon
|
|
icon='uil:arrow-left'
|
|
width={20}
|
|
height={20}
|
|
className='text-gray-400 group-disabled:text-gray-300'
|
|
/>{' '}
|
|
Previous
|
|
</button>
|
|
|
|
{totalPages <= 7 && (
|
|
<div className='join-item join gap-0.5'>
|
|
{range(1, totalPages).map((pageNumber) => (
|
|
<PaginationButton
|
|
key={pageNumber}
|
|
content={pageNumber}
|
|
disabled={currentPage === pageNumber}
|
|
onClick={() => pageChangeHandler(pageNumber)}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{totalPages > 7 && (
|
|
<div className='join-item join gap-0.5'>
|
|
<PaginationButton
|
|
content={1}
|
|
disabled={currentPage === 1}
|
|
onClick={() => pageChangeHandler(1)}
|
|
/>
|
|
|
|
{totalPages >= 2 &&
|
|
(currentPage <= 3 || currentPage >= totalPages - 2) && (
|
|
<PaginationButton
|
|
content={2}
|
|
disabled={currentPage === 2}
|
|
onClick={() => pageChangeHandler(2)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 2 &&
|
|
currentPage > 3 &&
|
|
currentPage < totalPages - 2 && (
|
|
<EtcPaginationButton
|
|
startPage={2}
|
|
endPage={currentPage - 2}
|
|
onPageItemClick={pageChangeHandler}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 3 &&
|
|
(currentPage <= 4 || currentPage >= totalPages - 2) &&
|
|
currentPage !== totalPages - 2 && (
|
|
<PaginationButton
|
|
content={3}
|
|
disabled={currentPage === 3}
|
|
onClick={() => pageChangeHandler(3)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 7 &&
|
|
(currentPage <= 2 || currentPage >= totalPages - 2) && (
|
|
<EtcPaginationButton
|
|
startPage={
|
|
currentPage <= 2
|
|
? currentPage + 2
|
|
: currentPage === totalPages - 2
|
|
? 3
|
|
: currentPage >= totalPages - 1
|
|
? 4
|
|
: 1
|
|
}
|
|
endPage={
|
|
currentPage <= 2 || currentPage >= totalPages - 1
|
|
? totalPages - 3
|
|
: currentPage === totalPages - 2
|
|
? totalPages - 4
|
|
: 2
|
|
}
|
|
onPageItemClick={pageChangeHandler}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 3 &&
|
|
currentPage > 4 &&
|
|
currentPage < totalPages - 1 && (
|
|
<PaginationButton
|
|
content={currentPage - 1}
|
|
onClick={() => pageChangeHandler(currentPage - 1)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 7 &&
|
|
currentPage > 3 &&
|
|
currentPage < totalPages - 2 && (
|
|
<PaginationButton content={currentPage} disabled />
|
|
)}
|
|
|
|
{totalPages >= 5 &&
|
|
currentPage > 2 &&
|
|
currentPage < totalPages - 2 && (
|
|
<PaginationButton
|
|
content={currentPage + 1}
|
|
onClick={() => pageChangeHandler(currentPage + 1)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 5 &&
|
|
(currentPage <= 2 || currentPage >= totalPages - 2) && (
|
|
<PaginationButton
|
|
content={totalPages - 2}
|
|
disabled={currentPage === totalPages - 2}
|
|
onClick={() => pageChangeHandler(totalPages - 2)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 6 &&
|
|
currentPage > 2 &&
|
|
currentPage < totalPages - 3 && (
|
|
<EtcPaginationButton
|
|
startPage={
|
|
currentPage <= 3
|
|
? currentPage + 2
|
|
: currentPage >= 4
|
|
? currentPage + 2
|
|
: 1
|
|
}
|
|
endPage={
|
|
currentPage <= 3
|
|
? totalPages - 2
|
|
: currentPage >= 4
|
|
? totalPages - 1
|
|
: 0
|
|
}
|
|
onPageItemClick={pageChangeHandler}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 6 &&
|
|
(currentPage <= 3 || currentPage >= totalPages - 3) && (
|
|
<PaginationButton
|
|
content={totalPages - 1}
|
|
disabled={currentPage === totalPages - 1}
|
|
onClick={() => pageChangeHandler(totalPages - 1)}
|
|
/>
|
|
)}
|
|
|
|
{totalPages >= 7 && (
|
|
<PaginationButton
|
|
content={totalPages}
|
|
disabled={currentPage === totalPages}
|
|
onClick={() => pageChangeHandler(totalPages)}
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
<button
|
|
disabled={currentPage === totalPages}
|
|
onClick={onNextPage}
|
|
className={cn(
|
|
'join-item btn btn-outline group px-3 py-2 text-sm font-semibold rounded-lg border border-gray-300 shadow-xs hidden sm:flex justify-center items-center gap-1.5',
|
|
'disabled:bg-[initial]! disabled:text-gray-400 disabled:pointer-events-auto! disabled:cursor-not-allowed disabled:active:translate-y-0'
|
|
)}
|
|
>
|
|
Next{' '}
|
|
<Icon
|
|
icon='uil:arrow-right'
|
|
width={20}
|
|
height={20}
|
|
className='text-gray-400 group-disabled:text-gray-300'
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
<div className='flex gap-2 mt-2 sm:hidden'>
|
|
<button
|
|
disabled={currentPage === 1}
|
|
onClick={onPrevPage}
|
|
className={cn(
|
|
'join-item btn btn-outline group px-3 py-2 text-sm font-semibold rounded-lg border border-gray-300 shadow-xs flex justify-center items-center gap-1.5',
|
|
'disabled:bg-[initial]! disabled:text-gray-400 disabled:pointer-events-auto! disabled:cursor-not-allowed disabled:active:translate-y-0'
|
|
)}
|
|
>
|
|
<Icon
|
|
icon='uil:arrow-left'
|
|
width={20}
|
|
height={20}
|
|
className='text-gray-400 group-disabled:text-gray-300'
|
|
/>{' '}
|
|
Previous
|
|
</button>
|
|
|
|
<button
|
|
disabled={currentPage === totalPages}
|
|
onClick={onNextPage}
|
|
className={cn(
|
|
'join-item btn btn-outline group px-3 py-2 text-sm font-semibold rounded-lg border border-gray-300 shadow-xs flex justify-center items-center gap-1.5',
|
|
'disabled:bg-[initial]! disabled:text-gray-400 disabled:pointer-events-auto! disabled:cursor-not-allowed disabled:active:translate-y-0'
|
|
)}
|
|
>
|
|
Next{' '}
|
|
<Icon
|
|
icon='uil:arrow-right'
|
|
width={20}
|
|
height={20}
|
|
className='text-gray-400 group-disabled:text-gray-300'
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Pagination;
|