363 lines
12 KiB
TypeScript
363 lines
12 KiB
TypeScript
import type {
|
|
PageSnapshot,
|
|
PublicCharacterCard,
|
|
} from "@/lib/content/types";
|
|
|
|
const ids = {
|
|
character: "10000000-0000-4000-8000-000000000001",
|
|
infoPage: "10000000-0000-4000-8000-000000000002",
|
|
comboPage: "10000000-0000-4000-8000-000000000003",
|
|
source: "10000000-0000-4000-8000-000000000004",
|
|
profile: "10000000-0000-4000-8000-000000000005",
|
|
section: "10000000-0000-4000-8000-000000000006",
|
|
stats: "10000000-0000-4000-8000-000000000007",
|
|
ranking: "10000000-0000-4000-8000-000000000008",
|
|
chart: "10000000-0000-4000-8000-000000000009",
|
|
rotation: "10000000-0000-4000-8000-000000000010",
|
|
callout: "10000000-0000-4000-8000-000000000011",
|
|
richText: "10000000-0000-4000-8000-000000000012",
|
|
table: "10000000-0000-4000-8000-000000000013",
|
|
links: "10000000-0000-4000-8000-000000000014",
|
|
statOne: "10000000-0000-4000-8000-000000000015",
|
|
statTwo: "10000000-0000-4000-8000-000000000016",
|
|
statThree: "10000000-0000-4000-8000-000000000017",
|
|
stepOne: "10000000-0000-4000-8000-000000000018",
|
|
stepTwo: "10000000-0000-4000-8000-000000000019",
|
|
stepThree: "10000000-0000-4000-8000-000000000020",
|
|
rowOne: "10000000-0000-4000-8000-000000000021",
|
|
rowTwo: "10000000-0000-4000-8000-000000000022",
|
|
rowThree: "10000000-0000-4000-8000-000000000023",
|
|
linkOne: "10000000-0000-4000-8000-000000000024",
|
|
} as const;
|
|
|
|
const character = {
|
|
id: ids.character,
|
|
slug: "astra",
|
|
nameTh: "แอสตรา",
|
|
nameEn: "Astra",
|
|
description: "นักวางกลยุทธ์ธาตุแสงสำหรับทีมที่เน้นจังหวะสกิล",
|
|
portraitMediaId: null,
|
|
element: "แสง",
|
|
role: "สนับสนุน",
|
|
rarity: 5,
|
|
sortOrder: 0,
|
|
visible: true,
|
|
};
|
|
|
|
const pages = [
|
|
{
|
|
id: ids.infoPage,
|
|
characterId: ids.character,
|
|
slug: "info",
|
|
title: "ภาพรวม",
|
|
navOrder: 0,
|
|
visible: true,
|
|
publicNote: "ตัวเลขตัวอย่างนี้ใช้เพื่อสาธิตโครงสร้างเท่านั้น",
|
|
version: 3,
|
|
},
|
|
{
|
|
id: ids.comboPage,
|
|
characterId: ids.character,
|
|
slug: "combo",
|
|
title: "คอมโบ",
|
|
navOrder: 1,
|
|
visible: true,
|
|
publicNote: null,
|
|
version: 1,
|
|
},
|
|
];
|
|
|
|
const dataSource = {
|
|
id: ids.source,
|
|
name: "อุปกรณ์ตัวอย่าง",
|
|
version: 2,
|
|
fields: [
|
|
{ key: "name", label: "ชื่อ", type: "text" as const },
|
|
{ key: "score", label: "คะแนน", type: "number" as const, displayPrecision: 1 },
|
|
{ key: "base", label: "ค่าฐาน", type: "number" as const },
|
|
{
|
|
key: "boosted",
|
|
label: "เมื่อเสริมพลัง",
|
|
type: "number" as const,
|
|
formula: "base * 1.25",
|
|
displayPrecision: 2,
|
|
},
|
|
{ key: "detail", label: "รายละเอียด", type: "text" as const },
|
|
{ key: "tag", label: "ระดับ", type: "badge" as const },
|
|
],
|
|
rows: [
|
|
{
|
|
id: ids.rowOne,
|
|
values: {
|
|
name: "ดาบดาวเหนือ",
|
|
score: "98.5",
|
|
base: "120",
|
|
boosted: null,
|
|
detail: "เหมาะกับรอบการเล่นสั้นและการฟื้นพลังงาน",
|
|
tag: "แนะนำ",
|
|
},
|
|
},
|
|
{
|
|
id: ids.rowTwo,
|
|
values: {
|
|
name: "คทาสายหมอก",
|
|
score: "91.25",
|
|
base: "108",
|
|
boosted: null,
|
|
detail: "ตัวเลือกสมดุลที่ใช้ได้กับหลายทีม",
|
|
tag: "ดีมาก",
|
|
},
|
|
},
|
|
{
|
|
id: ids.rowThree,
|
|
values: {
|
|
name: "หอกฝึกหัด",
|
|
score: "76",
|
|
base: "88",
|
|
boosted: null,
|
|
detail: "ตัวเลือกเข้าถึงง่ายสำหรับช่วงเริ่มต้น",
|
|
tag: "เริ่มต้น",
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
function snapshot(pageSlug: string): PageSnapshot | null {
|
|
const page = pages.find((candidate) => candidate.slug === pageSlug);
|
|
if (!page) return null;
|
|
|
|
const overviewBlocks: PageSnapshot["blocks"] = [
|
|
{
|
|
id: ids.profile,
|
|
type: "profile",
|
|
schemaVersion: 1,
|
|
sortOrder: 0,
|
|
config: {
|
|
eyebrow: "คู่มือตัวละคร",
|
|
title: "แอสตรา — ผู้กำหนดจังหวะสนามรบ",
|
|
subtitle: "ตัวสนับสนุนที่เพิ่มพลังให้ทีมผ่านการจัดลำดับสกิล",
|
|
summary:
|
|
"ตัวอย่างนี้แสดงว่าคู่มือสามารถอ่านง่ายบนมือถือและยังรองรับข้อมูลคำนวณที่ตรวจสอบได้",
|
|
mediaId: null,
|
|
badges: [
|
|
{ label: "ธาตุ", value: "แสง", tone: "element" },
|
|
{ label: "ตำแหน่ง", value: "สนับสนุน", tone: "neutral" },
|
|
{ label: "ระดับ", value: "5 ดาว", tone: "rarity" },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: ids.richText,
|
|
type: "rich-text",
|
|
schemaVersion: 1,
|
|
sortOrder: 1,
|
|
config: {
|
|
content: [
|
|
{
|
|
type: "paragraph",
|
|
text: "วางสกิลสนับสนุนก่อนตัวทำความเสียหายหลัก และเผื่อช่วงเวลาให้เอฟเฟกต์ครอบคลุมท่าไม้ตาย",
|
|
},
|
|
{
|
|
type: "bulleted-list",
|
|
items: [
|
|
"ให้ความสำคัญกับความเร็วและการฟื้นพลังงาน",
|
|
"ปรับลำดับสกิลตามระยะเวลาบัฟของทีม",
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: ids.section,
|
|
type: "section",
|
|
schemaVersion: 1,
|
|
sortOrder: 2,
|
|
config: {
|
|
title: "สรุปค่าสำคัญ",
|
|
description: "ค่าที่ควรตรวจสอบก่อนปรับอุปกรณ์",
|
|
anchor: "key-stats",
|
|
},
|
|
},
|
|
{
|
|
id: ids.stats,
|
|
type: "stat-cards",
|
|
schemaVersion: 1,
|
|
sortOrder: 3,
|
|
config: {
|
|
title: "เป้าหมายเบื้องต้น",
|
|
items: [
|
|
{ id: ids.statOne, label: "ความเร็ว", value: "134", suffix: "+" },
|
|
{ id: ids.statTwo, label: "ฟื้นพลังงาน", value: "120", suffix: "%" },
|
|
{ id: ids.statThree, label: "รอบบัฟ", value: "3", suffix: " เทิร์น" },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: ids.ranking,
|
|
type: "ranking",
|
|
schemaVersion: 1,
|
|
sortOrder: 4,
|
|
responsiveLayout: { width: "wide" },
|
|
config: {
|
|
title: "อันดับอุปกรณ์",
|
|
description: "แตะหรือชี้ที่ชื่อเพื่อดูเหตุผลประกอบ",
|
|
dataSourceId: ids.source,
|
|
labelField: "name",
|
|
valueField: "score",
|
|
detailField: "detail",
|
|
badgeField: "tag",
|
|
higherIsBetter: true,
|
|
},
|
|
},
|
|
{
|
|
id: ids.chart,
|
|
type: "comparison-chart",
|
|
schemaVersion: 1,
|
|
sortOrder: 5,
|
|
responsiveLayout: { width: "wide" },
|
|
config: {
|
|
title: "ผลก่อนและหลังเสริมพลัง",
|
|
description: "ค่าทั้งหมดมาจากแหล่งข้อมูลเวอร์ชันเดียวกัน",
|
|
dataSourceId: ids.source,
|
|
categoryField: "name",
|
|
series: [
|
|
{ field: "base", label: "ค่าฐาน", color: "chart-1" },
|
|
{ field: "boosted", label: "เมื่อเสริมพลัง", color: "chart-2" },
|
|
],
|
|
presentation: "grouped-bar",
|
|
normalization: "raw",
|
|
sort: "authored",
|
|
showValues: true,
|
|
showLegend: true,
|
|
tableFallback: true,
|
|
},
|
|
},
|
|
{
|
|
id: ids.callout,
|
|
type: "callout",
|
|
schemaVersion: 1,
|
|
sortOrder: 6,
|
|
config: {
|
|
title: "หมายเหตุ",
|
|
body: "ผลลัพธ์จริงเปลี่ยนตามเพื่อนร่วมทีมและลำดับการออกแอ็กชัน",
|
|
tone: "tip",
|
|
},
|
|
},
|
|
{
|
|
id: ids.table,
|
|
type: "table",
|
|
schemaVersion: 1,
|
|
sortOrder: 7,
|
|
responsiveLayout: { width: "wide" },
|
|
config: {
|
|
title: "ข้อมูลคำนวณแบบละเอียด",
|
|
dataSourceId: ids.source,
|
|
columns: [
|
|
{ field: "name", label: "อุปกรณ์", align: "start" },
|
|
{ field: "base", label: "ค่าฐาน", align: "end" },
|
|
{ field: "boosted", label: "เสริมพลัง", align: "end" },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: ids.links,
|
|
type: "links",
|
|
schemaVersion: 1,
|
|
sortOrder: 8,
|
|
config: {
|
|
title: "อ่านต่อ",
|
|
links: [
|
|
{
|
|
id: ids.linkOne,
|
|
label: "ไปยังหน้าคอมโบ",
|
|
href: "/astra/combo",
|
|
description: "ดูลำดับสกิลและจังหวะการเล่น",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
];
|
|
|
|
const comboBlocks: PageSnapshot["blocks"] = [
|
|
{
|
|
id: ids.profile,
|
|
type: "profile",
|
|
schemaVersion: 1,
|
|
sortOrder: 0,
|
|
config: {
|
|
eyebrow: "ลำดับการเล่น",
|
|
title: "คอมโบพื้นฐาน",
|
|
subtitle: "หนึ่งรอบที่จำง่ายและปรับใช้ได้กับหลายทีม",
|
|
mediaId: null,
|
|
badges: [],
|
|
},
|
|
},
|
|
{
|
|
id: ids.rotation,
|
|
type: "rotation",
|
|
schemaVersion: 1,
|
|
sortOrder: 1,
|
|
config: {
|
|
title: "รอบการใช้สกิล",
|
|
description: "เรียงจากการเตรียมสนามไปจนถึงช่วงทำความเสียหาย",
|
|
steps: [
|
|
{ id: ids.stepOne, actor: "ตัวสนับสนุน", action: "เปิดบัฟทีม", duration: "1 เทิร์น" },
|
|
{ id: ids.stepTwo, actor: "แอสตรา", action: "ใช้สกิลหลัก", detail: "เก็บพลังงานไว้สำหรับท่าไม้ตาย" },
|
|
{ id: ids.stepThree, actor: "ตัวทำความเสียหาย", action: "ใช้ท่าไม้ตายและโจมตีต่อเนื่อง" },
|
|
],
|
|
},
|
|
},
|
|
];
|
|
|
|
return {
|
|
character,
|
|
page,
|
|
pages,
|
|
blocks: pageSlug === "info" ? overviewBlocks : comboBlocks,
|
|
dataSources: { [ids.source]: dataSource },
|
|
versionVector: { [ids.source]: dataSource.version },
|
|
};
|
|
}
|
|
|
|
export const demoDirectory: PublicCharacterCard[] = [
|
|
{
|
|
id: character.id,
|
|
slug: character.slug,
|
|
nameTh: character.nameTh,
|
|
nameEn: character.nameEn,
|
|
portraitMediaId: character.portraitMediaId,
|
|
element: character.element,
|
|
role: character.role,
|
|
rarity: character.rarity,
|
|
firstPageSlug: pages[0].slug,
|
|
},
|
|
];
|
|
|
|
export function getDemoPage(
|
|
characterSlug: string,
|
|
pageSlug?: string,
|
|
):
|
|
| { type: "page"; snapshot: PageSnapshot }
|
|
| { type: "redirect"; location: string }
|
|
| { type: "not-found" } {
|
|
if (characterSlug !== character.slug) return { type: "not-found" };
|
|
if (!pageSlug) return { type: "redirect", location: "/astra/info" };
|
|
const pageSnapshot = snapshot(pageSlug);
|
|
return pageSnapshot
|
|
? { type: "page", snapshot: pageSnapshot }
|
|
: { type: "not-found" };
|
|
}
|
|
|
|
export function getDemoAdminPage(
|
|
characterSlug: string,
|
|
pageSlug: string,
|
|
): PageSnapshot | null {
|
|
if (characterSlug !== character.slug) return null;
|
|
return snapshot(pageSlug);
|
|
}
|
|
|
|
export const demoAdminNavigation = {
|
|
characters: [{ ...character, pages }],
|
|
templates: [],
|
|
};
|