"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 { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 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 { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Spinner } from "@/components/ui/spinner"; import type { GlossaryKind } from "@/lib/glossary"; import { 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 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 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 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} onValueChange={setItem} itemToStringLabel={(value) => value.name} itemToStringValue={(value) => value.name} > ไม่พบรายการ {(catalogItem) => ( {catalogItem.name} )} Shortcut setAlias(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter" && item && alias.trim()) submit(); }} /> Glossary {aliases.length} shortcuts ค้นหา
setQuery(event.target.value)} />
{visibleAliases.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"}
); })}
); }