forked from CSI-KJSCE/Travel-policy-
code base
This commit is contained in:
105
frontend/src/components/Pagination.jsx
Normal file
105
frontend/src/components/Pagination.jsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import React from 'react';
|
||||
|
||||
function Pagination({ numOfItems, itemsPerPage = 10, currentPage, onPageChange }) {
|
||||
const totalPages = Math.ceil(numOfItems / itemsPerPage);
|
||||
const pages = Array.from({ length: totalPages }, (_, index) => index + 1);
|
||||
const maxPageButtons = 5; // Maximum number of page buttons to display
|
||||
|
||||
const handlePrevious = () => {
|
||||
if (currentPage > 1) onPageChange(currentPage - 1);
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
if (currentPage < totalPages) onPageChange(currentPage + 1);
|
||||
};
|
||||
|
||||
const getPageButtons = () => {
|
||||
if (totalPages <= maxPageButtons) {
|
||||
return pages;
|
||||
}
|
||||
|
||||
const half = Math.floor(maxPageButtons / 2);
|
||||
let start = Math.max(1, currentPage - half);
|
||||
let end = Math.min(totalPages, currentPage + half);
|
||||
|
||||
if (currentPage <= half) {
|
||||
end = maxPageButtons;
|
||||
} else if (currentPage + half >= totalPages) {
|
||||
start = totalPages - maxPageButtons + 1;
|
||||
}
|
||||
|
||||
return Array.from({ length: end - start + 1 }, (_, index) => start + index);
|
||||
};
|
||||
|
||||
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">
|
||||
<button
|
||||
type='button'
|
||||
onClick={handlePrevious}
|
||||
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"
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<button
|
||||
type='button'
|
||||
onClick={handleNext}
|
||||
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"
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-gray-700">
|
||||
Showing <span className="font-medium">{(currentPage - 1) * itemsPerPage + 1}</span> to <span className="font-medium">{Math.min(currentPage * itemsPerPage, numOfItems)}</span> of <span className="font-medium">{numOfItems}</span> applications
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<nav className="isolate inline-flex -space-x-px rounded-md shadow-sm" aria-label="Pagination">
|
||||
<button
|
||||
type='button'
|
||||
onClick={handlePrevious}
|
||||
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"
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<span className="sr-only">Previous</span>
|
||||
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{getPageButtons().map(page => (
|
||||
<button
|
||||
type='button'
|
||||
key={page}
|
||||
onClick={() => onPageChange(page)}
|
||||
aria-current={currentPage === page ? 'page' : undefined}
|
||||
className={`relative inline-flex items-center px-4 py-2 text-sm font-semibold ${currentPage === page ? 'bg-red-700 text-white' : 'text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50'} focus:z-20 focus:outline-offset-0`}
|
||||
>
|
||||
{page}
|
||||
</button>
|
||||
))}
|
||||
|
||||
<button
|
||||
type='button'
|
||||
onClick={handleNext}
|
||||
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"
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<span className="sr-only">Next</span>
|
||||
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Pagination;
|
||||
Reference in New Issue
Block a user