Files
kita-planer/src/lib/alarms/format.ts
T

90 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { NotdienstAlarm } from "@prisma/client";
import {
addDays,
dateSchema,
dateKey,
todayKey,
minuteClock,
} from "@/lib/staff/calculations";
export { dateKey, todayKey };
const berlin = new Intl.DateTimeFormat("en-CA", {
timeZone: "Europe/Berlin",
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hourCycle: "h23",
});
export function berlinInstant(date: string, minute: number) {
dateSchema.parse(date);
const target = new Date(`${date}T00:00:00Z`).getTime() + minute * 60_000;
let value = target;
for (let i = 0; i < 3; i++) {
const parts = Object.fromEntries(
berlin.formatToParts(new Date(value)).map((p) => [p.type, p.value]),
);
const represented = Date.parse(
`${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:00Z`,
);
const diff = target - represented;
if (!diff) return new Date(value);
value += diff;
}
throw new Error(
"Diese Uhrzeit existiert wegen der Zeitumstellung nicht. Bitte eine andere Uhrzeit wählen.",
);
}
export function endOfAlarm(
date: string,
wholeDay: boolean,
endMinute?: number | null,
) {
return wholeDay
? berlinInstant(addDays(date, 1), 0)
: berlinInstant(date, endMinute!);
}
export function durationLabel(
alarm: Pick<NotdienstAlarm, "wholeDay" | "startMinute" | "endMinute">,
) {
return alarm.wholeDay
? "Ganzer Kita-Tag"
: `${minuteClock(alarm.startMinute!)}–${minuteClock(alarm.endMinute!)} Uhr`;
}
export function instantLabel(value: Date | string) {
return new Intl.DateTimeFormat("de-DE", {
timeZone: "Europe/Berlin",
day: "2-digit",
month: "2-digit",
hour: "2-digit",
minute: "2-digit",
}).format(new Date(value));
}
export function alarmLabel(
alarm: Pick<NotdienstAlarm, "status" | "deadline" | "expiresAt">,
now = new Date(),
) {
if (alarm.status === "CANCELLED") return "Storniert";
if (alarm.status === "CONFIRMED") return "Übernahme bestätigt";
if (alarm.status === "DECLINED") return "Klärung erforderlich – Absage";
if (alarm.status === "LATE_CONFIRMATION")
return "Verspätete Zusage – Freigabe erforderlich";
if (alarm.status === "REVIEW_REQUIRED")
return "Klärung erforderlich – bisherige Rückmeldungen prüfen";
if (alarm.deadline <= now || alarm.expiresAt <= now)
return "Klärung erforderlich – Frist abgelaufen";
return "Antwort ausstehend";
}
export function needsClarification(
alarm: Pick<NotdienstAlarm, "status" | "deadline" | "expiresAt">,
now = new Date(),
) {
return (
!["CONFIRMED", "CANCELLED"].includes(alarm.status) &&
(alarm.status !== "PENDING" ||
alarm.deadline <= now ||
alarm.expiresAt <= now)
);
}