feat: Betreuung, Kinderprofile und Aufnahmeverwaltung implementieren
Dashboard mit Abholslots und Filter-Scrolling, Anwesenheit mit Audit-Verlauf sowie Elternanmeldung, Warteliste und bestätigte Aufnahme ergänzen. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
10af6159b4
commit
c1513c040b
36 files changed
+2593
No files matched your search
@@ -0,0 +1,49 @@
|
||||
export function localClock(now = new Date()) {
|
||||
const parts = new Intl.DateTimeFormat("en-GB", {
|
||||
timeZone: process.env.APP_TIMEZONE ?? "Europe/Berlin",
|
||||
year: "numeric", month: "2-digit", day: "2-digit",
|
||||
hour: "2-digit", minute: "2-digit", hourCycle: "h23",
|
||||
}).formatToParts(now);
|
||||
const get = (type: Intl.DateTimeFormatPartTypes) => parts.find((p) => p.type === type)!.value;
|
||||
const day = `${get("year")}-${get("month")}-${get("day")}`;
|
||||
const weekday = new Date(`${day}T12:00:00Z`).getUTCDay() || 7;
|
||||
return { day, time: `${get("hour")}:${get("minute")}`, weekday };
|
||||
}
|
||||
|
||||
export function pickupState(pickup: string | null, time: string, end?: string | null) {
|
||||
if (!pickup) return "none";
|
||||
const minutes = (value: string) => Number(value.slice(0, 2)) * 60 + Number(value.slice(3, 5));
|
||||
const delta = minutes(pickup) - minutes(time);
|
||||
if (minutes(end ?? pickup) < minutes(time)) return "overdue";
|
||||
if (delta <= 15) return "due";
|
||||
return "later";
|
||||
}
|
||||
|
||||
export function displayDay(day: string) {
|
||||
return new Intl.DateTimeFormat("de-DE", {
|
||||
weekday: "long", day: "numeric", month: "long", timeZone: "UTC",
|
||||
}).format(new Date(`${day}T12:00:00Z`));
|
||||
}
|
||||
|
||||
export function timeInZone(instant: string, timeZone: string) {
|
||||
return new Intl.DateTimeFormat("en-GB", { timeZone, hour: "2-digit", minute: "2-digit", hourCycle: "h23" })
|
||||
.format(new Date(instant));
|
||||
}
|
||||
|
||||
export function localInstant(day: string, time: string, timeZone: string): Date {
|
||||
const wall = Date.parse(`${day}T${time}:00Z`);
|
||||
const format = (date: Date) => new Intl.DateTimeFormat("sv-SE", {
|
||||
timeZone, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit",
|
||||
minute: "2-digit", second: "2-digit", hourCycle: "h23",
|
||||
}).format(date).replace(" ", "T");
|
||||
const offsets = new Set([-36, 0, 36].map((hours) => {
|
||||
const sample = new Date(wall + hours * 3_600_000);
|
||||
return Date.parse(`${format(sample)}Z`) - sample.getTime();
|
||||
}));
|
||||
const candidates = [...offsets].map((offset) => new Date(wall - offset))
|
||||
.filter((date) => format(date) === `${day}T${time}:00`);
|
||||
if (candidates.length !== 1) {
|
||||
throw new Error("Diese Uhrzeit ist wegen der Zeitumstellung nicht eindeutig oder existiert nicht. Bitte eine andere Uhrzeit wählen.");
|
||||
}
|
||||
return candidates[0];
|
||||
}
|
||||
Reference in new issue
Block a user