diff --git a/app/admin/page.tsx b/app/admin/page.tsx
index f0eff8a..d347d56 100644
--- a/app/admin/page.tsx
+++ b/app/admin/page.tsx
@@ -23,7 +23,7 @@ export default async function AdminPage() {
-
Lunaris {catalogReady ? "พร้อมใช้งาน" : "ยังไม่ Sync"}
+
Lunaris {catalogVersion ? `v${catalogVersion}` : "ยังไม่ Sync"}
} nativeButton={false} disabled={!catalogReady}>
สร้าง Guide
{guides.length ? (
{guides.map((guide) => (
-
+
+ แก้ไข Guide {guide.name}
{guide.name}{guide.overview}v{guide.version}
แก้ไขล่าสุด {new Date(guide.updatedAt).toLocaleString("th-TH")}
- } nativeButton={false}>แก้ไข Guide} title={`ย้าย ${guide.name} ไปถังขยะ?`} description="Guide จะหายจากหน้าเว็บไซต์ทันที และสามารถกู้คืนได้ภายหลัง" confirmLabel="ย้ายไปถังขยะ" onConfirm={() => run(() => moveGuideToTrash(guide.id), "ย้ายไปถังขยะแล้ว")}>ย้าย {guide.name} ไปถังขยะ
+ } nativeButton={false}>แก้ไข Guide} title={`ย้าย ${guide.name} ไปถังขยะ?`} description="Guide จะหายจากหน้าเว็บไซต์ทันที และสามารถกู้คืนได้ภายหลัง" confirmLabel="ย้ายไปถังขยะ" onConfirm={() => run(() => moveGuideToTrash(guide.id), "ย้ายไปถังขยะแล้ว")}>ย้าย {guide.name} ไปถังขยะ
))}
) :
ยังไม่มี GuideSync Catalog แล้วเลือกตัวละครเพื่อสร้าง Guide แรก} nativeButton={false} disabled={!catalogReady}>สร้าง Guide}
diff --git a/lib/guides/queries.ts b/lib/guides/queries.ts
index cfddd62..ee24ad6 100644
--- a/lib/guides/queries.ts
+++ b/lib/guides/queries.ts
@@ -1,6 +1,7 @@
import "server-only";
import { and, asc, eq, inArray, isNotNull, isNull } from "drizzle-orm";
+import * as z from "zod";
import { getDb } from "@/db";
import {
@@ -20,7 +21,9 @@ import {
teamMembers,
weaponRecommendations,
} from "@/db/schema";
-import { publicMediaUrl } from "@/lib/media/storage";
+import { getMediaStorage, publicMediaUrl } from "@/lib/media/storage";
+
+const catalogVersionSchema = z.object({ version: z.string() });
function catalogCharacterWithUrls(item: typeof catalogCharacters.$inferSelect) {
return {
@@ -48,7 +51,12 @@ export async function getActiveCatalog() {
db.select().from(catalogArtifacts).orderBy(asc(catalogArtifacts.name)),
]);
if (!characters.length) return null;
+ const storage = await getMediaStorage();
+ const { version } = catalogVersionSchema.parse(
+ await storage.file("catalog/current.json").json(),
+ );
return {
+ version,
characters: characters.map(catalogCharacterWithUrls),
weapons: weapons.map((item) => ({ ...item, imageUrl: publicMediaUrl(item.imageKey) })),
artifacts: artifacts.map((item) => ({ ...item, imageUrl: publicMediaUrl(item.imageKey) })),