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

170 lines
5.8 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="bg-white border-t border-gray-200">
{/* 手機版 - 簡潔美觀設計 */}
<div className="block md:hidden p-4">
<div className="flex flex-col items-center gap-4">
{/* 分頁控制 - 圓形大按鈕 */}
<div className="flex items-center gap-4">
<button
onClick={handlePrevPage}
disabled={!hasPrev}
className={`flex items-center justify-center w-12 h-12 rounded-full transition-all ${
hasPrev
? 'bg-blue-100 text-blue-700 hover:bg-blue-200 shadow-md hover:shadow-lg active:scale-95'
: 'bg-gray-100 text-gray-400 cursor-not-allowed'
}`}
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<div className="px-4 py-2 bg-gray-100 rounded-full min-w-[60px] text-center">
<span className="text-lg font-bold text-gray-800">{currentPage}</span>
</div>
<button
onClick={handleNextPage}
disabled={!hasNext}
className={`flex items-center justify-center w-12 h-12 rounded-full transition-all ${
hasNext
? 'bg-blue-100 text-blue-700 hover:bg-blue-200 shadow-md hover:shadow-lg active:scale-95'
: 'bg-gray-100 text-gray-400 cursor-not-allowed'
}`}
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
</div>
{/* 桌面版 - 保持完整功能 */}
<div className="hidden md:flex items-center justify-between p-4">
{/* 左側:顯示資訊 */}
<div className="flex items-center gap-4">
{/* 每頁筆數選擇 */}
<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-3 py-2 text-sm focus:ring-blue-500 focus:border-blue-500 min-w-[80px]"
>
<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>
</div>
)
}