feat(housekeeping): deliver content vertical

This commit is contained in:
Simo committed 2026-08-30 01:54:43 +02:00
1 parent bdab924bdf
commit fd68819d9b
67 files changed
+5742 -1916

No files matched your search

+32 -59
View File
@@ -1,76 +1,49 @@
"use server";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import {
contentMutationService,
createContentMutationInvocation,
} from "@/features/housekeeping/domains/content/services/mutations";
import { createCorrelationId } from "@/features/housekeeping/foundation/contracts";
import { requirePermission } from "@/lib/admin/guard";
import { db, EmailTemplates } from "@/lib/db";
import { formPositiveBigInt } from "@/lib/form-data";
import { PERMS } from "@/lib/permissions";
export async function createEmailTemplate(formData: FormData): Promise<void> {
await requirePermission(PERMS.PAGES_EDIT);
const name = String(formData.get("name") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
const subject = String(formData.get("subject") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
const body = String(formData.get("body") ?? "").normalize("NFC");
const variablesRaw = String(formData.get("variables") ?? "")
.normalize("NFC")
.trim();
const isActive = formData.get("isActive") != null;
if (!name || !subject || !body) return;
function templateInput(formData: FormData) {
return {
name: String(formData.get("name") ?? "").normalize("NFC").trim().slice(0, 255),
subject: String(formData.get("subject") ?? "").normalize("NFC").trim().slice(0, 255),
body: String(formData.get("body") ?? "").normalize("NFC"),
variables: String(formData.get("variables") ?? "").normalize("NFC").trim(),
isActive: formData.get("isActive") != null,
};
}
await db.insert(EmailTemplates).values({
name,
subject,
body,
variables: variablesRaw || null,
isActive,
});
export async function createEmailTemplate(formData: FormData): Promise<void> {
const staff = await requirePermission(PERMS.PAGES_EDIT);
const input = templateInput(formData);
if (!input.name || !input.subject || !input.body) return;
const result = await contentMutationService.execute(createContentMutationInvocation(staff, createCorrelationId()), "email-template.change", { action: "create", ...input });
if (!result.ok) throw new Error("Email template creation failed");
revalidatePath("/admin/email-templates");
}
export async function updateEmailTemplate(formData: FormData): Promise<void> {
await requirePermission(PERMS.PAGES_EDIT);
const raw = String(formData.get("id") ?? "").normalize("NFC");
if (!raw) return;
let id: bigint;
try {
id = BigInt(raw);
} catch {
return;
}
const subject = String(formData.get("subject") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
const body = String(formData.get("body") ?? "").normalize("NFC");
const variablesRaw = String(formData.get("variables") ?? "")
.normalize("NFC")
.trim();
const isActive = formData.get("isActive") != null;
if (!subject || !body) return;
await db
.update(EmailTemplates)
.set({
subject,
body,
variables: variablesRaw || null,
isActive,
})
.where(eq(EmailTemplates.id, id));
const staff = await requirePermission(PERMS.PAGES_EDIT);
const id = String(formData.get("id") ?? "").normalize("NFC");
if (!/^\d+$/u.test(id)) return;
const input = templateInput(formData);
if (!input.subject || !input.body) return;
const result = await contentMutationService.execute(createContentMutationInvocation(staff, createCorrelationId()), "email-template.change", { action: "update", id, ...input });
if (!result.ok) throw new Error("Email template update failed");
revalidatePath("/admin/email-templates");
}
export async function deleteEmailTemplate(formData: FormData): Promise<void> {
await requirePermission(PERMS.PAGES_EDIT);
const id = formPositiveBigInt(formData, "id");
if (!id) return;
await db.delete(EmailTemplates).where(eq(EmailTemplates.id, id));
const staff = await requirePermission(PERMS.PAGES_EDIT);
const id = String(formData.get("id") ?? "").normalize("NFC").trim();
if (!/^[1-9]\d*$/u.test(id)) return;
const result = await contentMutationService.execute(createContentMutationInvocation(staff, createCorrelationId()), "email-template.change", { action: "delete", id });
if (!result.ok) throw new Error("Email template deletion failed");
revalidatePath("/admin/email-templates");
}