dramaling-vocab-learning/frontend/components/shared/PaginationControls.tsx

132 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
interface PaginationControlsProps {
currentPage: number
totalPages: number
pageSize: number
totalCount: number
hasNext: boolean
hasPrev: boolean
onPageChange: (page: number) => void
onPageSizeChange: (size: number) => void
}
export const PaginationControls: React.FC<PaginationControlsProps> = ({
currentPage,
totalPages,
pageSize,
totalCount,
hasNext,
hasPrev,
onPageChange,
onPageSizeChange
}) => {
const startItem = totalCount > 0 ? (currentPage - 1) * pageSize + 1 : 0
const endItem = Math.min(currentPage * pageSize, totalCount)
const handlePrevPage = () => {
if (hasPrev) {
onPageChange(currentPage - 1)
}
}
const handleNextPage = () => {
if (hasNext) {
onPageChange(currentPage + 1)
}
}
const handlePageSizeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
onPageSizeChange(Number(e.target.value))
}
if (totalCount === 0) {
return null
}
return (
<div className="flex items-center justify-between p-4 bg-white border-t border-gray-200">
{/* 左側:顯示資訊 */}
<div className="flex items-center gap-4">
<span className="text-sm text-gray-700">
{startItem} {endItem} {totalCount}
</span>
{/* 每頁筆數選擇 */}
<div className="flex items-center gap-2">
<label className="text-sm text-gray-600"></label>
<select
value={pageSize}
onChange={handlePageSizeChange}
className="border border-gray-300 rounded px-2 py-1 text-sm focus:ring-blue-500 focus:border-blue-500"
>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</option>
<option value={100}>100</option>
</select>
</div>
</div>
{/* 右側:分頁控制 */}
<div className="flex items-center gap-2">
{/* 上一頁按鈕 */}
<button
onClick={handlePrevPage}
disabled={!hasPrev}
className={`px-3 py-2 text-sm rounded-lg border transition-colors ${
hasPrev
? 'border-gray-300 text-gray-700 hover:bg-gray-50'
: 'border-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
</button>
{/* 頁碼顯示 */}
<div className="flex items-center gap-1">
{/* 顯示當前頁附近的頁碼 */}
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
let pageNumber
if (totalPages <= 5) {
pageNumber = i + 1
} else if (currentPage <= 3) {
pageNumber = i + 1
} else if (currentPage >= totalPages - 2) {
pageNumber = totalPages - 4 + i
} else {
pageNumber = currentPage - 2 + i
}
return (
<button
key={pageNumber}
onClick={() => onPageChange(pageNumber)}
className={`px-3 py-2 text-sm rounded-lg transition-colors ${
pageNumber === currentPage
? 'bg-blue-600 text-white'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
{pageNumber}
</button>
)
})}
</div>
{/* 下一頁按鈕 */}
<button
onClick={handleNextPage}
disabled={!hasNext}
className={`px-3 py-2 text-sm rounded-lg border transition-colors ${
hasNext
? 'border-gray-300 text-gray-700 hover:bg-gray-50'
: 'border-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
</button>
</div>
</div>
)
}