Add non-destructive dev seed on startup
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { UserRole } from "@prisma/client";
|
||||
import { Settings2 } from "lucide-react";
|
||||
|
||||
import { requireRole } from "@/lib/auth-utils";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getTargetMonthData, getWorkingDaysOfMonth } from "@/lib/date-utils";
|
||||
import { PlanView } from "./plan-view";
|
||||
|
||||
export const metadata = { title: "Plan-Generierung · Kita-Planer" };
|
||||
|
||||
export default async function PlanungsZentralePage() {
|
||||
const session = await requireRole([UserRole.ADMIN, UserRole.KOORDINATOR]);
|
||||
const kitaId = session.user.kitaId!;
|
||||
|
||||
const { targetYear, targetMonth, monthName } = getTargetMonthData();
|
||||
|
||||
// Aktuellen Plan suchen
|
||||
const plan = await prisma.notdienstPlan.findUnique({
|
||||
where: {
|
||||
kitaId_year_month: { kitaId, year: targetYear, month: targetMonth },
|
||||
},
|
||||
include: {
|
||||
assignments: {
|
||||
include: { child: { include: { parentLinks: { include: { user: true } } } } },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Alle Werktage
|
||||
const workingDays = getWorkingDaysOfMonth(targetYear, targetMonth);
|
||||
|
||||
// Wir laden auch alle aktiven Kinder (inkl. Eltern-Namen) für das manuelle Dropdown.
|
||||
// Idealerweise gruppiert man das nach "Verfügbar an diesem Tag" und "Alle",
|
||||
// aber für MVP reichen alle aktiven Kinder.
|
||||
const allChildrenRaw = await prisma.child.findMany({
|
||||
where: { kitaId, active: true },
|
||||
include: {
|
||||
parentLinks: { include: { user: true } },
|
||||
},
|
||||
orderBy: { lastName: "asc" },
|
||||
});
|
||||
|
||||
const allChildren = allChildrenRaw.map((c) => {
|
||||
// Einfachheit halber nehmen wir den ersten verknüpften Elternteil zur Anzeige
|
||||
const parent = c.parentLinks[0]?.user;
|
||||
const parentName = parent ? `${parent.firstName} ${parent.lastName}` : "Unbekannt";
|
||||
return {
|
||||
id: c.id,
|
||||
name: `${c.firstName} ${c.lastName}`,
|
||||
parentName,
|
||||
};
|
||||
});
|
||||
|
||||
// Wir mappen die Assignments auf die Werktage
|
||||
const daysWithAssignments = workingDays.map((day) => {
|
||||
const assignment = plan?.assignments.find(
|
||||
(a) => a.date.getTime() === day.getTime()
|
||||
);
|
||||
return {
|
||||
date: day.toISOString(),
|
||||
assignmentId: assignment?.id || null,
|
||||
childId: assignment?.childId || null,
|
||||
};
|
||||
});
|
||||
|
||||
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">
|
||||
<Settings2 className="h-6 w-6 text-primary" />
|
||||
Notdienst-Planung
|
||||
</h1>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
Koordiniere und generiere den Notdienst-Plan.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="rounded-full bg-primary/10 px-3 py-1 text-sm font-medium text-primary">
|
||||
Zielmonat: {monthName}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PlanView
|
||||
planId={plan?.id}
|
||||
status={plan?.status}
|
||||
days={daysWithAssignments}
|
||||
allChildren={allChildren}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user