Apply linen design system across app

This commit is contained in:
t.indorf
2026-05-20 22:47:52 +02:00
parent 99ff978116
commit 1c5d2f10ac
56 changed files with 4698 additions and 2159 deletions
+33 -16
View File
@@ -2,8 +2,14 @@
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { NotdienstPlanStatus } from "@prisma/client";
import { requireKitaSession } from "@/lib/auth-utils";
import {
CHILD_MAX_AGE_YEARS,
getChildBirthdateRange,
parseDateInput,
} from "@/lib/child-birthdate";
import { prisma } from "@/lib/prisma";
// Telefonnummern: führendes "+" optional, dann Ziffern, Leerzeichen, Bindestriche,
@@ -23,8 +29,8 @@ const childSchema = z
})
.superRefine((data, ctx) => {
if (!data.dateOfBirth) return;
const parsed = new Date(`${data.dateOfBirth}T00:00:00`);
if (Number.isNaN(parsed.getTime())) {
const parsed = parseDateInput(data.dateOfBirth);
if (!parsed) {
ctx.addIssue({
path: ["dateOfBirth"],
code: "custom",
@@ -32,22 +38,19 @@ const childSchema = z
});
return;
}
// In der Zukunft geborene Kinder existieren nicht.
const today = new Date();
today.setHours(23, 59, 59, 999);
if (parsed > today) {
const { min, max } = getChildBirthdateRange();
if (data.dateOfBirth > max) {
ctx.addIssue({
path: ["dateOfBirth"],
code: "custom",
message: "Geburtsdatum darf nicht in der Zukunft liegen.",
});
}
// Schutz vor offensichtlichen Tippfehlern (1899 statt 1989 o.ä.).
if (parsed.getFullYear() < 1900) {
if (data.dateOfBirth < min) {
ctx.addIssue({
path: ["dateOfBirth"],
code: "custom",
message: "Bitte ein realistisches Geburtsdatum angeben.",
message: `Kinder dürfen maximal ${CHILD_MAX_AGE_YEARS} Jahre alt sein.`,
});
}
});
@@ -79,13 +82,6 @@ const contactSchema = z.object({
city: z.string().trim().max(100).optional(),
});
function parseDateInput(value?: string) {
if (!value) return null;
const date = new Date(`${value}T00:00:00`);
return Number.isNaN(date.getTime()) ? null : date;
}
// Gibt die erste konkrete Field-Error-Message aus einem Zod-Fehler zurück,
// damit der User nicht nur "Ungültige Eingabedaten" sieht.
function firstZodMessage(
@@ -290,6 +286,27 @@ export async function deleteMyAccount() {
return { error: "Account wurde nicht gefunden." };
}
const today = new Date();
today.setHours(0, 0, 0, 0);
const activeNotdienstAssignments = user.familyId
? await prisma.notdienstAssignment.count({
where: {
kitaId: session.user.kitaId,
date: { gte: today },
plan: { status: NotdienstPlanStatus.PUBLISHED },
child: { familyId: user.familyId },
},
})
: 0;
if (activeNotdienstAssignments > 0) {
return {
error:
"Dein Account kann nicht gelöscht werden, solange aktive Notdienst-Verpflichtungen bestehen.",
};
}
if (!user.familyId) {
await prisma.user.delete({
where: { id: user.id },