diff --git a/app/admin/actions.ts b/app/admin/actions.ts new file mode 100644 index 0000000..fe81b94 --- /dev/null +++ b/app/admin/actions.ts @@ -0,0 +1,71 @@ +"use server"; + +import { z } from "zod"; + +import type { AutosaveResponse } from "@/lib/editor/autosave"; +import { savePageDraft } from "@/lib/content/mutations"; +import type { PageSnapshot } from "@/lib/content/types"; +import { requireAdmin } from "@/lib/auth/server"; + +const serializedBlockSchema = z.strictObject({ + id: z.string().uuid(), + type: z.string().min(1).max(64), + schemaVersion: z.number().int().nonnegative(), + config: z.unknown(), + responsiveLayout: z.unknown().optional(), + sortOrder: z.number().int().nonnegative(), +}); + +const editorDraftSchema = z.strictObject({ + pageId: z.string().uuid(), + expectedVersion: z.number().int().positive(), + title: z.string().max(300), + slug: z.string().max(120), + visible: z.boolean(), + publicNote: z.string().max(10_000).nullable().optional(), + blocks: z.array(serializedBlockSchema).max(500), +}); + +export type EditorSaveInput = z.input; +export type EditorSaveResult = AutosaveResponse; + +export async function saveEditorPage(input: unknown): Promise { + const admin = await requireAdmin(); + const parsed = editorDraftSchema.safeParse(input); + if (!parsed.success) { + return { + status: "validation-error", + issues: parsed.error.issues.map((issue) => issue.message), + }; + } + + if (process.env.BUZZ_DEMO_MODE === "true") { + return { status: "saved", version: parsed.data.expectedVersion + 1 }; + } + + try { + const result = await savePageDraft({ + ...parsed.data, + authorId: admin.user.id, + }); + if (result.status === "accepted") { + return { + status: "saved", + version: result.value.page.version, + snapshot: result.value, + }; + } + if (result.status === "not-found") { + return { + status: "validation-error", + issues: ["ไม่พบหน้าที่ต้องการบันทึก"], + }; + } + return result; + } catch (cause) { + return { + status: "transient-error", + message: cause instanceof Error ? cause.message : "บันทึกไม่สำเร็จ", + }; + } +}