From d47c9cb48ba48d7a1a2b0df6c2c23a1a3ed7c797 Mon Sep 17 00:00:00 2001 From: gunshiz Date: Sat, 5 Sep 2026 00:42:16 +0700 Subject: [PATCH] feat : update export image --- app/admin/[character]/[page]/page.tsx | 2 +- app/admin/[character]/page.tsx | 2 +- app/globals.css | 17 -- components/admin/guide-section-nav.tsx | 13 +- components/guide-topic-indicator.tsx | 22 -- components/public/structured-guide.tsx | 272 +++++++++++++++++++------ 6 files changed, 215 insertions(+), 113 deletions(-) delete mode 100644 components/guide-topic-indicator.tsx diff --git a/app/admin/[character]/[page]/page.tsx b/app/admin/[character]/[page]/page.tsx index 41f159a..2f799fb 100644 --- a/app/admin/[character]/[page]/page.tsx +++ b/app/admin/[character]/[page]/page.tsx @@ -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

{guide.name}

{guide.sections.find((section) => section.slug === page)?.title ?? page}

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 })) })) }} />
; + return

{guide.name}

{guide.sections.find((section) => section.slug === page)?.title ?? page}

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 })) })) }} />
; } diff --git a/app/admin/[character]/page.tsx b/app/admin/[character]/page.tsx index d20add2..b7f53c6 100644 --- a/app/admin/[character]/page.tsx +++ b/app/admin/[character]/page.tsx @@ -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
{guide.name}

เลือกส่วนที่ต้องการแก้ไข

{guide.name}

{sections.map(({ slug, title, description }) => {navigationIconPath(slug) ? : null}{title}{description})}Extra sectionsส่วนเสริมแบบภาพ หัวข้อ ข้อความสั้น และเปอร์เซ็นต์
; + return
{guide.name}

เลือกส่วนที่ต้องการแก้ไข

{guide.name}

{sections.map(({ slug, title, description }) => {navigationIconPath(slug) ? : null}{title}{description})}Extra sectionsส่วนเสริมแบบภาพ หัวข้อ ข้อความสั้น และเปอร์เซ็นต์
; } diff --git a/app/globals.css b/app/globals.css index 3793b8b..e9fe78f 100644 --- a/app/globals.css +++ b/app/globals.css @@ -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; } diff --git a/components/admin/guide-section-nav.tsx b/components/admin/guide-section-nav.tsx index b155e5e..64ea1fd 100644 --- a/components/admin/guide-section-nav.tsx +++ b/components/admin/guide-section-nav.tsx @@ -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) => { 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" ? : null} Overview @@ -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 ? : null} {iconPath ? : null} {section.label} diff --git a/components/guide-topic-indicator.tsx b/components/guide-topic-indicator.tsx deleted file mode 100644 index cf307bd..0000000 --- a/components/guide-topic-indicator.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { ViewTransition } from "react"; - -export function GuideTopicIndicator({ - guideId, - surface, -}: { - guideId: string; - surface: "public" | "admin"; -}) { - return ( - - - ); -} diff --git a/components/public/structured-guide.tsx b/components/public/structured-guide.tsx index 2d90479..4219bf7 100644 --- a/components/public/structured-guide.tsx +++ b/components/public/structured-guide.tsx @@ -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({
-
+
- {!section ? : null} - {section === item.slug ? : null} {navigationIconPath(item.slug) ? ( - - - } - /> - ); + return ; } 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 ( -
-
-

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

-

- Weapons -

- {note ? ( -

- {note} -

+
+ {exporting ? ( + <> + +
+ + + ) : null} +
+ {exporting ? ( + ) : null} - {action} +
+

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

+

+ Weapons +

+ {note ? ( +

+ {note} +

+ ) : null} +
- {guide.weaponGroups.filter((group) => group.rows.length > 0).map((group, groupIndex, groups) => ( -
- {groups.length > 1 ?

Condition {groupIndex + 1}

: null} + {weaponGroups.map((group, groupIndex, groups) => ( +
+
+ {groups.length > 1 || conditionNumber ? ( +

+ Condition {conditionNumber ?? groupIndex + 1} +

+ ) : } + {showExportActions ? ( + + 1 ? groupIndex + 1 : undefined} + /> + + ) : null} +
{group.note ?

{group.note}

: null} -
+
{group.rows.map((row, index) => (
@@ -392,23 +459,43 @@ function WeaponSectionContent({

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

{row.note ? ( -

{row.note}

+

+ {row.note} +

) : null}
-
+
{row.overallPercent ? ( -
+

@@ -418,8 +505,12 @@ function WeaponSectionContent({

ดาเมททั้งทีม @@ -427,11 +518,15 @@ function WeaponSectionContent({

) : null} {row.personalPercent ? ( -
+

@@ -441,8 +536,12 @@ function WeaponSectionContent({

ดาเมจส่วนตัว @@ -465,7 +564,10 @@ function ArtifactSection({ guide }: { guide: PublicGuide }) { + } @@ -484,19 +586,63 @@ function ArtifactSectionContent({ }) { const profile = guide.artifactProfile; return ( -

-
-

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

-

- Artifact & Stats -

- {action} +
+ {exporting ? ( + <> + +
+ + + ) : null} +
+ {exporting ? ( + + ) : null} +
+

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

+

+ Artifact & Stats +

+ {action} +