157 lines
3.5 KiB
TypeScript
157 lines
3.5 KiB
TypeScript
"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,
|
|
})),
|
|
};
|
|
}
|