diff --git a/components/admin/glossary-manager.tsx b/components/admin/glossary-manager.tsx index cddc1aa..bb7ebff 100644 --- a/components/admin/glossary-manager.tsx +++ b/components/admin/glossary-manager.tsx @@ -15,6 +15,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com import { FuzzyCombobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList } from "@/components/ui/combobox"; import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; +import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Spinner } from "@/components/ui/spinner"; import type { GlossaryKind } from "@/lib/glossary"; @@ -24,6 +25,15 @@ import { cn } from "@/lib/utils"; type CatalogItem = { key: string; name: string; imageUrl: string; rarity?: number | null }; type Alias = { id: string; kind: string; catalogKey: string; alias: string }; +const PAGE_SIZE = 25; + +function paginationItems(currentPage: number, totalPages: number) { + if (totalPages <= 7) return Array.from({ length: totalPages }, (_, index) => index + 1); + if (currentPage <= 4) return [1, 2, 3, 4, 5, "end-ellipsis", totalPages] as const; + if (currentPage >= totalPages - 3) return [1, "start-ellipsis", totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages] as const; + return [1, "start-ellipsis", currentPage - 1, currentPage, currentPage + 1, "end-ellipsis", totalPages] as const; +} + const kindLabels: Record = { character: "Character", weapon: "Weapon", @@ -43,6 +53,7 @@ export function GlossaryManager({ const [item, setItem] = useState(null); const [alias, setAlias] = useState(""); const [query, setQuery] = useState(""); + const [page, setPage] = useState(1); const itemsByKey = useMemo(() => new Map( Object.entries(catalogs).flatMap(([catalogKind, items]) => items.map((catalogItem) => [`${catalogKind}:${catalogItem.key}`, catalogItem] as const), @@ -52,6 +63,10 @@ export function GlossaryManager({ (entry) => `${entry.alias} ${itemsByKey.get(`${entry.kind}:${entry.catalogKey}`)?.name ?? entry.catalogKey}`, (entry) => [entry.alias, itemsByKey.get(`${entry.kind}:${entry.catalogKey}`)?.name ?? ""]); const visibleAliases = search.items; + const totalPages = Math.max(1, Math.ceil(visibleAliases.length / PAGE_SIZE)); + const currentPage = Math.min(page, totalPages); + const paginatedAliases = visibleAliases.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE); + const pages = paginationItems(currentPage, totalPages); const submit = () => startTransition(async () => { const result = await addGlossaryAlias({ kind, catalogKey: item?.key, alias }); @@ -142,11 +157,14 @@ export function GlossaryManager({ ค้นหา
- setQuery(event.target.value)} /> + { + setQuery(event.target.value); + setPage(1); + }} />
- {visibleAliases.map((entry) => { + {paginatedAliases.map((entry) => { const catalogItem = itemsByKey.get(`${entry.kind}:${entry.catalogKey}`); const name = catalogItem?.name; return ( @@ -175,6 +193,64 @@ export function GlossaryManager({ ); })} + + {totalPages > 1 ? ( + + + + { + event.preventDefault(); + setPage(currentPage - 1); + }} + /> + + +
    + {pages.map((pageItem) => ( + typeof pageItem === "number" ? ( + + { + event.preventDefault(); + setPage(pageItem); + }} + > + {pageItem} + + + ) : ( + + + + ) + ))} +
+
+ + { + event.preventDefault(); + setPage(currentPage + 1); + }} + /> + +
+
+ ) : null}