style : better ux
CI / Verify (push) Successful in 59s
CI / Build immutable images and deploy (push) Successful in 1m37s

This commit is contained in:
2026-08-30 07:09:03 +00:00 Unverified
parent 8ef702016b
commit 2f2cfb0274
2 changed files with 24 additions and 3 deletions
+21 -1
View File
@@ -45,7 +45,27 @@ function GuideSection({ guide, section }: { guide: PublicGuide; section: string
function metric(value: string | null) { return value === null ? null : `${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}%`; }
function WeaponSection({ guide }: { guide: PublicGuide }) { return <section className="flex flex-col gap-6"><header className="text-center"><p className="text-sm font-medium text-primary">อาวุธที่แนะนำ</p><h1 className="font-heading text-4xl font-semibold">Weapons</h1></header><div className="grid gap-3 lg:grid-cols-2">{guide.weapons.map((row, index) => <Card key={row.id} size="sm" className={cn(rarityGradientClass(row.weapon.rarity))}><CardContent className="flex items-center gap-4"><div className="relative size-16 shrink-0 overflow-hidden rounded-lg"><Image src={row.weapon.imageUrl} alt={row.weapon.name} fill className="object-contain" /></div><div className="min-w-0 flex-1"><p className="font-semibold">{index + 1}. {row.weapon.name} R{row.refinement}</p></div>{row.overallPercent ? <div className="text-right"><p className="text-xs text-muted-foreground">ดาเมทโดยรวม</p><p className="text-2xl font-semibold">{metric(row.overallPercent)}</p></div> : null}{row.personalPercent ? <div className="text-right"><p className="text-xs text-muted-foreground">ดาเมทส่วนตัว</p><p className="text-2xl font-semibold">{metric(row.personalPercent)}</p></div> : null}</CardContent></Card>)}</div></section>; }
function WeaponSection({ guide }: { guide: PublicGuide }) {
return (
<section className="flex flex-col gap-6">
<header className="text-center"><p className="text-sm font-medium text-primary">อาวุธที่แนะนำ</p><h1 className="font-heading text-4xl font-semibold">Weapons</h1></header>
<div className="grid gap-3 lg:grid-cols-2">
{guide.weapons.map((row, index) => (
<Card key={row.id} size="sm" className={cn(rarityGradientClass(row.weapon.rarity))}>
<CardContent className="flex items-center gap-3">
<div className="relative size-16 shrink-0 overflow-hidden rounded-lg bg-black"><Image src={row.weapon.imageUrl} alt={row.weapon.name} fill className="object-contain" /></div>
<div className="flex min-w-0 flex-1 flex-wrap items-center gap-4 rounded-lg bg-black p-3 text-white">
<p className="min-w-40 flex-1 font-semibold">{index + 1}. {row.weapon.name} R{row.refinement}</p>
{row.overallPercent ? <div className="text-right"><p className="text-xs text-white/70">ดาเมทโดยรวม</p><p className="text-2xl font-semibold">{metric(row.overallPercent)}</p></div> : null}
{row.personalPercent ? <div className="text-right"><p className="text-xs text-white/70">ดาเมทส่วนตัว</p><p className="text-2xl font-semibold">{metric(row.personalPercent)}</p></div> : null}
</div>
</CardContent>
</Card>
))}
</div>
</section>
);
}
function ArtifactSection({ guide }: { guide: PublicGuide }) { const profile = guide.artifactProfile; return <section className="flex flex-col gap-6"><header className="text-center"><p className="text-sm font-medium text-primary">อาร์ติแฟกต์และสเตตัสที่แนะนำ</p><h1 className="font-heading text-4xl font-semibold">Artifacts & Stats</h1></header><div className="grid gap-5 lg:grid-cols-[1.2fr_1fr]"> <div className="flex flex-col gap-5">{guide.artifactGroups.map((group) => <Card key={group.id}><CardHeader><CardTitle>{group.name}</CardTitle></CardHeader><CardContent className="flex flex-col gap-3">{group.rows.map((row, index) => <div key={row.id} className="flex items-center gap-3"><div className="flex -space-x-3"><div className={cn("relative size-14 overflow-hidden rounded-lg border", rarityGradientClass(row.first.rarity))}><Image src={row.first.imageUrl} alt={row.first.name} fill className="object-contain" /></div>{row.second ? <div className={cn("relative size-14 overflow-hidden rounded-lg border", rarityGradientClass(row.second.rarity))}><Image src={row.second.imageUrl} alt={row.second.name} fill className="object-contain" /></div> : null}</div><div className="min-w-0 flex-1"><p className="font-medium">{index + 1}. {row.first.name}{row.second ? ` + ${row.second.name}` : ""}</p></div><p className="text-2xl font-semibold">{metric(row.percent)}</p></div>)}</CardContent></Card>)}</div>{profile ? <Card><CardHeader><CardTitle>Recommended Stats</CardTitle></CardHeader><CardContent className="flex flex-col gap-5"><StatLine label="Sands" values={profile.sands} /><StatLine label="Goblet" values={profile.goblet} /><StatLine label="Circlet" values={profile.circlet} /><Separator /><StatLine label="Substats" values={profile.substats} />{profile.targets.length ? <div><p className="mb-2 text-sm font-medium">Target Stats</p>{profile.targets.map((target) => <div key={`${target.stat}-${target.value}`} className="flex justify-between py-1 text-sm"><span>{target.stat}</span><strong>{target.value}</strong></div>)}</div> : null}{profile.talents.length ? <div><p className="mb-2 text-sm font-medium">Talent Priority</p><div className="flex gap-2">{[...profile.talents].sort((a,b) => a.priority-b.priority).map((talent) => <Badge key={talent.type} variant="secondary">{talent.priority}. {talent.type}{talent.level ? ` ${talent.level}` : ""}</Badge>)}</div></div> : null}{profile.note ? <p className="text-sm leading-6 text-muted-foreground">{profile.note}</p> : null}</CardContent></Card> : null}</div></section>; }