import Link from "next/link"; import { format } from "date-fns"; import { de } from "date-fns/locale"; import { Users, CalendarCheck2, ShieldCheck, AlertTriangle, ClipboardList } from "lucide-react"; import { DutyAssignmentStatus, UserRole, NotdienstPlanStatus, TerminStatus } from "@prisma/client"; import { requireKitaSession } from "@/lib/auth-utils"; import { prisma } from "@/lib/prisma"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { OnboardingDialog } from "@/components/OnboardingDialog"; import { AlertButton } from "./alert-button"; import { AbsenceCard } from "./absence-card"; import { NewsTicker } from "./news-ticker"; import { RsvpActionCard } from "./rsvp-action-card"; export const metadata = { title: "Übersicht · Kita-Planer" }; export default async function DashboardPage() { const session = await requireKitaSession(); const now = new Date(); const kita = await prisma.kita.findUniqueOrThrow({ where: { id: session.user.kitaId }, select: { name: true, notdienstModuleEnabled: true, terminModuleEnabled: true, adressbuchModuleEnabled: true, }, }); const today = new Date(); today.setHours(0, 0, 0, 0); // Schnelle Statistiken und persönliche Dienste für die Übersicht. const [ familyCount, childCount, upcomingDuties, onboardingUser, absenceChildren, upcomingAbsences, latestAnnouncements, ] = await Promise.all([ prisma.family.count({ where: { kitaId: session.user.kitaId }, }), prisma.child.count({ where: { kitaId: session.user.kitaId }, }), session.user.familyId ? prisma.dutyAssignment.findMany({ where: { kitaId: session.user.kitaId, familyId: session.user.familyId, status: DutyAssignmentStatus.PLANNED, endDate: { gte: today }, }, select: { id: true, startDate: true, endDate: true, dutyType: { select: { name: true, }, }, }, orderBy: { startDate: "asc" }, take: 5, }) : Promise.resolve([]), prisma.user.findFirstOrThrow({ where: { id: session.user.id, kitaId: session.user.kitaId, }, select: { phone: true, street: true, postalCode: true, city: true, familyId: true, role: true, family: { select: { _count: { select: { children: true, }, }, }, }, }, }), session.user.familyId ? prisma.child.findMany({ where: { kitaId: session.user.kitaId, familyId: session.user.familyId, active: true, }, select: { id: true, firstName: true, lastName: true, }, orderBy: [{ lastName: "asc" }, { firstName: "asc" }], }) : Promise.resolve([]), session.user.familyId ? prisma.absence.findMany({ where: { kitaId: session.user.kitaId, endDate: { gte: today }, child: { familyId: session.user.familyId, }, }, select: { id: true, reason: true, note: true, startDate: true, endDate: true, child: { select: { firstName: true, lastName: true, }, }, }, orderBy: [{ startDate: "asc" }], take: 6, }) : Promise.resolve([]), prisma.announcement.findMany({ where: { kitaId: session.user.kitaId }, select: { id: true, title: true, content: true, createdAt: true, author: { select: { firstName: true, lastName: true, }, }, attachments: { select: { id: true, fileName: true, fileUrl: true, fileType: true, }, }, reads: { where: { userId: session.user.id }, select: { id: true }, take: 1, }, }, orderBy: { createdAt: "desc" }, take: 3, }), ]); const familyChildIds = absenceChildren.map((child) => child.id); const openRsvpTermine = session.user.familyId && familyChildIds.length > 0 ? await prisma.termin.findMany({ where: { kitaId: session.user.kitaId, status: TerminStatus.CONFIRMED, requiresRsvp: true, OR: [ { rsvpDeadline: { gt: now } }, { rsvpDeadline: null, startDate: { gt: now } }, ], }, select: { id: true, title: true, startDate: true, rsvpDeadline: true, participations: { where: { childId: { in: familyChildIds }, }, select: { childId: true, status: true, }, }, }, orderBy: { startDate: "asc" }, take: 5, }) : []; const rsvpActionEvents = openRsvpTermine .map((termin) => { const statusByChildId = new Map( termin.participations.map((participation) => [ participation.childId, participation.status, ]), ); return { id: termin.id, title: termin.title, startDate: termin.startDate.toISOString(), rsvpDeadline: termin.rsvpDeadline?.toISOString() ?? null, children: absenceChildren.map((child) => ({ id: child.id, name: `${child.firstName} ${child.lastName}`, status: statusByChildId.get(child.id) ?? null, })), }; }) .filter((termin) => termin.children.some((child) => !child.status)); const isAdmin = session.user.role === UserRole.ADMIN || session.user.role === UserRole.SUPERADMIN; const canReportAbsences = session.user.role !== UserRole.ERZIEHER; return (
Hier ist die Übersicht für {kita.name}.
{duty.dutyType.name}
{format(duty.startDate, "dd.MM.", { locale: de })} bis{" "} {format(duty.endDate, "dd.MM.yyyy", { locale: de })}
{description}
{parentNames || assignment.child.family.name}
Kind: {assignment.child.firstName} {assignment.child.lastName}