import dayjs, { Dayjs } from "dayjs"; import isBetween from "dayjs/plugin/isBetween"; import isToday from "dayjs/plugin/isToday"; import utc from "dayjs/plugin/utc"; import { getWorkingHours } from "./availability"; import { WorkingHours } from "./types/schedule"; dayjs.extend(isToday); dayjs.extend(utc); dayjs.extend(isBetween); export type GetSlots = { inviteeDate: Dayjs; frequency: number; workingHours: WorkingHours[]; minimumBookingNotice: number; }; const getMinuteOffset = (date: Dayjs, step: number) => { // Diffs the current time with the given date and iff same day; (handled by 1440) - return difference; otherwise 0 const minuteOffset = Math.min(date.diff(dayjs.utc().startOf("day"), "minute"), 1440) % 1440; // round down to nearest step return Math.ceil(minuteOffset / step) * step; }; // eslint-disable-next-line @typescript-eslint/no-unused-vars const getSlots = ({ inviteeDate, frequency, minimumBookingNotice, workingHours }: GetSlots) => { // current date in invitee tz const startDate = dayjs().add(minimumBookingNotice, "minute"); // checks if the start date is in the past if (inviteeDate.isBefore(startDate, "day")) { return []; } const localWorkingHours = getWorkingHours( { utcOffset: -inviteeDate.utcOffset() }, workingHours.map((schedule) => ({ days: schedule.days, startTime: dayjs.utc().startOf("day").add(schedule.startTime, "minute"), endTime: dayjs.utc().startOf("day").add(schedule.endTime, "minute"), })) ).filter((hours) => hours.days.includes(inviteeDate.day())); const slots: Dayjs[] = []; for (let minutes = getMinuteOffset(inviteeDate, frequency); minutes < 1440; minutes += frequency) { const slot = dayjs(inviteeDate).startOf("day").add(minutes, "minute"); // check if slot happened already if (slot.isBefore(startDate)) { continue; } // add slots to available slots if it is found to be between the start and end time of the checked working hours. if ( localWorkingHours.some((hours) => slot.isBetween( inviteeDate.startOf("day").add(hours.startTime, "minute"), inviteeDate.startOf("day").add(hours.endTime, "minute"), null, "[)" ) ) ) { slots.push(slot); } } return slots; }; export default getSlots;