diff --git a/app/admin/page.tsx b/app/admin/page.tsx index d347d56..ab92431 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -4,15 +4,17 @@ import { connection } from "next/server"; import { StructuredDashboard } from "@/components/admin/structured-dashboard"; import { AdminHeader } from "@/components/admin/admin-header"; import { getAdminSession } from "@/lib/auth/server"; +import { getLatestLunarisVersion } from "@/lib/catalog/sync"; import { getActiveCatalog, listGuideCards } from "@/lib/guides/queries"; export default async function AdminPage() { await connection(); if (!(await getAdminSession())) redirect("/admin/login"); - const [guides, trash, catalog] = await Promise.all([ + const [guides, trash, catalog, latestCatalogVersion] = await Promise.all([ listGuideCards(), listGuideCards(true), getActiveCatalog(), + getLatestLunarisVersion().catch(() => null), ]); return (
@@ -23,7 +25,7 @@ export default async function AdminPage() {

Guide Dashboard

จัดการ Guide แบบภาพ-first และบันทึกขึ้นเว็บไซต์ทันที

- +
); diff --git a/components/admin/structured-dashboard.tsx b/components/admin/structured-dashboard.tsx index 67cbb15..e9f3845 100644 --- a/components/admin/structured-dashboard.tsx +++ b/components/admin/structured-dashboard.tsx @@ -17,10 +17,11 @@ import { Spinner } from "@/components/ui/spinner"; type GuideCard = { id: string; characterKey: string; name: string; overview: string; coverUrl: string; version: number; updatedAt: Date; trashedAt: Date | null }; -export function StructuredDashboard({ guides, trash, catalogVersion }: { guides: GuideCard[]; trash: GuideCard[]; catalogVersion: string | null }) { +export function StructuredDashboard({ guides, trash, catalogVersion, latestCatalogVersion }: { guides: GuideCard[]; trash: GuideCard[]; catalogVersion: string | null; latestCatalogVersion: string | null }) { const router = useRouter(); const [pending, startTransition] = useTransition(); const catalogReady = Boolean(catalogVersion); + const updateAvailable = Boolean(catalogVersion && latestCatalogVersion && catalogVersion !== latestCatalogVersion); function run(action: () => Promise<{ status: string; message?: string }>, success: string) { startTransition(async () => { @@ -33,7 +34,7 @@ export function StructuredDashboard({ guides, trash, catalogVersion }: { guides: return (
-
Lunaris {catalogVersion ? `v${catalogVersion}` : "ยังไม่ Sync"}
+
Lunaris ที่ Sync: {catalogVersion ? `v${catalogVersion}` : "ยังไม่ Sync"}{latestCatalogVersion ? updateAvailable ? `มีอัปเดต: v${latestCatalogVersion}` : `ล่าสุด: v${latestCatalogVersion}` : "ตรวจสอบเวอร์ชันล่าสุดไม่ได้"}
{guides.length ? ( diff --git a/lib/catalog/sync.ts b/lib/catalog/sync.ts index cba1989..fc11af3 100644 --- a/lib/catalog/sync.ts +++ b/lib/catalog/sync.ts @@ -114,6 +114,10 @@ function rarity(value: string | undefined): number | null { ); } +export async function getLatestLunarisVersion(): Promise { + return versionSchema.parse(await getJson(VERSION_URL)).version; +} + async function mapConcurrent( items: T[], task: (item: T) => Promise, @@ -176,8 +180,7 @@ async function uploadAssets( } export async function processCatalogSync(): Promise { - const versionInfo = versionSchema.parse(await getJson(VERSION_URL)); - const version = versionInfo.version; + const version = await getLatestLunarisVersion(); const [charactersRaw, weaponsRaw, artifactsRaw] = await Promise.all([ getJson(`${API_ROOT}/${version}/charlist.json`), getJson(`${API_ROOT}/${version}/weaponlist.json`),