"use server"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; import { api, unwrap } from "@/lib/api"; import { attempt, field, type ActionState } from "@/lib/actions"; const rating = (form: FormData) => (field(form, "rating") === "adult" ? ("adult" as const) : ("general" as const)); const privacy = (form: FormData) => (field(form, "privacy") === "private" ? ("private" as const) : ("public" as const)); const moderators = (form: FormData) => field(form, "moderators") .split(/[,\n]/) .map((s) => s.trim()) .filter(Boolean); /** Makes a hosted room, then goes back to the list. */ export async function createRoom(_: ActionState, form: FormData): Promise { const state = await attempt(async () => { unwrap( await api["hosted-rooms"].post({ name: field(form, "name"), description: field(form, "description"), roomPid: Number(field(form, "roomPid")), rating: rating(form), maxUsers: Number(field(form, "maxUsers")), imvuId: Number(field(form, "imvuId")), privacy: privacy(form), }), ); revalidatePath("/rooms"); }); if (state?.error) return state; redirect("/rooms"); } /** The owner's changes to a room. */ export async function saveRoom(_: ActionState, form: FormData): Promise { const n = field(form, "n"); const state = await attempt(async () => { unwrap( await api["hosted-rooms"]({ n }).patch({ name: field(form, "name"), description: field(form, "description"), roomPid: Number(field(form, "roomPid")), rating: rating(form), maxUsers: Number(field(form, "maxUsers")), privacy: privacy(form), moderators: moderators(form), }), ); revalidatePath("/rooms"); }); if (state?.error) return state; redirect("/rooms"); } /** The room's image: a PNG or JPEG, up to 512 KB. */ export async function saveImage(_: ActionState, form: FormData): Promise { const n = field(form, "n"); const image = form.get("image"); if (!(image instanceof File) || image.size === 0) return { error: "Choose an image." }; if (image.size > 512 * 1024) return { error: "An image is up to 512 KB." }; return attempt(async () => { unwrap(await api["hosted-rooms"]({ n }).image.put({ image })); revalidatePath("/rooms"); revalidatePath(`/rooms/${n}/edit`); return "Image saved."; }); } export async function removeImage(_: ActionState, form: FormData): Promise { const n = field(form, "n"); return attempt(async () => { unwrap(await api["hosted-rooms"]({ n }).image.delete()); revalidatePath("/rooms"); revalidatePath(`/rooms/${n}/edit`); }); } /** Stars a room, or (favorite=0) unstars it. */ export async function setFavorite(_: ActionState, form: FormData): Promise { const n = field(form, "n"); return attempt(async () => { const room = api["hosted-rooms"]({ n }).favorite; unwrap(await (field(form, "favorite") === "1" ? room.put() : room.delete())); revalidatePath("/rooms"); }); } export async function rateRoom(_: ActionState, form: FormData): Promise { const n = field(form, "n"); return attempt(async () => { unwrap(await api["hosted-rooms"]({ n }).rating.put({ score: Number(field(form, "score")) })); revalidatePath("/rooms"); }); } /** Closes a room: everyone in it is sent out. */ export async function closeRoom(_: ActionState, form: FormData): Promise { const n = field(form, "n"); const state = await attempt(async () => { unwrap(await api["hosted-rooms"]({ n }).delete()); revalidatePath("/rooms"); }); if (state?.error) return state; redirect("/rooms"); }