"use client"; import Link from "next/link"; import { SearchIcon, SparklesIcon, XIcon } from "lucide-react"; import { useMemo, useState } from "react"; import { MediaImage } from "@/components/public/media-image"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@/components/ui/empty"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; import type { PublicCharacterCard } from "@/lib/content/types"; import { cn } from "@/lib/utils"; interface CharacterDirectoryProps { characters: PublicCharacterCard[]; } function unique(values: Array): string[] { return [...new Set(values.filter((value): value is string => Boolean(value)))]; } export function CharacterDirectory({ characters }: CharacterDirectoryProps) { const [query, setQuery] = useState(""); const [element, setElement] = useState(null); const [role, setRole] = useState(null); const elements = useMemo( () => unique(characters.map((character) => character.element)), [characters], ); const roles = useMemo( () => unique(characters.map((character) => character.role)), [characters], ); const normalizedQuery = query.trim().toLocaleLowerCase("th"); const filtered = characters.filter((character) => { const searchable = `${character.nameTh} ${character.nameEn ?? ""}`.toLocaleLowerCase("th"); return ( (!normalizedQuery || searchable.includes(normalizedQuery)) && (!element || character.element === element) && (!role || character.role === role) ); }); const hasFilters = Boolean(query || element || role); return (
setQuery(event.target.value)} placeholder="ค้นหาชื่อตัวละคร…" aria-label="ค้นหาตัวละคร" /> {query ? ( ) : null}
{elements.length > 0 ? ( ) : null} {roles.length > 0 ? ( ) : null}
{filtered.length > 0 ? (
{filtered.map((character) => ( {character.nameTh} {character.nameEn ?? "คู่มือตัวละคร"} {character.rarity ? ( {character.rarity}★ ) : null} {character.element ? {character.element} : null} {character.role ? ( {character.role} ) : null} ))}
) : ( ไม่พบตัวละครที่ตรงกัน ลองใช้ชื่ออื่นหรือเอาตัวกรองบางรายการออก {hasFilters ? ( ) : null} )}
); } function FilterGroup({ label, values, selected, onChange, }: { label: string; values: string[]; selected: string | null; onChange: (value: string | null) => void; }) { return (
{label} {values.map((value) => ( ))}
); }