"use client"; import { searchItems } from "@/lib/search"; import Image from "next/image"; import { SearchIcon, Trash2Icon } from "lucide-react"; import { useMemo, useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { addGlossaryAlias, removeGlossaryAlias } from "@/app/admin/actions"; import { CatalogDropdown } from "@/components/admin/ui/catalog-select"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 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"; import { characterRarityGradientClass, rarityGradientClass } from "@/lib/catalog/rarity"; 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", artifact: "Artifact", }; export function GlossaryManager({ aliases, catalogs, }: { aliases: Alias[]; catalogs: Record; }) { const router = useRouter(); const [pending, startTransition] = useTransition(); const [kind, setKind] = useState("character"); 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), ), ), [catalogs]); const search = searchItems(aliases, query, (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 }); if (result.status === "error") { toast.error(result.message); return; } setAlias(""); toast.success("เพิ่ม Shortcut แล้ว"); router.refresh(); }); return (
เพิ่ม Shortcut ผูกคำค้นแบบย่อกับรายการจาก Catalog ประเภท รายการ [value.name, ...aliases.filter((entry) => entry.kind === kind && entry.catalogKey === value.key).map((entry) => entry.alias)]} value={item?.key ?? ""} onValueChange={(key) => setItem(catalogs[kind].find((value) => value.key === key) ?? null)} placeholder="ค้นหารายการ…" rarityBackground characterBackground={kind === "character"} /> Shortcut setAlias(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter" && item && alias.trim()) submit(); }} /> Glossary {aliases.length} shortcuts ค้นหา
{ setQuery(event.target.value); setPage(1); }} />
{paginatedAliases.map((entry) => { const catalogItem = itemsByKey.get(`${entry.kind}:${entry.catalogKey}`); const name = catalogItem?.name; return (
{catalogItem ? ( ) : null}

{entry.alias}

{name ?? entry.catalogKey}

{name ? kindLabels[entry.kind as GlossaryKind] : "Unavailable"}
); })} {totalPages > 1 ? ( { event.preventDefault(); setPage(currentPage - 1); }} />
    {pages.map((pageItem) => ( typeof pageItem === "number" ? ( { event.preventDefault(); setPage(pageItem); }} > {pageItem} ) : ( ) ))}
{ event.preventDefault(); setPage(currentPage + 1); }} />
) : null}
); }