diff --git a/actions/user-settings.ts b/actions/user-settings.ts new file mode 100644 index 0000000..e3a9cbb --- /dev/null +++ b/actions/user-settings.ts @@ -0,0 +1,62 @@ +'use server' + +import { cookies } from 'next/headers' +import { getIronSession } from 'iron-session' +import { Prisma } from '@prisma/client' +import { prisma } from '@/lib/prisma' +import { SessionData, sessionOptions } from '@/lib/session' +import { + UserSettingsSchema, + mergeSettings, + parseUserSettings, + type UserSettings, +} from '@/lib/user-settings' + +async function getSession() { + return getIronSession(await cookies(), sessionOptions) +} + +export type UpdateUserSettingsResult = + | { success: true; settings: UserSettings } + | { error: string; code: 401 | 403 | 422; fieldErrors?: Record } + +export async function updateUserSettingsAction( + patch: Partial, +): Promise { + const session = await getSession() + if (!session.userId) return { error: 'Niet ingelogd', code: 401 } + if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus', code: 403 } + + const parsed = UserSettingsSchema.partial().safeParse(patch) + if (!parsed.success) { + return { + error: 'Ongeldige settings-patch', + code: 422, + fieldErrors: parsed.error.flatten().fieldErrors as Record, + } + } + + const merged = await prisma.$transaction(async (tx) => { + const user = await tx.user.findUnique({ + where: { id: session.userId! }, + select: { settings: true }, + }) + const current = parseUserSettings(user?.settings) + const next = mergeSettings(current, parsed.data) + await tx.user.update({ + where: { id: session.userId! }, + data: { settings: next as unknown as Prisma.InputJsonValue }, + }) + return next + }) + + await prisma.$executeRaw` + SELECT pg_notify('scrum4me_changes', ${JSON.stringify({ + kind: 'user_settings', + userId: session.userId, + patch: parsed.data, + })}::text) + ` + + return { success: true, settings: merged } +}