import Image from "next/image"; import Link from "next/link"; import { ChevronLeftIcon, DownloadIcon } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { buttonVariants } from "@/components/ui/button"; import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Kbd } from "@/components/ui/kbd"; import { Separator } from "@/components/ui/separator"; import { SiteHeader } from "@/components/public/site-header"; import { ElementIcon } from "@/components/public/element-icon"; import { LiveRefresh } from "@/components/live-refresh"; import { rarityGradientClass, rarityTextClass } from "@/lib/catalog/rarity"; import type { PublicGuide } from "@/lib/guides/queries"; import { normalizeTalentPriorities, talentRelationSymbol } from "@/lib/guides/talents"; import { cn } from "@/lib/utils"; function hasSection(guide: PublicGuide, slug: string): boolean { if (slug === "weapon") return guide.weapons.length > 0; if (slug === "artifact") return ( guide.artifactGroups.some((group) => group.rows.length > 0) || Boolean( guide.artifactProfile && (guide.artifactProfile.sands.length || guide.artifactProfile.goblet.length || guide.artifactProfile.circlet.length), ) ); if (slug === "constellations") return guide.constellations.length > 0; if (slug === "team") return guide.teams.length > 0; return guide.extras.some( (extra) => extra.slug === slug && extra.rows.length > 0, ); } export function publicSections(guide: PublicGuide) { return guide.sections.filter((section) => hasSection(guide, section.slug)); } export function StructuredGuideShell({ guide, section, }: { guide: PublicGuide; section?: string; }) { const sections = publicSections(guide); return (
{guide.name}

{guide.name}

{guide.character.element ? ( {guide.character.elementIconUrl ? ( ) : null} {guide.character.element} ) : null}
{section ? ( ) : ( )}
); } function GuideOverview({ guide, sections, }: { guide: PublicGuide; sections: ReturnType; }) { return (
{`Guide

Build Overview

{guide.name}

{guide.overview}

{sections.length ? (
{sections.map((item) => ( {item.title} เปิดดูคำแนะนำฉบับเต็ม ))}
) : ( กำลังจัดทำเนื้อหา กลับมาตรวจสอบอีกครั้งหลังผู้ดูแลเพิ่มข้อมูล )}
); } function GuideSection({ guide, section, }: { guide: PublicGuide; section: string; }) { if (section === "weapon") return ; if (section === "artifact") return ; if (section === "constellations") return ; if (section === "team") return ; const extra = guide.extras.find((item) => item.slug === section); return extra ? : null; } function metric(value: string | null) { return value === null ? null : `${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}%`; } function WeaponSection({ guide }: { guide: PublicGuide }) { return (

อาวุธที่แนะนำ

Weapons

Export image
{guide.weapons.map((row, index) => (
{row.weapon.name}

{index + 1}. {row.weapon.name} R{row.refinement}

{row.overallPercent ? (

{metric(row.overallPercent)}

ดาเมททั้งทีม

) : null} {row.personalPercent ? (

{metric(row.personalPercent)}

ดาเมจส่วนตัว

) : null}
))}
); } function ArtifactSection({ guide }: { guide: PublicGuide }) { const profile = guide.artifactProfile; return (

อาร์ติแฟกต์และสเตตัสที่แนะนำ

Artifacts & Stats

Export image
{" "}
{guide.artifactGroups.map((group) => ( {group.name} {group.rows.map((row, index) => (
{row.first.name}
{row.second ? (
{row.second.name}
) : null}

{index + 1}. {row.first.name} {row.second ? ` + ${row.second.name}` : ""}

{metric(row.percent)}

))}
))}
{profile ? (
Artifact Stats {profile.substats.length ? ( Stat Priority: {profile.substats.map(statLabel).join(" > ")} ) : null} รายละเอียดเพิ่มเติม {profile.targets.length ? (

Target Stats

{profile.targets.map((target) => (
{target.stat} {target.value}
))}
) : null} {profile.talents.length ? (

ลำดับการอัพพรสวรรค์

{normalizeTalentPriorities(profile.talents) .map((talent, index, talents) => { const catalogTalent = guide.character.talents.find((item) => item.type === talent.type); const talentName = catalogTalent?.name ?? talent.type; return (
{catalogTalent?.iconUrl ? {talentName} : {talent.type}}
{talent.level ? `Lv.${talent.level}+` : "—"}

{talentName}

{index < talents.length - 1 ? ( {talentRelationSymbol(talent.relationToNext)} ) : null}
); })}
) : null} {profile.note ? (

โน็ต

{profile.note}

) : null}
) : null}
); } function statLabel(value: string): string { return value === "EM" ? "Elemental Mastery" : value === "ER" ? "Energy Recharge" : value; } function ArtifactStat({ iconSrc, label, values }: { iconSrc: string; label: string; values: string[] }) { return (

{label}

{values.length ? values.map(statLabel).join(" > ") : "—"}

); } function ConstellationSection({ guide }: { guide: PublicGuide }) { return (

กลุ่มดาว

Constellations

{guide.constellations.map((row) => ( {metric(row.cumulativePercent)} C{row.level} · {row.name} {row.iconUrl ? ( ) : null}

{row.detail}

))}
); } function TeamSection({ guide }: { guide: PublicGuide }) { return (

คำนวณความเสียหาย

Team Calc

{guide.teams.map((team) => { const total = team.members.reduce( (sum, member) => sum + Number(member.damage), 0, ); const seconds = Number(team.rotationSeconds); return ( {team.title} {seconds}s rotation Export image
{team.members.map((member) => (
{member.character.name}
{member.weapon ? (
{member.weapon.name} R{member.refinement}
) : (
)} {member.artifact ? (
{member.artifact.name}
) : (
)}

C{member.constellation} {member.character.name}

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

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

))}

Total damage

{total.toLocaleString()}

Total DPS

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

{team.combo}

); })}
); } function ExtraSection({ extra }: { extra: PublicGuide["extras"][number] }) { return (

Extra Guide

{extra.title}

{extra.rows.map((row) => ( {row.imageUrl ? (
{row.heading}
) : null} {row.heading} {row.body} {row.percent ? {metric(row.percent)} : null}
))}
); }