feat(admin) : flag Lunaris catalog updates
This commit is contained in:
+4
-2
@@ -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 (
|
||||
<div className="min-h-svh">
|
||||
@@ -23,7 +25,7 @@ export default async function AdminPage() {
|
||||
<h1 className="font-heading text-3xl font-semibold">Guide Dashboard</h1>
|
||||
<p className="mt-2 text-muted-foreground">จัดการ Guide แบบภาพ-first และบันทึกขึ้นเว็บไซต์ทันที</p>
|
||||
</header>
|
||||
<StructuredDashboard guides={guides} trash={trash} catalogVersion={catalog?.version ?? null} />
|
||||
<StructuredDashboard guides={guides} trash={trash} catalogVersion={catalog?.version ?? null} latestCatalogVersion={latestCatalogVersion} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<div className="flex flex-col gap-10">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-2"><Badge variant="outline">Lunaris {catalogVersion ? `v${catalogVersion}` : "ยังไม่ Sync"}</Badge></div>
|
||||
<div className="flex flex-wrap items-center gap-2"><Badge variant="outline">Lunaris ที่ Sync: {catalogVersion ? `v${catalogVersion}` : "ยังไม่ Sync"}</Badge><Badge variant={updateAvailable ? "default" : "secondary"}>{latestCatalogVersion ? updateAvailable ? `มีอัปเดต: v${latestCatalogVersion}` : `ล่าสุด: v${latestCatalogVersion}` : "ตรวจสอบเวอร์ชันล่าสุดไม่ได้"}</Badge></div>
|
||||
<div className="flex gap-2"><Button variant="outline" disabled={pending} onClick={() => run(startCatalogSync, "Sync สำเร็จแล้ว")}>{pending ? <Spinner data-icon="inline-start" /> : <RefreshCwIcon data-icon="inline-start" />}Sync Catalog</Button><Button render={<Link href="/admin/create" />} nativeButton={false} disabled={!catalogReady}><PlusIcon data-icon="inline-start" />สร้าง Guide</Button></div>
|
||||
</div>
|
||||
{guides.length ? (
|
||||
|
||||
+5
-2
@@ -114,6 +114,10 @@ function rarity(value: string | undefined): number | null {
|
||||
);
|
||||
}
|
||||
|
||||
export async function getLatestLunarisVersion(): Promise<string> {
|
||||
return versionSchema.parse(await getJson(VERSION_URL)).version;
|
||||
}
|
||||
|
||||
async function mapConcurrent<T, R>(
|
||||
items: T[],
|
||||
task: (item: T) => Promise<R>,
|
||||
@@ -176,8 +180,7 @@ async function uploadAssets(
|
||||
}
|
||||
|
||||
export async function processCatalogSync(): Promise<void> {
|
||||
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`),
|
||||
|
||||
Reference in New Issue
Block a user