Add shared ConfirmDialog; upgrade wordfilter with client actions and toasts.
Local Build and Deploy / deploy (push) Successful in 1m6s

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-17 20:28:43 +02:00
1 parent 1039044e48
commit a2ca9b3c23
9 files changed
+366 -149

No files matched your search

+25 -11
View File
@@ -4,35 +4,49 @@ import { revalidatePath } from "next/cache";
import { requirePermission } from "@/lib/admin/guard";
import { PERMS } from "@/lib/permissions";
import { prisma } from "@/lib/prisma";
import {
actionError,
actionOk,
type ActionResult,
} from "@/lib/safe-action-shared";
import { reloadWordFilter } from "@/lib/services/moderation";
import { rcon } from "@/lib/services/rcon";
export async function addWord(formData: FormData): Promise<void> {
export async function addWord(input: {
word: string;
}): Promise<ActionResult<{ id: string }>> {
await requirePermission(PERMS.WORDFILTER_EDIT);
const word = String(formData.get("word") ?? "")
const word = String(input.word ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
if (!word) return;
if (!word) return actionError("Word is required");
try {
await prisma.websiteWordfilter.create({ data: { word } });
const created = await prisma.websiteWordfilter.create({ data: { word } });
reloadWordFilter();
await rcon.updateWordFilter();
revalidatePath("/admin/wordfilter");
return actionOk({ id: String(created.id) });
} catch {
// ignore (e.g. duplicate word) — page re-renders current state
return actionError("Could not add word (it may already exist)");
}
revalidatePath("/admin/wordfilter");
}
export async function deleteWord(formData: FormData): Promise<void> {
export async function deleteWord(input: {
id: string;
}): Promise<ActionResult> {
await requirePermission(PERMS.WORDFILTER_EDIT);
const raw = String(formData.get("id") ?? "").normalize("NFC");
if (!raw) return;
const raw = String(input.id ?? "").normalize("NFC");
if (!raw) return actionError("Missing word id");
try {
await prisma.websiteWordfilter.delete({ where: { id: BigInt(raw) } });
reloadWordFilter();
await rcon.updateWordFilter();
revalidatePath("/admin/wordfilter");
return actionOk();
} catch {
// ignore (e.g. already removed)
return actionError("Could not remove word");
}
revalidatePath("/admin/wordfilter");
}