feat : update export image
This commit is contained in:
@@ -22,5 +22,5 @@ export default async function StructuredEditorPage({ params }: { params: Promise
|
||||
const [catalog, content] = await Promise.all([getActiveCatalog(), getAdminGuideContent(guide.slug)]);
|
||||
if (!catalog || !content) notFound();
|
||||
const guideCharacter = catalog.characters.find((item) => item.key === guide.characterKey);
|
||||
return <div className="min-h-svh"><AdminHeader /><main className="mx-auto flex w-full max-w-6xl flex-col gap-6 p-4 sm:p-6 lg:p-8"><header className="flex items-center gap-4"><Button variant="outline" size="icon" render={<Link href={`/admin/${character}`} />} nativeButton={false} aria-label="กลับหน้า Guide"><ArrowLeftIcon /></Button><div className="min-w-0"><p className="text-sm text-muted-foreground">{guide.name}</p><h1 className="whitespace-nowrap font-heading text-3xl font-semibold">{guide.sections.find((section) => section.slug === page)?.title ?? page}</h1></div></header><GuideSectionNav characterKey={guide.characterKey} current={page as (typeof sections)[number]} guideId={guide.id} /><GuideSectionEditor section={page as (typeof sections)[number]} guide={guide} weapons={catalog.weapons} artifacts={catalog.artifacts} characters={catalog.characters} catalogConstellations={guideCharacter?.constellations ?? []} catalogTalents={guideCharacter?.talents ?? []} initial={{ sectionNote: guide.sections.find((section) => section.slug === page)?.note ?? null, weaponGroups: content.weaponGroups, artifactGroups: content.artifactGroups.map((group) => ({ id: group.id, name: group.name, rows: group.rows.map((row) => ({ firstArtifactKey: row.firstArtifactKey, secondArtifactKey: row.secondArtifactKey, percent: row.percent, note: row.note })) })), artifactProfile: content.artifactProfile, constellationGroups: content.constellationGroups.map((group) => ({ id: group.id, note: group.note, rows: group.rows })), teams: content.teams.map((team) => ({ id: team.id, title: team.title, rotationSeconds: team.rotationSeconds, combo: team.combo, members: team.members.map((member) => ({ characterKey: member.characterKey, weaponKey: member.weaponKey, artifactKey: member.artifactKey, secondArtifactKey: member.secondArtifactKey, constellation: member.constellation, refinement: member.refinement, damage: member.damage })) })), extras: content.extras.map((section) => ({ id: section.id, title: section.title, rows: section.rows.map((row) => ({ id: row.id, mediaId: row.mediaId, heading: row.heading, body: row.body, percent: row.percent, backgroundColor: row.backgroundColor, highlights: row.highlights, imageUrl: row.imageUrl, imageWidth: row.imageWidth, imageHeight: row.imageHeight })) })) }} /></main></div>;
|
||||
return <div className="min-h-svh"><AdminHeader /><main className="mx-auto flex w-full max-w-6xl flex-col gap-6 p-4 sm:p-6 lg:p-8"><header className="flex items-center gap-4"><Button variant="outline" size="icon" render={<Link href={`/admin/${character}`} />} nativeButton={false} aria-label="กลับหน้า Guide"><ArrowLeftIcon /></Button><div className="min-w-0"><p className="text-sm text-muted-foreground">{guide.name}</p><h1 className="whitespace-nowrap font-heading text-3xl font-semibold">{guide.sections.find((section) => section.slug === page)?.title ?? page}</h1></div></header><GuideSectionNav characterKey={guide.characterKey} current={page as (typeof sections)[number]} /><GuideSectionEditor section={page as (typeof sections)[number]} guide={guide} weapons={catalog.weapons} artifacts={catalog.artifacts} characters={catalog.characters} catalogConstellations={guideCharacter?.constellations ?? []} catalogTalents={guideCharacter?.talents ?? []} initial={{ sectionNote: guide.sections.find((section) => section.slug === page)?.note ?? null, weaponGroups: content.weaponGroups, artifactGroups: content.artifactGroups.map((group) => ({ id: group.id, name: group.name, rows: group.rows.map((row) => ({ firstArtifactKey: row.firstArtifactKey, secondArtifactKey: row.secondArtifactKey, percent: row.percent, note: row.note })) })), artifactProfile: content.artifactProfile, constellationGroups: content.constellationGroups.map((group) => ({ id: group.id, note: group.note, rows: group.rows })), teams: content.teams.map((team) => ({ id: team.id, title: team.title, rotationSeconds: team.rotationSeconds, combo: team.combo, members: team.members.map((member) => ({ characterKey: member.characterKey, weaponKey: member.weaponKey, artifactKey: member.artifactKey, secondArtifactKey: member.secondArtifactKey, constellation: member.constellation, refinement: member.refinement, damage: member.damage })) })), extras: content.extras.map((section) => ({ id: section.id, title: section.title, rows: section.rows.map((row) => ({ id: row.id, mediaId: row.mediaId, heading: row.heading, body: row.body, percent: row.percent, backgroundColor: row.backgroundColor, highlights: row.highlights, imageUrl: row.imageUrl, imageWidth: row.imageWidth, imageHeight: row.imageHeight })) })) }} /></main></div>;
|
||||
}
|
||||
|
||||
@@ -27,5 +27,5 @@ export default async function GuideOverviewPage({ params }: { params: Promise<{
|
||||
const { character } = await params;
|
||||
const guide = await getGuideByCharacterKey(character);
|
||||
if (!guide) notFound();
|
||||
return <div className="min-h-svh"><AdminHeader /><main className="mx-auto flex w-full max-w-6xl flex-col gap-8 p-4 sm:p-6 lg:p-8"><header className="flex flex-wrap items-center gap-4"><Button variant="outline" size="icon" render={<Link href="/admin" />} nativeButton={false} aria-label="กลับ Dashboard"><ArrowLeftIcon /></Button><div className="relative size-16 overflow-hidden rounded-lg border"><Image src={guide.coverUrl} alt={guide.name} fill className="object-cover" /></div><div className="min-w-0 flex-1"><p className="text-sm text-muted-foreground">เลือกส่วนที่ต้องการแก้ไข</p><h1 className="font-heading text-3xl font-semibold">{guide.name}</h1></div><GuideVisibilityControl guideId={guide.id} guideName={guide.name} isPublic={guide.isPublic} /></header><GuideSectionNav characterKey={guide.characterKey} current="overview" guideId={guide.id} /><GuideOverviewForm guide={guide} /><div className="grid gap-4 md:grid-cols-2">{sections.map(({ slug, title, description }) => <Link key={slug} href={`/admin/${guide.characterKey}/${slug}`} prefetch className="rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-ring"><Card className="h-full transition-colors hover:bg-muted/50"><CardHeader>{navigationIconPath(slug) ? <Image src={navigationIconPath(slug)!} alt="" width={40} height={40} className="size-10 object-contain" /> : null}<CardTitle>{title}</CardTitle><CardDescription>{description}</CardDescription><CardAction><ArrowUpRightIcon aria-hidden="true" className="size-5 text-primary" /></CardAction></CardHeader></Card></Link>)}<Link href={`/admin/${guide.characterKey}/extra`} prefetch className="rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-ring"><Card className="h-full transition-colors hover:bg-muted/50"><CardHeader><Image src={navigationIconPath("extra")!} alt="" width={40} height={40} className="size-10 object-contain" /><CardTitle>Extra sections</CardTitle><CardDescription>ส่วนเสริมแบบภาพ หัวข้อ ข้อความสั้น และเปอร์เซ็นต์</CardDescription><CardAction><ArrowUpRightIcon aria-hidden="true" className="size-5 text-primary" /></CardAction></CardHeader></Card></Link></div></main></div>;
|
||||
return <div className="min-h-svh"><AdminHeader /><main className="mx-auto flex w-full max-w-6xl flex-col gap-8 p-4 sm:p-6 lg:p-8"><header className="flex flex-wrap items-center gap-4"><Button variant="outline" size="icon" render={<Link href="/admin" />} nativeButton={false} aria-label="กลับ Dashboard"><ArrowLeftIcon /></Button><div className="relative size-16 overflow-hidden rounded-lg border"><Image src={guide.coverUrl} alt={guide.name} fill className="object-cover" /></div><div className="min-w-0 flex-1"><p className="text-sm text-muted-foreground">เลือกส่วนที่ต้องการแก้ไข</p><h1 className="font-heading text-3xl font-semibold">{guide.name}</h1></div><GuideVisibilityControl guideId={guide.id} guideName={guide.name} isPublic={guide.isPublic} /></header><GuideSectionNav characterKey={guide.characterKey} current="overview" /><GuideOverviewForm guide={guide} /><div className="grid gap-4 md:grid-cols-2">{sections.map(({ slug, title, description }) => <Link key={slug} href={`/admin/${guide.characterKey}/${slug}`} prefetch className="rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-ring"><Card className="h-full transition-colors hover:bg-muted/50"><CardHeader>{navigationIconPath(slug) ? <Image src={navigationIconPath(slug)!} alt="" width={40} height={40} className="size-10 object-contain" /> : null}<CardTitle>{title}</CardTitle><CardDescription>{description}</CardDescription><CardAction><ArrowUpRightIcon aria-hidden="true" className="size-5 text-primary" /></CardAction></CardHeader></Card></Link>)}<Link href={`/admin/${guide.characterKey}/extra`} prefetch className="rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-ring"><Card className="h-full transition-colors hover:bg-muted/50"><CardHeader><Image src={navigationIconPath("extra")!} alt="" width={40} height={40} className="size-10 object-contain" /><CardTitle>Extra sections</CardTitle><CardDescription>ส่วนเสริมแบบภาพ หัวข้อ ข้อความสั้น และเปอร์เซ็นต์</CardDescription><CardAction><ArrowUpRightIcon aria-hidden="true" className="size-5 text-primary" /></CardAction></CardHeader></Card></Link></div></main></div>;
|
||||
}
|
||||
|
||||
@@ -140,21 +140,4 @@
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
|
||||
::view-transition-old(*),
|
||||
::view-transition-new(*),
|
||||
::view-transition-group(*) {
|
||||
animation-delay: 0s !important;
|
||||
animation-duration: 0s !important;
|
||||
}
|
||||
}
|
||||
|
||||
::view-transition {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
::view-transition-group(.guide-topic-indicator) {
|
||||
animation-duration: 300ms;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import type { MouseEvent } from "react";
|
||||
|
||||
import { GuideTopicIndicator } from "@/components/guide-topic-indicator";
|
||||
import { ScrollableNav } from "@/components/public/scrollable-nav";
|
||||
import { navigationIconPath } from "@/lib/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -20,11 +19,9 @@ const sections = [
|
||||
export function GuideSectionNav({
|
||||
characterKey,
|
||||
current,
|
||||
guideId,
|
||||
}: {
|
||||
characterKey: string;
|
||||
current: "overview" | (typeof sections)[number]["slug"];
|
||||
guideId: string;
|
||||
}) {
|
||||
const confirmNavigation = (event: MouseEvent<HTMLAnchorElement>) => {
|
||||
const browserWindow = window as Window & { __guideHasUnsavedChanges?: boolean };
|
||||
@@ -42,11 +39,10 @@ export function GuideSectionNav({
|
||||
prefetch
|
||||
onClick={confirmNavigation}
|
||||
className={cn(
|
||||
"relative isolate flex min-h-8 shrink-0 items-center gap-2 rounded-md px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
current === "overview" ? "text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
"flex min-h-8 shrink-0 items-center gap-2 rounded-md px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
current === "overview" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{current === "overview" ? <GuideTopicIndicator guideId={guideId} surface="admin" /> : null}
|
||||
<Image src={navigationIconPath("overview")!} alt="" width={20} height={20} className="size-5 object-contain" />
|
||||
Overview
|
||||
</Link>
|
||||
@@ -59,11 +55,10 @@ export function GuideSectionNav({
|
||||
prefetch
|
||||
onClick={confirmNavigation}
|
||||
className={cn(
|
||||
"relative isolate flex min-h-8 shrink-0 items-center gap-2 rounded-md px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
current === section.slug ? "text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
"flex min-h-8 shrink-0 items-center gap-2 rounded-md px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
current === section.slug ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{current === section.slug ? <GuideTopicIndicator guideId={guideId} surface="admin" /> : null}
|
||||
{iconPath ? <Image src={iconPath} alt="" width={20} height={20} className="size-5 object-contain" /> : null}
|
||||
{section.label}
|
||||
</Link>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ViewTransition } from "react";
|
||||
|
||||
export function GuideTopicIndicator({
|
||||
guideId,
|
||||
surface,
|
||||
}: {
|
||||
guideId: string;
|
||||
surface: "public" | "admin";
|
||||
}) {
|
||||
return (
|
||||
<ViewTransition
|
||||
name={`guide-topic-indicator-${surface}-${guideId}`}
|
||||
share="guide-topic-indicator"
|
||||
default="none"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="absolute inset-0 -z-10 rounded-md bg-muted"
|
||||
/>
|
||||
</ViewTransition>
|
||||
);
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import { GuideImageExport } from "@/components/public/guide-image-export";
|
||||
import { ConstellationImage } from "@/components/public/constellation-image";
|
||||
import { RichTextContent } from "@/components/rich-text-content";
|
||||
import { LiveRefresh } from "@/components/live-refresh";
|
||||
import { GuideTopicIndicator } from "@/components/guide-topic-indicator";
|
||||
import { rarityGradientClass, rarityTextClass } from "@/lib/catalog/rarity";
|
||||
import { elementIconFilter } from "@/lib/catalog/element";
|
||||
import type { PublicGuide } from "@/lib/guides/queries";
|
||||
@@ -89,7 +88,7 @@ export function StructuredGuideShell({
|
||||
<div className="flex min-h-svh flex-col bg-background">
|
||||
<LiveRefresh endpoint={`/api/events/page/${guide.id}`} />
|
||||
<SiteHeader editHref={`/admin/${guide.characterKey}`} />
|
||||
<div className="sticky top-0 z-10 bg-background/95 supports-backdrop-filter:backdrop-blur">
|
||||
<div className="sticky top-0 z-40 bg-background/95 supports-backdrop-filter:backdrop-blur">
|
||||
<div className="mx-auto flex min-h-16 w-full max-w-7xl items-center gap-3 px-4 sm:px-6">
|
||||
<Link
|
||||
href="/"
|
||||
@@ -127,14 +126,13 @@ export function StructuredGuideShell({
|
||||
<Link
|
||||
href={`/${guide.slug}`}
|
||||
className={cn(
|
||||
"relative isolate flex min-h-8 shrink-0 items-center gap-2 whitespace-nowrap rounded-md px-3 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
"flex min-h-8 shrink-0 items-center gap-2 whitespace-nowrap rounded-md px-3 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
!section
|
||||
? "text-foreground"
|
||||
? "bg-muted text-foreground"
|
||||
: "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
)}
|
||||
prefetch
|
||||
>
|
||||
{!section ? <GuideTopicIndicator guideId={guide.id} surface="public" /> : null}
|
||||
<Image
|
||||
src={navigationIconPath("overview")!}
|
||||
alt=""
|
||||
@@ -149,14 +147,13 @@ export function StructuredGuideShell({
|
||||
key={item.id}
|
||||
href={`/${guide.slug}/${item.slug}`}
|
||||
className={cn(
|
||||
"relative isolate flex min-h-8 shrink-0 items-center gap-2 whitespace-nowrap rounded-md px-3 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
"flex min-h-8 shrink-0 items-center gap-2 whitespace-nowrap rounded-md px-3 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
section === item.slug
|
||||
? "text-foreground"
|
||||
? "bg-muted text-foreground"
|
||||
: "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
)}
|
||||
prefetch
|
||||
>
|
||||
{section === item.slug ? <GuideTopicIndicator guideId={guide.id} surface="public" /> : null}
|
||||
{navigationIconPath(item.slug) ? (
|
||||
<Image
|
||||
src={navigationIconPath(item.slug)!}
|
||||
@@ -316,65 +313,135 @@ function metric(value: string | null) {
|
||||
}
|
||||
|
||||
function WeaponSection({ guide }: { guide: PublicGuide }) {
|
||||
return (
|
||||
<WeaponSectionContent
|
||||
guide={guide}
|
||||
action={
|
||||
<GuideImageExport fileName={`${guide.name}-Weapon.png`}>
|
||||
<WeaponSectionContent guide={guide} exporting />
|
||||
</GuideImageExport>
|
||||
}
|
||||
/>
|
||||
);
|
||||
return <WeaponSectionContent guide={guide} showExportActions />;
|
||||
}
|
||||
|
||||
function WeaponSectionContent({
|
||||
guide,
|
||||
action,
|
||||
exporting = false,
|
||||
groups: providedGroups,
|
||||
conditionNumber,
|
||||
showExportActions = false,
|
||||
}: {
|
||||
guide: PublicGuide;
|
||||
action?: React.ReactNode;
|
||||
exporting?: boolean;
|
||||
groups?: PublicGuide["weaponGroups"];
|
||||
conditionNumber?: number;
|
||||
showExportActions?: boolean;
|
||||
}) {
|
||||
const note = guide.sections.find(
|
||||
(section) => section.slug === "weapon",
|
||||
)?.note;
|
||||
const weaponGroups = (providedGroups ?? guide.weaponGroups).filter(
|
||||
(group) => group.rows.length > 0,
|
||||
);
|
||||
const useCompactExportGrid =
|
||||
exporting &&
|
||||
weaponGroups.reduce((total, group) => total + group.rows.length, 0) > 6;
|
||||
|
||||
return (
|
||||
<section className="flex flex-col gap-6">
|
||||
<header className="flex flex-col items-center gap-3 text-center">
|
||||
<p className="text-sm font-medium text-primary">อาวุธที่แนะนำ</p>
|
||||
<h1 className="whitespace-nowrap font-heading text-4xl font-semibold">
|
||||
Weapons
|
||||
</h1>
|
||||
{note ? (
|
||||
<p className="max-w-3xl whitespace-pre-wrap text-muted-foreground">
|
||||
{note}
|
||||
</p>
|
||||
<section
|
||||
className={cn(
|
||||
"flex flex-col gap-6",
|
||||
exporting &&
|
||||
"relative isolate overflow-hidden bg-[#070b20] p-10 text-white",
|
||||
)}
|
||||
>
|
||||
{exporting ? (
|
||||
<>
|
||||
<Image
|
||||
src={guide.character.splashImageUrl ?? guide.coverUrl}
|
||||
alt=""
|
||||
fill
|
||||
loading="eager"
|
||||
sizes="1200px"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-[#050817]/65" />
|
||||
<Image
|
||||
src="/icon/Watermark.png"
|
||||
alt=""
|
||||
width={180}
|
||||
height={101}
|
||||
loading="eager"
|
||||
className="absolute top-4 right-4 z-30 h-auto w-[180px] object-contain drop-shadow-[0_4px_3px_rgba(0,0,0,0.8)]"
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<header
|
||||
className={cn(
|
||||
"relative z-10 flex items-center justify-center gap-3 text-center",
|
||||
!exporting && "flex-col",
|
||||
)}
|
||||
>
|
||||
{exporting ? (
|
||||
<Image
|
||||
src="/icon/nav/Weapon.png"
|
||||
alt=""
|
||||
width={56}
|
||||
height={56}
|
||||
loading="eager"
|
||||
className="size-14 shrink-0 object-contain drop-shadow-[0_4px_3px_rgba(0,0,0,0.8)]"
|
||||
/>
|
||||
) : null}
|
||||
{action}
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<p className="text-sm font-medium text-primary">อาวุธที่แนะนำ</p>
|
||||
<h1 className="whitespace-nowrap font-heading text-4xl font-semibold">
|
||||
Weapons
|
||||
</h1>
|
||||
{note ? (
|
||||
<p className="max-w-3xl whitespace-pre-wrap text-muted-foreground">
|
||||
{note}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
</header>
|
||||
{guide.weaponGroups.filter((group) => group.rows.length > 0).map((group, groupIndex, groups) => (
|
||||
<div key={group.id} className="flex flex-col gap-3">
|
||||
{groups.length > 1 ? <h2 className="font-heading text-2xl font-semibold">Condition {groupIndex + 1}</h2> : null}
|
||||
{weaponGroups.map((group, groupIndex, groups) => (
|
||||
<div key={group.id} className="relative z-10 flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
{groups.length > 1 || conditionNumber ? (
|
||||
<h2 className="font-heading text-2xl font-semibold">
|
||||
Condition {conditionNumber ?? groupIndex + 1}
|
||||
</h2>
|
||||
) : <span />}
|
||||
{showExportActions ? (
|
||||
<GuideImageExport
|
||||
fileName={`${guide.name}-Weapon-Condition-${groupIndex + 1}.png`}
|
||||
captureClassName="p-0"
|
||||
>
|
||||
<WeaponSectionContent
|
||||
guide={guide}
|
||||
exporting
|
||||
groups={[group]}
|
||||
conditionNumber={groups.length > 1 ? groupIndex + 1 : undefined}
|
||||
/>
|
||||
</GuideImageExport>
|
||||
) : null}
|
||||
</div>
|
||||
{group.note ? <p className="whitespace-pre-wrap text-muted-foreground">{group.note}</p> : null}
|
||||
<div className="grid gap-3">
|
||||
<div
|
||||
className={cn("grid gap-3", useCompactExportGrid && "grid-cols-2")}
|
||||
>
|
||||
{group.rows.map((row, index) => (
|
||||
<Card key={row.id} size="sm" className="bg-white py-0">
|
||||
<CardContent
|
||||
className={cn(
|
||||
"grid p-0",
|
||||
exporting
|
||||
? "grid-cols-[minmax(0,3fr)_minmax(0,1fr)]"
|
||||
: "md:grid-cols-[minmax(0,3fr)_minmax(0,1fr)]",
|
||||
useCompactExportGrid
|
||||
? "grid-cols-[minmax(0,3fr)_minmax(0,2fr)]"
|
||||
: exporting
|
||||
? "grid-cols-[minmax(0,3fr)_minmax(0,1fr)]"
|
||||
: "md:grid-cols-[minmax(0,3fr)_minmax(0,1fr)]",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"flex min-h-28 min-w-0 items-center gap-4 rounded-br-[4rem] p-4 pr-10 text-white",
|
||||
exporting
|
||||
? "rounded-br-[8rem] pr-16"
|
||||
: "md:rounded-br-[8rem] md:pr-16",
|
||||
useCompactExportGrid
|
||||
? "rounded-br-[8rem] pr-10"
|
||||
: exporting
|
||||
? "rounded-br-[8rem] pr-16"
|
||||
: "md:rounded-br-[8rem] md:pr-16",
|
||||
rarityGradientClass(row.weapon.rarity),
|
||||
)}
|
||||
>
|
||||
@@ -392,23 +459,43 @@ function WeaponSectionContent({
|
||||
<p
|
||||
className={cn(
|
||||
"truncate font-semibold",
|
||||
exporting ? "text-lg" : "text-base sm:text-lg",
|
||||
useCompactExportGrid
|
||||
? "text-sm"
|
||||
: exporting
|
||||
? "text-lg"
|
||||
: "text-base sm:text-lg",
|
||||
)}
|
||||
>
|
||||
{index + 1}. {row.weapon.name} R{row.refinement}
|
||||
</p>
|
||||
{row.note ? (
|
||||
<p className="whitespace-pre-wrap text-sm">{row.note}</p>
|
||||
<p
|
||||
className={cn(
|
||||
"whitespace-pre-wrap",
|
||||
useCompactExportGrid ? "text-xs" : "text-sm",
|
||||
)}
|
||||
>
|
||||
{row.note}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-around gap-4 bg-white px-4 py-5 text-black">
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-around bg-white py-5 text-black",
|
||||
useCompactExportGrid ? "gap-1 px-2" : "gap-4 px-4",
|
||||
)}
|
||||
>
|
||||
{row.overallPercent ? (
|
||||
<div className="flex-1 text-center">
|
||||
<div className="min-w-0 flex-1 text-center">
|
||||
<p
|
||||
className={cn(
|
||||
"whitespace-nowrap leading-none font-bold",
|
||||
exporting ? "text-5xl" : "text-4xl sm:text-5xl",
|
||||
useCompactExportGrid
|
||||
? "text-2xl"
|
||||
: exporting
|
||||
? "text-5xl"
|
||||
: "text-4xl sm:text-5xl",
|
||||
rarityTextClass(row.weapon.rarity),
|
||||
)}
|
||||
>
|
||||
@@ -418,8 +505,12 @@ function WeaponSectionContent({
|
||||
</p>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-1",
|
||||
exporting ? "text-base" : "text-sm sm:text-base",
|
||||
"mt-1 whitespace-nowrap",
|
||||
useCompactExportGrid
|
||||
? "text-[10px]"
|
||||
: exporting
|
||||
? "text-base"
|
||||
: "text-sm sm:text-base",
|
||||
)}
|
||||
>
|
||||
ดาเมททั้งทีม
|
||||
@@ -427,11 +518,15 @@ function WeaponSectionContent({
|
||||
</div>
|
||||
) : null}
|
||||
{row.personalPercent ? (
|
||||
<div className="flex-1 text-center">
|
||||
<div className="min-w-0 flex-1 text-center">
|
||||
<p
|
||||
className={cn(
|
||||
"whitespace-nowrap leading-none font-bold",
|
||||
exporting ? "text-5xl" : "text-4xl sm:text-5xl",
|
||||
useCompactExportGrid
|
||||
? "text-2xl"
|
||||
: exporting
|
||||
? "text-5xl"
|
||||
: "text-4xl sm:text-5xl",
|
||||
rarityTextClass(row.weapon.rarity),
|
||||
)}
|
||||
>
|
||||
@@ -441,8 +536,12 @@ function WeaponSectionContent({
|
||||
</p>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-1",
|
||||
exporting ? "text-base" : "text-sm sm:text-base",
|
||||
"mt-1 whitespace-nowrap",
|
||||
useCompactExportGrid
|
||||
? "text-[10px]"
|
||||
: exporting
|
||||
? "text-base"
|
||||
: "text-sm sm:text-base",
|
||||
)}
|
||||
>
|
||||
ดาเมจส่วนตัว
|
||||
@@ -465,7 +564,10 @@ function ArtifactSection({ guide }: { guide: PublicGuide }) {
|
||||
<ArtifactSectionContent
|
||||
guide={guide}
|
||||
action={
|
||||
<GuideImageExport fileName={`${guide.name}-Artifact.png`}>
|
||||
<GuideImageExport
|
||||
fileName={`${guide.name}-Artifact.png`}
|
||||
captureClassName="p-0"
|
||||
>
|
||||
<ArtifactSectionContent guide={guide} exporting />
|
||||
</GuideImageExport>
|
||||
}
|
||||
@@ -484,19 +586,63 @@ function ArtifactSectionContent({
|
||||
}) {
|
||||
const profile = guide.artifactProfile;
|
||||
return (
|
||||
<section className="flex flex-col gap-6">
|
||||
<header className="flex flex-col items-center gap-3 text-center">
|
||||
<p className="text-sm font-medium text-primary">
|
||||
อาร์ติแฟกต์และสแตทที่แนะนำ
|
||||
</p>
|
||||
<h1 className="font-heading text-4xl font-semibold">
|
||||
Artifact & Stats
|
||||
</h1>
|
||||
{action}
|
||||
<section
|
||||
className={cn(
|
||||
"flex flex-col gap-6",
|
||||
exporting &&
|
||||
"relative isolate overflow-hidden bg-[#070b20] p-10 text-white",
|
||||
)}
|
||||
>
|
||||
{exporting ? (
|
||||
<>
|
||||
<Image
|
||||
src={guide.character.splashImageUrl ?? guide.coverUrl}
|
||||
alt=""
|
||||
fill
|
||||
loading="eager"
|
||||
sizes="1200px"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-[#050817]/65" />
|
||||
<Image
|
||||
src="/icon/Watermark.png"
|
||||
alt=""
|
||||
width={180}
|
||||
height={101}
|
||||
loading="eager"
|
||||
className="absolute top-4 right-4 z-30 h-auto w-[180px] object-contain drop-shadow-[0_4px_3px_rgba(0,0,0,0.8)]"
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<header
|
||||
className={cn(
|
||||
"relative z-10 flex items-center justify-center gap-3 text-center",
|
||||
!exporting && "flex-col",
|
||||
)}
|
||||
>
|
||||
{exporting ? (
|
||||
<Image
|
||||
src="/icon/nav/Artifact.webp"
|
||||
alt=""
|
||||
width={56}
|
||||
height={56}
|
||||
loading="eager"
|
||||
className="size-14 shrink-0 object-contain drop-shadow-[0_4px_3px_rgba(0,0,0,0.8)]"
|
||||
/>
|
||||
) : null}
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<p className="text-sm font-medium text-primary">
|
||||
อาร์ติแฟกต์และสแตทที่แนะนำ
|
||||
</p>
|
||||
<h1 className="font-heading text-4xl font-semibold">
|
||||
Artifact & Stats
|
||||
</h1>
|
||||
{action}
|
||||
</div>
|
||||
</header>
|
||||
<div
|
||||
className={cn(
|
||||
"grid gap-5",
|
||||
"relative z-10 grid gap-5",
|
||||
exporting ? "grid-cols-[1.2fr_1fr]" : "lg:grid-cols-[1.2fr_1fr]",
|
||||
)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user