mirror of
https://github.com/ceratic/MediaCollectorLibaryFrontend.git
synced 2026-05-13 23:56:45 +02:00
first commit
This commit is contained in:
128
src/components/Pagination.tsx
Normal file
128
src/components/Pagination.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
interface PaginationProps {
|
||||
currentPage: number
|
||||
lastPage: number
|
||||
total: number
|
||||
onPageChange: (page: number) => void
|
||||
itemsPerPage: number
|
||||
onItemsPerPageChange: (items: number) => void
|
||||
}
|
||||
|
||||
export default function Pagination({
|
||||
currentPage,
|
||||
lastPage,
|
||||
total,
|
||||
onPageChange,
|
||||
itemsPerPage,
|
||||
onItemsPerPageChange
|
||||
}: PaginationProps) {
|
||||
const handlePrevious = () => {
|
||||
if (currentPage > 1) {
|
||||
onPageChange(currentPage - 1)
|
||||
}
|
||||
}
|
||||
|
||||
const handleNext = () => {
|
||||
if (currentPage < lastPage) {
|
||||
onPageChange(currentPage + 1)
|
||||
}
|
||||
}
|
||||
|
||||
const handlePageSelect = (page: number) => {
|
||||
onPageChange(page)
|
||||
}
|
||||
|
||||
// Generate page numbers to show
|
||||
const getVisiblePages = () => {
|
||||
const pages: number[] = []
|
||||
const maxVisible = 5
|
||||
|
||||
if (lastPage <= maxVisible) {
|
||||
for (let i = 1; i <= lastPage; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
} else {
|
||||
const start = Math.max(1, currentPage - 2)
|
||||
const end = Math.min(lastPage, start + maxVisible - 1)
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
if (lastPage <= 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col sm:flex-row items-center justify-between gap-4 mt-8 p-4 bg-white/5 dark:bg-gray-800/50 rounded-xl border border-white/10">
|
||||
{/* Items per page selector */}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-gray-600 dark:text-gray-400">Show:</span>
|
||||
<select
|
||||
value={itemsPerPage}
|
||||
onChange={(e) => onItemsPerPageChange(parseInt(e.target.value))}
|
||||
className="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
||||
>
|
||||
<option value={10}>10</option>
|
||||
<option value={20}>20</option>
|
||||
<option value={50}>50</option>
|
||||
<option value={100}>100</option>
|
||||
</select>
|
||||
<span className="text-sm text-gray-600 dark:text-gray-400">
|
||||
of {total} items
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Pagination controls */}
|
||||
<div className="flex items-center gap-2">
|
||||
<motion.button
|
||||
onClick={handlePrevious}
|
||||
disabled={currentPage === 1}
|
||||
className="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
whileHover={{ scale: currentPage !== 1 ? 1.05 : 1 }}
|
||||
whileTap={{ scale: currentPage !== 1 ? 0.95 : 1 }}
|
||||
>
|
||||
Previous
|
||||
</motion.button>
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
{getVisiblePages().map((page) => (
|
||||
<motion.button
|
||||
key={page}
|
||||
onClick={() => handlePageSelect(page)}
|
||||
className={`w-8 h-8 text-sm rounded-lg transition-colors ${
|
||||
currentPage === page
|
||||
? 'bg-purple-600 text-white'
|
||||
: 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-600'
|
||||
}`}
|
||||
whileHover={{ scale: 1.1 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
>
|
||||
{page}
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={handleNext}
|
||||
disabled={currentPage === lastPage}
|
||||
className="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
whileHover={{ scale: currentPage !== lastPage ? 1.05 : 1 }}
|
||||
whileTap={{ scale: currentPage !== lastPage ? 0.95 : 1 }}
|
||||
>
|
||||
Next
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
{/* Page info */}
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Page {currentPage} of {lastPage}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user