@perdieminc/time-slots 0.0.1 → 0.0.3
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.
- package/README.md +9 -8
- package/lib/constants.d.ts +37 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/constants.js +37 -0
- package/lib/constants.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +41 -0
- package/lib/index.js.map +1 -0
- package/lib/schedule/available-dates.d.ts +3 -0
- package/lib/schedule/available-dates.d.ts.map +1 -0
- package/lib/schedule/available-dates.js +84 -0
- package/lib/schedule/available-dates.js.map +1 -0
- package/lib/schedule/generate.d.ts +3 -0
- package/lib/schedule/generate.d.ts.map +1 -0
- package/lib/schedule/generate.js +155 -0
- package/lib/schedule/generate.js.map +1 -0
- package/lib/schedule/get-schedules.d.ts +3 -0
- package/lib/schedule/get-schedules.d.ts.map +1 -0
- package/lib/schedule/get-schedules.js +182 -0
- package/lib/schedule/get-schedules.js.map +1 -0
- package/lib/schedule/location.d.ts +3 -0
- package/lib/schedule/location.d.ts.map +1 -0
- package/lib/schedule/location.js +38 -0
- package/lib/schedule/location.js.map +1 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +3 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types.d.ts +24 -0
- package/lib/types.js +2 -0
- package/lib/utils/business-hours.d.ts +6 -0
- package/lib/utils/business-hours.d.ts.map +1 -0
- package/lib/utils/business-hours.js +82 -0
- package/lib/utils/business-hours.js.map +1 -0
- package/lib/utils/catering.d.ts +9 -0
- package/lib/utils/catering.d.ts.map +1 -0
- package/lib/utils/catering.js +56 -0
- package/lib/utils/catering.js.map +1 -0
- package/lib/utils/date.d.ts +15 -0
- package/lib/utils/date.d.ts.map +1 -0
- package/lib/utils/date.js +109 -0
- package/lib/utils/date.js.map +1 -0
- package/lib/utils/schedule-filter.d.ts +8 -0
- package/lib/utils/schedule-filter.d.ts.map +1 -0
- package/lib/utils/schedule-filter.js +95 -0
- package/lib/utils/schedule-filter.js.map +1 -0
- package/lib/utils/store-hours.d.ts +14 -0
- package/lib/utils/store-hours.d.ts.map +1 -0
- package/lib/utils/store-hours.js +120 -0
- package/lib/utils/store-hours.js.map +1 -0
- package/lib/utils/time.d.ts +12 -0
- package/lib/utils/time.d.ts.map +1 -0
- package/lib/utils/time.js +30 -0
- package/lib/utils/time.js.map +1 -0
- package/lib/utils.d.ts +8 -0
- package/lib/utils.js +18 -0
- package/package.json +8 -7
- package/src/constants.ts +0 -45
- package/src/index.ts +0 -23
- package/src/schedule/available-dates.ts +0 -129
- package/src/schedule/generate.ts +0 -276
- package/src/schedule/get-schedules.ts +0 -264
- package/src/schedule/location.ts +0 -58
- package/src/types/business-hours.d.ts +0 -32
- package/src/types/common.d.ts +0 -5
- package/src/types/get-schedules.d.ts +0 -122
- package/src/types/index.ts +0 -34
- package/src/types/location.d.ts +0 -25
- package/src/types/schedule-filter.d.ts +0 -27
- package/src/types/schedule.d.ts +0 -83
- package/src/types/timezone-support.d.ts +0 -31
- package/src/utils/business-hours.ts +0 -120
- package/src/utils/catering.ts +0 -85
- package/src/utils/date.ts +0 -163
- package/src/utils/schedule-filter.ts +0 -140
- package/src/utils/store-hours.ts +0 -223
- package/src/utils/time.ts +0 -38
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import type { PrepTimeCadence } from "../constants";
|
|
2
|
-
|
|
3
|
-
export interface GetCateringPrepTimeParams {
|
|
4
|
-
items: CartItem[];
|
|
5
|
-
prepTimeCadence?: PrepTimeCadence;
|
|
6
|
-
prepTimeFrequency?: number;
|
|
7
|
-
timezone?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
import type {
|
|
11
|
-
BusinessHoursOverrideInput,
|
|
12
|
-
BusinessHoursOverrideOutput,
|
|
13
|
-
} from "./business-hours";
|
|
14
|
-
import type { BusyTimeItem } from "./common";
|
|
15
|
-
import type { FulfillmentPreference, LocationLike } from "./location";
|
|
16
|
-
import type { FulfillmentSchedule, Platform } from "./schedule";
|
|
17
|
-
|
|
18
|
-
// ── High-level input objects ────────────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
export interface PreSaleConfig {
|
|
21
|
-
active: boolean;
|
|
22
|
-
due_start_date?: string | Date;
|
|
23
|
-
due_end_date?: string | Date;
|
|
24
|
-
use_store_hours_due?: boolean;
|
|
25
|
-
due_start_time?: string | null;
|
|
26
|
-
due_end_time?: string | null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface WeeklyPreSaleConfig {
|
|
30
|
-
active: boolean;
|
|
31
|
-
pickup_days: number[];
|
|
32
|
-
ordering_days: number[];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface StoreConfig {
|
|
36
|
-
isAsapOrders: boolean;
|
|
37
|
-
isSameDayOrders: boolean;
|
|
38
|
-
max_future_order_days?: number;
|
|
39
|
-
businessHoursOverrides: BusinessHoursOverrideInput[];
|
|
40
|
-
preSaleConfig?: PreSaleConfig;
|
|
41
|
-
weeklyPreSaleConfig?: WeeklyPreSaleConfig;
|
|
42
|
-
}
|
|
43
|
-
export type CateringServiceType = {
|
|
44
|
-
min_quantity: number;
|
|
45
|
-
max_quantity: number;
|
|
46
|
-
serve_count: number;
|
|
47
|
-
prep_time: {
|
|
48
|
-
cadence: PrepTimeCadence;
|
|
49
|
-
frequency: number;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
export interface CartItem {
|
|
53
|
-
preSale?: boolean;
|
|
54
|
-
weeklyPreSale?: boolean;
|
|
55
|
-
internalCategoryId?: string;
|
|
56
|
-
cateringService?: CateringServiceType;
|
|
57
|
-
}
|
|
58
|
-
export interface CateringPrepTimeResult {
|
|
59
|
-
prepTimeCadence: PrepTimeCadence;
|
|
60
|
-
prepTimeFrequency: number;
|
|
61
|
-
/** Only set when prepTimeCadence is not DAY (e.g. HOUR). */
|
|
62
|
-
weekDayPrepTimes?: Record<number, number>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface PrepTimeSettings {
|
|
66
|
-
prepTimeInMinutes: number;
|
|
67
|
-
weekDayPrepTimes: Record<number, number>;
|
|
68
|
-
gapInMinutes: number;
|
|
69
|
-
busyTimes: Record<string, BusyTimeItem[]>;
|
|
70
|
-
prepTimeFrequency: number;
|
|
71
|
-
prepTimeCadence: PrepTimeCadence;
|
|
72
|
-
/** When fulfillment is DELIVERY, added to each weekday prep time so slots reflect when order is received. */
|
|
73
|
-
estimatedDeliveryMinutes?: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ── getSchedules params / result ────────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
export interface GetSchedulesParams {
|
|
79
|
-
store: StoreConfig;
|
|
80
|
-
locations: LocationLike[];
|
|
81
|
-
cartItems: CartItem[];
|
|
82
|
-
fulfillmentPreference: FulfillmentPreference;
|
|
83
|
-
prepTimeSettings: PrepTimeSettings;
|
|
84
|
-
currentLocation: LocationLike;
|
|
85
|
-
isCateringFlow?: boolean;
|
|
86
|
-
/** Platform for timezone handling in next-available-date logic. Default "web". */
|
|
87
|
-
platform?: Platform;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface GetSchedulesResult {
|
|
91
|
-
schedule: FulfillmentSchedule;
|
|
92
|
-
isWeeklyPreSaleAvailable: boolean;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ── Legacy flat params (kept for backward-compat if needed) ─────────────────
|
|
96
|
-
|
|
97
|
-
export interface InitScheduleParams {
|
|
98
|
-
isAsapOrders: boolean;
|
|
99
|
-
isSameDayOrders: boolean;
|
|
100
|
-
preSalePickupDays: number[];
|
|
101
|
-
isWeeklyPreSaleActive: boolean;
|
|
102
|
-
preSaleOrderingDays: number[];
|
|
103
|
-
locations: LocationLike[];
|
|
104
|
-
daysCount?: number;
|
|
105
|
-
fulfillmentPreference: FulfillmentPreference;
|
|
106
|
-
prepTimeInMinutes: number;
|
|
107
|
-
weekDayPrepTimes: Record<number, number>;
|
|
108
|
-
hasCartWeeklyPreSaleItem: boolean;
|
|
109
|
-
busyTimes: BusyTimeItem[];
|
|
110
|
-
cartCategoryIds: string[];
|
|
111
|
-
gapInMinutes: number;
|
|
112
|
-
businessHoursOverrides: Record<string, BusinessHoursOverrideOutput[]>;
|
|
113
|
-
currentLocation: LocationLike;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface InitScheduleResult {
|
|
117
|
-
businessHoursOverrides: Record<string, BusinessHoursOverrideOutput[]>;
|
|
118
|
-
locationId: string;
|
|
119
|
-
fulfillmentPreference: FulfillmentPreference;
|
|
120
|
-
schedule: FulfillmentSchedule;
|
|
121
|
-
isWeeklyPreSaleAvailable: boolean;
|
|
122
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
BusinessHour,
|
|
3
|
-
BusinessHourInput,
|
|
4
|
-
BusinessHoursOverrideInput,
|
|
5
|
-
BusinessHoursOverrideOutput,
|
|
6
|
-
} from "./business-hours";
|
|
7
|
-
export type { BusyTimeItem } from "./common";
|
|
8
|
-
export type {
|
|
9
|
-
CartItem,
|
|
10
|
-
CateringPrepTimeResult,
|
|
11
|
-
GetCateringPrepTimeParams,
|
|
12
|
-
GetSchedulesParams,
|
|
13
|
-
GetSchedulesResult,
|
|
14
|
-
InitScheduleParams,
|
|
15
|
-
InitScheduleResult,
|
|
16
|
-
PrepTimeSettings,
|
|
17
|
-
PreSaleConfig,
|
|
18
|
-
StoreConfig,
|
|
19
|
-
WeeklyPreSaleConfig,
|
|
20
|
-
} from "./get-schedules";
|
|
21
|
-
export type { FulfillmentPreference, LocationLike } from "./location";
|
|
22
|
-
export type {
|
|
23
|
-
DaySchedule,
|
|
24
|
-
FulfillmentSchedule,
|
|
25
|
-
GenerateLocationFulfillmentScheduleParams,
|
|
26
|
-
GenerateScheduleParams,
|
|
27
|
-
GetNextAvailableDatesParams,
|
|
28
|
-
GetOpeningClosingTimeOnDateParams,
|
|
29
|
-
Platform,
|
|
30
|
-
} from "./schedule";
|
|
31
|
-
export type {
|
|
32
|
-
FilterBusyTimesFromScheduleParams,
|
|
33
|
-
MenuType,
|
|
34
|
-
} from "./schedule-filter";
|
package/src/types/location.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { BusinessHourInput } from "./business-hours";
|
|
2
|
-
|
|
3
|
-
export type FulfillmentPreference = "PICKUP" | "DELIVERY" | "CURBSIDE";
|
|
4
|
-
export type BusinessHourType = {
|
|
5
|
-
day: number;
|
|
6
|
-
start_time: string;
|
|
7
|
-
end_time: string;
|
|
8
|
-
};
|
|
9
|
-
export interface LocationLike {
|
|
10
|
-
location_id: string;
|
|
11
|
-
id?: string;
|
|
12
|
-
timezone: string;
|
|
13
|
-
pickup_hours?: BusinessHourInput[];
|
|
14
|
-
delivery_hours?: BusinessHourInput[];
|
|
15
|
-
curbside_hours?: {
|
|
16
|
-
use_pickup_hours?: boolean;
|
|
17
|
-
times?: BusinessHourInput[];
|
|
18
|
-
};
|
|
19
|
-
catering?: {
|
|
20
|
-
enabled: boolean | string;
|
|
21
|
-
pickup: Omit<BusinessHourType, "day">;
|
|
22
|
-
delivery: Omit<BusinessHourType, "day">;
|
|
23
|
-
};
|
|
24
|
-
[key: string]: unknown;
|
|
25
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { BusyTimeItem } from "./common";
|
|
2
|
-
import type { FulfillmentSchedule } from "./schedule";
|
|
3
|
-
export type MenuTimeSlot = {
|
|
4
|
-
all_day: boolean;
|
|
5
|
-
end_time: string | null;
|
|
6
|
-
start_time: string | null;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export type MenuType = {
|
|
10
|
-
menu_id: string;
|
|
11
|
-
store_id: string;
|
|
12
|
-
location_id: string | null;
|
|
13
|
-
all_locations: boolean;
|
|
14
|
-
display_name: string;
|
|
15
|
-
description: string | null;
|
|
16
|
-
times: Record<string, MenuTimeSlot>;
|
|
17
|
-
category_ids: string[];
|
|
18
|
-
last_modified_by: string;
|
|
19
|
-
created_at: string;
|
|
20
|
-
updated_at: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export interface FilterBusyTimesFromScheduleParams {
|
|
24
|
-
schedule: FulfillmentSchedule;
|
|
25
|
-
busyTimes?: BusyTimeItem[];
|
|
26
|
-
cartCategoryIds?: string[];
|
|
27
|
-
}
|
package/src/types/schedule.d.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { PLATFORM } from "../constants";
|
|
2
|
-
import type {
|
|
3
|
-
BusinessHour,
|
|
4
|
-
BusinessHoursOverrideOutput,
|
|
5
|
-
} from "./business-hours";
|
|
6
|
-
import type { FulfillmentPreference, LocationLike } from "./location";
|
|
7
|
-
|
|
8
|
-
export interface DaySchedule {
|
|
9
|
-
date: Date;
|
|
10
|
-
originalStoreOpeningTime: Date | null;
|
|
11
|
-
originalStoreClosingTime: Date | null;
|
|
12
|
-
remainingShifts: number;
|
|
13
|
-
openingTime: Date;
|
|
14
|
-
closingTime: Date;
|
|
15
|
-
firstAvailableSlot: Date;
|
|
16
|
-
slots: Date[];
|
|
17
|
-
[key: string]: unknown;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type FulfillmentSchedule = DaySchedule[];
|
|
21
|
-
|
|
22
|
-
export interface GenerateScheduleParams {
|
|
23
|
-
currentDate?: Date;
|
|
24
|
-
prepTimeBehaviour?: number;
|
|
25
|
-
prepTimeInMinutes?: number;
|
|
26
|
-
weekDayPrepTimes?: Record<number, number>;
|
|
27
|
-
timeZone: string;
|
|
28
|
-
dates?: Date[];
|
|
29
|
-
businessHours?: BusinessHour[];
|
|
30
|
-
businessHoursOverrides?: BusinessHoursOverrideOutput[];
|
|
31
|
-
preSaleHoursOverride?: Array<{
|
|
32
|
-
startTime: string;
|
|
33
|
-
endTime: string;
|
|
34
|
-
month?: number;
|
|
35
|
-
day?: number;
|
|
36
|
-
}> | null;
|
|
37
|
-
gapInMinutes?: number;
|
|
38
|
-
prepTimeCadence?: PrepTimeCadence;
|
|
39
|
-
}
|
|
40
|
-
export type Platform = (typeof PLATFORM)[keyof typeof PLATFORM];
|
|
41
|
-
export interface GetNextAvailableDatesParams {
|
|
42
|
-
startDate: Date;
|
|
43
|
-
timeZone: string;
|
|
44
|
-
businessHours: BusinessHour[];
|
|
45
|
-
businessHoursOverrides?: BusinessHoursOverrideOutput[];
|
|
46
|
-
datesCount?: number;
|
|
47
|
-
preSaleDates?: number[];
|
|
48
|
-
presalePickupWeekDays?: number[];
|
|
49
|
-
endDate?: Date | null;
|
|
50
|
-
isDaysCadence?: boolean;
|
|
51
|
-
/** Platform for timezone handling. Web uses @date-fns/tz; ios/android use timezone-support. Default "web". */
|
|
52
|
-
platform?: Platform;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface GenerateLocationFulfillmentScheduleParams {
|
|
56
|
-
startDate: Date;
|
|
57
|
-
prepTimeFrequency?: number;
|
|
58
|
-
prepTimeCadence?: PrepTimeCadence;
|
|
59
|
-
weekDayPrepTimes?: Record<number, number>;
|
|
60
|
-
location: LocationLike;
|
|
61
|
-
fulfillmentPreference: FulfillmentPreference;
|
|
62
|
-
/** Overrides for this location only (not keyed by location_id). */
|
|
63
|
-
businessHoursOverrides?: BusinessHoursOverrideOutput[];
|
|
64
|
-
preSaleHoursOverride?: Array<{
|
|
65
|
-
startTime: string;
|
|
66
|
-
endTime: string;
|
|
67
|
-
month?: number;
|
|
68
|
-
day?: number;
|
|
69
|
-
}> | null;
|
|
70
|
-
gapInMinutes?: number;
|
|
71
|
-
daysCount?: number;
|
|
72
|
-
preSaleDates?: number[];
|
|
73
|
-
presalePickupWeekDays?: number[];
|
|
74
|
-
endDate?: Date | null;
|
|
75
|
-
platform?: Platform;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface GetOpeningClosingTimeOnDateParams {
|
|
79
|
-
date?: Date;
|
|
80
|
-
businessHours?: BusinessHour[];
|
|
81
|
-
businessHoursOverrides?: BusinessHoursOverrideOutput[];
|
|
82
|
-
timeZone: string;
|
|
83
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
declare module "timezone-support" {
|
|
2
|
-
export function findTimeZone(timezone: string): string;
|
|
3
|
-
export function getUnixTime(time: {
|
|
4
|
-
zone: string;
|
|
5
|
-
year: number;
|
|
6
|
-
month: number;
|
|
7
|
-
day: number;
|
|
8
|
-
hours: number | string;
|
|
9
|
-
minutes: number | string;
|
|
10
|
-
seconds: number | string;
|
|
11
|
-
milliseconds: number | string;
|
|
12
|
-
}): number;
|
|
13
|
-
export function getZonedTime(
|
|
14
|
-
date: Date | number,
|
|
15
|
-
timezone: string,
|
|
16
|
-
): {
|
|
17
|
-
zone: string;
|
|
18
|
-
year: number;
|
|
19
|
-
month: number;
|
|
20
|
-
day: number;
|
|
21
|
-
hours: number | string;
|
|
22
|
-
minutes: number | string;
|
|
23
|
-
seconds: number | string;
|
|
24
|
-
milliseconds: number | string;
|
|
25
|
-
dayOfWeek: number;
|
|
26
|
-
};
|
|
27
|
-
export function toZonedTime(
|
|
28
|
-
date: Date | number | string,
|
|
29
|
-
timezone: string,
|
|
30
|
-
): Date;
|
|
31
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { FULFILLMENT_TYPES } from "../constants";
|
|
2
|
-
import type {
|
|
3
|
-
BusinessHour,
|
|
4
|
-
BusinessHoursOverrideInput,
|
|
5
|
-
BusinessHoursOverrideOutput,
|
|
6
|
-
FulfillmentPreference,
|
|
7
|
-
LocationLike,
|
|
8
|
-
} from "../types";
|
|
9
|
-
|
|
10
|
-
export function toBusinessHoursOverride(
|
|
11
|
-
businessHoursOverride: BusinessHoursOverrideInput,
|
|
12
|
-
): BusinessHoursOverrideOutput {
|
|
13
|
-
const {
|
|
14
|
-
month,
|
|
15
|
-
day,
|
|
16
|
-
start_time: startTime,
|
|
17
|
-
end_time: endTime,
|
|
18
|
-
is_open: isOpen,
|
|
19
|
-
} = businessHoursOverride;
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
month,
|
|
23
|
-
day,
|
|
24
|
-
startTime: isOpen ? startTime : null,
|
|
25
|
-
endTime: isOpen ? endTime : null,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getLocationsBusinessHoursOverrides(
|
|
30
|
-
businessHoursOverrides: BusinessHoursOverrideInput[],
|
|
31
|
-
locations: LocationLike[],
|
|
32
|
-
): Record<string, BusinessHoursOverrideOutput[]> {
|
|
33
|
-
const result: Record<string, BusinessHoursOverrideOutput[]> = {};
|
|
34
|
-
|
|
35
|
-
for (const override of businessHoursOverrides) {
|
|
36
|
-
const { all_locations: allLocations, location_ids: locationIds } =
|
|
37
|
-
override || {};
|
|
38
|
-
|
|
39
|
-
if (allLocations === true) {
|
|
40
|
-
for (const location of locations || []) {
|
|
41
|
-
const id = location.location_id;
|
|
42
|
-
result[id] ??= [];
|
|
43
|
-
result[id].push(toBusinessHoursOverride(override));
|
|
44
|
-
}
|
|
45
|
-
} else {
|
|
46
|
-
for (const id of locationIds || []) {
|
|
47
|
-
const location = locations.find((loc) => loc.location_id === id);
|
|
48
|
-
if (location) {
|
|
49
|
-
result[id] ??= [];
|
|
50
|
-
result[id].push(toBusinessHoursOverride(override));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return result;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const isLocationCateringEnabled = (
|
|
60
|
-
location: LocationLike | undefined,
|
|
61
|
-
): boolean => {
|
|
62
|
-
if (!location) return false;
|
|
63
|
-
return (
|
|
64
|
-
!!location?.catering?.enabled && location?.catering?.enabled !== "false"
|
|
65
|
-
);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export function getLocationBusinessHoursForFulfillment(
|
|
69
|
-
location: LocationLike,
|
|
70
|
-
fulfillmentPreference: FulfillmentPreference,
|
|
71
|
-
isCatering = false,
|
|
72
|
-
): BusinessHour[] {
|
|
73
|
-
const fulfillmentBusinessHours: Record<
|
|
74
|
-
string,
|
|
75
|
-
Array<{ day: number; start_time: string; end_time: string }> | undefined
|
|
76
|
-
> = {
|
|
77
|
-
[FULFILLMENT_TYPES.PICKUP]: location?.pickup_hours,
|
|
78
|
-
[FULFILLMENT_TYPES.DELIVERY]: location?.delivery_hours,
|
|
79
|
-
[FULFILLMENT_TYPES.CURBSIDE]: location?.curbside_hours?.use_pickup_hours
|
|
80
|
-
? location?.pickup_hours
|
|
81
|
-
: location?.curbside_hours?.times,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const cateringBusinessTimings: Partial<
|
|
85
|
-
Record<FulfillmentPreference, { start_time: string; end_time: string }>
|
|
86
|
-
> = {
|
|
87
|
-
[FULFILLMENT_TYPES.PICKUP]: location?.catering?.pickup,
|
|
88
|
-
[FULFILLMENT_TYPES.DELIVERY]: location?.catering?.delivery,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const businessHours = fulfillmentBusinessHours[fulfillmentPreference];
|
|
92
|
-
|
|
93
|
-
const cateringBusinessTiming =
|
|
94
|
-
isCatering && isLocationCateringEnabled(location)
|
|
95
|
-
? cateringBusinessTimings[fulfillmentPreference]
|
|
96
|
-
: null;
|
|
97
|
-
|
|
98
|
-
if (isCatering && !cateringBusinessTiming) {
|
|
99
|
-
//if catering is enabled but no business hours are set, return empty arrayif
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
businessHours?.map((businessHour) => {
|
|
105
|
-
if (isCatering && cateringBusinessTiming) {
|
|
106
|
-
//if catering is enabled and catering business hours are set, return catering business hours
|
|
107
|
-
return {
|
|
108
|
-
day: businessHour.day,
|
|
109
|
-
startTime: cateringBusinessTiming.start_time,
|
|
110
|
-
endTime: cateringBusinessTiming.end_time,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
day: businessHour.day,
|
|
115
|
-
startTime: businessHour.start_time,
|
|
116
|
-
endTime: businessHour.end_time,
|
|
117
|
-
};
|
|
118
|
-
}) ?? []
|
|
119
|
-
);
|
|
120
|
-
}
|
package/src/utils/catering.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { findTimeZone, getZonedTime } from "timezone-support";
|
|
2
|
-
import { DEFAULT_TIMEZONE, PREP_TIME_CADENCE } from "../constants";
|
|
3
|
-
import type {
|
|
4
|
-
CateringPrepTimeResult,
|
|
5
|
-
GetCateringPrepTimeParams,
|
|
6
|
-
} from "../types";
|
|
7
|
-
|
|
8
|
-
function buildCateringPrepTimeResult(
|
|
9
|
-
prepTimeCadence: CateringPrepTimeResult["prepTimeCadence"],
|
|
10
|
-
prepTimeFrequency: number,
|
|
11
|
-
timezone: string = DEFAULT_TIMEZONE,
|
|
12
|
-
): CateringPrepTimeResult {
|
|
13
|
-
const result: CateringPrepTimeResult = {
|
|
14
|
-
prepTimeCadence,
|
|
15
|
-
prepTimeFrequency,
|
|
16
|
-
};
|
|
17
|
-
if (prepTimeCadence === PREP_TIME_CADENCE.DAY) {
|
|
18
|
-
result.weekDayPrepTimes = {};
|
|
19
|
-
} else {
|
|
20
|
-
result.weekDayPrepTimes = {
|
|
21
|
-
[getZonedTime(new Date(), findTimeZone(timezone)).dayOfWeek]:
|
|
22
|
-
prepTimeCadence === PREP_TIME_CADENCE.HOUR
|
|
23
|
-
? prepTimeFrequency * 60
|
|
24
|
-
: prepTimeFrequency,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Derives prep time config (cadence, frequency, weekDayPrepTimes) from cart items for catering flow.
|
|
32
|
-
* DAY cadence has priority; if any item uses days, returns max day frequency.
|
|
33
|
-
* Otherwise returns HOUR cadence with max hour frequency across items.
|
|
34
|
-
* When items are empty or have no catering prep time, falls back to params (e.g. from prepTimeSettings).
|
|
35
|
-
*/
|
|
36
|
-
export function getCateringPrepTimeConfig(
|
|
37
|
-
params: GetCateringPrepTimeParams,
|
|
38
|
-
): CateringPrepTimeResult {
|
|
39
|
-
const { items, timezone = DEFAULT_TIMEZONE } = params;
|
|
40
|
-
|
|
41
|
-
if (items.length === 0) {
|
|
42
|
-
return buildCateringPrepTimeResult(
|
|
43
|
-
params.prepTimeCadence ?? PREP_TIME_CADENCE.HOUR,
|
|
44
|
-
params.prepTimeFrequency ?? 1,
|
|
45
|
-
timezone,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const dayFrequencies: number[] = [];
|
|
50
|
-
const hourFrequencies: number[] = [];
|
|
51
|
-
|
|
52
|
-
for (const item of items) {
|
|
53
|
-
const cadence = item.cateringService?.prep_time?.cadence;
|
|
54
|
-
const frequency = item.cateringService?.prep_time?.frequency;
|
|
55
|
-
if (cadence == null || frequency == null) continue;
|
|
56
|
-
|
|
57
|
-
if (cadence === PREP_TIME_CADENCE.DAY) {
|
|
58
|
-
dayFrequencies.push(frequency);
|
|
59
|
-
} else if (cadence === PREP_TIME_CADENCE.HOUR) {
|
|
60
|
-
hourFrequencies.push(frequency);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (dayFrequencies.length > 0) {
|
|
65
|
-
return buildCateringPrepTimeResult(
|
|
66
|
-
PREP_TIME_CADENCE.DAY,
|
|
67
|
-
Math.max(...dayFrequencies),
|
|
68
|
-
timezone,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (hourFrequencies.length > 0) {
|
|
73
|
-
return buildCateringPrepTimeResult(
|
|
74
|
-
PREP_TIME_CADENCE.HOUR,
|
|
75
|
-
Math.max(...hourFrequencies),
|
|
76
|
-
timezone,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return buildCateringPrepTimeResult(
|
|
81
|
-
params.prepTimeCadence ?? PREP_TIME_CADENCE.HOUR,
|
|
82
|
-
params.prepTimeFrequency ?? 1,
|
|
83
|
-
timezone,
|
|
84
|
-
);
|
|
85
|
-
}
|
package/src/utils/date.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { addDays, compareAsc } from "date-fns";
|
|
2
|
-
import { findTimeZone, getUnixTime, getZonedTime } from "timezone-support";
|
|
3
|
-
|
|
4
|
-
import type { BusinessHour } from "../types";
|
|
5
|
-
|
|
6
|
-
export function setHmOnDate(date: Date, hm: string, timeZone: string): Date {
|
|
7
|
-
const [hours, minutes] = String(hm).split(":");
|
|
8
|
-
|
|
9
|
-
const zonedTime = getZonedTime(new Date(date), findTimeZone(timeZone));
|
|
10
|
-
|
|
11
|
-
return new Date(
|
|
12
|
-
getUnixTime({
|
|
13
|
-
zone: zonedTime.zone,
|
|
14
|
-
year: zonedTime.year,
|
|
15
|
-
month: zonedTime.month,
|
|
16
|
-
day: zonedTime.day,
|
|
17
|
-
hours: hours === "24" ? 23 : Number(hours),
|
|
18
|
-
minutes: hours === "24" ? 59 : Number(minutes),
|
|
19
|
-
seconds: 0,
|
|
20
|
-
milliseconds: 0,
|
|
21
|
-
}),
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getNextDateForDayOfWeek(
|
|
26
|
-
targetDayIndex: number,
|
|
27
|
-
referenceDate: Date = new Date(),
|
|
28
|
-
): Date {
|
|
29
|
-
const currentDayIndex = referenceDate.getDay();
|
|
30
|
-
const daysUntilTarget = (targetDayIndex - currentDayIndex + 7) % 7;
|
|
31
|
-
return addDays(referenceDate, daysUntilTarget);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function getPreSalePickupDates(
|
|
35
|
-
preSalePickupDays: number[] = [],
|
|
36
|
-
preSaleOrderingDays: number[] = [],
|
|
37
|
-
): Date[] {
|
|
38
|
-
const today = new Date();
|
|
39
|
-
const currentDayIndex = today.getDay();
|
|
40
|
-
|
|
41
|
-
if (preSalePickupDays.includes(currentDayIndex)) {
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!preSaleOrderingDays.includes(currentDayIndex)) {
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return preSalePickupDays
|
|
50
|
-
.map((day) => getNextDateForDayOfWeek(day))
|
|
51
|
-
.sort(compareAsc);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function overrideTimeZoneOnUTC(
|
|
55
|
-
date: Date | string,
|
|
56
|
-
timeZoneB: string,
|
|
57
|
-
): Date {
|
|
58
|
-
const timeZoneATime = getZonedTime(new Date(date), findTimeZone("UTC"));
|
|
59
|
-
const timeZoneBTime = getZonedTime(new Date(date), findTimeZone(timeZoneB));
|
|
60
|
-
|
|
61
|
-
return new Date(
|
|
62
|
-
getUnixTime({
|
|
63
|
-
...timeZoneATime,
|
|
64
|
-
zone: timeZoneBTime.zone,
|
|
65
|
-
}),
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function isTodayInTimeZone(date: Date, timeZone: string): boolean {
|
|
70
|
-
if (!date) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
const zonedNow = getZonedTime(Date.now(), findTimeZone(timeZone));
|
|
74
|
-
const zonedTime = getZonedTime(date, findTimeZone(timeZone));
|
|
75
|
-
|
|
76
|
-
return zonedNow.day === zonedTime.day && zonedNow.month === zonedTime.month;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function isTomorrowInTimeZone(date: Date, timeZone: string): boolean {
|
|
80
|
-
const zonedNow = getZonedTime(addDays(Date.now(), 1), findTimeZone(timeZone));
|
|
81
|
-
const zonedTime = getZonedTime(date, findTimeZone(timeZone));
|
|
82
|
-
|
|
83
|
-
return zonedNow.day === zonedTime.day && zonedNow.month === zonedTime.month;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function isSameDateInTimeZone(
|
|
87
|
-
dateLeft: Date,
|
|
88
|
-
dateRight: Date,
|
|
89
|
-
timeZone: string,
|
|
90
|
-
): boolean {
|
|
91
|
-
const zonedDateLeft = getZonedTime(dateLeft, findTimeZone(timeZone));
|
|
92
|
-
const zonedDateRight = getZonedTime(dateRight, findTimeZone(timeZone));
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
zonedDateLeft.year === zonedDateRight.year &&
|
|
96
|
-
zonedDateLeft.month === zonedDateRight.month &&
|
|
97
|
-
zonedDateLeft.day === zonedDateRight.day
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function isMidnightTransition(
|
|
102
|
-
endDate: Date,
|
|
103
|
-
startDateNextDay: Date,
|
|
104
|
-
timeZone: string,
|
|
105
|
-
): boolean {
|
|
106
|
-
if (!endDate || !startDateNextDay) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
const zonedEndDate = getZonedTime(endDate, findTimeZone(timeZone));
|
|
110
|
-
const zonedStartDate = getZonedTime(startDateNextDay, findTimeZone(timeZone));
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
zonedEndDate.hours === 23 &&
|
|
114
|
-
zonedEndDate.minutes === 59 &&
|
|
115
|
-
zonedStartDate.hours === 0 &&
|
|
116
|
-
zonedStartDate.minutes === 0
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function addDaysInTimeZone(
|
|
121
|
-
date: Date,
|
|
122
|
-
days: number,
|
|
123
|
-
timeZone: string,
|
|
124
|
-
): Date {
|
|
125
|
-
const zonedTime = getZonedTime(addDays(date, days), findTimeZone(timeZone));
|
|
126
|
-
return new Date(
|
|
127
|
-
getUnixTime({
|
|
128
|
-
...zonedTime,
|
|
129
|
-
hours: 0,
|
|
130
|
-
minutes: 0,
|
|
131
|
-
seconds: 0,
|
|
132
|
-
milliseconds: 0,
|
|
133
|
-
}),
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function isZeroPrepTimeForMidnightShift({
|
|
138
|
-
prevDayBusinessHours,
|
|
139
|
-
businessHour,
|
|
140
|
-
}: {
|
|
141
|
-
prevDayBusinessHours: BusinessHour[];
|
|
142
|
-
businessHour: BusinessHour;
|
|
143
|
-
}): boolean {
|
|
144
|
-
if (
|
|
145
|
-
!Array.isArray(prevDayBusinessHours) ||
|
|
146
|
-
prevDayBusinessHours.length === 0
|
|
147
|
-
) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (!businessHour || businessHour.startTime !== "00:00") {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const currentDay = businessHour.day;
|
|
156
|
-
const prevDay = (currentDay + 6) % 7;
|
|
157
|
-
|
|
158
|
-
const prevDayHas24End = prevDayBusinessHours.some(
|
|
159
|
-
(bh) =>
|
|
160
|
-
bh.day === prevDay && (bh.endTime === "24:00" || bh.endTime === "23:59"),
|
|
161
|
-
);
|
|
162
|
-
return prevDayHas24End;
|
|
163
|
-
}
|