@wix/headless-restaurants-olo 0.0.22 → 0.0.24
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 +2 -1
- package/cjs/dist/react/ItemDetails.js +3 -1
- package/cjs/dist/react/ModifierGroup.js +2 -2
- package/cjs/dist/react/core/ItemDetails.d.ts +1 -0
- package/cjs/dist/react/core/ItemDetails.js +8 -3
- package/cjs/dist/react/core/ModifierGroup.js +2 -4
- package/cjs/dist/services/common-types.d.ts +7 -7
- package/cjs/dist/services/item-details-service.d.ts +7 -0
- package/cjs/dist/services/item-details-service.js +42 -6
- package/cjs/dist/services/utils.d.ts +3 -2
- package/cjs/dist/services/utils.js +32 -10
- package/dist/react/ItemDetails.d.ts +2 -1
- package/dist/react/ItemDetails.js +3 -1
- package/dist/react/ModifierGroup.js +2 -2
- package/dist/react/core/ItemDetails.d.ts +1 -0
- package/dist/react/core/ItemDetails.js +8 -3
- package/dist/react/core/ModifierGroup.js +2 -4
- package/dist/services/common-types.d.ts +7 -7
- package/dist/services/item-details-service.d.ts +7 -0
- package/dist/services/item-details-service.js +42 -6
- package/dist/services/utils.d.ts +3 -2
- package/dist/services/utils.js +32 -10
- package/package.json +3 -3
|
@@ -71,7 +71,7 @@ export declare const Variants: React.ForwardRefExoticComponent<ItemDetailsVarian
|
|
|
71
71
|
export interface SpecialRequestProps {
|
|
72
72
|
asChild?: boolean;
|
|
73
73
|
children?: AsChildChildren<{
|
|
74
|
-
|
|
74
|
+
value: string;
|
|
75
75
|
onChange: (value: string) => void;
|
|
76
76
|
}>;
|
|
77
77
|
/** Placeholder text for the textarea */
|
|
@@ -108,6 +108,7 @@ export interface AddToCartButtonProps {
|
|
|
108
108
|
/** Text label for the button */
|
|
109
109
|
label: React.ReactNode;
|
|
110
110
|
formattedPrice: string;
|
|
111
|
+
modifierGroupHasError: boolean;
|
|
111
112
|
}) => React.ReactNode;
|
|
112
113
|
}
|
|
113
114
|
export declare const AddToCartButton: React.ForwardRefExoticComponent<AddToCartButtonProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -39,7 +39,7 @@ export const Variants = React.forwardRef(({ children, className, asChild, varian
|
|
|
39
39
|
});
|
|
40
40
|
Variants.displayName = 'ItemDetails.Variants';
|
|
41
41
|
export const AddToCartButton = React.forwardRef(({ asChild, children, className, addToCartLabelMap, ...props }, ref) => {
|
|
42
|
-
return (_jsx(CoreItemDetails.LineItemComponent, { addToCartLabelMap: addToCartLabelMap, children: ({ lineItem, buttonState, addToCartButtonDisabled, loadingState, labelText, formattedPrice, }) => {
|
|
42
|
+
return (_jsx(CoreItemDetails.LineItemComponent, { addToCartLabelMap: addToCartLabelMap, children: ({ lineItem, buttonState, addToCartButtonDisabled, loadingState, labelText, formattedPrice, modifierGroupHasError, }) => {
|
|
43
43
|
const label = (_jsxs(_Fragment, { children: [_jsx("span", { children: labelText }), " ", _jsx("span", { children: " | " }), _jsx("span", { children: formattedPrice })] }));
|
|
44
44
|
return (_jsx(AsChildSlot, { asChild: asChild, className: className, customElement: children, customElementProps: {
|
|
45
45
|
buttonState,
|
|
@@ -49,6 +49,7 @@ export const AddToCartButton = React.forwardRef(({ asChild, children, className,
|
|
|
49
49
|
lineItems: [lineItem],
|
|
50
50
|
label,
|
|
51
51
|
formattedPrice,
|
|
52
|
+
modifierGroupHasError,
|
|
52
53
|
}, ref: ref, ...props, children: _jsx(Commerce.Actions.AddToCart, { asChild: false, label: label, className: className, lineItems: [lineItem], ...props, children: children({
|
|
53
54
|
lineItem,
|
|
54
55
|
buttonState,
|
|
@@ -56,6 +57,7 @@ export const AddToCartButton = React.forwardRef(({ asChild, children, className,
|
|
|
56
57
|
loadingState,
|
|
57
58
|
label,
|
|
58
59
|
formattedPrice,
|
|
60
|
+
modifierGroupHasError,
|
|
59
61
|
}) }) }));
|
|
60
62
|
} }));
|
|
61
63
|
});
|
|
@@ -44,12 +44,12 @@ export const Description = React.forwardRef(({ ruleTypeMap, className, asChild,
|
|
|
44
44
|
} }));
|
|
45
45
|
});
|
|
46
46
|
Description.displayName = 'ItemDetailsModifierGroup.Description';
|
|
47
|
-
export const Error = React.forwardRef(({ ruleTypeMap, className, asChild, children }, ref) => {
|
|
47
|
+
export const Error = React.forwardRef(({ ruleTypeMap, className, asChild, children, ...otherProps }, ref) => {
|
|
48
48
|
return (_jsx(GroupError, { ruleTypeMap: ruleTypeMap, children: ({ error }) => {
|
|
49
49
|
if (!error) {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild,
|
|
52
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, "data-testid": TestIds.modifierGroupError, className: className, customElement: children, customElementProps: { error }, content: error, ...otherProps, children: _jsx("p", { className: className, children: error }) }));
|
|
53
53
|
} }));
|
|
54
54
|
});
|
|
55
55
|
Error.displayName = 'ItemDetailsModifierGroup.Error';
|
|
@@ -26,6 +26,7 @@ interface ItemDetailsLineItemProps {
|
|
|
26
26
|
addToCartButtonDisabled: boolean;
|
|
27
27
|
labelText: string;
|
|
28
28
|
formattedPrice: string;
|
|
29
|
+
modifierGroupHasError: boolean;
|
|
29
30
|
}) => React.ReactNode;
|
|
30
31
|
}
|
|
31
32
|
export declare const LineItemComponent: React.FC<ItemDetailsLineItemProps>;
|
|
@@ -24,11 +24,14 @@ export const Root = ({ children, itemDetailsServiceConfig, }) => {
|
|
|
24
24
|
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ItemServiceDefinition, ItemService, config), children: children({ item: itemDetailsServiceConfig?.item ?? selectedItem }) }));
|
|
25
25
|
};
|
|
26
26
|
export const SpecialRequest = ({ children, }) => {
|
|
27
|
-
const [value, setValue] = useState('');
|
|
28
27
|
const service = useService(ItemServiceDefinition);
|
|
28
|
+
const initialSpecialRequest = service.specialRequest?.get?.() ?? '';
|
|
29
|
+
const [value, setValue] = useState(initialSpecialRequest);
|
|
29
30
|
const onChange = (newValue) => {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
if (typeof newValue === 'string') {
|
|
32
|
+
setValue(newValue);
|
|
33
|
+
service.updateSpecialRequest(newValue);
|
|
34
|
+
}
|
|
32
35
|
};
|
|
33
36
|
return children({
|
|
34
37
|
value,
|
|
@@ -48,6 +51,7 @@ export const LineItemComponent = ({ addToCartLabelMap, children, }) => {
|
|
|
48
51
|
const formatCurrency = oloSettingsService.formatCurrency;
|
|
49
52
|
const formattedPrice = formatCurrency(price);
|
|
50
53
|
const labelText = addToCartLabelMap[buttonState];
|
|
54
|
+
const modifierGroupHasError = service.doesModifierGroupHaveError?.get?.() ?? false;
|
|
51
55
|
return children({
|
|
52
56
|
loadingState,
|
|
53
57
|
lineItem,
|
|
@@ -55,6 +59,7 @@ export const LineItemComponent = ({ addToCartLabelMap, children, }) => {
|
|
|
55
59
|
addToCartButtonDisabled,
|
|
56
60
|
labelText,
|
|
57
61
|
formattedPrice,
|
|
62
|
+
modifierGroupHasError,
|
|
58
63
|
});
|
|
59
64
|
};
|
|
60
65
|
export const QuantityComponent = ({ children, }) => {
|
|
@@ -49,8 +49,7 @@ export const ModifiersComponent = ({ children, }) => {
|
|
|
49
49
|
};
|
|
50
50
|
export const Description = ({ ruleTypeMap, children, }) => {
|
|
51
51
|
const { ruleType, modifierGroup } = useModifiersContext();
|
|
52
|
-
const
|
|
53
|
-
const description = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroupName, modifierGroup.rule);
|
|
52
|
+
const description = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroup.rule);
|
|
54
53
|
return children({ description });
|
|
55
54
|
};
|
|
56
55
|
export const GroupError = ({ ruleTypeMap, children, }) => {
|
|
@@ -58,10 +57,9 @@ export const GroupError = ({ ruleTypeMap, children, }) => {
|
|
|
58
57
|
const { ruleType, modifierGroup } = useModifiersContext();
|
|
59
58
|
const groupId = modifierGroup._id || '';
|
|
60
59
|
const modifierGroupErrors = service.modifierGroupError?.get() || {};
|
|
61
|
-
const modifierGroupName = modifierGroup.name || '';
|
|
62
60
|
let error;
|
|
63
61
|
if (modifierGroupErrors[groupId]) {
|
|
64
|
-
error = getRuleTypeMapValue(ruleTypeMap, ruleType,
|
|
62
|
+
error = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroup.rule);
|
|
65
63
|
}
|
|
66
64
|
return children({ error });
|
|
67
65
|
};
|
|
@@ -11,13 +11,13 @@ export declare enum RuleType {
|
|
|
11
11
|
CHOOSE_BETWEEN_X_AND_Y = "CHOOSE_BETWEEN_X_AND_Y"
|
|
12
12
|
}
|
|
13
13
|
export interface RuleTypeMap {
|
|
14
|
-
[RuleType.NO_LIMIT]?: (
|
|
15
|
-
[RuleType.CHOOSE_ONE]?: (
|
|
16
|
-
[RuleType.CHOOSE_X]?: (
|
|
17
|
-
[RuleType.CHOOSE_AT_LEAST_ONE]?: (
|
|
18
|
-
[RuleType.CHOOSE_AT_LEAST_X]?: (
|
|
19
|
-
[RuleType.CHOOSE_UP_TO_X]?: (
|
|
20
|
-
[RuleType.CHOOSE_BETWEEN_X_AND_Y]?: (
|
|
14
|
+
[RuleType.NO_LIMIT]?: () => string;
|
|
15
|
+
[RuleType.CHOOSE_ONE]?: () => string;
|
|
16
|
+
[RuleType.CHOOSE_X]?: (x: number) => string;
|
|
17
|
+
[RuleType.CHOOSE_AT_LEAST_ONE]?: () => string;
|
|
18
|
+
[RuleType.CHOOSE_AT_LEAST_X]?: (x: number) => string;
|
|
19
|
+
[RuleType.CHOOSE_UP_TO_X]?: (x: number) => string;
|
|
20
|
+
[RuleType.CHOOSE_BETWEEN_X_AND_Y]?: (x: number, y: number) => string;
|
|
21
21
|
}
|
|
22
22
|
export declare enum AvailabilityStatus {
|
|
23
23
|
AVAILABLE = 0,
|
|
@@ -43,6 +43,7 @@ export interface ItemServiceAPI {
|
|
|
43
43
|
endDate?: Date;
|
|
44
44
|
weeklyAvailabilitySummary?: WeeklyAvailability;
|
|
45
45
|
};
|
|
46
|
+
doesModifierGroupHaveError: ReadOnlySignal<boolean>;
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Service definition for the Item service.
|
|
@@ -67,6 +68,12 @@ export interface ItemServiceConfig {
|
|
|
67
68
|
operationId?: string;
|
|
68
69
|
availabilityStatus?: AvailabilityStatus;
|
|
69
70
|
editItemMode?: boolean;
|
|
71
|
+
editingItemValues?: {
|
|
72
|
+
quantity?: number;
|
|
73
|
+
specialRequest?: string;
|
|
74
|
+
selectedVariantId?: string;
|
|
75
|
+
selectedModifiers?: Record<string, Array<string>>;
|
|
76
|
+
};
|
|
70
77
|
menuId?: string;
|
|
71
78
|
sectionId?: string;
|
|
72
79
|
futureAvailability?: FutureAvailability;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
2
2
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
3
3
|
import { AddToCartButtonState, AvailabilityStatus, } from './common-types.js';
|
|
4
|
-
import { getAreNotEnoughModifiersOfMandatoryModifierGroupInStock, getModifiersInitState, getLineItemModifiers, getPriceVariantOptions, getSelectedModifierPrices, getSelectedVariantPrice, calculateItemPrice, } from './utils.js';
|
|
4
|
+
import { getAreNotEnoughModifiersOfMandatoryModifierGroupInStock, getModifiersInitState, getLineItemModifiers, getPriceVariantOptions, getSelectedModifierPrices, getSelectedVariantPrice, calculateItemPrice, checkModifiersValidation, } from './utils.js';
|
|
5
5
|
import { OLOSettingsServiceDefinition } from './olo-settings-service.js';
|
|
6
6
|
/**
|
|
7
7
|
* Service definition for the Item service.
|
|
@@ -56,13 +56,27 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
56
56
|
const item = signalsService.signal(config.item);
|
|
57
57
|
const isLoading = signalsService.signal(!!config.item);
|
|
58
58
|
const error = signalsService.signal(config.item ? null : 'Item not found');
|
|
59
|
-
const quantity = signalsService.signal(1);
|
|
60
|
-
const specialRequest = signalsService.signal(
|
|
59
|
+
const quantity = signalsService.signal(config.editItemMode ? (config.editingItemValues?.quantity ?? 1) : 1);
|
|
60
|
+
const specialRequest = signalsService.signal(config.editItemMode
|
|
61
|
+
? (config.editingItemValues?.specialRequest ?? '')
|
|
62
|
+
: '');
|
|
61
63
|
const priceVariants = config.item?.priceVariants || [];
|
|
62
|
-
|
|
64
|
+
let initialVariant;
|
|
65
|
+
if (!config.editItemMode) {
|
|
66
|
+
initialVariant = priceVariants.length > 0 ? priceVariants[0] : undefined;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (config.editingItemValues?.selectedVariantId) {
|
|
70
|
+
initialVariant = priceVariants.find((variant) => variant._id === config.editingItemValues?.selectedVariantId);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
initialVariant =
|
|
74
|
+
priceVariants.length > 0 ? priceVariants[0] : undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
63
77
|
const selectedVariant = signalsService.signal(initialVariant);
|
|
64
78
|
const modifierGroups = config.item?.modifierGroups || [];
|
|
65
|
-
const initialSelectedModifiers = getModifiersInitState(modifierGroups);
|
|
79
|
+
const initialSelectedModifiers = getModifiersInitState(modifierGroups, config.editItemMode, config.editingItemValues?.selectedModifiers);
|
|
66
80
|
const selectedModifiers = signalsService.signal(initialSelectedModifiers);
|
|
67
81
|
const initialModifierGroupError = modifierGroups.reduce((acc, group) => {
|
|
68
82
|
if (group._id) {
|
|
@@ -121,7 +135,9 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
121
135
|
quantity.set(_quantity);
|
|
122
136
|
};
|
|
123
137
|
const updateSpecialRequest = (_specialRequest) => {
|
|
124
|
-
|
|
138
|
+
if (typeof _specialRequest === 'string') {
|
|
139
|
+
specialRequest.set(_specialRequest);
|
|
140
|
+
}
|
|
125
141
|
};
|
|
126
142
|
const updateSelectedVariant = (variant) => {
|
|
127
143
|
selectedVariant.set(variant);
|
|
@@ -148,6 +164,20 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
148
164
|
}
|
|
149
165
|
}
|
|
150
166
|
};
|
|
167
|
+
const doesModifierGroupHaveError = signalsService.computed(() => {
|
|
168
|
+
const currentSelectedModifiers = selectedModifiers.get();
|
|
169
|
+
const errors = {};
|
|
170
|
+
modifierGroups.forEach((group) => {
|
|
171
|
+
if (group._id) {
|
|
172
|
+
const selectedCount = (currentSelectedModifiers[group._id] || [])
|
|
173
|
+
.length;
|
|
174
|
+
const isValid = checkModifiersValidation(group.rule, selectedCount);
|
|
175
|
+
errors[group._id] = !isValid;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
modifierGroupError.set(errors);
|
|
179
|
+
return Object.values(errors).some((error) => error);
|
|
180
|
+
});
|
|
151
181
|
const toggleModifier = (modifierGroupId, modifierId, singleSelect = false) => {
|
|
152
182
|
const currentSelectedModifiers = selectedModifiers.get();
|
|
153
183
|
const modifierIds = getModifierIds(modifierGroupId, modifierId, singleSelect);
|
|
@@ -155,6 +185,11 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
155
185
|
...currentSelectedModifiers,
|
|
156
186
|
[modifierGroupId]: modifierIds,
|
|
157
187
|
});
|
|
188
|
+
const currentModifierGroupError = modifierGroupError.get();
|
|
189
|
+
modifierGroupError.set({
|
|
190
|
+
...currentModifierGroupError,
|
|
191
|
+
[modifierGroupId]: false,
|
|
192
|
+
});
|
|
158
193
|
};
|
|
159
194
|
const getSelectedModifiers = (modifierGroupId) => {
|
|
160
195
|
const currentSelectedModifiers = selectedModifiers.get();
|
|
@@ -180,6 +215,7 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
180
215
|
addToCartButtonDisabled,
|
|
181
216
|
price,
|
|
182
217
|
futureAvailability,
|
|
218
|
+
doesModifierGroupHaveError,
|
|
183
219
|
};
|
|
184
220
|
});
|
|
185
221
|
/**
|
|
@@ -5,7 +5,7 @@ interface ruleUtilsArgs {
|
|
|
5
5
|
minSelections: number;
|
|
6
6
|
maxSelections?: number | null;
|
|
7
7
|
}
|
|
8
|
-
export declare const getModifiersInitState: (modifierGroups: EnhancedModifierGroup[]) => Record<string, string[]>;
|
|
8
|
+
export declare const getModifiersInitState: (modifierGroups: EnhancedModifierGroup[], editingItemMode?: boolean, editItemSelectedModifiers?: Record<string, Array<string>>) => Record<string, string[]>;
|
|
9
9
|
export declare const isSingleSelectRule: (rule: NonNullable<EnhancedModifierGroup["rule"]>) => boolean | null | undefined;
|
|
10
10
|
export declare const getFirstPreSelectedModifier: (modifiers: EnhancedModifier[]) => string | null | undefined;
|
|
11
11
|
export declare const getPreSelectedModifiers: (modifiers: EnhancedModifier[]) => string[];
|
|
@@ -33,7 +33,8 @@ export declare const hasToChooseAtLeastOne: ({ required, minSelections, maxSelec
|
|
|
33
33
|
export declare const hasToChooseAtLeastX: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
34
34
|
export declare const chooseUpToX: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
35
35
|
export declare const hasToChooseBetweenXAndY: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
36
|
-
export declare const getRuleTypeMapValue: (ruleTypeMap: RuleTypeMap, ruleType: RuleType,
|
|
36
|
+
export declare const getRuleTypeMapValue: (ruleTypeMap: RuleTypeMap, ruleType: RuleType, rule: EnhancedModifierGroup["rule"]) => string | undefined;
|
|
37
|
+
export declare const checkModifiersValidation: (rule: EnhancedModifierGroup["rule"], selectedCount: number) => boolean;
|
|
37
38
|
export declare const getAreNotEnoughModifiersOfMandatoryModifierGroupInStock: (modifierGroups: EnhancedModifierGroup[]) => boolean;
|
|
38
39
|
export declare const getLineItemModifiers: (selectedModifiers: Record<string, Array<string>>, modifierGroups: EnhancedModifierGroup[], formatCurrency: (price?: number) => string) => {
|
|
39
40
|
id: string;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { AvailabilityStatus, RuleType, } from './common-types.js';
|
|
2
|
-
export const getModifiersInitState = (modifierGroups) => {
|
|
2
|
+
export const getModifiersInitState = (modifierGroups, editingItemMode, editItemSelectedModifiers) => {
|
|
3
3
|
const initialSelectedModifiers = {};
|
|
4
4
|
modifierGroups.forEach((group) => {
|
|
5
5
|
if (group._id) {
|
|
6
|
-
|
|
6
|
+
if (editingItemMode) {
|
|
7
|
+
const selectedModifiers = editItemSelectedModifiers?.[group._id ?? ''];
|
|
8
|
+
if (selectedModifiers) {
|
|
9
|
+
initialSelectedModifiers[group._id] = selectedModifiers;
|
|
10
|
+
}
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
7
13
|
const formModifiers = group.modifiers.map(convertModifierToFormModifier);
|
|
14
|
+
const isMultiSelectItem = !isSingleSelectRule(group.rule ?? {});
|
|
8
15
|
if (isMultiSelectItem) {
|
|
9
16
|
const preSelectedModifiers = getPreSelectedModifiers(formModifiers);
|
|
10
17
|
initialSelectedModifiers[group._id] = preSelectedModifiers;
|
|
@@ -80,62 +87,77 @@ export const hasToChooseBetweenXAndY = ({ required, minSelections, maxSelections
|
|
|
80
87
|
? minSelections > 0 && maxSelections > minSelections
|
|
81
88
|
: false
|
|
82
89
|
: false;
|
|
83
|
-
export const getRuleTypeMapValue = (ruleTypeMap, ruleType,
|
|
90
|
+
export const getRuleTypeMapValue = (ruleTypeMap, ruleType, rule) => {
|
|
84
91
|
const minSelections = rule?.minSelections ?? 0;
|
|
85
92
|
const maxSelections = rule?.maxSelections;
|
|
86
93
|
switch (ruleType) {
|
|
87
94
|
case RuleType.NO_LIMIT: {
|
|
88
95
|
const callback = ruleTypeMap[RuleType.NO_LIMIT];
|
|
89
96
|
if (callback) {
|
|
90
|
-
return callback(
|
|
97
|
+
return callback();
|
|
91
98
|
}
|
|
92
99
|
break;
|
|
93
100
|
}
|
|
94
101
|
case RuleType.CHOOSE_ONE: {
|
|
95
102
|
const callback = ruleTypeMap[RuleType.CHOOSE_ONE];
|
|
96
103
|
if (callback) {
|
|
97
|
-
return callback(
|
|
104
|
+
return callback();
|
|
98
105
|
}
|
|
99
106
|
break;
|
|
100
107
|
}
|
|
101
108
|
case RuleType.CHOOSE_X: {
|
|
102
109
|
const callback = ruleTypeMap[RuleType.CHOOSE_X];
|
|
103
110
|
if (callback) {
|
|
104
|
-
return callback(
|
|
111
|
+
return callback(minSelections);
|
|
105
112
|
}
|
|
106
113
|
break;
|
|
107
114
|
}
|
|
108
115
|
case RuleType.CHOOSE_AT_LEAST_ONE: {
|
|
109
116
|
const callback = ruleTypeMap[RuleType.CHOOSE_AT_LEAST_ONE];
|
|
110
117
|
if (callback) {
|
|
111
|
-
return callback(
|
|
118
|
+
return callback();
|
|
112
119
|
}
|
|
113
120
|
break;
|
|
114
121
|
}
|
|
115
122
|
case RuleType.CHOOSE_AT_LEAST_X: {
|
|
116
123
|
const callback = ruleTypeMap[RuleType.CHOOSE_AT_LEAST_X];
|
|
117
124
|
if (callback) {
|
|
118
|
-
return callback(
|
|
125
|
+
return callback(minSelections);
|
|
119
126
|
}
|
|
120
127
|
break;
|
|
121
128
|
}
|
|
122
129
|
case RuleType.CHOOSE_UP_TO_X: {
|
|
123
130
|
const callback = ruleTypeMap[RuleType.CHOOSE_UP_TO_X];
|
|
124
131
|
if (callback && maxSelections) {
|
|
125
|
-
return callback(
|
|
132
|
+
return callback(maxSelections);
|
|
126
133
|
}
|
|
127
134
|
break;
|
|
128
135
|
}
|
|
129
136
|
case RuleType.CHOOSE_BETWEEN_X_AND_Y: {
|
|
130
137
|
const callback = ruleTypeMap[RuleType.CHOOSE_BETWEEN_X_AND_Y];
|
|
131
138
|
if (callback && maxSelections) {
|
|
132
|
-
return callback(
|
|
139
|
+
return callback(minSelections, maxSelections);
|
|
133
140
|
}
|
|
134
141
|
break;
|
|
135
142
|
}
|
|
136
143
|
}
|
|
137
144
|
return undefined;
|
|
138
145
|
};
|
|
146
|
+
export const checkModifiersValidation = (rule, selectedCount) => {
|
|
147
|
+
const required = rule?.required ?? false;
|
|
148
|
+
const minSelections = rule?.minSelections ?? 0;
|
|
149
|
+
const maxSelections = rule?.maxSelections;
|
|
150
|
+
if (required && selectedCount === 0) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (selectedCount < minSelections) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
if (maxSelections && selectedCount > maxSelections) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
};
|
|
139
161
|
export const getAreNotEnoughModifiersOfMandatoryModifierGroupInStock = (modifierGroups) => modifierGroups.some((modifierGroup) => {
|
|
140
162
|
const isModifierGroupMandatory = modifierGroup.rule?.required;
|
|
141
163
|
const minimumRequiredModifiers = modifierGroup.rule?.minSelections ?? 0;
|
|
@@ -71,7 +71,7 @@ export declare const Variants: React.ForwardRefExoticComponent<ItemDetailsVarian
|
|
|
71
71
|
export interface SpecialRequestProps {
|
|
72
72
|
asChild?: boolean;
|
|
73
73
|
children?: AsChildChildren<{
|
|
74
|
-
|
|
74
|
+
value: string;
|
|
75
75
|
onChange: (value: string) => void;
|
|
76
76
|
}>;
|
|
77
77
|
/** Placeholder text for the textarea */
|
|
@@ -108,6 +108,7 @@ export interface AddToCartButtonProps {
|
|
|
108
108
|
/** Text label for the button */
|
|
109
109
|
label: React.ReactNode;
|
|
110
110
|
formattedPrice: string;
|
|
111
|
+
modifierGroupHasError: boolean;
|
|
111
112
|
}) => React.ReactNode;
|
|
112
113
|
}
|
|
113
114
|
export declare const AddToCartButton: React.ForwardRefExoticComponent<AddToCartButtonProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -39,7 +39,7 @@ export const Variants = React.forwardRef(({ children, className, asChild, varian
|
|
|
39
39
|
});
|
|
40
40
|
Variants.displayName = 'ItemDetails.Variants';
|
|
41
41
|
export const AddToCartButton = React.forwardRef(({ asChild, children, className, addToCartLabelMap, ...props }, ref) => {
|
|
42
|
-
return (_jsx(CoreItemDetails.LineItemComponent, { addToCartLabelMap: addToCartLabelMap, children: ({ lineItem, buttonState, addToCartButtonDisabled, loadingState, labelText, formattedPrice, }) => {
|
|
42
|
+
return (_jsx(CoreItemDetails.LineItemComponent, { addToCartLabelMap: addToCartLabelMap, children: ({ lineItem, buttonState, addToCartButtonDisabled, loadingState, labelText, formattedPrice, modifierGroupHasError, }) => {
|
|
43
43
|
const label = (_jsxs(_Fragment, { children: [_jsx("span", { children: labelText }), " ", _jsx("span", { children: " | " }), _jsx("span", { children: formattedPrice })] }));
|
|
44
44
|
return (_jsx(AsChildSlot, { asChild: asChild, className: className, customElement: children, customElementProps: {
|
|
45
45
|
buttonState,
|
|
@@ -49,6 +49,7 @@ export const AddToCartButton = React.forwardRef(({ asChild, children, className,
|
|
|
49
49
|
lineItems: [lineItem],
|
|
50
50
|
label,
|
|
51
51
|
formattedPrice,
|
|
52
|
+
modifierGroupHasError,
|
|
52
53
|
}, ref: ref, ...props, children: _jsx(Commerce.Actions.AddToCart, { asChild: false, label: label, className: className, lineItems: [lineItem], ...props, children: children({
|
|
53
54
|
lineItem,
|
|
54
55
|
buttonState,
|
|
@@ -56,6 +57,7 @@ export const AddToCartButton = React.forwardRef(({ asChild, children, className,
|
|
|
56
57
|
loadingState,
|
|
57
58
|
label,
|
|
58
59
|
formattedPrice,
|
|
60
|
+
modifierGroupHasError,
|
|
59
61
|
}) }) }));
|
|
60
62
|
} }));
|
|
61
63
|
});
|
|
@@ -44,12 +44,12 @@ export const Description = React.forwardRef(({ ruleTypeMap, className, asChild,
|
|
|
44
44
|
} }));
|
|
45
45
|
});
|
|
46
46
|
Description.displayName = 'ItemDetailsModifierGroup.Description';
|
|
47
|
-
export const Error = React.forwardRef(({ ruleTypeMap, className, asChild, children }, ref) => {
|
|
47
|
+
export const Error = React.forwardRef(({ ruleTypeMap, className, asChild, children, ...otherProps }, ref) => {
|
|
48
48
|
return (_jsx(GroupError, { ruleTypeMap: ruleTypeMap, children: ({ error }) => {
|
|
49
49
|
if (!error) {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
|
-
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild,
|
|
52
|
+
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, "data-testid": TestIds.modifierGroupError, className: className, customElement: children, customElementProps: { error }, content: error, ...otherProps, children: _jsx("p", { className: className, children: error }) }));
|
|
53
53
|
} }));
|
|
54
54
|
});
|
|
55
55
|
Error.displayName = 'ItemDetailsModifierGroup.Error';
|
|
@@ -26,6 +26,7 @@ interface ItemDetailsLineItemProps {
|
|
|
26
26
|
addToCartButtonDisabled: boolean;
|
|
27
27
|
labelText: string;
|
|
28
28
|
formattedPrice: string;
|
|
29
|
+
modifierGroupHasError: boolean;
|
|
29
30
|
}) => React.ReactNode;
|
|
30
31
|
}
|
|
31
32
|
export declare const LineItemComponent: React.FC<ItemDetailsLineItemProps>;
|
|
@@ -24,11 +24,14 @@ export const Root = ({ children, itemDetailsServiceConfig, }) => {
|
|
|
24
24
|
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ItemServiceDefinition, ItemService, config), children: children({ item: itemDetailsServiceConfig?.item ?? selectedItem }) }));
|
|
25
25
|
};
|
|
26
26
|
export const SpecialRequest = ({ children, }) => {
|
|
27
|
-
const [value, setValue] = useState('');
|
|
28
27
|
const service = useService(ItemServiceDefinition);
|
|
28
|
+
const initialSpecialRequest = service.specialRequest?.get?.() ?? '';
|
|
29
|
+
const [value, setValue] = useState(initialSpecialRequest);
|
|
29
30
|
const onChange = (newValue) => {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
if (typeof newValue === 'string') {
|
|
32
|
+
setValue(newValue);
|
|
33
|
+
service.updateSpecialRequest(newValue);
|
|
34
|
+
}
|
|
32
35
|
};
|
|
33
36
|
return children({
|
|
34
37
|
value,
|
|
@@ -48,6 +51,7 @@ export const LineItemComponent = ({ addToCartLabelMap, children, }) => {
|
|
|
48
51
|
const formatCurrency = oloSettingsService.formatCurrency;
|
|
49
52
|
const formattedPrice = formatCurrency(price);
|
|
50
53
|
const labelText = addToCartLabelMap[buttonState];
|
|
54
|
+
const modifierGroupHasError = service.doesModifierGroupHaveError?.get?.() ?? false;
|
|
51
55
|
return children({
|
|
52
56
|
loadingState,
|
|
53
57
|
lineItem,
|
|
@@ -55,6 +59,7 @@ export const LineItemComponent = ({ addToCartLabelMap, children, }) => {
|
|
|
55
59
|
addToCartButtonDisabled,
|
|
56
60
|
labelText,
|
|
57
61
|
formattedPrice,
|
|
62
|
+
modifierGroupHasError,
|
|
58
63
|
});
|
|
59
64
|
};
|
|
60
65
|
export const QuantityComponent = ({ children, }) => {
|
|
@@ -49,8 +49,7 @@ export const ModifiersComponent = ({ children, }) => {
|
|
|
49
49
|
};
|
|
50
50
|
export const Description = ({ ruleTypeMap, children, }) => {
|
|
51
51
|
const { ruleType, modifierGroup } = useModifiersContext();
|
|
52
|
-
const
|
|
53
|
-
const description = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroupName, modifierGroup.rule);
|
|
52
|
+
const description = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroup.rule);
|
|
54
53
|
return children({ description });
|
|
55
54
|
};
|
|
56
55
|
export const GroupError = ({ ruleTypeMap, children, }) => {
|
|
@@ -58,10 +57,9 @@ export const GroupError = ({ ruleTypeMap, children, }) => {
|
|
|
58
57
|
const { ruleType, modifierGroup } = useModifiersContext();
|
|
59
58
|
const groupId = modifierGroup._id || '';
|
|
60
59
|
const modifierGroupErrors = service.modifierGroupError?.get() || {};
|
|
61
|
-
const modifierGroupName = modifierGroup.name || '';
|
|
62
60
|
let error;
|
|
63
61
|
if (modifierGroupErrors[groupId]) {
|
|
64
|
-
error = getRuleTypeMapValue(ruleTypeMap, ruleType,
|
|
62
|
+
error = getRuleTypeMapValue(ruleTypeMap, ruleType, modifierGroup.rule);
|
|
65
63
|
}
|
|
66
64
|
return children({ error });
|
|
67
65
|
};
|
|
@@ -11,13 +11,13 @@ export declare enum RuleType {
|
|
|
11
11
|
CHOOSE_BETWEEN_X_AND_Y = "CHOOSE_BETWEEN_X_AND_Y"
|
|
12
12
|
}
|
|
13
13
|
export interface RuleTypeMap {
|
|
14
|
-
[RuleType.NO_LIMIT]?: (
|
|
15
|
-
[RuleType.CHOOSE_ONE]?: (
|
|
16
|
-
[RuleType.CHOOSE_X]?: (
|
|
17
|
-
[RuleType.CHOOSE_AT_LEAST_ONE]?: (
|
|
18
|
-
[RuleType.CHOOSE_AT_LEAST_X]?: (
|
|
19
|
-
[RuleType.CHOOSE_UP_TO_X]?: (
|
|
20
|
-
[RuleType.CHOOSE_BETWEEN_X_AND_Y]?: (
|
|
14
|
+
[RuleType.NO_LIMIT]?: () => string;
|
|
15
|
+
[RuleType.CHOOSE_ONE]?: () => string;
|
|
16
|
+
[RuleType.CHOOSE_X]?: (x: number) => string;
|
|
17
|
+
[RuleType.CHOOSE_AT_LEAST_ONE]?: () => string;
|
|
18
|
+
[RuleType.CHOOSE_AT_LEAST_X]?: (x: number) => string;
|
|
19
|
+
[RuleType.CHOOSE_UP_TO_X]?: (x: number) => string;
|
|
20
|
+
[RuleType.CHOOSE_BETWEEN_X_AND_Y]?: (x: number, y: number) => string;
|
|
21
21
|
}
|
|
22
22
|
export declare enum AvailabilityStatus {
|
|
23
23
|
AVAILABLE = 0,
|
|
@@ -43,6 +43,7 @@ export interface ItemServiceAPI {
|
|
|
43
43
|
endDate?: Date;
|
|
44
44
|
weeklyAvailabilitySummary?: WeeklyAvailability;
|
|
45
45
|
};
|
|
46
|
+
doesModifierGroupHaveError: ReadOnlySignal<boolean>;
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Service definition for the Item service.
|
|
@@ -67,6 +68,12 @@ export interface ItemServiceConfig {
|
|
|
67
68
|
operationId?: string;
|
|
68
69
|
availabilityStatus?: AvailabilityStatus;
|
|
69
70
|
editItemMode?: boolean;
|
|
71
|
+
editingItemValues?: {
|
|
72
|
+
quantity?: number;
|
|
73
|
+
specialRequest?: string;
|
|
74
|
+
selectedVariantId?: string;
|
|
75
|
+
selectedModifiers?: Record<string, Array<string>>;
|
|
76
|
+
};
|
|
70
77
|
menuId?: string;
|
|
71
78
|
sectionId?: string;
|
|
72
79
|
futureAvailability?: FutureAvailability;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineService, implementService } from '@wix/services-definitions';
|
|
2
2
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
3
3
|
import { AddToCartButtonState, AvailabilityStatus, } from './common-types.js';
|
|
4
|
-
import { getAreNotEnoughModifiersOfMandatoryModifierGroupInStock, getModifiersInitState, getLineItemModifiers, getPriceVariantOptions, getSelectedModifierPrices, getSelectedVariantPrice, calculateItemPrice, } from './utils.js';
|
|
4
|
+
import { getAreNotEnoughModifiersOfMandatoryModifierGroupInStock, getModifiersInitState, getLineItemModifiers, getPriceVariantOptions, getSelectedModifierPrices, getSelectedVariantPrice, calculateItemPrice, checkModifiersValidation, } from './utils.js';
|
|
5
5
|
import { OLOSettingsServiceDefinition } from './olo-settings-service.js';
|
|
6
6
|
/**
|
|
7
7
|
* Service definition for the Item service.
|
|
@@ -56,13 +56,27 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
56
56
|
const item = signalsService.signal(config.item);
|
|
57
57
|
const isLoading = signalsService.signal(!!config.item);
|
|
58
58
|
const error = signalsService.signal(config.item ? null : 'Item not found');
|
|
59
|
-
const quantity = signalsService.signal(1);
|
|
60
|
-
const specialRequest = signalsService.signal(
|
|
59
|
+
const quantity = signalsService.signal(config.editItemMode ? (config.editingItemValues?.quantity ?? 1) : 1);
|
|
60
|
+
const specialRequest = signalsService.signal(config.editItemMode
|
|
61
|
+
? (config.editingItemValues?.specialRequest ?? '')
|
|
62
|
+
: '');
|
|
61
63
|
const priceVariants = config.item?.priceVariants || [];
|
|
62
|
-
|
|
64
|
+
let initialVariant;
|
|
65
|
+
if (!config.editItemMode) {
|
|
66
|
+
initialVariant = priceVariants.length > 0 ? priceVariants[0] : undefined;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (config.editingItemValues?.selectedVariantId) {
|
|
70
|
+
initialVariant = priceVariants.find((variant) => variant._id === config.editingItemValues?.selectedVariantId);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
initialVariant =
|
|
74
|
+
priceVariants.length > 0 ? priceVariants[0] : undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
63
77
|
const selectedVariant = signalsService.signal(initialVariant);
|
|
64
78
|
const modifierGroups = config.item?.modifierGroups || [];
|
|
65
|
-
const initialSelectedModifiers = getModifiersInitState(modifierGroups);
|
|
79
|
+
const initialSelectedModifiers = getModifiersInitState(modifierGroups, config.editItemMode, config.editingItemValues?.selectedModifiers);
|
|
66
80
|
const selectedModifiers = signalsService.signal(initialSelectedModifiers);
|
|
67
81
|
const initialModifierGroupError = modifierGroups.reduce((acc, group) => {
|
|
68
82
|
if (group._id) {
|
|
@@ -121,7 +135,9 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
121
135
|
quantity.set(_quantity);
|
|
122
136
|
};
|
|
123
137
|
const updateSpecialRequest = (_specialRequest) => {
|
|
124
|
-
|
|
138
|
+
if (typeof _specialRequest === 'string') {
|
|
139
|
+
specialRequest.set(_specialRequest);
|
|
140
|
+
}
|
|
125
141
|
};
|
|
126
142
|
const updateSelectedVariant = (variant) => {
|
|
127
143
|
selectedVariant.set(variant);
|
|
@@ -148,6 +164,20 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
148
164
|
}
|
|
149
165
|
}
|
|
150
166
|
};
|
|
167
|
+
const doesModifierGroupHaveError = signalsService.computed(() => {
|
|
168
|
+
const currentSelectedModifiers = selectedModifiers.get();
|
|
169
|
+
const errors = {};
|
|
170
|
+
modifierGroups.forEach((group) => {
|
|
171
|
+
if (group._id) {
|
|
172
|
+
const selectedCount = (currentSelectedModifiers[group._id] || [])
|
|
173
|
+
.length;
|
|
174
|
+
const isValid = checkModifiersValidation(group.rule, selectedCount);
|
|
175
|
+
errors[group._id] = !isValid;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
modifierGroupError.set(errors);
|
|
179
|
+
return Object.values(errors).some((error) => error);
|
|
180
|
+
});
|
|
151
181
|
const toggleModifier = (modifierGroupId, modifierId, singleSelect = false) => {
|
|
152
182
|
const currentSelectedModifiers = selectedModifiers.get();
|
|
153
183
|
const modifierIds = getModifierIds(modifierGroupId, modifierId, singleSelect);
|
|
@@ -155,6 +185,11 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
155
185
|
...currentSelectedModifiers,
|
|
156
186
|
[modifierGroupId]: modifierIds,
|
|
157
187
|
});
|
|
188
|
+
const currentModifierGroupError = modifierGroupError.get();
|
|
189
|
+
modifierGroupError.set({
|
|
190
|
+
...currentModifierGroupError,
|
|
191
|
+
[modifierGroupId]: false,
|
|
192
|
+
});
|
|
158
193
|
};
|
|
159
194
|
const getSelectedModifiers = (modifierGroupId) => {
|
|
160
195
|
const currentSelectedModifiers = selectedModifiers.get();
|
|
@@ -180,6 +215,7 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
|
|
|
180
215
|
addToCartButtonDisabled,
|
|
181
216
|
price,
|
|
182
217
|
futureAvailability,
|
|
218
|
+
doesModifierGroupHaveError,
|
|
183
219
|
};
|
|
184
220
|
});
|
|
185
221
|
/**
|
package/dist/services/utils.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ interface ruleUtilsArgs {
|
|
|
5
5
|
minSelections: number;
|
|
6
6
|
maxSelections?: number | null;
|
|
7
7
|
}
|
|
8
|
-
export declare const getModifiersInitState: (modifierGroups: EnhancedModifierGroup[]) => Record<string, string[]>;
|
|
8
|
+
export declare const getModifiersInitState: (modifierGroups: EnhancedModifierGroup[], editingItemMode?: boolean, editItemSelectedModifiers?: Record<string, Array<string>>) => Record<string, string[]>;
|
|
9
9
|
export declare const isSingleSelectRule: (rule: NonNullable<EnhancedModifierGroup["rule"]>) => boolean | null | undefined;
|
|
10
10
|
export declare const getFirstPreSelectedModifier: (modifiers: EnhancedModifier[]) => string | null | undefined;
|
|
11
11
|
export declare const getPreSelectedModifiers: (modifiers: EnhancedModifier[]) => string[];
|
|
@@ -33,7 +33,8 @@ export declare const hasToChooseAtLeastOne: ({ required, minSelections, maxSelec
|
|
|
33
33
|
export declare const hasToChooseAtLeastX: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
34
34
|
export declare const chooseUpToX: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
35
35
|
export declare const hasToChooseBetweenXAndY: ({ required, minSelections, maxSelections, }: ruleUtilsArgs) => boolean;
|
|
36
|
-
export declare const getRuleTypeMapValue: (ruleTypeMap: RuleTypeMap, ruleType: RuleType,
|
|
36
|
+
export declare const getRuleTypeMapValue: (ruleTypeMap: RuleTypeMap, ruleType: RuleType, rule: EnhancedModifierGroup["rule"]) => string | undefined;
|
|
37
|
+
export declare const checkModifiersValidation: (rule: EnhancedModifierGroup["rule"], selectedCount: number) => boolean;
|
|
37
38
|
export declare const getAreNotEnoughModifiersOfMandatoryModifierGroupInStock: (modifierGroups: EnhancedModifierGroup[]) => boolean;
|
|
38
39
|
export declare const getLineItemModifiers: (selectedModifiers: Record<string, Array<string>>, modifierGroups: EnhancedModifierGroup[], formatCurrency: (price?: number) => string) => {
|
|
39
40
|
id: string;
|
package/dist/services/utils.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { AvailabilityStatus, RuleType, } from './common-types.js';
|
|
2
|
-
export const getModifiersInitState = (modifierGroups) => {
|
|
2
|
+
export const getModifiersInitState = (modifierGroups, editingItemMode, editItemSelectedModifiers) => {
|
|
3
3
|
const initialSelectedModifiers = {};
|
|
4
4
|
modifierGroups.forEach((group) => {
|
|
5
5
|
if (group._id) {
|
|
6
|
-
|
|
6
|
+
if (editingItemMode) {
|
|
7
|
+
const selectedModifiers = editItemSelectedModifiers?.[group._id ?? ''];
|
|
8
|
+
if (selectedModifiers) {
|
|
9
|
+
initialSelectedModifiers[group._id] = selectedModifiers;
|
|
10
|
+
}
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
7
13
|
const formModifiers = group.modifiers.map(convertModifierToFormModifier);
|
|
14
|
+
const isMultiSelectItem = !isSingleSelectRule(group.rule ?? {});
|
|
8
15
|
if (isMultiSelectItem) {
|
|
9
16
|
const preSelectedModifiers = getPreSelectedModifiers(formModifiers);
|
|
10
17
|
initialSelectedModifiers[group._id] = preSelectedModifiers;
|
|
@@ -80,62 +87,77 @@ export const hasToChooseBetweenXAndY = ({ required, minSelections, maxSelections
|
|
|
80
87
|
? minSelections > 0 && maxSelections > minSelections
|
|
81
88
|
: false
|
|
82
89
|
: false;
|
|
83
|
-
export const getRuleTypeMapValue = (ruleTypeMap, ruleType,
|
|
90
|
+
export const getRuleTypeMapValue = (ruleTypeMap, ruleType, rule) => {
|
|
84
91
|
const minSelections = rule?.minSelections ?? 0;
|
|
85
92
|
const maxSelections = rule?.maxSelections;
|
|
86
93
|
switch (ruleType) {
|
|
87
94
|
case RuleType.NO_LIMIT: {
|
|
88
95
|
const callback = ruleTypeMap[RuleType.NO_LIMIT];
|
|
89
96
|
if (callback) {
|
|
90
|
-
return callback(
|
|
97
|
+
return callback();
|
|
91
98
|
}
|
|
92
99
|
break;
|
|
93
100
|
}
|
|
94
101
|
case RuleType.CHOOSE_ONE: {
|
|
95
102
|
const callback = ruleTypeMap[RuleType.CHOOSE_ONE];
|
|
96
103
|
if (callback) {
|
|
97
|
-
return callback(
|
|
104
|
+
return callback();
|
|
98
105
|
}
|
|
99
106
|
break;
|
|
100
107
|
}
|
|
101
108
|
case RuleType.CHOOSE_X: {
|
|
102
109
|
const callback = ruleTypeMap[RuleType.CHOOSE_X];
|
|
103
110
|
if (callback) {
|
|
104
|
-
return callback(
|
|
111
|
+
return callback(minSelections);
|
|
105
112
|
}
|
|
106
113
|
break;
|
|
107
114
|
}
|
|
108
115
|
case RuleType.CHOOSE_AT_LEAST_ONE: {
|
|
109
116
|
const callback = ruleTypeMap[RuleType.CHOOSE_AT_LEAST_ONE];
|
|
110
117
|
if (callback) {
|
|
111
|
-
return callback(
|
|
118
|
+
return callback();
|
|
112
119
|
}
|
|
113
120
|
break;
|
|
114
121
|
}
|
|
115
122
|
case RuleType.CHOOSE_AT_LEAST_X: {
|
|
116
123
|
const callback = ruleTypeMap[RuleType.CHOOSE_AT_LEAST_X];
|
|
117
124
|
if (callback) {
|
|
118
|
-
return callback(
|
|
125
|
+
return callback(minSelections);
|
|
119
126
|
}
|
|
120
127
|
break;
|
|
121
128
|
}
|
|
122
129
|
case RuleType.CHOOSE_UP_TO_X: {
|
|
123
130
|
const callback = ruleTypeMap[RuleType.CHOOSE_UP_TO_X];
|
|
124
131
|
if (callback && maxSelections) {
|
|
125
|
-
return callback(
|
|
132
|
+
return callback(maxSelections);
|
|
126
133
|
}
|
|
127
134
|
break;
|
|
128
135
|
}
|
|
129
136
|
case RuleType.CHOOSE_BETWEEN_X_AND_Y: {
|
|
130
137
|
const callback = ruleTypeMap[RuleType.CHOOSE_BETWEEN_X_AND_Y];
|
|
131
138
|
if (callback && maxSelections) {
|
|
132
|
-
return callback(
|
|
139
|
+
return callback(minSelections, maxSelections);
|
|
133
140
|
}
|
|
134
141
|
break;
|
|
135
142
|
}
|
|
136
143
|
}
|
|
137
144
|
return undefined;
|
|
138
145
|
};
|
|
146
|
+
export const checkModifiersValidation = (rule, selectedCount) => {
|
|
147
|
+
const required = rule?.required ?? false;
|
|
148
|
+
const minSelections = rule?.minSelections ?? 0;
|
|
149
|
+
const maxSelections = rule?.maxSelections;
|
|
150
|
+
if (required && selectedCount === 0) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (selectedCount < minSelections) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
if (maxSelections && selectedCount > maxSelections) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
};
|
|
139
161
|
export const getAreNotEnoughModifiersOfMandatoryModifierGroupInStock = (modifierGroups) => modifierGroups.some((modifierGroup) => {
|
|
140
162
|
const isModifierGroupMandatory = modifierGroup.rule?.required;
|
|
141
163
|
const minimumRequiredModifiers = modifierGroup.rule?.minSelections ?? 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-restaurants-olo",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@radix-ui/react-slot": "^1.1.0",
|
|
57
57
|
"@wix/auto_sdk_restaurants_items": "^1.0.48",
|
|
58
58
|
"@wix/ecom": "^1.0.1461",
|
|
59
|
-
"@wix/headless-components": "0.0.
|
|
59
|
+
"@wix/headless-components": "0.0.30",
|
|
60
60
|
"@wix/headless-media": "0.0.17",
|
|
61
61
|
"@wix/headless-restaurants-menus": "0.0.20",
|
|
62
62
|
"@wix/headless-utils": "0.0.7",
|
|
@@ -76,5 +76,5 @@
|
|
|
76
76
|
"groupId": "com.wixpress.headless-components"
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
|
-
"falconPackageHash": "
|
|
79
|
+
"falconPackageHash": "8a5140aec5569bc45df3f464fbf17f0cdcbc5a879f3cb33e3acfbe36"
|
|
80
80
|
}
|