Files
EpicNext-Cms/src/actions/admin-ads.ts
T

89 lines
2.5 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";
import {
contentMutationService,
createContentMutationInvocation,
} from "@/features/housekeeping/domains/content/services/mutations";
import { createCorrelationId } from "@/features/housekeeping/foundation/contracts";
import { requirePermission } from "@/lib/admin/guard";
import { logger } from "@/lib/logger";
import { PERMS } from "@/lib/permissions";
import { adminAction } from "@/lib/safe-action";
import { ActionError, actionOk } from "@/lib/safe-action-shared";
export async function createAd(formData: FormData): Promise<void> {
const staff = await requirePermission(PERMS.PAGES_EDIT);
const image = String(formData.get("image") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
if (!image) return;
const result = await contentMutationService.execute(
createContentMutationInvocation(staff, createCorrelationId()),
"ad.change",
{ action: "create", image },
);
if (!result.ok) {
logger.error("Action failed: createAd", {
action: "createAd",
error: result.error.messageKey,
});
revalidatePath("/admin/ads");
return;
}
redirect("/admin/ads");
}
export async function updateAd(formData: FormData): Promise<void> {
const staff = await requirePermission(PERMS.PAGES_EDIT);
const raw = String(formData.get("id") ?? "").normalize("NFC");
if (!/^\d+$/u.test(raw)) return;
const image = String(formData.get("image") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
if (!image) return;
const result = await contentMutationService.execute(
createContentMutationInvocation(staff, createCorrelationId()),
"ad.change",
{ action: "update", id: raw, image },
);
if (!result.ok) {
logger.error("Action failed: updateAd", {
action: "updateAd",
id: Number(raw),
error: result.error.messageKey,
});
revalidatePath("/admin/ads/" + raw);
return;
}
redirect("/admin/ads");
}
const deleteAdInput = z.object({
id: z
.union([z.string(), z.number(), z.bigint()])
.transform((value) => BigInt(String(value))),
});
export const deleteAd = adminAction(
{ permission: PERMS.PAGES_EDIT, schema: deleteAdInput },
async (ctx) => {
const result = await contentMutationService.execute(
{
correlationId: String(ctx.requestId),
expectedActorId: Number(ctx.session.user.id),
legacy: true,
},
"ad.change",
{ action: "delete", id: ctx.data.id.toString() },
);
if (!result.ok) throw new ActionError("Advertisement not found");
revalidatePath("/admin/ads");
return actionOk();
},
);