Add non-destructive dev seed on startup
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { UserRole } from "@prisma/client";
|
||||
import { Info, Calendar } from "lucide-react";
|
||||
|
||||
import { requireRole } from "@/lib/auth-utils";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getTargetMonthData } from "@/lib/date-utils";
|
||||
import { NotdienstForm } from "./notdienst-form";
|
||||
|
||||
export const metadata = { title: "Notdienst · Kita-Planer" };
|
||||
|
||||
export default async function NotdienstPage() {
|
||||
// ELTERN können eintragen; Admins/Koordinatoren haben hier eigentlich
|
||||
// andere Ansichten (Plan-Generierung), aber wir lassen sie zur Demonstration
|
||||
// ebenfalls durch, falls sie selbst Kinder haben.
|
||||
const session = await requireRole([
|
||||
UserRole.ELTERN,
|
||||
UserRole.ADMIN,
|
||||
UserRole.KOORDINATOR,
|
||||
]);
|
||||
|
||||
const kitaId = session.user.kitaId;
|
||||
if (!kitaId) {
|
||||
return <div className="p-8">Kein Mandant zugeordnet.</div>;
|
||||
}
|
||||
|
||||
// Kita-Einstellungen laden
|
||||
const kita = await prisma.kita.findUniqueOrThrow({
|
||||
where: { id: kitaId },
|
||||
select: { notdienstMinPerChildPerMonth: true },
|
||||
});
|
||||
|
||||
// Nur eigene, aktive Kinder laden
|
||||
const children = await prisma.child.findMany({
|
||||
where: {
|
||||
kitaId,
|
||||
active: true,
|
||||
parentLinks: { some: { userId: session.user.id } },
|
||||
},
|
||||
select: { id: true, firstName: true },
|
||||
});
|
||||
|
||||
const targetData = getTargetMonthData();
|
||||
const { targetYear, targetMonth, monthName, isLocked } = targetData;
|
||||
|
||||
const requiredDaysTotal = children.length * kita.notdienstMinPerChildPerMonth;
|
||||
|
||||
// Bisherige Einträge für den Zielmonat laden
|
||||
// Wir filtern bewusst nach den eigenen Kindern und dem User
|
||||
const availabilities = await prisma.notdienstAvailability.findMany({
|
||||
where: {
|
||||
kitaId,
|
||||
userId: session.user.id,
|
||||
date: {
|
||||
gte: new Date(targetYear, targetMonth - 1, 1),
|
||||
lt: new Date(targetYear, targetMonth, 1),
|
||||
},
|
||||
},
|
||||
select: { date: true },
|
||||
});
|
||||
|
||||
const selectedDates = availabilities.map((a) => a.date.toISOString());
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-4xl px-4 py-8 sm:px-8">
|
||||
<div className="mb-6 flex flex-col justify-between gap-4 sm:flex-row sm:items-center">
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold tracking-tight flex items-center gap-2">
|
||||
<Calendar className="h-6 w-6 text-primary" />
|
||||
Notdienst planen
|
||||
</h1>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
Gib hier an, an welchen Tagen du im Notdienst unterstützen kannst.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-start gap-1 sm:items-end">
|
||||
<span className="rounded-full bg-primary/10 px-3 py-1 text-sm font-medium text-primary">
|
||||
Zielmonat: {monthName}
|
||||
</span>
|
||||
{isLocked && (
|
||||
<span className="text-xs font-medium text-destructive flex items-center gap-1">
|
||||
<Info className="h-3 w-3" />
|
||||
Eingabefrist abgelaufen
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{children.length === 0 ? (
|
||||
<div className="rounded-lg border border-dashed p-8 text-center text-muted-foreground">
|
||||
Deinem Account sind noch keine Kinder zugeordnet.
|
||||
</div>
|
||||
) : (
|
||||
<NotdienstForm
|
||||
targetYear={targetYear}
|
||||
targetMonth={targetMonth}
|
||||
isLocked={isLocked}
|
||||
requiredDaysTotal={requiredDaysTotal}
|
||||
initialSelectedDates={selectedDates}
|
||||
childrenIds={children.map((c) => c.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user