"use server"; import { z } from "zod"; import { PERMS } from "@/lib/permissions"; import { prisma } from "@/lib/prisma"; import { adminAction } from "@/lib/safe-action"; import { ActionError, actionOk } from "@/lib/safe-action-shared"; import { logAudit } from "@/lib/services/audit"; import { createEventSchema, eventPrizeSchema, eventTypeSchema, eventWinnerSchema, updateEventSchema, } from "@/lib/validators/event"; // ── Event Types ───────────────────────────────────────────────────── export const createEventType = adminAction( { permission: PERMS.EVENTS_EDIT, schema: eventTypeSchema }, async (ctx) => { const eventType = await prisma.websiteEventType.create({ data: ctx.data, }); logAudit({ userId: ctx.session.user.id, action: "event_type_create", target: "WebsiteEventType", targetId: eventType.id, after: { name: eventType.name }, }); return actionOk({ id: eventType.id }); }, ); const updateEventTypeInput = eventTypeSchema.partial().extend({ id: z.coerce.number().int().positive(), }); export const updateEventType = adminAction( { permission: PERMS.EVENTS_EDIT, schema: updateEventTypeInput }, async (ctx) => { const { id, ...data } = ctx.data; const existing = await prisma.websiteEventType.findUnique({ where: { id }, }); if (!existing) throw new ActionError("Event type not found"); await prisma.websiteEventType.update({ where: { id }, data }); logAudit({ userId: ctx.session.user.id, action: "event_type_update", target: "WebsiteEventType", targetId: id, before: { name: existing.name }, after: data, }); return actionOk({ id }); }, ); const deleteEventTypeInput = z.object({ id: z.coerce.number().int().positive(), }); export const deleteEventType = adminAction( { permission: PERMS.EVENTS_EDIT, schema: deleteEventTypeInput }, async (ctx) => { const existing = await prisma.websiteEventType.findUnique({ where: { id: ctx.data.id }, }); if (!existing) throw new ActionError("Event type not found"); await prisma.websiteEventType.delete({ where: { id: ctx.data.id } }); logAudit({ userId: ctx.session.user.id, action: "event_type_delete", target: "WebsiteEventType", targetId: ctx.data.id, before: { name: existing.name }, }); return actionOk(); }, ); // ── Events ────────────────────────────────────────────────────────── export const createEvent = adminAction( { permission: PERMS.EVENTS_EDIT, schema: createEventSchema }, async (ctx) => { const event = await prisma.websiteEvent.create({ data: { ...ctx.data, hostUserId: Number(ctx.session.user.id), }, }); logAudit({ userId: ctx.session.user.id, action: "event_create", target: "WebsiteEvent", targetId: event.id, after: { title: event.title }, }); return actionOk({ id: event.id }); }, ); const updateEventInput = updateEventSchema.extend({ id: z.coerce.number().int().positive(), }); export const updateEvent = adminAction( { permission: PERMS.EVENTS_EDIT, schema: updateEventInput }, async (ctx) => { const { id, ...data } = ctx.data; const existing = await prisma.websiteEvent.findUnique({ where: { id } }); if (!existing) throw new ActionError("Event not found"); await prisma.websiteEvent.update({ where: { id }, data }); logAudit({ userId: ctx.session.user.id, action: "event_update", target: "WebsiteEvent", targetId: id, before: { title: existing.title, status: existing.status }, after: data, }); return actionOk({ id }); }, ); const deleteEventInput = z.object({ id: z.coerce.number().int().positive(), }); export const deleteEvent = adminAction( { permission: PERMS.EVENTS_EDIT, schema: deleteEventInput }, async (ctx) => { const existing = await prisma.websiteEvent.findUnique({ where: { id: ctx.data.id }, }); if (!existing) throw new ActionError("Event not found"); await prisma.websiteEvent.delete({ where: { id: ctx.data.id } }); logAudit({ userId: ctx.session.user.id, action: "event_delete", target: "WebsiteEvent", targetId: ctx.data.id, before: { title: existing.title }, }); return actionOk(); }, ); // ── Prizes ────────────────────────────────────────────────────────── export const addEventPrize = adminAction( { permission: PERMS.EVENTS_EDIT, schema: eventPrizeSchema }, async (ctx) => { const prize = await prisma.websiteEventPrize.create({ data: ctx.data }); return actionOk({ id: prize.id }); }, ); const deletePrizeInput = z.object({ id: z.coerce.number().int().positive() }); export const deleteEventPrize = adminAction( { permission: PERMS.EVENTS_EDIT, schema: deletePrizeInput }, async (ctx) => { await prisma.websiteEventPrize.delete({ where: { id: ctx.data.id } }); return actionOk(); }, ); // ── Winners ───────────────────────────────────────────────────────── export const addEventWinner = adminAction( { permission: PERMS.EVENTS_EDIT, schema: eventWinnerSchema }, async (ctx) => { const winner = await prisma.websiteEventWinner.create({ data: ctx.data }); logAudit({ userId: ctx.session.user.id, action: "event_winner_add", target: "WebsiteEventWinner", targetId: winner.id, after: { eventId: ctx.data.eventId, userId: ctx.data.userId, position: ctx.data.position, }, }); return actionOk({ id: winner.id }); }, );