@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.
@@ -1,5 +1,8 @@
1
1
  import { defineService, implementService } from '@wix/services-definitions';
2
2
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
+ import { OLOSettingsServiceDefinition } from './olo-settings-service.js';
4
+ import { AvailabilityStatus } from './common-types.js';
5
+ import { getModifiersInitState } from './utils.js';
3
6
  /**
4
7
  * Service definition for the Item service.
5
8
  * This defines the contract that the ItemService must implement.
@@ -43,6 +46,11 @@ export const ItemServiceDefinition = defineService('item');
43
46
  const APP_ID = '9a5d83fd-8570-482e-81ab-cfa88942ee60';
44
47
  export const ItemService = implementService.withConfig()(ItemServiceDefinition, ({ getService, config }) => {
45
48
  const signalsService = getService(SignalsServiceDefinition);
49
+ const oloSettingsService = getService(OLOSettingsServiceDefinition);
50
+ const getAvailabilityStatusFn = oloSettingsService.getAvailabilityStatus?.get?.();
51
+ const initialAvailabilityStatus = getAvailabilityStatusFn?.(config.menuId ?? '') ??
52
+ AvailabilityStatus.AVAILABLE;
53
+ const availabilityStatus = signalsService.signal(initialAvailabilityStatus);
46
54
  const item = signalsService.signal(config.item);
47
55
  const isLoading = signalsService.signal(!!config.item);
48
56
  const error = signalsService.signal(config.item ? null : 'Item not found');
@@ -52,6 +60,9 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
52
60
  const priceVariants = config.item?.priceVariants || [];
53
61
  const initialVariant = priceVariants.length > 0 ? priceVariants[0] : undefined;
54
62
  const selectedVariant = signalsService.signal(initialVariant);
63
+ const modifierGroups = config.item?.modifierGroups || [];
64
+ const initialSelectedModifiers = getModifiersInitState(modifierGroups);
65
+ const selectedModifiers = signalsService.signal(initialSelectedModifiers);
55
66
  if (config.item) {
56
67
  console.log('config.item', config.item);
57
68
  lineItem.set({
@@ -95,17 +106,55 @@ export const ItemService = implementService.withConfig()(ItemServiceDefinition,
95
106
  const updateSelectedVariant = (variant) => {
96
107
  selectedVariant.set(variant);
97
108
  };
109
+ const getModifierIds = (modifierGroupId, modifierId, singleSelect = false) => {
110
+ const currentSelectedModifiers = selectedModifiers.get();
111
+ const groupModifierIds = currentSelectedModifiers[modifierGroupId] || [];
112
+ // Check if this modifier is already selected
113
+ const isModifierSelected = groupModifierIds.includes(modifierId);
114
+ if (singleSelect) {
115
+ // Single select behavior: select the modifier, replacing any existing selection
116
+ return [modifierId];
117
+ }
118
+ else {
119
+ // Multi-select behavior: toggle the modifier
120
+ if (isModifierSelected) {
121
+ // Remove the modifier if it exists
122
+ const updatedModifierIds = groupModifierIds.filter((id) => id !== modifierId);
123
+ return updatedModifierIds;
124
+ }
125
+ else {
126
+ // Add the modifier to the existing selection
127
+ return [...groupModifierIds, modifierId];
128
+ }
129
+ }
130
+ };
131
+ const toggleModifier = (modifierGroupId, modifierId, singleSelect = false) => {
132
+ const currentSelectedModifiers = selectedModifiers.get();
133
+ const modifierIds = getModifierIds(modifierGroupId, modifierId, singleSelect);
134
+ selectedModifiers.set({
135
+ ...currentSelectedModifiers,
136
+ [modifierGroupId]: modifierIds,
137
+ });
138
+ };
139
+ const getSelectedModifiers = (modifierGroupId) => {
140
+ const currentSelectedModifiers = selectedModifiers.get();
141
+ return currentSelectedModifiers[modifierGroupId] || [];
142
+ };
98
143
  return {
99
144
  item,
100
145
  quantity,
101
146
  updateQuantity,
102
147
  updateSpecialRequest,
103
148
  updateSelectedVariant,
149
+ toggleModifier,
104
150
  isLoading,
105
151
  error,
106
152
  specialRequest,
107
153
  lineItem,
108
154
  selectedVariant,
155
+ selectedModifiers,
156
+ availabilityStatus,
157
+ getSelectedModifiers,
109
158
  };
110
159
  });
111
160
  /**
@@ -1,16 +1,21 @@
1
1
  import * as operationGroupsApi from '@wix/auto_sdk_restaurants_operation-groups';
2
2
  import * as operationsApi from '@wix/auto_sdk_restaurants_operations';
3
3
  import { type Signal } from '@wix/services-definitions/core-services/signals';
4
+ import { AvailabilityStatus } from './common-types.js';
4
5
  export interface OLOSettingsServiceAPI {
5
6
  operationGroup: Signal<operationGroupsApi.OperationGroup | undefined>;
6
7
  operation: Signal<operationsApi.Operation | undefined>;
7
8
  selectedItem?: Signal<unknown>;
8
9
  isLoading: Signal<boolean>;
9
10
  error: Signal<string | null>;
11
+ getAvailabilityStatus: Signal<(menuId: string) => AvailabilityStatus>;
12
+ availabilityDispatchAction?: Signal<(() => void) | undefined>;
10
13
  }
11
14
  export interface OLOSettingsServiceConfig {
12
15
  operationGroup?: operationGroupsApi.OperationGroup;
13
16
  operation?: operationsApi.Operation;
17
+ availabilityStatusMenuMap: Record<string, AvailabilityStatus>;
18
+ availabilityDispatchAction?: () => void;
14
19
  }
15
20
  export declare const OLOSettingsServiceDefinition: string & {
16
21
  __api: OLOSettingsServiceAPI;
@@ -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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-restaurants-olo",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "npm run build:esm && npm run build:cjs",
@@ -48,11 +48,12 @@
48
48
  "vitest": "^3.1.4"
49
49
  },
50
50
  "dependencies": {
51
+ "@radix-ui/react-checkbox": "^1.3.3",
51
52
  "@radix-ui/react-radio-group": "^1.1.3",
52
53
  "@radix-ui/react-slot": "^1.1.0",
53
54
  "@wix/auto_sdk_restaurants_items": "^1.0.48",
54
55
  "@wix/headless-media": "0.0.15",
55
- "@wix/headless-restaurants-menus": "^0.0.10",
56
+ "@wix/headless-restaurants-menus": "^0.0.12",
56
57
  "@wix/headless-utils": "^0.0.4",
57
58
  "@wix/redirects": "^1.0.0",
58
59
  "@wix/restaurants": "^1.0.396",