@wix/headless-restaurants-olo 0.0.32 → 0.0.34
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/cjs/dist/react/FulfillmentDetails.d.ts +139 -15
- package/cjs/dist/react/FulfillmentDetails.js +128 -24
- package/cjs/dist/react/Settings.d.ts +8 -0
- package/cjs/dist/react/Settings.js +18 -25
- package/cjs/dist/react/core/FulfillmentDetails.d.ts +73 -7
- package/cjs/dist/react/core/FulfillmentDetails.js +133 -86
- package/cjs/dist/react/core/ItemDetails.js +2 -13
- package/cjs/dist/react/core/Settings.d.ts +19 -4
- package/cjs/dist/react/core/Settings.js +29 -20
- package/cjs/dist/services/fulfillment-details-service.d.ts +127 -0
- package/cjs/dist/services/fulfillment-details-service.js +351 -0
- package/cjs/dist/services/fulfillments-service.js +67 -43
- package/cjs/dist/services/index.d.ts +2 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/olo-settings-service.d.ts +0 -1
- package/cjs/dist/services/olo-settings-service.js +1 -3
- package/cjs/dist/types/fulfillments-types.d.ts +18 -1
- package/cjs/dist/types/fulfillments-types.js +9 -0
- package/cjs/dist/utils/date-utils.d.ts +164 -0
- package/cjs/dist/utils/date-utils.js +297 -0
- package/cjs/dist/utils/fulfillments-utils.d.ts +3 -2
- package/cjs/dist/utils/fulfillments-utils.js +13 -57
- package/dist/react/FulfillmentDetails.d.ts +139 -15
- package/dist/react/FulfillmentDetails.js +128 -24
- package/dist/react/Settings.d.ts +8 -0
- package/dist/react/Settings.js +18 -25
- package/dist/react/core/FulfillmentDetails.d.ts +73 -7
- package/dist/react/core/FulfillmentDetails.js +133 -86
- package/dist/react/core/ItemDetails.js +2 -13
- package/dist/react/core/Settings.d.ts +19 -4
- package/dist/react/core/Settings.js +29 -20
- package/dist/services/fulfillment-details-service.d.ts +127 -0
- package/dist/services/fulfillment-details-service.js +351 -0
- package/dist/services/fulfillments-service.js +67 -43
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +1 -0
- package/dist/services/olo-settings-service.d.ts +0 -1
- package/dist/services/olo-settings-service.js +1 -3
- package/dist/types/fulfillments-types.d.ts +18 -1
- package/dist/types/fulfillments-types.js +9 -0
- package/dist/utils/date-utils.d.ts +164 -0
- package/dist/utils/date-utils.js +297 -0
- package/dist/utils/fulfillments-utils.d.ts +3 -2
- package/dist/utils/fulfillments-utils.js +13 -57
- package/package.json +4 -3
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { type FulfillmentDetailsServiceConfig } from '../../services/fulfillment-details-service.js';
|
|
3
|
+
import { DispatchType, FulfillmentTypeEnum } from '../../types/fulfillments-types.js';
|
|
3
4
|
export interface RootProps {
|
|
4
5
|
children: React.ReactNode;
|
|
6
|
+
fulfillmentDetailsServiceConfig?: FulfillmentDetailsServiceConfig;
|
|
5
7
|
}
|
|
6
8
|
/**
|
|
7
9
|
* Root component for FulfillmentDetails
|
|
8
10
|
* Provides context for all fulfillment detail sub-components
|
|
11
|
+
* Adds FulfillmentDetailsService to the services map after FulfillmentsService is loaded
|
|
9
12
|
*/
|
|
10
13
|
export declare const Root: React.FC<RootProps>;
|
|
11
14
|
export interface AddressNameProps {
|
|
@@ -56,18 +59,18 @@ export interface AvailableTimeSlotsProps {
|
|
|
56
59
|
* Shows time ranges when the order can be fulfilled
|
|
57
60
|
*/
|
|
58
61
|
export declare const AvailableTimeSlots: React.FC<AvailableTimeSlotsProps>;
|
|
59
|
-
export declare enum FulfillmentTypeEnum {
|
|
60
|
-
ASAP = "ASAP",
|
|
61
|
-
PREORDER = "PREORDER",
|
|
62
|
-
ASAP_AND_FUTURE = "ASAP_AND_FUTURE"
|
|
63
|
-
}
|
|
64
62
|
export interface FulfillmentTypeProps {
|
|
65
63
|
children: (props: {
|
|
66
|
-
selectedType: FulfillmentTypeEnum;
|
|
64
|
+
selectedType: FulfillmentTypeEnum | undefined;
|
|
67
65
|
onTypeChange: (type: FulfillmentTypeEnum) => void;
|
|
68
66
|
hasAsapOption: boolean;
|
|
69
67
|
hasPreorderOption: boolean;
|
|
70
68
|
hasAsapAndFutureOption: boolean;
|
|
69
|
+
asapTime: number | undefined;
|
|
70
|
+
asapTimeRange: {
|
|
71
|
+
minDuration?: number;
|
|
72
|
+
maxDuration?: number;
|
|
73
|
+
} | undefined;
|
|
71
74
|
}) => React.ReactNode;
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
@@ -76,3 +79,66 @@ export interface FulfillmentTypeProps {
|
|
|
76
79
|
* Pre-order: Order will be fulfilled at a scheduled time
|
|
77
80
|
*/
|
|
78
81
|
export declare const FulfillmentType: React.FC<FulfillmentTypeProps>;
|
|
82
|
+
/**
|
|
83
|
+
* Address fields that can be updated
|
|
84
|
+
*/
|
|
85
|
+
export interface DeliveryAddressFields {
|
|
86
|
+
/** Street address line 1 */
|
|
87
|
+
addressLine?: string;
|
|
88
|
+
/** Street address line 2 (apartment, suite, etc.) */
|
|
89
|
+
addressLine2?: string;
|
|
90
|
+
/** City */
|
|
91
|
+
city?: string;
|
|
92
|
+
/** State/Province/Subdivision */
|
|
93
|
+
subdivision?: string;
|
|
94
|
+
/** Postal/ZIP code */
|
|
95
|
+
postalCode?: string;
|
|
96
|
+
/** Country */
|
|
97
|
+
country?: string;
|
|
98
|
+
/** Formatted full address string */
|
|
99
|
+
formattedAddress?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface DeliveryAddressProps {
|
|
102
|
+
children: (props: {
|
|
103
|
+
/** Current address fields */
|
|
104
|
+
address: DeliveryAddressFields | null;
|
|
105
|
+
/** Whether there is a current address */
|
|
106
|
+
hasAddress: boolean;
|
|
107
|
+
/** Current dispatch type */
|
|
108
|
+
dispatchType: DispatchType | null;
|
|
109
|
+
/** Whether delivery is selected */
|
|
110
|
+
isDelivery: boolean;
|
|
111
|
+
/** Update the delivery address */
|
|
112
|
+
onAddressChange: (address: DeliveryAddressFields) => void;
|
|
113
|
+
/** Clear the delivery address */
|
|
114
|
+
onAddressClear: () => void;
|
|
115
|
+
}) => React.ReactNode;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Component that provides delivery address editing functionality
|
|
119
|
+
* Only renders content when dispatch type is DELIVERY
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```tsx
|
|
123
|
+
* <CoreFulfillmentDetails.DeliveryAddress>
|
|
124
|
+
* {({ address, hasAddress, isDelivery, onAddressChange, onAddressClear }) => (
|
|
125
|
+
* isDelivery && (
|
|
126
|
+
* <div>
|
|
127
|
+
* <input
|
|
128
|
+
* value={address?.addressLine || ''}
|
|
129
|
+
* onChange={(e) => onAddressChange({ ...address, addressLine: e.target.value })}
|
|
130
|
+
* placeholder="Street Address"
|
|
131
|
+
* />
|
|
132
|
+
* <input
|
|
133
|
+
* value={address?.city || ''}
|
|
134
|
+
* onChange={(e) => onAddressChange({ ...address, city: e.target.value })}
|
|
135
|
+
* placeholder="City"
|
|
136
|
+
* />
|
|
137
|
+
* <button onClick={onAddressClear}>Clear</button>
|
|
138
|
+
* </div>
|
|
139
|
+
* )
|
|
140
|
+
* )}
|
|
141
|
+
* </CoreFulfillmentDetails.DeliveryAddress>
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare const DeliveryAddress: React.FC<DeliveryAddressProps>;
|
|
@@ -1,13 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { useService } from '@wix/services-manager-react';
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { WixServices, useService } from '@wix/services-manager-react';
|
|
4
4
|
import { FulfillmentsServiceDefinition } from '../../services/fulfillments-service.js';
|
|
5
|
+
import { FulfillmentDetailsService, FulfillmentDetailsServiceDefinition, loadFulfillmentDetailsServiceConfig, } from '../../services/fulfillment-details-service.js';
|
|
6
|
+
import { OLOSettingsServiceDefinition } from '../../services/olo-settings-service.js';
|
|
7
|
+
import { DispatchType, FulfillmentTypeEnum, } from '../../types/fulfillments-types.js';
|
|
8
|
+
import { createServicesMap } from '@wix/services-manager';
|
|
9
|
+
import { formatTimeRange, getToday, getFutureDate, } from '../../utils/date-utils.js';
|
|
5
10
|
/**
|
|
6
11
|
* Root component for FulfillmentDetails
|
|
7
12
|
* Provides context for all fulfillment detail sub-components
|
|
13
|
+
* Adds FulfillmentDetailsService to the services map after FulfillmentsService is loaded
|
|
8
14
|
*/
|
|
9
|
-
export const Root = ({ children }) => {
|
|
10
|
-
|
|
15
|
+
export const Root = ({ children, fulfillmentDetailsServiceConfig, }) => {
|
|
16
|
+
const oloSettingsService = useService(OLOSettingsServiceDefinition);
|
|
17
|
+
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
18
|
+
const [config, setConfig] = useState(fulfillmentDetailsServiceConfig);
|
|
19
|
+
const isFulfillmentsLoading = fulfillmentsService.isLoading?.get() ?? true;
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!fulfillmentDetailsServiceConfig &&
|
|
22
|
+
oloSettingsService.operation?.get()) {
|
|
23
|
+
const operation = oloSettingsService.operation.get();
|
|
24
|
+
if (operation) {
|
|
25
|
+
const loadedConfig = loadFulfillmentDetailsServiceConfig(operation);
|
|
26
|
+
setConfig(loadedConfig);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}, [fulfillmentDetailsServiceConfig, oloSettingsService.operation]);
|
|
30
|
+
if (!config || isFulfillmentsLoading) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(FulfillmentDetailsServiceDefinition, FulfillmentDetailsService, config), children: children }));
|
|
11
34
|
};
|
|
12
35
|
/**
|
|
13
36
|
* Component that provides the address name for the selected fulfillment
|
|
@@ -15,12 +38,11 @@ export const Root = ({ children }) => {
|
|
|
15
38
|
* For delivery: shows the delivery address
|
|
16
39
|
*/
|
|
17
40
|
export const AddressName = ({ children }) => {
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const addressName = selectedAddress?.formatted ?? null;
|
|
41
|
+
const fulfillmentDetailsService = useService(FulfillmentDetailsServiceDefinition);
|
|
42
|
+
const selectedAddress = fulfillmentDetailsService?.address?.get();
|
|
43
|
+
console.log('selectedAddress', selectedAddress);
|
|
44
|
+
const dispatchType = fulfillmentDetailsService.dispatchType?.get();
|
|
45
|
+
const addressName = selectedAddress?.formatted;
|
|
24
46
|
const fullAddress = selectedAddress
|
|
25
47
|
? [
|
|
26
48
|
// @ts-expect-error - selectedAddress is not typed
|
|
@@ -49,30 +71,23 @@ export const AddressName = ({ children }) => {
|
|
|
49
71
|
*/
|
|
50
72
|
export const FulfillmentDate = ({ children, }) => {
|
|
51
73
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (slotsForDate.length > 0) {
|
|
66
|
-
fulfillmentsService.setSelectedTimeSlot(slotsForDate[0]);
|
|
67
|
-
}
|
|
74
|
+
const hasAsapOption = fulfillmentsService.hasAsapOption?.get();
|
|
75
|
+
const hasAsapAndFutureOption = fulfillmentsService.hasAsapAndFutureOption?.get();
|
|
76
|
+
if (hasAsapOption && !hasAsapAndFutureOption) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const fulfillmentDetailsService = useService(FulfillmentDetailsServiceDefinition);
|
|
80
|
+
if (fulfillmentDetailsService?.schedulingType.get() === FulfillmentTypeEnum.ASAP) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const selectedDate = fulfillmentDetailsService.date?.get();
|
|
84
|
+
const availableDates = fulfillmentDetailsService.availableDates?.get() ?? [];
|
|
85
|
+
const onDateChange = async (date) => {
|
|
86
|
+
await fulfillmentDetailsService.setDate(date);
|
|
68
87
|
};
|
|
69
|
-
//
|
|
70
|
-
const minDate =
|
|
71
|
-
|
|
72
|
-
// Set max date to 30 days from now (reasonable booking window)
|
|
73
|
-
const maxDate = new Date();
|
|
74
|
-
maxDate.setDate(maxDate.getDate() + 30);
|
|
75
|
-
maxDate.setHours(23, 59, 59, 999);
|
|
88
|
+
// Calculate min/max dates from available dates if available, otherwise use defaults
|
|
89
|
+
const minDate = availableDates[0]?.date ?? getToday();
|
|
90
|
+
const maxDate = availableDates[availableDates.length - 1]?.date ?? getFutureDate(30);
|
|
76
91
|
return children({
|
|
77
92
|
selectedDate,
|
|
78
93
|
onDateChange,
|
|
@@ -86,24 +101,20 @@ export const FulfillmentDate = ({ children, }) => {
|
|
|
86
101
|
*/
|
|
87
102
|
export const AvailableTimeSlots = ({ children, }) => {
|
|
88
103
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return `${start} - ${end}`;
|
|
101
|
-
};
|
|
104
|
+
const hasAsapOption = fulfillmentsService.hasAsapOption?.get();
|
|
105
|
+
const hasAsapAndFutureOption = fulfillmentsService.hasAsapAndFutureOption?.get();
|
|
106
|
+
if (hasAsapOption && !hasAsapAndFutureOption) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const fulfillmentDetailsService = useService(FulfillmentDetailsServiceDefinition);
|
|
110
|
+
if (fulfillmentDetailsService?.schedulingType.get() === FulfillmentTypeEnum.ASAP) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const timeSlots = fulfillmentDetailsService.availableTimeSlots?.get() ?? [];
|
|
114
|
+
const selectedTimeSlot = fulfillmentDetailsService.timeslot?.get();
|
|
102
115
|
const timeSlotOptions = timeSlots.map((slot) => ({
|
|
103
116
|
id: slot.id,
|
|
104
|
-
label: slot.
|
|
105
|
-
? 'ASAP'
|
|
106
|
-
: formatTimeRange(slot.startTime, slot.endTime),
|
|
117
|
+
label: formatTimeRange(slot.startTime, slot.endTime),
|
|
107
118
|
startTime: slot.startTime,
|
|
108
119
|
endTime: slot.endTime,
|
|
109
120
|
dispatchType: slot.dispatchType,
|
|
@@ -112,7 +123,7 @@ export const AvailableTimeSlots = ({ children, }) => {
|
|
|
112
123
|
const onTimeSlotChange = (timeSlotId) => {
|
|
113
124
|
const timeSlot = timeSlots.find((slot) => slot.id === timeSlotId);
|
|
114
125
|
if (timeSlot) {
|
|
115
|
-
|
|
126
|
+
fulfillmentDetailsService.setTimeslot(timeSlot);
|
|
116
127
|
}
|
|
117
128
|
};
|
|
118
129
|
const hasTimeSlots = timeSlotOptions.length > 0;
|
|
@@ -124,15 +135,6 @@ export const AvailableTimeSlots = ({ children, }) => {
|
|
|
124
135
|
hasTimeSlots,
|
|
125
136
|
});
|
|
126
137
|
};
|
|
127
|
-
// ========================================
|
|
128
|
-
// FULFILLMENT TYPE COMPONENT
|
|
129
|
-
// ========================================
|
|
130
|
-
export var FulfillmentTypeEnum;
|
|
131
|
-
(function (FulfillmentTypeEnum) {
|
|
132
|
-
FulfillmentTypeEnum["ASAP"] = "ASAP";
|
|
133
|
-
FulfillmentTypeEnum["PREORDER"] = "PREORDER";
|
|
134
|
-
FulfillmentTypeEnum["ASAP_AND_FUTURE"] = "ASAP_AND_FUTURE";
|
|
135
|
-
})(FulfillmentTypeEnum || (FulfillmentTypeEnum = {}));
|
|
136
138
|
/**
|
|
137
139
|
* Component that provides fulfillment type selection (ASAP or Pre-order)
|
|
138
140
|
* ASAP: Order will be fulfilled as soon as possible
|
|
@@ -140,38 +142,83 @@ export var FulfillmentTypeEnum;
|
|
|
140
142
|
*/
|
|
141
143
|
export const FulfillmentType = ({ children, }) => {
|
|
142
144
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
const hasAsapOption =
|
|
146
|
-
const hasPreorderOption =
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
145
|
+
const fulfillmentDetailsService = useService(FulfillmentDetailsServiceDefinition);
|
|
146
|
+
// Get fulfillment type options from service
|
|
147
|
+
const hasAsapOption = fulfillmentsService.hasAsapOption?.get();
|
|
148
|
+
const hasPreorderOption = fulfillmentsService.hasPreorderOption?.get();
|
|
149
|
+
const hasAsapAndFutureOption = fulfillmentsService.hasAsapAndFutureOption?.get();
|
|
150
|
+
const asapTime = fulfillmentsService.asapTimeSignal?.get();
|
|
151
|
+
const asapTimeRange = fulfillmentsService.asapTimeRangeSignal?.get();
|
|
152
|
+
const selectedType = fulfillmentDetailsService.schedulingType?.get();
|
|
151
153
|
const onTypeChange = (type) => {
|
|
152
|
-
|
|
153
|
-
setSelectedType(type);
|
|
154
|
-
// Find appropriate time slot based on type
|
|
155
|
-
const targetSlot = timeSlots.find((slot) => {
|
|
156
|
-
if (type === FulfillmentTypeEnum.ASAP) {
|
|
157
|
-
return slot.startsNow;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
return !slot.startsNow;
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
if (targetSlot) {
|
|
164
|
-
fulfillmentsService.setSelectedTimeSlot(targetSlot);
|
|
165
|
-
}
|
|
154
|
+
fulfillmentDetailsService.setSchedulingType(type);
|
|
166
155
|
};
|
|
167
|
-
console.log('selectedType', selectedType);
|
|
168
|
-
console.log('hasAsapOption', hasAsapOption);
|
|
169
|
-
console.log('hasPreorderOption', hasPreorderOption);
|
|
170
156
|
return children({
|
|
171
157
|
selectedType,
|
|
172
158
|
onTypeChange,
|
|
173
159
|
hasAsapOption,
|
|
174
160
|
hasPreorderOption,
|
|
175
|
-
hasAsapAndFutureOption
|
|
161
|
+
hasAsapAndFutureOption,
|
|
162
|
+
asapTime,
|
|
163
|
+
asapTimeRange,
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Component that provides delivery address editing functionality
|
|
168
|
+
* Only renders content when dispatch type is DELIVERY
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* <CoreFulfillmentDetails.DeliveryAddress>
|
|
173
|
+
* {({ address, hasAddress, isDelivery, onAddressChange, onAddressClear }) => (
|
|
174
|
+
* isDelivery && (
|
|
175
|
+
* <div>
|
|
176
|
+
* <input
|
|
177
|
+
* value={address?.addressLine || ''}
|
|
178
|
+
* onChange={(e) => onAddressChange({ ...address, addressLine: e.target.value })}
|
|
179
|
+
* placeholder="Street Address"
|
|
180
|
+
* />
|
|
181
|
+
* <input
|
|
182
|
+
* value={address?.city || ''}
|
|
183
|
+
* onChange={(e) => onAddressChange({ ...address, city: e.target.value })}
|
|
184
|
+
* placeholder="City"
|
|
185
|
+
* />
|
|
186
|
+
* <button onClick={onAddressClear}>Clear</button>
|
|
187
|
+
* </div>
|
|
188
|
+
* )
|
|
189
|
+
* )}
|
|
190
|
+
* </CoreFulfillmentDetails.DeliveryAddress>
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export const DeliveryAddress = ({ children, }) => {
|
|
194
|
+
const fulfillmentDetailsService = useService(FulfillmentDetailsServiceDefinition);
|
|
195
|
+
const currentAddress = fulfillmentDetailsService?.address?.get();
|
|
196
|
+
const dispatchType = fulfillmentDetailsService.dispatchType?.get();
|
|
197
|
+
const isDelivery = dispatchType === DispatchType.DELIVERY;
|
|
198
|
+
const address = currentAddress
|
|
199
|
+
? {
|
|
200
|
+
addressLine: currentAddress.addressLine,
|
|
201
|
+
addressLine2: currentAddress.addressLine2,
|
|
202
|
+
city: currentAddress.city,
|
|
203
|
+
subdivision: currentAddress.subdivision,
|
|
204
|
+
postalCode: currentAddress.postalCode,
|
|
205
|
+
country: currentAddress.country,
|
|
206
|
+
formattedAddress: currentAddress.formattedAddress,
|
|
207
|
+
}
|
|
208
|
+
: null;
|
|
209
|
+
const hasAddress = Boolean(currentAddress);
|
|
210
|
+
const onAddressChange = (newAddress) => {
|
|
211
|
+
fulfillmentDetailsService.setAddress(newAddress);
|
|
212
|
+
};
|
|
213
|
+
const onAddressClear = () => {
|
|
214
|
+
fulfillmentDetailsService.setAddress(null);
|
|
215
|
+
};
|
|
216
|
+
return children({
|
|
217
|
+
address,
|
|
218
|
+
hasAddress,
|
|
219
|
+
dispatchType,
|
|
220
|
+
isDelivery,
|
|
221
|
+
onAddressChange,
|
|
222
|
+
onAddressClear,
|
|
176
223
|
});
|
|
177
224
|
};
|
|
@@ -2,24 +2,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { useService, WixServices } from '@wix/services-manager-react';
|
|
4
4
|
import { createServicesMap } from '@wix/services-manager';
|
|
5
|
-
import { ItemService, ItemServiceDefinition,
|
|
5
|
+
import { ItemService, ItemServiceDefinition, } from '../../services/item-details-service.js';
|
|
6
6
|
import { OLOSettingsServiceDefinition } from '../../services/olo-settings-service.js';
|
|
7
7
|
import { useItemContext } from '@wix/headless-restaurants-menus/react';
|
|
8
8
|
import { AvailabilityStatus, AddToCartButtonState, } from '../../services/common-types.js';
|
|
9
9
|
import { getAvailabilityText } from '../../services/utils.js';
|
|
10
10
|
export const Root = ({ children, itemDetailsServiceConfig, }) => {
|
|
11
|
-
|
|
12
|
-
const selectedItem = service.selectedItem?.get();
|
|
13
|
-
const config = itemDetailsServiceConfig ??
|
|
14
|
-
loadItemServiceConfig({
|
|
15
|
-
item: selectedItem,
|
|
16
|
-
// @ts-expect-error - operation is not typed
|
|
17
|
-
operationId: service.operation?.get()?.id ?? '',
|
|
18
|
-
});
|
|
19
|
-
if (config.item) {
|
|
20
|
-
service.selectedItem?.set(config.item);
|
|
21
|
-
}
|
|
22
|
-
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ItemServiceDefinition, ItemService, config), children: children({ item: itemDetailsServiceConfig?.item ?? selectedItem }) }));
|
|
11
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ItemServiceDefinition, ItemService, itemDetailsServiceConfig), children: children({ item: itemDetailsServiceConfig?.item }) }));
|
|
23
12
|
};
|
|
24
13
|
export const SpecialRequest = ({ children, }) => {
|
|
25
14
|
const service = useService(ItemServiceDefinition);
|
|
@@ -12,15 +12,30 @@ export interface RootProps {
|
|
|
12
12
|
* Core Settings Root component that provides service context
|
|
13
13
|
* Wraps children with both OLOSettingsService and FulfillmentsService providers
|
|
14
14
|
*
|
|
15
|
+
* Note: Use loadFulfillmentsServiceConfig from '@wix/headless-restaurants-olo/services'
|
|
16
|
+
* to load the config before rendering this component.
|
|
17
|
+
*
|
|
15
18
|
* @example
|
|
16
19
|
* ```tsx
|
|
17
|
-
*
|
|
18
|
-
*
|
|
20
|
+
* import { loadFulfillmentsServiceConfig, OLOSettingsServiceDefinition } from '@wix/headless-restaurants-olo/services';
|
|
21
|
+
*
|
|
22
|
+
* // In your component:
|
|
23
|
+
* const service = useService(OLOSettingsServiceDefinition);
|
|
24
|
+
* const [config, setConfig] = useState(null);
|
|
25
|
+
*
|
|
26
|
+
* useEffect(() => {
|
|
27
|
+
* loadFulfillmentsServiceConfig(service.operation?.get()).then(setConfig);
|
|
28
|
+
* }, []);
|
|
29
|
+
*
|
|
30
|
+
* if (!config) return <div>Loading...</div>;
|
|
31
|
+
*
|
|
32
|
+
* <Settings.Root fulfillmentsServiceConfig={config}>
|
|
33
|
+
* <Settings.CurrentTimeSlot>
|
|
19
34
|
* {({ timeSlot, hasDetails }) => (
|
|
20
35
|
* <div>{timeSlot?.dispatchType}</div>
|
|
21
36
|
* )}
|
|
22
|
-
* </
|
|
23
|
-
* </
|
|
37
|
+
* </Settings.CurrentTimeSlot>
|
|
38
|
+
* </Settings.Root>
|
|
24
39
|
* ```
|
|
25
40
|
*/
|
|
26
41
|
export declare const Root: React.FC<RootProps>;
|
|
@@ -1,39 +1,43 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
2
|
import { WixServices, useService } from '@wix/services-manager-react';
|
|
4
3
|
import { OLOSettingsServiceDefinition } from '../../services/olo-settings-service.js';
|
|
5
|
-
import { FulfillmentsService, FulfillmentsServiceDefinition,
|
|
4
|
+
import { FulfillmentsService, FulfillmentsServiceDefinition, } from '../../services/fulfillments-service.js';
|
|
6
5
|
import { createServicesMap } from '@wix/services-manager';
|
|
7
6
|
/**
|
|
8
7
|
* Core Settings Root component that provides service context
|
|
9
8
|
* Wraps children with both OLOSettingsService and FulfillmentsService providers
|
|
10
9
|
*
|
|
10
|
+
* Note: Use loadFulfillmentsServiceConfig from '@wix/headless-restaurants-olo/services'
|
|
11
|
+
* to load the config before rendering this component.
|
|
12
|
+
*
|
|
11
13
|
* @example
|
|
12
14
|
* ```tsx
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* import { loadFulfillmentsServiceConfig, OLOSettingsServiceDefinition } from '@wix/headless-restaurants-olo/services';
|
|
16
|
+
*
|
|
17
|
+
* // In your component:
|
|
18
|
+
* const service = useService(OLOSettingsServiceDefinition);
|
|
19
|
+
* const [config, setConfig] = useState(null);
|
|
20
|
+
*
|
|
21
|
+
* useEffect(() => {
|
|
22
|
+
* loadFulfillmentsServiceConfig(service.operation?.get()).then(setConfig);
|
|
23
|
+
* }, []);
|
|
24
|
+
*
|
|
25
|
+
* if (!config) return <div>Loading...</div>;
|
|
26
|
+
*
|
|
27
|
+
* <Settings.Root fulfillmentsServiceConfig={config}>
|
|
28
|
+
* <Settings.CurrentTimeSlot>
|
|
15
29
|
* {({ timeSlot, hasDetails }) => (
|
|
16
30
|
* <div>{timeSlot?.dispatchType}</div>
|
|
17
31
|
* )}
|
|
18
|
-
* </
|
|
19
|
-
* </
|
|
32
|
+
* </Settings.CurrentTimeSlot>
|
|
33
|
+
* </Settings.Root>
|
|
20
34
|
* ```
|
|
21
35
|
*/
|
|
22
36
|
export const Root = ({ children, fulfillmentsServiceConfig, }) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (!fulfillmentsServiceConfig) {
|
|
27
|
-
loadFulfillmentsServiceConfig(service.operation?.get()).then((loadedConfig) => {
|
|
28
|
-
setConfig(loadedConfig);
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}, [fulfillmentsServiceConfig]);
|
|
32
|
-
service.isLoading.set(!config);
|
|
33
|
-
if (!config) {
|
|
34
|
-
return children({ isLoading: !config });
|
|
37
|
+
if (!fulfillmentsServiceConfig) {
|
|
38
|
+
return children({ isLoading: true });
|
|
35
39
|
}
|
|
36
|
-
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(FulfillmentsServiceDefinition, FulfillmentsService,
|
|
40
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(FulfillmentsServiceDefinition, FulfillmentsService, fulfillmentsServiceConfig), children: children({ isLoading: false }) }));
|
|
37
41
|
};
|
|
38
42
|
/**
|
|
39
43
|
* Component that provides access to current time slot
|
|
@@ -160,6 +164,10 @@ export const MinOrderAmount = ({ children }) => {
|
|
|
160
164
|
export const AcceptingOrders = ({ children, }) => {
|
|
161
165
|
const service = useService(OLOSettingsServiceDefinition);
|
|
162
166
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
167
|
+
// Check if FulfillmentsService is available (it won't be during loading)
|
|
168
|
+
if (!fulfillmentsService?.selectedFulfillment) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
163
171
|
const operation = service.operation?.get();
|
|
164
172
|
const selectedFulfillment = fulfillmentsService.selectedFulfillment?.get();
|
|
165
173
|
const acceptingOrders = Boolean(operation?.enabled) && Boolean(selectedFulfillment);
|
|
@@ -184,7 +192,6 @@ export const AcceptingOrders = ({ children, }) => {
|
|
|
184
192
|
export const DeliveryFee = ({ children }) => {
|
|
185
193
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
186
194
|
const selectedDispatchInfo = fulfillmentsService.selectedDispatchInfoSignal?.get();
|
|
187
|
-
console.log('selectedDispatchInfo', selectedDispatchInfo);
|
|
188
195
|
const deliveryFee = selectedDispatchInfo?.deliveryFee ?? undefined;
|
|
189
196
|
const hasDeliveryFee = Boolean(deliveryFee);
|
|
190
197
|
return children({ deliveryFee, hasDeliveryFee });
|
|
@@ -231,6 +238,8 @@ export const FreeDeliveryThreshold = ({ children, }) => {
|
|
|
231
238
|
export const SelectedAddress = ({ children, }) => {
|
|
232
239
|
const fulfillmentsService = useService(FulfillmentsServiceDefinition);
|
|
233
240
|
const selectedDispatchInfo = fulfillmentsService.selectedDispatchInfoSignal?.get();
|
|
241
|
+
const fulfillments = fulfillmentsService.fulfillments?.get() ?? null;
|
|
242
|
+
console.log('fulfillments', fulfillments);
|
|
234
243
|
const selectedAddress = selectedDispatchInfo?.address ?? null;
|
|
235
244
|
const hasAddress = Boolean(selectedAddress);
|
|
236
245
|
const selectedTimeSlot = fulfillmentsService.selectedTimeSlot?.get();
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { type Signal, type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
|
|
2
|
+
import { DispatchType, TimeSlot, FulfillmentTypeEnum } from '../types/fulfillments-types.js';
|
|
3
|
+
import { Operation } from '../types/operation.js';
|
|
4
|
+
import { Address } from '@wix/auto_sdk_restaurants_operations';
|
|
5
|
+
/**
|
|
6
|
+
* Date availability information
|
|
7
|
+
*/
|
|
8
|
+
export interface AvailableDate {
|
|
9
|
+
/** The date that is available */
|
|
10
|
+
date: Date;
|
|
11
|
+
/** Whether this date has available slots */
|
|
12
|
+
hasAvailableSlots: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* API interface for the Fulfillment Details service
|
|
16
|
+
* Provides reactive state management for fulfillment scheduling
|
|
17
|
+
*/
|
|
18
|
+
export interface FulfillmentDetailsServiceAPI {
|
|
19
|
+
/** Currently selected time slot */
|
|
20
|
+
timeslot: Signal<TimeSlot | null>;
|
|
21
|
+
/** Delivery/pickup address */
|
|
22
|
+
address: Signal<Address | null>;
|
|
23
|
+
/** Selected date for fulfillment */
|
|
24
|
+
date: Signal<Date | null>;
|
|
25
|
+
/** Dispatch type (PICKUP or DELIVERY) */
|
|
26
|
+
dispatchType: Signal<DispatchType | null>;
|
|
27
|
+
/** ASAP time slot (when user wants the order as soon as possible) */
|
|
28
|
+
asapTimeSlot: Signal<TimeSlot | null>;
|
|
29
|
+
/** Loading state for async operations */
|
|
30
|
+
isLoading: Signal<boolean>;
|
|
31
|
+
/** Error state */
|
|
32
|
+
error: Signal<string | null>;
|
|
33
|
+
/** Available dates within the configured range */
|
|
34
|
+
availableDates: Signal<AvailableDate[]>;
|
|
35
|
+
/** Available time slots for the selected date */
|
|
36
|
+
availableTimeSlotsForDate: Signal<TimeSlot[]>;
|
|
37
|
+
/** Available time slots filtered by current dispatch type */
|
|
38
|
+
availableTimeSlots: ReadOnlySignal<TimeSlot[]>;
|
|
39
|
+
/** Selected scheduling type (ASAP or PREORDER) */
|
|
40
|
+
schedulingType: Signal<FulfillmentTypeEnum | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Get the currently selected time slot
|
|
43
|
+
* @returns The selected time slot or null
|
|
44
|
+
*/
|
|
45
|
+
getTimeslot: () => TimeSlot | null;
|
|
46
|
+
/**
|
|
47
|
+
* Set the selected time slot
|
|
48
|
+
* @param timeslot - The time slot to select
|
|
49
|
+
*/
|
|
50
|
+
setTimeslot: (timeslot: TimeSlot | null) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Set the delivery/pickup address
|
|
53
|
+
* @param address - The address to set
|
|
54
|
+
*/
|
|
55
|
+
setAddress: (address: Address | null) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Set the selected date for fulfillment
|
|
58
|
+
* Also triggers fetching available time slots for the date
|
|
59
|
+
* @param date - The date to select
|
|
60
|
+
*/
|
|
61
|
+
setDate: (date: Date | null) => Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Set the dispatch type (PICKUP or DELIVERY)
|
|
64
|
+
* @param type - The dispatch type to set
|
|
65
|
+
*/
|
|
66
|
+
setDispatchType: (type: DispatchType | null) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Set the ASAP time slot
|
|
69
|
+
* @param timeslot - The ASAP time slot to set
|
|
70
|
+
*/
|
|
71
|
+
setAsapTimeSlot: (timeslot: TimeSlot | null) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Set the scheduling type (ASAP or PREORDER)
|
|
74
|
+
* Also selects an appropriate time slot based on the type
|
|
75
|
+
* @param type - The scheduling type to set
|
|
76
|
+
*/
|
|
77
|
+
setSchedulingType: (type: FulfillmentTypeEnum | undefined) => void;
|
|
78
|
+
/**
|
|
79
|
+
* Calculate available dates within a date range
|
|
80
|
+
* @param startDate - Start of the date range
|
|
81
|
+
* @param endDate - End of the date range
|
|
82
|
+
* @returns Promise that resolves to available dates
|
|
83
|
+
*/
|
|
84
|
+
calculateAvailableDatesInRange: (startDate: Date, endDate: Date) => Promise<AvailableDate[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Calculate available time slots for a specific date
|
|
87
|
+
* @param date - The date to get time slots for
|
|
88
|
+
* @returns Promise that resolves to available time slots
|
|
89
|
+
*/
|
|
90
|
+
calculateAvailableTimeSlotsForDate: (date: Date) => Promise<TimeSlot[]>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Configuration for the Fulfillment Details service
|
|
94
|
+
*/
|
|
95
|
+
export interface FulfillmentDetailsServiceConfig {
|
|
96
|
+
/** The operation to get fulfillment details for */
|
|
97
|
+
operation?: Operation;
|
|
98
|
+
/** Initial dispatch type */
|
|
99
|
+
initialDispatchType?: DispatchType;
|
|
100
|
+
/** Initial address */
|
|
101
|
+
initialAddress?: Address;
|
|
102
|
+
/** Number of days ahead to calculate available dates (default: 30) */
|
|
103
|
+
daysAhead?: number;
|
|
104
|
+
}
|
|
105
|
+
export declare const FulfillmentDetailsServiceDefinition: string & {
|
|
106
|
+
__api: FulfillmentDetailsServiceAPI;
|
|
107
|
+
__config: {};
|
|
108
|
+
isServiceDefinition?: boolean;
|
|
109
|
+
} & FulfillmentDetailsServiceAPI;
|
|
110
|
+
export declare const FulfillmentDetailsService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
111
|
+
__api: FulfillmentDetailsServiceAPI;
|
|
112
|
+
__config: {};
|
|
113
|
+
isServiceDefinition?: boolean;
|
|
114
|
+
} & FulfillmentDetailsServiceAPI, FulfillmentDetailsServiceConfig>;
|
|
115
|
+
/**
|
|
116
|
+
* Load configuration for the FulfillmentDetailsService
|
|
117
|
+
* Used for SSR initialization
|
|
118
|
+
*
|
|
119
|
+
* @param operation - The operation to configure the service with
|
|
120
|
+
* @param options - Additional configuration options
|
|
121
|
+
* @returns The service configuration
|
|
122
|
+
*/
|
|
123
|
+
export declare function loadFulfillmentDetailsServiceConfig(operation: Operation, options?: {
|
|
124
|
+
initialDispatchType?: DispatchType;
|
|
125
|
+
initialAddress?: Address;
|
|
126
|
+
daysAhead?: number;
|
|
127
|
+
}): FulfillmentDetailsServiceConfig;
|