@wix/headless-restaurants-olo 0.0.7 → 0.0.9
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/ItemDetails.d.ts +70 -57
- package/cjs/dist/react/ItemDetails.js +56 -13
- package/cjs/dist/react/core/ItemDetails.d.ts +24 -9
- package/cjs/dist/react/core/ItemDetails.js +42 -9
- package/cjs/dist/services/common-types.d.ts +16 -0
- package/cjs/dist/services/common-types.js +8 -1
- package/cjs/dist/services/index.d.ts +1 -0
- package/cjs/dist/services/index.js +1 -0
- package/cjs/dist/services/item-details-service.d.ts +12 -4
- package/cjs/dist/services/item-details-service.js +49 -0
- package/cjs/dist/services/olo-settings-service.d.ts +5 -0
- package/cjs/dist/services/olo-settings-service.js +10 -0
- package/cjs/dist/services/utils.d.ts +20 -0
- package/cjs/dist/services/utils.js +34 -0
- package/dist/react/ItemDetails.d.ts +70 -57
- package/dist/react/ItemDetails.js +56 -13
- package/dist/react/core/ItemDetails.d.ts +24 -9
- package/dist/react/core/ItemDetails.js +42 -9
- package/dist/services/common-types.d.ts +16 -0
- package/dist/services/common-types.js +8 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/item-details-service.d.ts +12 -4
- package/dist/services/item-details-service.js +49 -0
- package/dist/services/olo-settings-service.d.ts +5 -0
- package/dist/services/olo-settings-service.js +10 -0
- package/dist/services/utils.d.ts +20 -0
- package/dist/services/utils.js +34 -0
- package/package.json +3 -2
|
@@ -2,20 +2,30 @@ import { defineService, implementService } from '@wix/services-definitions';
|
|
|
2
2
|
import * as operationGroupsApi from '@wix/auto_sdk_restaurants_operation-groups';
|
|
3
3
|
import * as operationsApi from '@wix/auto_sdk_restaurants_operations';
|
|
4
4
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
5
|
+
import { AvailabilityStatus } from './common-types.js';
|
|
5
6
|
export const OLOSettingsServiceDefinition = defineService('oloSettings');
|
|
6
7
|
export const OLOSettingsService = implementService.withConfig()(OLOSettingsServiceDefinition, ({ getService, config }) => {
|
|
7
8
|
const signalsService = getService(SignalsServiceDefinition);
|
|
9
|
+
const availabilityStatusMenuMap = signalsService.signal(config.availabilityStatusMenuMap);
|
|
10
|
+
const availabilityDispatchAction = signalsService.signal(config.availabilityDispatchAction);
|
|
8
11
|
const operationGroup = signalsService.signal(config.operationGroup);
|
|
9
12
|
const operation = signalsService.signal(config.operation);
|
|
10
13
|
const selectedItem = signalsService.signal(null);
|
|
11
14
|
const isLoading = signalsService.signal(false);
|
|
12
15
|
const error = signalsService.signal(null);
|
|
16
|
+
const getAvailabilityStatusFn = (menuId) => {
|
|
17
|
+
return (availabilityStatusMenuMap.get()?.[menuId] ??
|
|
18
|
+
AvailabilityStatus.AVAILABLE);
|
|
19
|
+
};
|
|
20
|
+
const getAvailabilityStatus = signalsService.signal(getAvailabilityStatusFn);
|
|
13
21
|
return {
|
|
14
22
|
operationGroup,
|
|
15
23
|
operation,
|
|
16
24
|
isLoading,
|
|
17
25
|
error,
|
|
18
26
|
selectedItem,
|
|
27
|
+
getAvailabilityStatus,
|
|
28
|
+
availabilityDispatchAction,
|
|
19
29
|
};
|
|
20
30
|
});
|
|
21
31
|
export async function loadOLOSettingsServiceConfig() {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { EnhancedModifier, EnhancedModifierGroup } from '@wix/headless-restaurants-menus/services';
|
|
2
|
+
export declare const getModifiersInitState: (modifierGroups: EnhancedModifierGroup[]) => Record<string, string[]>;
|
|
3
|
+
export declare const isSingleSelectRule: (rule: NonNullable<EnhancedModifierGroup["rule"]>) => boolean | null | undefined;
|
|
4
|
+
export declare const getFirstPreSelectedModifier: (modifiers: EnhancedModifier[]) => string | null | undefined;
|
|
5
|
+
export declare const getPreSelectedModifiers: (modifiers: EnhancedModifier[]) => string[];
|
|
6
|
+
export declare const convertModifierToFormModifier: (modifier: EnhancedModifier, index: number) => {
|
|
7
|
+
_id: string;
|
|
8
|
+
revision?: string | null;
|
|
9
|
+
_createdDate?: Date | null;
|
|
10
|
+
_updatedDate?: Date | null;
|
|
11
|
+
name?: string | null;
|
|
12
|
+
extendedFields?: import("@wix/auto_sdk_restaurants_item-modifiers").ExtendedFields;
|
|
13
|
+
inStock?: boolean | null;
|
|
14
|
+
businessLocationIds?: string[];
|
|
15
|
+
additionalChargeInfo?: {
|
|
16
|
+
additionalCharge?: string;
|
|
17
|
+
formattedAdditionalCharge?: string;
|
|
18
|
+
};
|
|
19
|
+
preSelected?: boolean;
|
|
20
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const getModifiersInitState = (modifierGroups) => {
|
|
2
|
+
const initialSelectedModifiers = {};
|
|
3
|
+
modifierGroups.forEach((group) => {
|
|
4
|
+
if (group._id) {
|
|
5
|
+
const isMultiSelectItem = !isSingleSelectRule(group.rule ?? {});
|
|
6
|
+
const formModifiers = group.modifiers.map(convertModifierToFormModifier);
|
|
7
|
+
if (isMultiSelectItem) {
|
|
8
|
+
const preSelectedModifiers = getPreSelectedModifiers(formModifiers);
|
|
9
|
+
initialSelectedModifiers[group._id] = preSelectedModifiers;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
const preSelectedModifier = getFirstPreSelectedModifier(formModifiers);
|
|
13
|
+
initialSelectedModifiers[group._id] = preSelectedModifier
|
|
14
|
+
? [preSelectedModifier]
|
|
15
|
+
: [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return initialSelectedModifiers;
|
|
20
|
+
};
|
|
21
|
+
export const isSingleSelectRule = (rule) => rule.required && rule.minSelections === 1 && rule.maxSelections === 1;
|
|
22
|
+
export const getFirstPreSelectedModifier = (modifiers) => modifiers.find(({ preSelected, inStock }) => preSelected && inStock)?._id;
|
|
23
|
+
export const getPreSelectedModifiers = (modifiers) => modifiers.reduce((acc, modifier) => {
|
|
24
|
+
if (modifier.preSelected && modifier.inStock && modifier._id) {
|
|
25
|
+
return [...acc, modifier._id];
|
|
26
|
+
}
|
|
27
|
+
return acc;
|
|
28
|
+
}, []);
|
|
29
|
+
export const convertModifierToFormModifier = (modifier, index) => {
|
|
30
|
+
return {
|
|
31
|
+
...modifier,
|
|
32
|
+
_id: `${modifier._id}~${index}`,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -3,6 +3,8 @@ import { Commerce } from '@wix/ecom/components';
|
|
|
3
3
|
import { type LineItem } from '@wix/ecom/services';
|
|
4
4
|
import { type AsChildChildren } from '@wix/headless-utils/react';
|
|
5
5
|
import { ItemServiceConfig } from '../services/item-details-service.js';
|
|
6
|
+
import { EnhancedModifier, EnhancedModifierGroup, EnhancedVariant } from '@wix/headless-restaurants-menus/services';
|
|
7
|
+
import { AvailabilityStatus, AvailabilityStatusMap } from '../services/common-types.js';
|
|
6
8
|
/**
|
|
7
9
|
* Root component for menu item display and interaction.
|
|
8
10
|
* Provides context for all menu item-related components like name, price, description, image, etc.
|
|
@@ -46,36 +48,6 @@ export interface ItemDetailsNameProps {
|
|
|
46
48
|
className?: string;
|
|
47
49
|
}
|
|
48
50
|
export declare const Name: React.ForwardRefExoticComponent<ItemDetailsNameProps & React.RefAttributes<HTMLElement>>;
|
|
49
|
-
/**
|
|
50
|
-
* Displays the item image with customizable rendering.
|
|
51
|
-
*
|
|
52
|
-
* @component
|
|
53
|
-
* @example
|
|
54
|
-
* ```tsx
|
|
55
|
-
* <ItemDetails.Image />
|
|
56
|
-
* <ItemDetails.Image asChild>
|
|
57
|
-
* <img className="rounded" />
|
|
58
|
-
* </ItemDetails.Image>
|
|
59
|
-
* ```
|
|
60
|
-
*/
|
|
61
|
-
export interface ItemDetailsImageProps {
|
|
62
|
-
asChild?: boolean;
|
|
63
|
-
/**
|
|
64
|
-
* Custom render function when using asChild.
|
|
65
|
-
* Receives an object with:
|
|
66
|
-
* - hasImage: boolean - whether the item has an image
|
|
67
|
-
* - image: string - the actual image element (WixMediaImage)
|
|
68
|
-
* - altText: string - the alt text for the image
|
|
69
|
-
*/
|
|
70
|
-
children?: (props: {
|
|
71
|
-
hasImage: boolean;
|
|
72
|
-
image?: string;
|
|
73
|
-
altText: string;
|
|
74
|
-
}) => React.ReactNode;
|
|
75
|
-
/** CSS classes to apply to the default element */
|
|
76
|
-
className?: string;
|
|
77
|
-
}
|
|
78
|
-
export declare const Image: React.ForwardRefExoticComponent<ItemDetailsImageProps & React.RefAttributes<HTMLElement>>;
|
|
79
51
|
/**
|
|
80
52
|
* Displays the item price with customizable rendering.
|
|
81
53
|
*
|
|
@@ -113,49 +85,77 @@ export interface ItemDetailsDescriptionProps {
|
|
|
113
85
|
}
|
|
114
86
|
export declare const Description: React.ForwardRefExoticComponent<ItemDetailsDescriptionProps & React.RefAttributes<HTMLElement>>;
|
|
115
87
|
/**
|
|
116
|
-
* Wrapper component for
|
|
117
|
-
* Renders
|
|
88
|
+
* Wrapper component for CoreItemDetails.ModifierComponent.
|
|
89
|
+
* Renders a single modifier with checkbox functionality.
|
|
118
90
|
*
|
|
119
91
|
* @component
|
|
120
92
|
* @example
|
|
121
93
|
* ```tsx
|
|
122
|
-
* <ItemDetails.
|
|
123
|
-
* {(
|
|
124
|
-
*
|
|
94
|
+
* <ItemDetails.Modifier>
|
|
95
|
+
* {({ modifier, isSelected, onToggle }) => (
|
|
96
|
+
* <div style={{ display: "flex", alignItems: "center" }}>
|
|
97
|
+
* <CheckboxPrimitive.Root
|
|
98
|
+
* className="CheckboxRoot"
|
|
99
|
+
* checked={isSelected}
|
|
100
|
+
* onCheckedChange={onToggle}
|
|
101
|
+
* id={modifier._id}
|
|
102
|
+
* >
|
|
103
|
+
* <CheckboxPrimitive.Indicator className="CheckboxIndicator">
|
|
104
|
+
* <CheckIcon />
|
|
105
|
+
* </CheckboxPrimitive.Indicator>
|
|
106
|
+
* </CheckboxPrimitive.Root>
|
|
107
|
+
* <label className="Label" htmlFor={modifier._id}>
|
|
108
|
+
* {modifier.name}
|
|
109
|
+
* </label>
|
|
110
|
+
* </div>
|
|
111
|
+
* )}
|
|
112
|
+
* </ItemDetails.Modifier>
|
|
125
113
|
* ```
|
|
126
114
|
*/
|
|
127
|
-
export interface
|
|
115
|
+
export interface ItemDetailsModifiersSingleSelectProps {
|
|
128
116
|
children?: AsChildChildren<{
|
|
129
|
-
|
|
117
|
+
selectedModifierIds: string[];
|
|
118
|
+
onToggle: (modifierId: string) => void;
|
|
119
|
+
modifierGroup: EnhancedModifierGroup;
|
|
120
|
+
modifiers: EnhancedModifier[];
|
|
130
121
|
}>;
|
|
131
122
|
className?: string;
|
|
132
123
|
asChild?: boolean;
|
|
133
|
-
|
|
134
|
-
|
|
124
|
+
modifierNameClassName?: string;
|
|
125
|
+
modifierPriceClassName?: string;
|
|
135
126
|
}
|
|
136
|
-
export
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* ```tsx
|
|
144
|
-
* <ItemDetails.ModifierGroups>
|
|
145
|
-
* {(modifierGroup) => <span>{modifierGroup.name}</span>}
|
|
146
|
-
* </ItemDetails.ModifierGroups>
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
export interface ItemDetailsModifierGroupsProps {
|
|
127
|
+
export interface ModifierCheckboxProps {
|
|
128
|
+
selectedModifierIds: string[];
|
|
129
|
+
onToggle: (modifierId: string) => void;
|
|
130
|
+
className?: string;
|
|
131
|
+
asChild?: boolean;
|
|
132
|
+
modifierNameClassName?: string;
|
|
133
|
+
modifierPriceClassName?: string;
|
|
150
134
|
children?: AsChildChildren<{
|
|
151
|
-
|
|
135
|
+
selectedModifierIds: string[];
|
|
136
|
+
onToggle: (modifierId: string) => void;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
export declare const ModifierCheckbox: React.ForwardRefExoticComponent<ModifierCheckboxProps & React.RefAttributes<HTMLElement>>;
|
|
140
|
+
export interface ModifierRadioProps {
|
|
141
|
+
modifierNameClassName?: string;
|
|
142
|
+
modifierPriceClassName?: string;
|
|
143
|
+
}
|
|
144
|
+
export declare const ModifierRadio: React.ForwardRefExoticComponent<ModifierRadioProps & React.RefAttributes<HTMLElement>>;
|
|
145
|
+
export declare const ModifiersSingleSelect: React.ForwardRefExoticComponent<ItemDetailsModifiersSingleSelectProps & React.RefAttributes<HTMLElement>>;
|
|
146
|
+
export interface ItemDetailsModifiersMultiSelectProps {
|
|
147
|
+
children?: AsChildChildren<{
|
|
148
|
+
selectedModifierIds: string[];
|
|
149
|
+
onToggle: (modifierId: string) => void;
|
|
150
|
+
modifierGroup: EnhancedModifierGroup;
|
|
151
|
+
modifiers: EnhancedModifier[];
|
|
152
152
|
}>;
|
|
153
153
|
className?: string;
|
|
154
154
|
asChild?: boolean;
|
|
155
155
|
modifierNameClassName?: string;
|
|
156
156
|
modifierPriceClassName?: string;
|
|
157
157
|
}
|
|
158
|
-
export declare const
|
|
158
|
+
export declare const ModifiersMultiSelect: React.ForwardRefExoticComponent<ItemDetailsModifiersMultiSelectProps & React.RefAttributes<HTMLElement>>;
|
|
159
159
|
/**
|
|
160
160
|
* Wrapper component for CoreItemDetails.VariantsComponent.
|
|
161
161
|
* Renders the variants for the item using Radix UI RadioGroup.
|
|
@@ -170,8 +170,8 @@ export declare const ModifierGroups: React.ForwardRefExoticComponent<ItemDetails
|
|
|
170
170
|
*/
|
|
171
171
|
export interface ItemDetailsVariantsProps {
|
|
172
172
|
children?: AsChildChildren<{
|
|
173
|
-
variant:
|
|
174
|
-
variants:
|
|
173
|
+
variant: EnhancedVariant;
|
|
174
|
+
variants: EnhancedVariant[];
|
|
175
175
|
hasVariants: boolean;
|
|
176
176
|
selectedVariantId?: string;
|
|
177
177
|
onVariantChange?: (variantId: string) => void;
|
|
@@ -267,3 +267,16 @@ export interface ItemDetailsQuantityProps {
|
|
|
267
267
|
export declare const AddToCartButton: React.FC<AddToCartButtonProps>;
|
|
268
268
|
export declare const Quantity: React.FC<ItemDetailsQuantityProps>;
|
|
269
269
|
export declare const SpecialRequest: React.ForwardRefExoticComponent<SpecialRequestProps & React.RefAttributes<never>>;
|
|
270
|
+
export interface ItemDetailsAvailabilityProps {
|
|
271
|
+
asChild?: boolean;
|
|
272
|
+
textClassName?: string;
|
|
273
|
+
buttonClassName?: string;
|
|
274
|
+
availabilityStatusMap: AvailabilityStatusMap;
|
|
275
|
+
children: (props: {
|
|
276
|
+
availabilityStatus: AvailabilityStatus;
|
|
277
|
+
availabilityStatusText?: string;
|
|
278
|
+
availabilityStatusButtonText?: string;
|
|
279
|
+
availabilityAction?: () => void;
|
|
280
|
+
}) => React.ReactNode;
|
|
281
|
+
}
|
|
282
|
+
export declare const AvailabilityComponent: React.ForwardRefExoticComponent<ItemDetailsAvailabilityProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -4,8 +4,10 @@ import { Commerce } from '@wix/ecom/components';
|
|
|
4
4
|
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
5
5
|
import { Quantity as QuantityComponent } from '@wix/headless-components/react';
|
|
6
6
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
7
|
-
import
|
|
7
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
8
|
+
import { Item, Modifier, ModifierGroup, useModifierContext, } from '@wix/headless-restaurants-menus/react';
|
|
8
9
|
import * as CoreItemDetails from './core/ItemDetails.js';
|
|
10
|
+
import { AvailabilityStatus, } from '../services/common-types.js';
|
|
9
11
|
var TestIds;
|
|
10
12
|
(function (TestIds) {
|
|
11
13
|
TestIds["itemName"] = "item-name";
|
|
@@ -15,9 +17,11 @@ var TestIds;
|
|
|
15
17
|
TestIds["itemAddToCart"] = "item-add-to-cart";
|
|
16
18
|
TestIds["itemSpecialRequest"] = "item-special-request";
|
|
17
19
|
TestIds["itemLabels"] = "item-labels";
|
|
18
|
-
TestIds["itemModifierGroups"] = "item-modifier-groups";
|
|
19
20
|
TestIds["itemVariants"] = "item-variants";
|
|
21
|
+
TestIds["itemModifier"] = "item-modifier";
|
|
22
|
+
TestIds["itemAvailability"] = "item-availability";
|
|
20
23
|
})(TestIds || (TestIds = {}));
|
|
24
|
+
const CheckIcon = () => (_jsx("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z", fill: "currentColor" }) }));
|
|
21
25
|
export const Root = ({ children, itemDetailsServiceConfig }) => {
|
|
22
26
|
return (_jsx(CoreItemDetails.Root, { itemDetailsServiceConfig: itemDetailsServiceConfig, children: ({ item }) => _jsx(Item.Root, { item: item, children: children }) }));
|
|
23
27
|
};
|
|
@@ -25,10 +29,6 @@ export const Name = React.forwardRef(({ asChild, children, className, ...rest },
|
|
|
25
29
|
return (_jsx(Item.Name, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemName, ...rest, children: children }));
|
|
26
30
|
});
|
|
27
31
|
Name.displayName = 'ItemDetails.Name';
|
|
28
|
-
export const Image = React.forwardRef(({ asChild, children, className, ...rest }) => {
|
|
29
|
-
return (_jsx(Item.Image, { asChild: asChild, className: className, "data-testid": TestIds.itemImage, ...rest, children: children }));
|
|
30
|
-
});
|
|
31
|
-
Image.displayName = 'ItemDetails.Image';
|
|
32
32
|
export const Price = React.forwardRef(({ asChild, className, ...rest }, ref) => {
|
|
33
33
|
return (_jsx(Item.Price, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemPrice, ...rest }));
|
|
34
34
|
});
|
|
@@ -37,13 +37,43 @@ export const Description = React.forwardRef(({ asChild, className, ...rest }, re
|
|
|
37
37
|
return (_jsx(Item.Description, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.itemDescription, ...rest }));
|
|
38
38
|
});
|
|
39
39
|
Description.displayName = 'ItemDetails.Description';
|
|
40
|
-
export const
|
|
41
|
-
|
|
40
|
+
export const ModifierCheckbox = React.forwardRef(({ selectedModifierIds, onToggle, className, asChild, modifierNameClassName, modifierPriceClassName, children, ...rest }) => {
|
|
41
|
+
const { modifier } = useModifierContext();
|
|
42
|
+
const isSelected = selectedModifierIds.includes(modifier._id || '');
|
|
43
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
44
|
+
selectedModifierIds,
|
|
45
|
+
onToggle,
|
|
46
|
+
}, ...rest, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsx(CheckboxPrimitive.Root, { className: "CheckboxRoot", checked: isSelected, onCheckedChange: () => onToggle(modifier._id || ''), id: modifier._id || undefined, children: _jsx(CheckboxPrimitive.Indicator, { className: "CheckboxIndicator", children: _jsx(CheckIcon, {}) }) }), _jsxs("label", { className: "Label", htmlFor: modifier._id || undefined, children: [_jsx(Modifier.Name, { className: modifierNameClassName }), _jsx(Modifier.Price, { className: modifierPriceClassName })] })] }) }));
|
|
47
|
+
});
|
|
48
|
+
ModifierCheckbox.displayName = 'ItemDetails.ModifierCheckbox';
|
|
49
|
+
export const ModifierRadio = React.forwardRef(({ modifierNameClassName, modifierPriceClassName }) => {
|
|
50
|
+
const { modifier } = useModifierContext();
|
|
51
|
+
return (_jsx(RadioGroupPrimitive.Item, { className: "RadioGroupItem", value: modifier._id || '', id: modifier._id || undefined, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsx(RadioGroupPrimitive.Indicator, { className: "RadioGroupIndicator" }), _jsxs("label", { className: "Label", htmlFor: modifier._id || undefined, children: [_jsx(Modifier.Name, { className: modifierNameClassName }), _jsx(Modifier.Price, { className: modifierPriceClassName })] })] }) }));
|
|
52
|
+
});
|
|
53
|
+
ModifierRadio.displayName = 'ItemDetails.ModifierRadio';
|
|
54
|
+
export const ModifiersSingleSelect = React.forwardRef(({ children, className, asChild, modifierNameClassName, modifierPriceClassName, ...rest }) => {
|
|
55
|
+
return (_jsx(CoreItemDetails.ModifiersComponent, { singleSelect: true, children: ({ selectedModifierIds, onToggle, modifierGroup, modifiers }) => {
|
|
56
|
+
const selectedModifierId = selectedModifierIds.length > 0 ? selectedModifierIds[0] : '';
|
|
57
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
58
|
+
selectedModifierIds,
|
|
59
|
+
onToggle,
|
|
60
|
+
modifierGroup,
|
|
61
|
+
modifiers,
|
|
62
|
+
}, ...rest, children: _jsx(RadioGroupPrimitive.Root, { value: selectedModifierId, onValueChange: onToggle, children: _jsx(ModifierGroup.ModifiersRepeater, { children: _jsx(ModifierRadio, { modifierNameClassName: modifierNameClassName, modifierPriceClassName: modifierPriceClassName }) }) }) }));
|
|
63
|
+
} }));
|
|
42
64
|
});
|
|
43
|
-
|
|
44
|
-
export const
|
|
45
|
-
return (_jsx(
|
|
65
|
+
ModifiersSingleSelect.displayName = 'ItemDetails.ModifiersSingleSelect';
|
|
66
|
+
export const ModifiersMultiSelect = React.forwardRef(({ children, className, asChild, modifierNameClassName, modifierPriceClassName, ...rest }) => {
|
|
67
|
+
return (_jsx(CoreItemDetails.ModifiersComponent, { singleSelect: false, children: ({ selectedModifierIds, onToggle, modifierGroup, modifiers }) => {
|
|
68
|
+
return (_jsx(AsChildSlot, { asChild: asChild, testId: TestIds.itemModifier, className: className, customElement: children, customElementProps: {
|
|
69
|
+
selectedModifierIds,
|
|
70
|
+
onToggle,
|
|
71
|
+
modifierGroup,
|
|
72
|
+
modifiers,
|
|
73
|
+
}, ...rest, children: _jsx(ModifierGroup.ModifiersRepeater, { children: _jsx(ModifierCheckbox, { selectedModifierIds: selectedModifierIds, onToggle: onToggle, modifierNameClassName: modifierNameClassName, modifierPriceClassName: modifierPriceClassName }) }) }));
|
|
74
|
+
} }));
|
|
46
75
|
});
|
|
76
|
+
ModifiersMultiSelect.displayName = 'ItemDetails.ModifiersMultiSelect';
|
|
47
77
|
export const Variants = React.forwardRef(({ children, className, asChild, variantNameClassName, variantPriceClassName, emptyState, }, ref) => {
|
|
48
78
|
return (_jsx(CoreItemDetails.VariantsComponent, { children: ({ variants, hasVariants, selectedVariantId, onVariantChange }) => {
|
|
49
79
|
if (!hasVariants) {
|
|
@@ -54,13 +84,12 @@ export const Variants = React.forwardRef(({ children, className, asChild, varian
|
|
|
54
84
|
hasVariants,
|
|
55
85
|
selectedVariantId,
|
|
56
86
|
onVariantChange,
|
|
57
|
-
}, children: _jsx(RadioGroupPrimitive.Root, { value: selectedVariantId, onValueChange: onVariantChange, children: variants.map((variant) => (_jsx(RadioGroupPrimitive.Item, { value: variant._id, children: _jsxs("div", { children: [_jsx("div", { className: variantNameClassName, children: variant.name }), _jsx("div", { className: variantPriceClassName, children: variant.priceInfo?.formattedPrice ||
|
|
87
|
+
}, children: _jsx(RadioGroupPrimitive.Root, { value: selectedVariantId, onValueChange: onVariantChange, children: variants.map((variant) => (_jsx(RadioGroupPrimitive.Item, { value: variant._id ?? '', children: _jsxs("div", { children: [_jsx("div", { className: variantNameClassName, children: variant.name }), _jsx("div", { className: variantPriceClassName, children: variant.priceInfo?.formattedPrice ||
|
|
58
88
|
variant.priceInfo?.price ||
|
|
59
89
|
'' })] }) }, variant._id))) }) }));
|
|
60
90
|
} }));
|
|
61
91
|
});
|
|
62
92
|
Variants.displayName = 'ItemDetails.Variants';
|
|
63
|
-
ModifierGroups.displayName = 'ItemDetails.ModifierGroups';
|
|
64
93
|
/**
|
|
65
94
|
* Add to Cart button for the menu item.
|
|
66
95
|
* Triggers the action to add the selected item (and its modifiers/variants) to the cart.
|
|
@@ -93,3 +122,17 @@ export const SpecialRequest = React.forwardRef(({ className, labelClassName, pla
|
|
|
93
122
|
return (_jsx(CoreItemDetails.SpecialRequest, { children: ({ value, onChange, }) => (_jsxs(AsChildSlot, { ref: ref, asChild: asChild, className: className, onChange: onChange, "data-testid": TestIds.itemSpecialRequest, customElement: children, customElementProps: { label, value }, content: value, ...props, children: [label && _jsx("label", { className: labelClassName, children: label }), _jsx("textarea", { value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, maxLength: maxLength, rows: rows, className: className, children: value })] })) }));
|
|
94
123
|
});
|
|
95
124
|
SpecialRequest.displayName = 'SpecialRequest';
|
|
125
|
+
export const AvailabilityComponent = React.forwardRef(({ asChild, children, textClassName, buttonClassName, availabilityStatusMap, ...rest }, ref) => {
|
|
126
|
+
return (_jsx(CoreItemDetails.AvailabilityComponent, { availabilityStatusMap: availabilityStatusMap, children: ({ availabilityStatus, availabilityAction, availabilityStatusText, availabilityStatusButtonText, }) => {
|
|
127
|
+
if (availabilityStatus === AvailabilityStatus.AVAILABLE) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return (_jsxs(AsChildSlot, { asChild: asChild, "data-testid": TestIds.itemAvailability, customElement: children, customElementProps: {
|
|
131
|
+
availabilityStatus,
|
|
132
|
+
availabilityStatusText,
|
|
133
|
+
availabilityStatusButtonText,
|
|
134
|
+
availabilityAction,
|
|
135
|
+
}, ref: ref, ...rest, children: [_jsx("p", { className: textClassName, children: availabilityStatusText }), availabilityStatusButtonText && availabilityAction && (_jsx("button", { className: buttonClassName, onClick: availabilityAction, children: availabilityStatusButtonText }))] }));
|
|
136
|
+
} }));
|
|
137
|
+
});
|
|
138
|
+
AvailabilityComponent.displayName = 'AvailabilityComponent';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type LineItem } from '@wix/ecom/services';
|
|
3
3
|
import { ItemServiceConfig } from '../../services/item-details-service.js';
|
|
4
|
+
import { EnhancedModifier, EnhancedModifierGroup, EnhancedVariant } from '@wix/headless-restaurants-menus/services';
|
|
5
|
+
import { AvailabilityStatus, AvailabilityStatusMap } from '../../services/common-types.js';
|
|
4
6
|
interface ItemDetailsRootProps {
|
|
5
7
|
children: (props: {
|
|
6
8
|
item: unknown;
|
|
@@ -8,13 +10,6 @@ interface ItemDetailsRootProps {
|
|
|
8
10
|
itemDetailsServiceConfig?: ItemServiceConfig;
|
|
9
11
|
}
|
|
10
12
|
export declare const Root: React.FC<ItemDetailsRootProps>;
|
|
11
|
-
interface ItemDetailsModifiersRepeaterProps {
|
|
12
|
-
children: (props: {
|
|
13
|
-
modifiers: [];
|
|
14
|
-
hasModifiers: boolean;
|
|
15
|
-
}) => React.ReactNode;
|
|
16
|
-
}
|
|
17
|
-
export declare const ModifiersRepeater: React.FC<ItemDetailsModifiersRepeaterProps>;
|
|
18
13
|
interface ItemDetailsSpecialRequestProps {
|
|
19
14
|
children: (props: {
|
|
20
15
|
value: string;
|
|
@@ -42,12 +37,32 @@ interface ItemDetailsQuantityProps {
|
|
|
42
37
|
export declare const QuantityComponent: React.FC<ItemDetailsQuantityProps>;
|
|
43
38
|
interface ItemDetailsVariantsProps {
|
|
44
39
|
children: (props: {
|
|
45
|
-
variants:
|
|
40
|
+
variants: EnhancedVariant[];
|
|
46
41
|
hasVariants: boolean;
|
|
47
42
|
selectedVariantId?: string;
|
|
48
43
|
onVariantChange?: (variantId: string) => void;
|
|
49
|
-
selectedVariant?:
|
|
44
|
+
selectedVariant?: EnhancedVariant;
|
|
50
45
|
}) => React.ReactNode;
|
|
51
46
|
}
|
|
52
47
|
export declare const VariantsComponent: React.FC<ItemDetailsVariantsProps>;
|
|
48
|
+
interface ItemDetailsModifiersProps {
|
|
49
|
+
children: (props: {
|
|
50
|
+
selectedModifierIds: string[];
|
|
51
|
+
onToggle: (modifierId: string) => void;
|
|
52
|
+
modifierGroup: EnhancedModifierGroup;
|
|
53
|
+
modifiers: EnhancedModifier[];
|
|
54
|
+
}) => React.ReactNode;
|
|
55
|
+
singleSelect?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare const ModifiersComponent: React.FC<ItemDetailsModifiersProps>;
|
|
58
|
+
interface ItemDetailsAvailabilityProps {
|
|
59
|
+
availabilityStatusMap: AvailabilityStatusMap;
|
|
60
|
+
children: (props: {
|
|
61
|
+
availabilityStatus: AvailabilityStatus;
|
|
62
|
+
availabilityAction?: () => void;
|
|
63
|
+
availabilityStatusText?: string;
|
|
64
|
+
availabilityStatusButtonText?: string;
|
|
65
|
+
}) => React.ReactNode;
|
|
66
|
+
}
|
|
67
|
+
export declare const AvailabilityComponent: React.FC<ItemDetailsAvailabilityProps>;
|
|
53
68
|
export {};
|
|
@@ -4,7 +4,9 @@ import { useService, WixServices } from '@wix/services-manager-react';
|
|
|
4
4
|
import { createServicesMap } from '@wix/services-manager';
|
|
5
5
|
import { ItemService, ItemServiceDefinition, loadItemServiceConfig, } from '../../services/item-details-service.js';
|
|
6
6
|
import { OLOSettingsServiceDefinition } from '../../services/olo-settings-service.js';
|
|
7
|
-
import { useItemContext } from '@wix/headless-restaurants-menus/react';
|
|
7
|
+
import { useItemContext, useModifierGroupContext, } from '@wix/headless-restaurants-menus/react';
|
|
8
|
+
import { AvailabilityStatus, } from '../../services/common-types.js';
|
|
9
|
+
import { convertModifierToFormModifier } from '../../services/utils.js';
|
|
8
10
|
export const Root = ({ children, itemDetailsServiceConfig, }) => {
|
|
9
11
|
const service = useService(OLOSettingsServiceDefinition);
|
|
10
12
|
const selectedItem = service.selectedItem?.get();
|
|
@@ -20,14 +22,6 @@ export const Root = ({ children, itemDetailsServiceConfig, }) => {
|
|
|
20
22
|
}
|
|
21
23
|
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ItemServiceDefinition, ItemService, config), children: children({ item: itemDetailsServiceConfig?.item ?? selectedItem }) }));
|
|
22
24
|
};
|
|
23
|
-
export const ModifiersRepeater = ({ children, }) => {
|
|
24
|
-
const service = useService(ItemServiceDefinition);
|
|
25
|
-
const item = service.item?.get();
|
|
26
|
-
// TODO: Check if modifiers exist on item type - might be in a different property
|
|
27
|
-
const modifiers = item?.modifiers || [];
|
|
28
|
-
const hasModifiers = modifiers.length > 0;
|
|
29
|
-
return children({ modifiers, hasModifiers });
|
|
30
|
-
};
|
|
31
25
|
export const SpecialRequest = ({ children, }) => {
|
|
32
26
|
const [value, setValue] = useState('');
|
|
33
27
|
const service = useService(ItemServiceDefinition);
|
|
@@ -92,3 +86,42 @@ export const VariantsComponent = ({ children, }) => {
|
|
|
92
86
|
selectedVariant,
|
|
93
87
|
});
|
|
94
88
|
};
|
|
89
|
+
export const ModifiersComponent = ({ children, singleSelect, }) => {
|
|
90
|
+
const service = useService(ItemServiceDefinition);
|
|
91
|
+
const { modifierGroup } = useModifierGroupContext();
|
|
92
|
+
// Get selected modifier IDs for this group
|
|
93
|
+
const groupId = modifierGroup._id;
|
|
94
|
+
const groupSelectedModifierIds = service.getSelectedModifiers?.(groupId ?? '');
|
|
95
|
+
const onToggle = (modifierId) => {
|
|
96
|
+
if (groupId) {
|
|
97
|
+
service.toggleModifier?.(groupId, modifierId, singleSelect);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
return children({
|
|
101
|
+
selectedModifierIds: groupSelectedModifierIds,
|
|
102
|
+
onToggle,
|
|
103
|
+
modifierGroup,
|
|
104
|
+
modifiers: modifierGroup.modifiers.map(convertModifierToFormModifier),
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
export const AvailabilityComponent = ({ children, availabilityStatusMap, }) => {
|
|
108
|
+
const oloSettingsService = useService(OLOSettingsServiceDefinition);
|
|
109
|
+
const availabilityDispatchAction = oloSettingsService.availabilityDispatchAction?.get?.();
|
|
110
|
+
const itemService = useService(ItemServiceDefinition);
|
|
111
|
+
const availabilityStatus = itemService.availabilityStatus?.get?.() ?? AvailabilityStatus.AVAILABLE;
|
|
112
|
+
const availabilityStatusWithAction = availabilityStatus === AvailabilityStatus.NEXT_AVAILABILITY_PICKUP ||
|
|
113
|
+
availabilityStatus === AvailabilityStatus.NEXT_AVAILABILITY_DELIVERY;
|
|
114
|
+
const availabilityStatusObject = availabilityStatusMap[availabilityStatus];
|
|
115
|
+
const availabilityStatusButtonText = availabilityStatusWithAction
|
|
116
|
+
? availabilityStatusObject
|
|
117
|
+
?.buttonText
|
|
118
|
+
: undefined;
|
|
119
|
+
return children({
|
|
120
|
+
availabilityStatus,
|
|
121
|
+
availabilityAction: availabilityStatusWithAction
|
|
122
|
+
? availabilityDispatchAction
|
|
123
|
+
: undefined,
|
|
124
|
+
availabilityStatusText: availabilityStatusObject?.text,
|
|
125
|
+
availabilityStatusButtonText,
|
|
126
|
+
});
|
|
127
|
+
};
|
|
@@ -1,3 +1,19 @@
|
|
|
1
1
|
import * as currentCart from '@wix/auto_sdk_ecom_current-cart';
|
|
2
2
|
export type LineItem = currentCart.LineItem;
|
|
3
3
|
export type DescriptionLine = currentCart.DescriptionLine;
|
|
4
|
+
export declare enum AvailabilityStatus {
|
|
5
|
+
AVAILABLE = 0,
|
|
6
|
+
NOT_AVAILABLE = 1,
|
|
7
|
+
OUT_OF_STOCK = 2,
|
|
8
|
+
NEXT_AVAILABILITY_PICKUP = 3,
|
|
9
|
+
NEXT_AVAILABILITY_DELIVERY = 4
|
|
10
|
+
}
|
|
11
|
+
export type NextAvailability = AvailabilityStatus.NEXT_AVAILABILITY_PICKUP | AvailabilityStatus.NEXT_AVAILABILITY_DELIVERY;
|
|
12
|
+
export type AvailabilityStatusWithActionObject = {
|
|
13
|
+
text?: string;
|
|
14
|
+
buttonText?: string;
|
|
15
|
+
};
|
|
16
|
+
export type AvailabilityStatusObject = {
|
|
17
|
+
text?: string;
|
|
18
|
+
};
|
|
19
|
+
export type AvailabilityStatusMap = Partial<Record<Exclude<AvailabilityStatus, NextAvailability>, AvailabilityStatusObject>> & Record<NextAvailability, AvailabilityStatusWithActionObject>;
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var AvailabilityStatus;
|
|
2
|
+
(function (AvailabilityStatus) {
|
|
3
|
+
AvailabilityStatus[AvailabilityStatus["AVAILABLE"] = 0] = "AVAILABLE";
|
|
4
|
+
AvailabilityStatus[AvailabilityStatus["NOT_AVAILABLE"] = 1] = "NOT_AVAILABLE";
|
|
5
|
+
AvailabilityStatus[AvailabilityStatus["OUT_OF_STOCK"] = 2] = "OUT_OF_STOCK";
|
|
6
|
+
AvailabilityStatus[AvailabilityStatus["NEXT_AVAILABILITY_PICKUP"] = 3] = "NEXT_AVAILABILITY_PICKUP";
|
|
7
|
+
AvailabilityStatus[AvailabilityStatus["NEXT_AVAILABILITY_DELIVERY"] = 4] = "NEXT_AVAILABILITY_DELIVERY";
|
|
8
|
+
})(AvailabilityStatus || (AvailabilityStatus = {}));
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { ItemService, ItemServiceDefinition, loadItemServiceConfig, ItemServiceConfig, } from './item-details-service.js';
|
|
2
2
|
export { OLOSettingsService, OLOSettingsServiceDefinition, loadOLOSettingsServiceConfig, type OLOSettingsServiceConfig, type OLOSettingsServiceAPI, } from './olo-settings-service.js';
|
|
3
|
+
export { AvailabilityStatus, AvailabilityStatusMap } from './common-types.js';
|
package/dist/services/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { ItemService, ItemServiceDefinition, loadItemServiceConfig, } from './item-details-service.js';
|
|
2
2
|
export { OLOSettingsService, OLOSettingsServiceDefinition, loadOLOSettingsServiceConfig, } from './olo-settings-service.js';
|
|
3
|
+
export { AvailabilityStatus } from './common-types.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type Signal } from '@wix/services-definitions/core-services/signals';
|
|
2
|
-
import * as items from '@wix/auto_sdk_restaurants_items';
|
|
3
2
|
import { type LineItem } from '@wix/ecom/services';
|
|
4
3
|
import { itemVariants } from '@wix/restaurants';
|
|
4
|
+
import type { EnhancedItem } from '@wix/headless-restaurants-menus/services';
|
|
5
|
+
import { AvailabilityStatus } from './common-types.js';
|
|
5
6
|
type Variant = itemVariants.Variant;
|
|
6
7
|
/**
|
|
7
8
|
* API interface for the Item Detailsservice, providing reactive item data management.
|
|
@@ -11,11 +12,13 @@ type Variant = itemVariants.Variant;
|
|
|
11
12
|
*/
|
|
12
13
|
export interface ItemServiceAPI {
|
|
13
14
|
/** Reactive signal containing the current item data */
|
|
14
|
-
item?: Signal<
|
|
15
|
+
item?: Signal<EnhancedItem | undefined>;
|
|
15
16
|
quantity: Signal<number>;
|
|
16
17
|
specialRequest: Signal<string>;
|
|
17
18
|
lineItem: Signal<LineItem>;
|
|
18
19
|
selectedVariant: Signal<Variant | undefined>;
|
|
20
|
+
selectedModifiers: Signal<Record<string, Array<string>>>;
|
|
21
|
+
availabilityStatus: Signal<AvailabilityStatus>;
|
|
19
22
|
/** Reactive signal indicating if a item is currently being loaded */
|
|
20
23
|
isLoading: Signal<boolean>;
|
|
21
24
|
/** Reactive signal containing any error message, or null if no error */
|
|
@@ -26,6 +29,10 @@ export interface ItemServiceAPI {
|
|
|
26
29
|
updateSpecialRequest: (specialRequest: string) => void;
|
|
27
30
|
/** Function to update the selected variant of the item */
|
|
28
31
|
updateSelectedVariant: (variant: Variant) => void;
|
|
32
|
+
/** Function to toggle a modifier instance in a specific group */
|
|
33
|
+
toggleModifier: (modifierGroupId: string, modifierId: string, singleSelect?: boolean) => void;
|
|
34
|
+
/** Function to get the selected modifiers for a specific group */
|
|
35
|
+
getSelectedModifiers: (modifierGroupId: string) => Array<string>;
|
|
29
36
|
}
|
|
30
37
|
/**
|
|
31
38
|
* Service definition for the Item service.
|
|
@@ -46,9 +53,10 @@ export declare const ItemServiceDefinition: string & {
|
|
|
46
53
|
*/
|
|
47
54
|
export interface ItemServiceConfig {
|
|
48
55
|
/** The initial item data to configure the service with */
|
|
49
|
-
item?:
|
|
56
|
+
item?: EnhancedItem;
|
|
50
57
|
itemId?: string;
|
|
51
58
|
operationId?: string;
|
|
59
|
+
menuId?: string;
|
|
52
60
|
}
|
|
53
61
|
export declare const ItemService: import("@wix/services-definitions").ServiceFactory<string & {
|
|
54
62
|
__api: ItemServiceAPI;
|
|
@@ -154,7 +162,7 @@ export interface NotFoundItemServiceConfigResult {
|
|
|
154
162
|
* ```
|
|
155
163
|
*/
|
|
156
164
|
export declare function loadItemServiceConfig({ item, operationId, }: {
|
|
157
|
-
item:
|
|
165
|
+
item: EnhancedItem;
|
|
158
166
|
operationId: string;
|
|
159
167
|
}): ItemServiceConfig;
|
|
160
168
|
export {};
|