"use server"; // Cases (reports, reviews, requests, appeals) and notifications, from the website. import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { api, unwrap } from "@/lib/api"; import { attempt, field, type ActionState } from "@/lib/actions"; /** Reports a product, catalog, room or person. */ export async function report(_: ActionState, form: FormData): Promise { const kind = field(form, "about"); const id = field(form, "id"); if (!["product", "catalog", "room", "person"].includes(kind)) return { error: "Nothing to report." }; return attempt(async () => { unwrap(await api.cases.post({ kind: "report", about: { [kind]: id }, reason: field(form, "reason") })); revalidatePath("/console/cases"); return "Reported. Moderators will look at it; you'll be told what they decide."; }); } /** Appeals an action from the audit log. */ export async function appeal(_: ActionState, form: FormData): Promise { let id = 0; const state = await attempt(async () => { const { case: c } = unwrap(await api.cases.post({ kind: "appeal", audit: Number(field(form, "audit")), reason: field(form, "reason") })); id = c.id; }); if (state?.error) return state; redirect(`/console/cases/${id}`); } /** A catalog's team asks moderators to remove a product everywhere. */ export async function requestRemoval(_: ActionState, form: FormData): Promise { return attempt(async () => { unwrap( await api.cases.post({ kind: "removal-request", about: { product: field(form, "product") }, catalog: field(form, "catalog"), reason: field(form, "reason"), }), ); revalidatePath("/console/cases"); return "Asked. Moderators will decide."; }); } /** A catalog's owner asks for it to be deleted. */ export async function requestDeletion(_: ActionState, form: FormData): Promise { const id = field(form, "id"); let kase = 0; const state = await attempt(async () => { kase = unwrap(await api.catalogs({ id }).delete.post({ reason: field(form, "reason") })).case; }); if (state?.error) return state; redirect(`/console/cases/${kase}`); } const onCase = (form: FormData) => { const id = Number(field(form, "case")); return { id, done: () => revalidatePath(`/console/cases/${id}`) }; }; export async function addNote(_: ActionState, form: FormData): Promise { const { id, done } = onCase(form); return attempt(async () => { unwrap(await api.cases({ id }).notes.post({ body: field(form, "body"), internal: form.get("internal") === "on" })); done(); }); } export async function assign(_: ActionState, form: FormData): Promise { const { id, done } = onCase(form); return attempt(async () => { const to = field(form, "to"); unwrap(await api.cases({ id }).assign.post({ to: to || null })); done(); }); } export async function decide(_: ActionState, form: FormData): Promise { const { id, done } = onCase(form); const decision = field(form, "decision"); if (decision !== "resolve" && decision !== "decline") return { error: "Choose to resolve or decline it." }; return attempt(async () => { unwrap(await api.cases({ id }).decide.post({ decision, resolution: field(form, "resolution") })); done(); revalidatePath("/console/cases"); revalidatePath("/console"); }); } export async function markAllRead(_: ActionState): Promise { return attempt(async () => { unwrap(await api.notifications.read.post({})); revalidatePath("/notifications"); revalidatePath("/", "layout"); }); }