132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
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>
|
||
)
|
||
} |