* perf: optimize getSlots performance by selectively merging overlapping date ranges Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: handle date ranges with end time before start time in filterRedundantDateRanges Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * perf: apply filterRedundantDateRanges to all scheduling types Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: preserve uniqueness check before filtering redundant date ranges Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: keith@cal.com <keithwillcode@gmail.com>
57 lines
2.0 KiB
TypeScript
57 lines
2.0 KiB
TypeScript
import type { DateRange } from "@calcom/lib/date-ranges";
|
|
import { intersect } from "@calcom/lib/date-ranges";
|
|
import { SchedulingType } from "@calcom/prisma/enums";
|
|
|
|
import { filterRedundantDateRanges } from "./getAggregatedAvailability/date-range-utils/filterRedundantDateRanges";
|
|
import { mergeOverlappingDateRanges } from "./getAggregatedAvailability/date-range-utils/mergeOverlappingDateRanges";
|
|
|
|
function uniqueAndSortedDateRanges(ranges: DateRange[]): DateRange[] {
|
|
const seen = new Set<string>();
|
|
|
|
return ranges
|
|
.sort((a, b) => {
|
|
const startDiff = a.start.valueOf() - b.start.valueOf();
|
|
return startDiff !== 0 ? startDiff : a.end.valueOf() - b.end.valueOf();
|
|
})
|
|
.filter((range) => {
|
|
const key = `${range.start.valueOf()}-${range.end.valueOf()}`;
|
|
if (seen.has(key)) return false;
|
|
seen.add(key);
|
|
return true;
|
|
});
|
|
}
|
|
|
|
export const getAggregatedAvailability = (
|
|
userAvailability: {
|
|
dateRanges: DateRange[];
|
|
oooExcludedDateRanges: DateRange[];
|
|
user?: { isFixed?: boolean };
|
|
}[],
|
|
schedulingType: SchedulingType | null
|
|
): DateRange[] => {
|
|
const isTeamEvent =
|
|
schedulingType === SchedulingType.COLLECTIVE ||
|
|
schedulingType === SchedulingType.ROUND_ROBIN ||
|
|
userAvailability.length > 1;
|
|
|
|
const fixedHosts = userAvailability.filter(
|
|
({ user }) => !schedulingType || schedulingType === SchedulingType.COLLECTIVE || user?.isFixed
|
|
);
|
|
|
|
const fixedDateRanges = mergeOverlappingDateRanges(
|
|
intersect(fixedHosts.map((s) => (!isTeamEvent ? s.dateRanges : s.oooExcludedDateRanges)))
|
|
);
|
|
const dateRangesToIntersect = !!fixedDateRanges.length ? [fixedDateRanges] : [];
|
|
const roundRobinHosts = userAvailability.filter(({ user }) => user?.isFixed !== true);
|
|
if (roundRobinHosts.length) {
|
|
dateRangesToIntersect.push(
|
|
roundRobinHosts.flatMap((s) => (!isTeamEvent ? s.dateRanges : s.oooExcludedDateRanges))
|
|
);
|
|
}
|
|
const availability = intersect(dateRangesToIntersect);
|
|
|
|
const uniqueRanges = uniqueAndSortedDateRanges(availability);
|
|
|
|
return filterRedundantDateRanges(uniqueRanges);
|
|
};
|