feat: add admin content module actions

This commit is contained in:
Simo committed 2026-07-12 15:27:07 +02:00
1 parent b9525c8e6b
commit f422bb4a0b
6 files changed
+596

No files matched your search

+185
View File
@@ -0,0 +1,185 @@
'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 })
},
)