"use client"; import Image from "next/image"; import Link from "next/link"; import { ArrowUpRightIcon, SearchIcon } from "lucide-react"; import { useMemo, useState, type ReactNode } from "react"; import { GuideImageExport } from "@/components/public/guide-image-export"; import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Kbd } from "@/components/ui/kbd"; import { Separator } from "@/components/ui/separator"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { elementBackgroundColor } from "@/lib/catalog/element"; import { rarityGradientClass } from "@/lib/catalog/rarity"; import { isCustomTravelerKey } from "@/lib/catalog/travelers"; import type { PublicGuide } from "@/lib/guides/queries"; import { matchesTeamSearch, type TeamSearchTarget, } from "@/lib/guides/team-search"; import { cn } from "@/lib/utils"; type Team = PublicGuide["teams"][number]; type TeamArtifact = NonNullable; function ArtifactHalf({ artifact, side, eager, linked, sizes, }: { artifact: TeamArtifact; side: "left" | "right"; eager: boolean; linked: boolean; sizes: string; }) { const content = ( <> {linked {linked ? ( ) : null} ); const className = cn( "absolute inset-0 overflow-hidden", side === "left" ? "[clip-path:polygon(0_0,0_100%,100%_100%)]" : "[clip-path:polygon(0_0,100%_0,100%_100%)]", rarityGradientClass(artifact.rarity), ); return linked ? ( {content} ) : ( {content} ); } function TeamArtifactIcon({ first, second, eager = false, linked = false, className, sizes, }: { first: TeamArtifact | null; second: TeamArtifact | null; eager?: boolean; linked?: boolean; className?: string; sizes: string; }) { const primary = first ?? second; const secondary = first ? second : null; if (!primary) { return
; } if (!secondary) { const content = ( <> {linked {linked ? ( ) : null} ); const artifactClassName = cn( "relative aspect-square scale-110 overflow-hidden rounded-md bg-muted", rarityGradientClass(primary.rarity), className, ); return linked ? ( {content} ) : (
{content}
); } return (
); } function TeamExportImage({ team }: { team: Team }) { const total = team.members.reduce((sum, member) => sum + Number(member.damage), 0); const seconds = Number(team.rotationSeconds); return (

{team.title}

ระยะเวลาโรเทชั่น {seconds.toLocaleString(undefined, { maximumFractionDigits: 2 })} วิ

{team.members.map((member) => { const damage = Number(member.damage); const percent = total > 0 ? damage / total * 100 : 0; return (
C{member.constellation}
{member.weapon ?
R{member.refinement}
: null}
{member.character.name}{damage.toLocaleString()}
{percent.toFixed(1)}%
); })}

{team.combo}

DPS: {seconds > 0 ? (total / seconds).toLocaleString(undefined, { maximumFractionDigits: 0 }) : "0"}
By YT เกนชินไม่ใช่เกมมือถือ
); } function TeamCard({ team, action, exporting = false, }: { team: Team; action?: ReactNode; exporting?: boolean; }) { const total = team.members.reduce( (sum, member) => sum + Number(member.damage), 0, ); const seconds = Number(team.rotationSeconds); return ( {team.title} โรเทชั่น {seconds} วิ {action ? {action} : null}
{team.members.map((member) => (
{member.character.name} C{member.constellation}
{member.weapon ? ( {member.weapon.name} R{member.refinement} ) : (
)}

{member.character.name}

{Number(member.damage).toLocaleString(undefined, { maximumFractionDigits: 2, })}

{total ? ((Number(member.damage) / total) * 100).toFixed(2) : "0.00"} %

))}

ดาเมจรวม

{total.toLocaleString()}

DPS

{seconds > 0 ? (total / seconds).toLocaleString(undefined, { maximumFractionDigits: 0, }) : "0"}

{team.combo}

); } export function TeamSearch({ teams }: { teams: PublicGuide["teams"] }) { const [query, setQuery] = useState(""); const [searchTarget, setSearchTarget] = useState("all"); const filteredTeams = useMemo( () => teams.filter((team) => matchesTeamSearch({ team: [team.title], character: team.members.map((member) => member.character.name), weapon: team.members.flatMap((member) => member.weapon ? [member.weapon.name] : []), artifact: team.members.flatMap((member) => [member.artifact, member.secondArtifact].flatMap((artifact) => artifact ? [artifact.name] : [])), }, query, searchTarget)), [query, searchTarget, teams], ); return (
{ const target = value[0] as TeamSearchTarget | undefined; if (target) setSearchTarget(target); }} > ทั้งหมด ชื่อทีม ตัวละคร อาวุธ อาร์ติแฟกต์ {filteredTeams.length ? (
{filteredTeams.map((team) => ( } /> ))}
) : ( ไม่พบทีมที่ตรงกับคำค้นหา )}
); }