@perdieminc/time-slots 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +2 -2
  2. package/lib/constants.d.ts +36 -0
  3. package/lib/constants.d.ts.map +1 -0
  4. package/lib/constants.js +36 -0
  5. package/lib/constants.js.map +1 -0
  6. package/lib/index.d.ts +10 -0
  7. package/lib/index.d.ts.map +1 -0
  8. package/lib/index.js +41 -0
  9. package/lib/index.js.map +1 -0
  10. package/lib/schedule/available-dates.d.ts +3 -0
  11. package/lib/schedule/available-dates.d.ts.map +1 -0
  12. package/lib/schedule/available-dates.js +84 -0
  13. package/lib/schedule/available-dates.js.map +1 -0
  14. package/lib/schedule/generate.d.ts +3 -0
  15. package/lib/schedule/generate.d.ts.map +1 -0
  16. package/lib/schedule/generate.js +155 -0
  17. package/lib/schedule/generate.js.map +1 -0
  18. package/lib/schedule/get-schedules.d.ts +3 -0
  19. package/lib/schedule/get-schedules.d.ts.map +1 -0
  20. package/lib/schedule/get-schedules.js +161 -0
  21. package/lib/schedule/get-schedules.js.map +1 -0
  22. package/lib/schedule/location.d.ts +3 -0
  23. package/lib/schedule/location.d.ts.map +1 -0
  24. package/lib/schedule/location.js +38 -0
  25. package/lib/schedule/location.js.map +1 -0
  26. package/lib/types/index.d.ts +7 -0
  27. package/lib/types/index.d.ts.map +1 -0
  28. package/lib/types/index.js +3 -0
  29. package/lib/types/index.js.map +1 -0
  30. package/lib/types.d.ts +24 -0
  31. package/lib/types.js +2 -0
  32. package/lib/utils/business-hours.d.ts +6 -0
  33. package/lib/utils/business-hours.d.ts.map +1 -0
  34. package/lib/utils/business-hours.js +82 -0
  35. package/lib/utils/business-hours.js.map +1 -0
  36. package/lib/utils/catering.d.ts +9 -0
  37. package/lib/utils/catering.d.ts.map +1 -0
  38. package/lib/utils/catering.js +56 -0
  39. package/lib/utils/catering.js.map +1 -0
  40. package/lib/utils/date.d.ts +15 -0
  41. package/lib/utils/date.d.ts.map +1 -0
  42. package/lib/utils/date.js +109 -0
  43. package/lib/utils/date.js.map +1 -0
  44. package/lib/utils/schedule-filter.d.ts +8 -0
  45. package/lib/utils/schedule-filter.d.ts.map +1 -0
  46. package/lib/utils/schedule-filter.js +95 -0
  47. package/lib/utils/schedule-filter.js.map +1 -0
  48. package/lib/utils/store-hours.d.ts +14 -0
  49. package/lib/utils/store-hours.d.ts.map +1 -0
  50. package/lib/utils/store-hours.js +120 -0
  51. package/lib/utils/store-hours.js.map +1 -0
  52. package/lib/utils/time.d.ts +12 -0
  53. package/lib/utils/time.d.ts.map +1 -0
  54. package/lib/utils/time.js +30 -0
  55. package/lib/utils/time.js.map +1 -0
  56. package/lib/utils.d.ts +8 -0
  57. package/lib/utils.js +18 -0
  58. package/package.json +8 -7
  59. package/src/constants.ts +0 -45
  60. package/src/index.ts +0 -23
  61. package/src/schedule/available-dates.ts +0 -129
  62. package/src/schedule/generate.ts +0 -276
  63. package/src/schedule/get-schedules.ts +0 -264
  64. package/src/schedule/location.ts +0 -58
  65. package/src/types/business-hours.d.ts +0 -32
  66. package/src/types/common.d.ts +0 -5
  67. package/src/types/get-schedules.d.ts +0 -122
  68. package/src/types/index.ts +0 -34
  69. package/src/types/location.d.ts +0 -25
  70. package/src/types/schedule-filter.d.ts +0 -27
  71. package/src/types/schedule.d.ts +0 -83
  72. package/src/types/timezone-support.d.ts +0 -31
  73. package/src/utils/business-hours.ts +0 -120
  74. package/src/utils/catering.ts +0 -85
  75. package/src/utils/date.ts +0 -163
  76. package/src/utils/schedule-filter.ts +0 -140
  77. package/src/utils/store-hours.ts +0 -223
  78. package/src/utils/time.ts +0 -38
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOpeningClosingTimeOnDate = getOpeningClosingTimeOnDate;
4
+ exports.getOpeningClosingTime = getOpeningClosingTime;
5
+ const date_fns_1 = require("date-fns");
6
+ const timezone_support_1 = require("timezone-support");
7
+ const available_dates_1 = require("../schedule/available-dates");
8
+ const business_hours_1 = require("./business-hours");
9
+ const date_1 = require("./date");
10
+ function getAvailableBusinessHours({ businessHours = [], businessHoursOverrides = [], timeZone, nextAvailableDate, }) {
11
+ const zonedDate = (0, timezone_support_1.getZonedTime)(nextAvailableDate, (0, timezone_support_1.findTimeZone)(timeZone));
12
+ const dayBusinessHours = businessHours.filter((bh) => bh.day ===
13
+ (0, timezone_support_1.getZonedTime)(nextAvailableDate, (0, timezone_support_1.findTimeZone)(timeZone)).dayOfWeek);
14
+ const businessHoursOverride = businessHoursOverrides.find((override) => override.day === zonedDate.day && override.month === zonedDate.month);
15
+ const dayBusinessTimes = dayBusinessHours
16
+ .map((businessHour) => {
17
+ const effectiveHour = businessHoursOverride
18
+ ? {
19
+ day: businessHour.day,
20
+ startTime: businessHoursOverride.startTime ?? "00:00",
21
+ endTime: businessHoursOverride.endTime ?? "23:59",
22
+ }
23
+ : businessHour;
24
+ const startDate = (0, date_1.setHmOnDate)(nextAvailableDate, effectiveHour.startTime, timeZone);
25
+ const endDate = (0, date_1.setHmOnDate)(nextAvailableDate, effectiveHour.endTime, timeZone);
26
+ if (!(0, date_fns_1.isBefore)(startDate, endDate)) {
27
+ return null;
28
+ }
29
+ return { startDate, endDate };
30
+ })
31
+ .filter((time) => time !== null)
32
+ .sort((a, b) => (0, date_fns_1.compareAsc)(a.startDate, b.startDate));
33
+ return { dayBusinessTimes, businessHoursOverride };
34
+ }
35
+ // ── Public API ──────────────────────────────────────────────────────────────
36
+ function getOpeningClosingTimeOnDate({ date = new Date(), businessHours = [], businessHoursOverrides = [], timeZone, }) {
37
+ try {
38
+ const nextAvailableDates = (0, available_dates_1.getNextAvailableDates)({
39
+ startDate: date,
40
+ businessHours,
41
+ businessHoursOverrides,
42
+ timeZone,
43
+ datesCount: 7,
44
+ });
45
+ if (!Array.isArray(nextAvailableDates) || !nextAvailableDates.length) {
46
+ return null;
47
+ }
48
+ for (let nextDateIndex = 0; nextDateIndex < nextAvailableDates.length; ++nextDateIndex) {
49
+ const nextAvailableDate = nextAvailableDates[nextDateIndex];
50
+ const { dayBusinessTimes, businessHoursOverride } = getAvailableBusinessHours({
51
+ businessHours,
52
+ businessHoursOverrides,
53
+ timeZone,
54
+ nextAvailableDate,
55
+ });
56
+ if (!Array.isArray(dayBusinessTimes) || dayBusinessTimes.length === 0) {
57
+ if (businessHoursOverride?.startTime &&
58
+ businessHoursOverride?.endTime) {
59
+ const openingTime = (0, date_1.setHmOnDate)(nextAvailableDate, businessHoursOverride.startTime, timeZone);
60
+ const closingTime = (0, date_1.setHmOnDate)(nextAvailableDate, businessHoursOverride.endTime, timeZone);
61
+ if ((0, date_fns_1.isBefore)(closingTime, date)) {
62
+ continue;
63
+ }
64
+ return { openingTime, closingTime };
65
+ }
66
+ continue;
67
+ }
68
+ const currentTime = date;
69
+ let currentSlot = null;
70
+ for (const slot of dayBusinessTimes) {
71
+ if ((0, date_fns_1.isBefore)(currentTime, slot.endDate)) {
72
+ currentSlot = slot;
73
+ break;
74
+ }
75
+ }
76
+ if (!currentSlot) {
77
+ currentSlot = dayBusinessTimes[0];
78
+ }
79
+ if ((0, date_fns_1.isBefore)(currentSlot.endDate, date)) {
80
+ continue;
81
+ }
82
+ if ((0, date_1.isTodayInTimeZone)(nextAvailableDate, timeZone) &&
83
+ nextDateIndex + 1 < nextAvailableDates.length) {
84
+ const { dayBusinessTimes: nextDayTimes } = getAvailableBusinessHours({
85
+ businessHours,
86
+ businessHoursOverrides,
87
+ timeZone,
88
+ nextAvailableDate: nextAvailableDates[nextDateIndex + 1],
89
+ });
90
+ if (nextDayTimes.length) {
91
+ const firstNextDaySlot = nextDayTimes?.[0];
92
+ if (firstNextDaySlot &&
93
+ (0, date_1.isMidnightTransition)(currentSlot.endDate, firstNextDaySlot.startDate, timeZone)) {
94
+ currentSlot = {
95
+ ...currentSlot,
96
+ endDate: firstNextDaySlot.endDate,
97
+ };
98
+ }
99
+ }
100
+ }
101
+ return {
102
+ openingTime: currentSlot.startDate,
103
+ closingTime: currentSlot.endDate,
104
+ };
105
+ }
106
+ return null;
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ function getOpeningClosingTime({ location, fulfillmentPreference, businessHoursOverrides, }) {
113
+ const businessHours = (0, business_hours_1.getLocationBusinessHoursForFulfillment)(location, fulfillmentPreference);
114
+ return getOpeningClosingTimeOnDate({
115
+ businessHours,
116
+ businessHoursOverrides: businessHoursOverrides?.[location.location_id] ?? [],
117
+ timeZone: location.timezone,
118
+ });
119
+ }
120
+ //# sourceMappingURL=store-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-hours.js","sourceRoot":"","sources":["../../src/utils/store-hours.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare function parseTimeString(timeString: string | null | undefined): {
2
+ hours: number;
3
+ minutes: number;
4
+ };
5
+ export declare function isTimeInRange(schedule: {
6
+ start_time?: string;
7
+ end_time?: string;
8
+ }, time: {
9
+ hours: number;
10
+ minutes: number;
11
+ }): boolean;
12
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB,CAQA;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EACpD,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtC,OAAO,CAqBT"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTimeString = parseTimeString;
4
+ exports.isTimeInRange = isTimeInRange;
5
+ function parseTimeString(timeString) {
6
+ if (!timeString) {
7
+ return { hours: 0, minutes: 0 };
8
+ }
9
+ const [hours = 0, minutes = 0] = String(timeString).split(":");
10
+ return { hours: Number(hours), minutes: Number(minutes) };
11
+ }
12
+ function isTimeInRange(schedule, time) {
13
+ const startTime = parseTimeString(schedule?.start_time);
14
+ const endTime = parseTimeString(schedule?.end_time);
15
+ if (time.hours < startTime.hours || time.hours > endTime.hours) {
16
+ return false;
17
+ }
18
+ if (time.hours === startTime.hours) {
19
+ if (time.minutes < startTime.minutes) {
20
+ return false;
21
+ }
22
+ }
23
+ if (time.hours === endTime.hours) {
24
+ if (time.minutes > endTime.minutes) {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":";;AAAA,0CAWC;AAED,sCAwBC;AArCD,SAAgB,eAAe,CAAC,UAAqC;IAIpE,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/D,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,SAAgB,aAAa,CAC5B,QAAoD,EACpD,IAAwC;IAExC,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEpD,IAAI,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
package/lib/utils.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Add minutes to a date and return a new Date.
3
+ */
4
+ export declare function addMinutes(date: Date, minutes: number): Date;
5
+ /**
6
+ * Check if a date is before another (by time value).
7
+ */
8
+ export declare function isBefore(a: Date, b: Date): boolean;
package/lib/utils.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addMinutes = addMinutes;
4
+ exports.isBefore = isBefore;
5
+ /**
6
+ * Add minutes to a date and return a new Date.
7
+ */
8
+ function addMinutes(date, minutes) {
9
+ const result = new Date(date);
10
+ result.setMinutes(result.getMinutes() + minutes);
11
+ return result;
12
+ }
13
+ /**
14
+ * Check if a date is before another (by time value).
15
+ */
16
+ function isBefore(a, b) {
17
+ return a.getTime() < b.getTime();
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perdieminc/time-slots",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Generate time slots for scheduling",
5
5
  "keywords": [
6
6
  "time-slots",
@@ -9,18 +9,18 @@
9
9
  ],
10
10
  "license": "MIT",
11
11
  "author": "Per Diem Subscriptions Inc.",
12
- "homepage": "https://github.com/PerDiemInc/perdiem-pkgs#readme",
12
+ "homepage": "https://github.com/PerDiemInc/time-slots#readme",
13
13
  "bugs": {
14
- "url": "https://github.com/PerDiemInc/perdiem-pkgs/issues"
14
+ "url": "https://github.com/PerDiemInc/time-slots/issues"
15
15
  },
16
- "main": "src/index.ts",
17
- "types": "src/index.ts",
16
+ "main": "lib/index.js",
17
+ "types": "lib/index.d.ts",
18
18
  "engines": {
19
19
  "node": ">=20"
20
20
  },
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/PerDiemInc/perdiem-pkgs.git"
23
+ "url": "git+https://github.com/PerDiemInc/time-slots.git"
24
24
  },
25
25
  "scripts": {
26
26
  "lint": "biome lint .",
@@ -28,6 +28,7 @@
28
28
  "format": "biome check --write .",
29
29
  "clean": "rm -rf lib types coverage",
30
30
  "build": "tsc -b .",
31
+ "prepublishOnly": "npm run build",
31
32
  "build:watch": "tsc --watch",
32
33
  "test": "vitest run",
33
34
  "test:coverage": "vitest run --coverage",
@@ -51,7 +52,7 @@
51
52
  "vitest": "^3.2.4"
52
53
  },
53
54
  "files": [
54
- "src"
55
+ "lib"
55
56
  ],
56
57
  "directories": {
57
58
  "lib": "lib",
package/src/constants.ts DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * Fulfillment types for pickup, delivery, curbside.
3
- */
4
- export const FULFILLMENT_TYPES = {
5
- PICKUP: "PICKUP",
6
- DELIVERY: "DELIVERY",
7
- CURBSIDE: "CURBSIDE",
8
- } as const;
9
-
10
- export const DEFAULT_TIMEZONE = "America/New_York";
11
- export type FulfillmentType =
12
- (typeof FULFILLMENT_TYPES)[keyof typeof FULFILLMENT_TYPES];
13
-
14
- export const DEFAULT_GAP_IN_MINUTES = 15;
15
- export const DEFAULT_PREP_TIME_IN_MINUTES = 5;
16
-
17
- /**
18
- * Prep time behaviour when computing first available slot.
19
- */
20
- export const PrepTimeBehaviour = Object.freeze({
21
- FIRST_SHIFT: 0,
22
- EVERY_SHIFT: 1,
23
- ROLL_FROM_FIRST_SHIFT: 2,
24
- });
25
-
26
- export type PrepTimeBehaviourType =
27
- (typeof PrepTimeBehaviour)[keyof typeof PrepTimeBehaviour];
28
-
29
- export const PREP_TIME_CADENCE = {
30
- MINUTE: "minute",
31
- DAY: "day",
32
- HOUR: "hour",
33
- } as const;
34
-
35
- export type PrepTimeCadence =
36
- (typeof PREP_TIME_CADENCE)[keyof typeof PREP_TIME_CADENCE];
37
-
38
- /**
39
- * Platform for timezone handling (web uses @date-fns/tz; ios/android use timezone-support).
40
- */
41
- export const PLATFORM = {
42
- WEB: "web",
43
- IOS: "ios",
44
- ANDROID: "android",
45
- } as const;
package/src/index.ts DELETED
@@ -1,23 +0,0 @@
1
- export type { FulfillmentType, PrepTimeBehaviourType } from "./constants";
2
- export {
3
- DEFAULT_GAP_IN_MINUTES,
4
- DEFAULT_PREP_TIME_IN_MINUTES,
5
- FULFILLMENT_TYPES,
6
- PLATFORM,
7
- PrepTimeBehaviour,
8
- } from "./constants";
9
- export { getSchedules } from "./schedule/get-schedules";
10
- export * from "./types";
11
- export { getLocationsBusinessHoursOverrides } from "./utils/business-hours";
12
- export { getCateringPrepTimeConfig } from "./utils/catering";
13
- export {
14
- getPreSalePickupDates,
15
- isTodayInTimeZone,
16
- isTomorrowInTimeZone,
17
- overrideTimeZoneOnUTC,
18
- } from "./utils/date";
19
- export {
20
- filterBusyTimesFromSchedule,
21
- filterMenusFromSchedule,
22
- } from "./utils/schedule-filter";
23
- export { getOpeningClosingTime } from "./utils/store-hours";
@@ -1,129 +0,0 @@
1
- import { tz } from "@date-fns/tz";
2
- import { isAfter, isSameDay, startOfDay } from "date-fns";
3
- import { findTimeZone, getUnixTime, getZonedTime } from "timezone-support";
4
-
5
- import { PLATFORM } from "../constants";
6
- import type { GetNextAvailableDatesParams, Platform } from "../types";
7
- import { addDaysInTimeZone, setHmOnDate } from "../utils/date";
8
-
9
- function getStartOfDayInZone(
10
- startDate: Date,
11
- timeZone: string,
12
- platform: Platform,
13
- ): Date {
14
- if (platform !== PLATFORM.ANDROID) {
15
- return startOfDay(startDate, { in: tz(timeZone) });
16
- }
17
- const zoned = getZonedTime(startDate, findTimeZone(timeZone));
18
- return new Date(
19
- getUnixTime({
20
- ...zoned,
21
- hours: 0,
22
- minutes: 0,
23
- seconds: 0,
24
- milliseconds: 0,
25
- }),
26
- );
27
- }
28
-
29
- export function getNextAvailableDates({
30
- startDate,
31
- timeZone,
32
- businessHours,
33
- businessHoursOverrides = [],
34
- datesCount = 1,
35
- preSaleDates = [],
36
- presalePickupWeekDays = [],
37
- endDate = null,
38
- isDaysCadence = false,
39
- platform = PLATFORM.WEB,
40
- }: GetNextAvailableDatesParams): Date[] {
41
- const startOfDayInZone = getStartOfDayInZone(startDate, timeZone, platform);
42
- const zonedStartTime = getZonedTime(startOfDayInZone, findTimeZone(timeZone));
43
-
44
- const dates: Date[] = [];
45
-
46
- for (
47
- let date = new Date(
48
- getUnixTime({
49
- ...zonedStartTime,
50
- hours: 0,
51
- minutes: 0,
52
- seconds: 0,
53
- milliseconds: 0,
54
- }),
55
- ),
56
- maxRuns = 0;
57
- dates.length < datesCount && maxRuns <= 30;
58
- date = addDaysInTimeZone(date, 1, timeZone), maxRuns += 1
59
- ) {
60
- const lastDate = dates?.at(-1);
61
- if (lastDate && isSameDay(lastDate, date)) {
62
- continue;
63
- }
64
-
65
- if (endDate && isAfter(date, endDate)) {
66
- break;
67
- }
68
-
69
- if (date.getTime() < getUnixTime(zonedStartTime)) {
70
- continue;
71
- }
72
-
73
- const zonedDate = getZonedTime(date, findTimeZone(timeZone));
74
- const dayOfWeek = zonedDate.dayOfWeek ?? 0;
75
-
76
- const todayBusinessHoursOverride = businessHoursOverrides.filter(
77
- (override) =>
78
- zonedDate.month === override.month && zonedDate.day === override.day,
79
- );
80
-
81
- const closedBusinessHoursOverride = todayBusinessHoursOverride.filter(
82
- (override) => !override.startTime && !override.endTime,
83
- );
84
-
85
- if (closedBusinessHoursOverride.length) {
86
- continue;
87
- }
88
-
89
- const todayBusinessHours = businessHours.filter(
90
- (bh) => bh.day === dayOfWeek,
91
- );
92
- // If days cadence, we dont need to skip date even if it is after the last shift end time
93
- if (isDaysCadence) {
94
- const lastShiftEndTime = todayBusinessHours.at(-1)?.endTime;
95
- const shiftEndDate = lastShiftEndTime
96
- ? setHmOnDate(date, lastShiftEndTime, timeZone)
97
- : null;
98
- /**
99
- * Skip current date if current time is after the last shift end time
100
- */
101
- if (shiftEndDate && isAfter(startDate, shiftEndDate)) {
102
- continue;
103
- }
104
- }
105
- /**
106
- * Skip if today is closed by location hours or by override hours
107
- */
108
- if (
109
- !todayBusinessHours?.length &&
110
- !todayBusinessHoursOverride.length &&
111
- !endDate
112
- ) {
113
- continue;
114
- }
115
-
116
- if (preSaleDates.length && presalePickupWeekDays.length) {
117
- if (
118
- preSaleDates.includes(zonedDate.day) &&
119
- presalePickupWeekDays.includes(dayOfWeek)
120
- ) {
121
- dates.push(date);
122
- }
123
- } else {
124
- dates.push(date);
125
- }
126
- }
127
-
128
- return dates;
129
- }