75 lines
3.2 KiB
TypeScript
75 lines
3.2 KiB
TypeScript
|
|
import { Link } from "@inertiajs/react";
|
|||
|
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|||
|
|
import { cn } from "@/lib/utils";
|
|||
|
|
|
|||
|
|
interface PaginationProps {
|
|||
|
|
links: {
|
|||
|
|
url: string | null;
|
|||
|
|
label: string;
|
|||
|
|
active: boolean;
|
|||
|
|
}[];
|
|||
|
|
className?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default function Pagination({ links, className }: PaginationProps) {
|
|||
|
|
// 如果只有一頁,不顯示分頁
|
|||
|
|
if (links.length <= 3) return null;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className={cn("flex flex-wrap justify-center gap-1", className)}>
|
|||
|
|
{links.map((link, key) => {
|
|||
|
|
// 處理特殊標籤
|
|||
|
|
let label = link.label;
|
|||
|
|
if (label.includes("«")) label = "Previous";
|
|||
|
|
if (label.includes("»")) label = "Next";
|
|||
|
|
|
|||
|
|
const isPrevious = label === "Previous";
|
|||
|
|
const isNext = label === "Next";
|
|||
|
|
|
|||
|
|
// 如果是 Previous/Next 但沒有 URL,則不渲染(或者渲染為 disabled)
|
|||
|
|
if ((isPrevious || isNext) && !link.url) {
|
|||
|
|
return (
|
|||
|
|
<div
|
|||
|
|
key={key}
|
|||
|
|
className={cn(
|
|||
|
|
"flex h-9 items-center justify-center rounded-md border border-input bg-transparent px-3 text-sm text-muted-foreground opacity-50 cursor-not-allowed",
|
|||
|
|
isPrevious || isNext ? "px-2" : ""
|
|||
|
|
)}
|
|||
|
|
>
|
|||
|
|
{isPrevious && <ChevronLeft className="h-4 w-4" />}
|
|||
|
|
{isNext && <ChevronRight className="h-4 w-4" />}
|
|||
|
|
{!isPrevious && !isNext && <span dangerouslySetInnerHTML={{ __html: link.label }} />}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return link.url ? (
|
|||
|
|
<Link
|
|||
|
|
key={key}
|
|||
|
|
href={link.url}
|
|||
|
|
preserveScroll
|
|||
|
|
className={cn(
|
|||
|
|
"flex h-9 items-center justify-center rounded-md border px-3 text-sm transition-colors hover:bg-accent hover:text-accent-foreground",
|
|||
|
|
link.active
|
|||
|
|
? "border-primary bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground"
|
|||
|
|
: "border-input bg-transparent text-foreground",
|
|||
|
|
isPrevious || isNext ? "px-2" : ""
|
|||
|
|
)}
|
|||
|
|
>
|
|||
|
|
{isPrevious && <ChevronLeft className="h-4 w-4" />}
|
|||
|
|
{isNext && <ChevronRight className="h-4 w-4" />}
|
|||
|
|
{!isPrevious && !isNext && <span dangerouslySetInnerHTML={{ __html: link.label }} />}
|
|||
|
|
</Link>
|
|||
|
|
) : (
|
|||
|
|
<div
|
|||
|
|
key={key}
|
|||
|
|
className="flex h-9 items-center justify-center rounded-md border border-input bg-transparent px-3 text-sm text-foreground"
|
|||
|
|
>
|
|||
|
|
<span dangerouslySetInnerHTML={{ __html: link.label }} />
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
})}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|