Files
anouma/lib/meeting/status.ts
T

57 lines
1.7 KiB
TypeScript

import { berlinParts, berlinWallTimeToUTC } from "@/lib/calendar/timezone";
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);
if (Number.isNaN(date.getTime()) || Number.isNaN(time.getTime())) return new Date(NaN);
const dateParts = berlinParts(date);
const timeParts = berlinParts(time);
return berlinWallTimeToUTC(dateParts, timeParts.hour, timeParts.minute);
}
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 (![openAt, closeAt, t].every(Number.isFinite) || end <= start) return "ended";
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<MeetingStatus, string> = {
scheduled: "Online-Termin",
open: "Termin beginnt bald",
live: "Jetzt teilnehmen",
ended: "Termin beendet",
};