2021-06-29 01:45:58 +00:00
|
|
|
import dayjs, { Dayjs } from "dayjs";
|
2021-11-18 01:03:19 +00:00
|
|
|
import isBetween from "dayjs/plugin/isBetween";
|
2021-11-24 22:53:41 +00:00
|
|
|
import isToday from "dayjs/plugin/isToday";
|
2021-09-22 19:52:38 +00:00
|
|
|
import utc from "dayjs/plugin/utc";
|
|
|
|
|
2021-11-18 01:03:19 +00:00
|
|
|
import { getWorkingHours } from "./availability";
|
|
|
|
import { WorkingHours } from "./types/schedule";
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2021-11-24 22:53:41 +00:00
|
|
|
dayjs.extend(isToday);
|
2021-11-18 01:03:19 +00:00
|
|
|
dayjs.extend(utc);
|
|
|
|
dayjs.extend(isBetween);
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2021-11-18 01:03:19 +00:00
|
|
|
export type GetSlots = {
|
2021-06-24 22:15:18 +00:00
|
|
|
inviteeDate: Dayjs;
|
|
|
|
frequency: number;
|
2021-11-18 01:03:19 +00:00
|
|
|
workingHours: WorkingHours[];
|
|
|
|
minimumBookingNotice: number;
|
2021-06-29 22:35:13 +00:00
|
|
|
};
|
2022-02-27 22:51:41 +00:00
|
|
|
export type WorkingHoursTimeFrame = { startTime: number; endTime: number };
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2022-02-27 22:51:41 +00:00
|
|
|
const splitAvailableTime = (
|
|
|
|
startTimeMinutes: number,
|
|
|
|
endTimeMinutes: number,
|
|
|
|
frequency: number
|
|
|
|
): Array<WorkingHoursTimeFrame> => {
|
|
|
|
let initialTime = startTimeMinutes;
|
|
|
|
const finalizationTime = endTimeMinutes;
|
|
|
|
const result = [] as Array<WorkingHoursTimeFrame>;
|
|
|
|
while (initialTime < finalizationTime) {
|
|
|
|
const periodTime = initialTime + frequency;
|
|
|
|
result.push({ startTime: initialTime, endTime: periodTime });
|
|
|
|
initialTime += frequency;
|
|
|
|
}
|
|
|
|
return result;
|
2021-06-29 22:35:13 +00:00
|
|
|
};
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2021-11-18 01:03:19 +00:00
|
|
|
const getSlots = ({ inviteeDate, frequency, minimumBookingNotice, workingHours }: GetSlots) => {
|
|
|
|
// current date in invitee tz
|
2021-12-16 15:20:38 +00:00
|
|
|
const startDate = dayjs().add(minimumBookingNotice, "minute");
|
2022-02-27 00:19:50 +00:00
|
|
|
const startOfDay = dayjs.utc().startOf("day");
|
|
|
|
const startOfInviteeDay = inviteeDate.startOf("day");
|
2021-11-18 01:03:19 +00:00
|
|
|
// checks if the start date is in the past
|
2021-12-16 15:20:38 +00:00
|
|
|
if (inviteeDate.isBefore(startDate, "day")) {
|
2021-11-18 01:03:19 +00:00
|
|
|
return [];
|
2021-04-17 00:08:35 +00:00
|
|
|
}
|
2021-07-08 21:14:29 +00:00
|
|
|
|
2021-11-18 01:03:19 +00:00
|
|
|
const localWorkingHours = getWorkingHours(
|
|
|
|
{ utcOffset: -inviteeDate.utcOffset() },
|
|
|
|
workingHours.map((schedule) => ({
|
|
|
|
days: schedule.days,
|
2022-02-27 00:19:50 +00:00
|
|
|
startTime: startOfDay.add(schedule.startTime, "minute"),
|
|
|
|
endTime: startOfDay.add(schedule.endTime, "minute"),
|
2021-11-18 01:03:19 +00:00
|
|
|
}))
|
|
|
|
).filter((hours) => hours.days.includes(inviteeDate.day()));
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2021-06-24 22:15:18 +00:00
|
|
|
const slots: Dayjs[] = [];
|
2022-02-27 22:51:41 +00:00
|
|
|
|
|
|
|
const slotsTimeFrameAvailable = [] as Array<WorkingHoursTimeFrame>;
|
|
|
|
|
|
|
|
// Here we split working hour in chunks for every frequency available that can fit in whole working hour
|
|
|
|
localWorkingHours.forEach((item, index) => {
|
|
|
|
slotsTimeFrameAvailable.push(...splitAvailableTime(item.startTime, item.endTime, frequency));
|
|
|
|
});
|
|
|
|
|
|
|
|
slotsTimeFrameAvailable.forEach((item) => {
|
|
|
|
const slot = startOfInviteeDay.add(item.startTime, "minute");
|
|
|
|
// Validating slot its not on the past
|
|
|
|
if (!slot.isBefore(startDate)) {
|
2022-01-27 15:16:38 +00:00
|
|
|
slots.push(slot);
|
2021-11-18 01:03:19 +00:00
|
|
|
}
|
2022-02-27 22:51:41 +00:00
|
|
|
});
|
2021-11-18 01:03:19 +00:00
|
|
|
return slots;
|
2021-06-29 01:45:58 +00:00
|
|
|
};
|
2021-04-17 00:08:35 +00:00
|
|
|
|
2021-06-24 22:15:18 +00:00
|
|
|
export default getSlots;
|