"use server"; import { revalidatePath } from "next/cache"; import { EventParticipationStatus, TerminStatus, UserRole, } from "@prisma/client"; import { z } from "zod"; import { requireKitaSession, requireRole } from "@/lib/auth-utils"; import { prisma } from "@/lib/prisma"; const submitRsvpSchema = z.object({ eventId: z.string().min(1), childId: z.string().min(1), status: z.nativeEnum(EventParticipationStatus), }); export type EventParticipantDto = { childId: string; childName: string; familyName: string; status: EventParticipationStatus | null; }; export async function submitEventRsvp(rawPayload: unknown) { const session = await requireKitaSession(); const parsed = submitRsvpSchema.safeParse(rawPayload); if (!parsed.success) { return { error: "Ungültige Eingabedaten." }; } if (!session.user.familyId) { return { error: "Dein Account ist noch keinem Haushalt zugeordnet." }; } const { eventId, childId, status } = parsed.data; const event = await prisma.termin.findFirst({ where: { id: eventId, kitaId: session.user.kitaId, }, select: { id: true, status: true, requiresRsvp: true, rsvpDeadline: true, startDate: true, }, }); if (!event || !event.requiresRsvp || event.status !== TerminStatus.CONFIRMED) { return { error: "Für diesen Termin ist keine Rückmeldung aktiv." }; } const deadline = event.rsvpDeadline ?? event.startDate; if (deadline < new Date()) { return { error: "Die Rückmeldefrist ist bereits abgelaufen." }; } const child = await prisma.child.findFirst({ where: { id: childId, kitaId: session.user.kitaId, familyId: session.user.familyId, active: true, }, select: { id: true }, }); if (!child) { return { error: "Dieses Kind gehört nicht zu deinem Haushalt." }; } await prisma.eventParticipation.upsert({ where: { eventId_childId: { eventId, childId, }, }, create: { kitaId: session.user.kitaId, eventId, childId, status, }, update: { status, }, }); revalidatePath("/dashboard"); revalidatePath("/dashboard/kalender"); revalidatePath("/dashboard/admin/kalender"); return { success: true }; } export async function getEventParticipants( eventId: string, ): Promise<{ participants?: EventParticipantDto[]; error?: string }> { const session = await requireRole([UserRole.ADMIN, UserRole.KOORDINATOR]); const kitaId = session.user.kitaId; if (!kitaId) { return { error: "Kein Mandant zugeordnet." }; } const event = await prisma.termin.findFirst({ where: { id: eventId, kitaId }, select: { id: true }, }); if (!event) { return { error: "Termin wurde nicht gefunden." }; } const children = await prisma.child.findMany({ where: { kitaId, active: true, }, select: { id: true, firstName: true, lastName: true, family: { select: { name: true, }, }, eventParticipations: { where: { eventId }, select: { status: true }, take: 1, }, }, orderBy: [ { family: { name: "asc" } }, { lastName: "asc" }, { firstName: "asc" }, ], }); return { participants: children.map((child) => ({ childId: child.id, childName: `${child.firstName} ${child.lastName}`, familyName: child.family.name, status: child.eventParticipations[0]?.status ?? null, })), }; }