export type MeetingStatus = "scheduled" | "open" | "live" | "ended"; /** * Payload's "time only" date fields still store a full ISO timestamp, just * with an arbitrary date portion — this combines the real event date with * the hour/minute from a time-only field into one correct Date. */ export function combineDateAndTime(dateISO: string, timeISO?: string | null): Date { const date = new Date(dateISO); if (!timeISO) return date; const time = new Date(timeISO); const combined = new Date(date); combined.setHours(time.getHours(), time.getMinutes(), 0, 0); return combined; } export type MeetingWindow = { start: Date; end: Date; joinWindowMinutes: number; closeAfterMinutes: number; now?: Date; }; export function getMeetingStatus({ start, end, joinWindowMinutes, closeAfterMinutes, now = new Date(), }: MeetingWindow): MeetingStatus { const openAt = start.getTime() - joinWindowMinutes * 60_000; const closeAt = end.getTime() + closeAfterMinutes * 60_000; const t = now.getTime(); if (t >= closeAt) return "ended"; if (t >= start.getTime()) return "live"; if (t >= openAt) return "open"; return "scheduled"; } export function canJoinMeeting(status: MeetingStatus): boolean { return status === "open" || status === "live"; } export const statusLabel: Record = { scheduled: "Online-Termin", open: "Termin beginnt bald", live: "Jetzt teilnehmen", ended: "Termin beendet", };