@wix/headless-bookings 1.0.19 → 1.0.20

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.
@@ -71,8 +71,18 @@ function buildBookingRequest(params) {
71
71
  ...(depositSelectedApplies && {
72
72
  depositSelected: params.depositSelected,
73
73
  }),
74
- // Participants
75
- totalParticipants: item.totalParticipants || 1,
74
+ ...(item.priceChoices?.length
75
+ ? {
76
+ participantsChoices: {
77
+ serviceChoices: [
78
+ {
79
+ numberOfParticipants: item.totalParticipants || 1,
80
+ choices: item.priceChoices,
81
+ },
82
+ ],
83
+ },
84
+ }
85
+ : { totalParticipants: item.totalParticipants || 1 }),
76
86
  // App that created the booking (used to filter bookings by source app).
77
87
  ...(params.sourceAppId && {
78
88
  bookingSource: { appDefId: params.sourceAppId },
@@ -45,7 +45,12 @@ function buildDayRangeBookingRequest(params) {
45
45
  // fields (service, resource, location, payment, participants) are derived
46
46
  // exactly once and consistently. Each per-day Booking is then a shallow
47
47
  // clone with only the slot start/end overridden from `slots[i]`.
48
- const baseSelection = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
48
+ const isOneBooking = params.allDay || slots.length === 1;
49
+ const withSlot = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
50
+ // A Booking per day may not carry another day's rules.
51
+ const baseSelection = isOneBooking
52
+ ? withSlot
53
+ : { ...withSlot, priceChoices: undefined };
49
54
  const baseRequest = (0, buildBookingRequest_js_1.buildBookingRequest)({
50
55
  ...params,
51
56
  serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
@@ -6,6 +6,7 @@
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { Service, V2Location as ServiceLocationType } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix/auto_sdk_bookings_availability-time-slots';
9
+ import type { ServiceChoice } from '@wix/auto_sdk_bookings_bookings';
9
10
  import type { FormValues } from '@wix/forms/components';
10
11
  import type { BookResult, SelectedPaymentOption } from './book-action/types.js';
11
12
  export type { SelectedPaymentOption } from './book-action/types.js';
@@ -56,7 +57,11 @@ export interface ServiceSelection {
56
57
  rangeTimeSlots?: ServiceSelectionTimeSlot[];
57
58
  /** Number of participants for this service selection */
58
59
  totalParticipants?: number;
60
+ /** Date & time pricing rules to record on the booking (at most five). */
61
+ priceChoices?: ServiceChoice[];
59
62
  }
63
+ /** Rules priced for the old dates don't follow the slot to new ones. */
64
+ export declare function applySelectionUpdates(item: ServiceSelection, updates: Partial<Omit<ServiceSelection, 'instanceId'>>): ServiceSelection;
60
65
  /**
61
66
  * BookingService actions - setters only, no API calls
62
67
  */
@@ -6,6 +6,7 @@
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.BookingService = exports.BookingServiceDefinition = void 0;
9
+ exports.applySelectionUpdates = applySelectionUpdates;
9
10
  const services_definitions_1 = require("@wix/services-definitions");
10
11
  const signals_1 = require("@wix/services-definitions/core-services/signals");
11
12
  const bookAction_js_1 = require("./book-action/bookAction.js");
@@ -30,6 +31,17 @@ function getClientTimezone() {
30
31
  ? Intl.DateTimeFormat().resolvedOptions().timeZone
31
32
  : undefined;
32
33
  }
34
+ const datesOf = (selection) => JSON.stringify([selection.timeSlot, ...(selection.rangeTimeSlots ?? [])].map((slot) => [
35
+ slot?.startDate,
36
+ slot?.endDate,
37
+ ]));
38
+ /** Rules priced for the old dates don't follow the slot to new ones. */
39
+ function applySelectionUpdates(item, updates) {
40
+ const updated = { ...item, ...updates };
41
+ return datesOf(updated) !== datesOf(item) && !('priceChoices' in updates)
42
+ ? { ...updated, priceChoices: undefined }
43
+ : updated;
44
+ }
33
45
  /**
34
46
  * Service definition for Booking
35
47
  */
@@ -117,7 +129,9 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
117
129
  const current = serviceSelectionsSignal.get();
118
130
  // If no instanceId provided, update the first item (index 0)
119
131
  const targetId = instanceId ?? current[0]?.instanceId;
120
- const updated = current.map((item) => item.instanceId === targetId ? { ...item, ...updates } : item);
132
+ const updated = current.map((item) => item.instanceId === targetId
133
+ ? applySelectionUpdates(item, updates)
134
+ : item);
121
135
  serviceSelectionsSignal.set(updated);
122
136
  },
123
137
  removeItem(instanceId) {
@@ -40,9 +40,9 @@ export interface AppliedAdditionalFee {
40
40
  /** The service's additional fee ID. */
41
41
  feeId?: string;
42
42
  /** Units the fee was charged for (1 for a per-reservation fee). */
43
- units?: number;
43
+ units?: number | null;
44
44
  /** The fee amount for this line. */
45
- amount?: number;
45
+ amount?: number | null;
46
46
  }
47
47
  /**
48
48
  * `PriceInfo` with the additional-fee fields `previewPrice` serves, which the
@@ -167,7 +167,7 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
167
167
  serviceId: item.service._id,
168
168
  localStartDate: slot.localStartDate,
169
169
  localEndDate: slot.localEndDate,
170
- numberOfParticipants: totalParticipants,
170
+ serviceChoices: [{ numberOfParticipants: totalParticipants }],
171
171
  ...(item.timeZone ? { timeZone: item.timeZone } : {}),
172
172
  }));
173
173
  const priceInfo = await getPreviewedPrice(bookingLineItems).catch(() => null);
@@ -68,8 +68,18 @@ export function buildBookingRequest(params) {
68
68
  ...(depositSelectedApplies && {
69
69
  depositSelected: params.depositSelected,
70
70
  }),
71
- // Participants
72
- totalParticipants: item.totalParticipants || 1,
71
+ ...(item.priceChoices?.length
72
+ ? {
73
+ participantsChoices: {
74
+ serviceChoices: [
75
+ {
76
+ numberOfParticipants: item.totalParticipants || 1,
77
+ choices: item.priceChoices,
78
+ },
79
+ ],
80
+ },
81
+ }
82
+ : { totalParticipants: item.totalParticipants || 1 }),
73
83
  // App that created the booking (used to filter bookings by source app).
74
84
  ...(params.sourceAppId && {
75
85
  bookingSource: { appDefId: params.sourceAppId },
@@ -42,7 +42,12 @@ export function buildDayRangeBookingRequest(params) {
42
42
  // fields (service, resource, location, payment, participants) are derived
43
43
  // exactly once and consistently. Each per-day Booking is then a shallow
44
44
  // clone with only the slot start/end overridden from `slots[i]`.
45
- const baseSelection = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
45
+ const isOneBooking = params.allDay || slots.length === 1;
46
+ const withSlot = item.timeSlot ? item : { ...item, timeSlot: slots[0] };
47
+ // A Booking per day may not carry another day's rules.
48
+ const baseSelection = isOneBooking
49
+ ? withSlot
50
+ : { ...withSlot, priceChoices: undefined };
46
51
  const baseRequest = buildBookingRequest({
47
52
  ...params,
48
53
  serviceSelections: [baseSelection, ...params.serviceSelections.slice(1)],
@@ -6,6 +6,7 @@
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { Service, V2Location as ServiceLocationType } from '@wix/auto_sdk_bookings_services';
8
8
  import type { Resource, EventInfo, Location as TimeSlotLocationType } from '@wix/auto_sdk_bookings_availability-time-slots';
9
+ import type { ServiceChoice } from '@wix/auto_sdk_bookings_bookings';
9
10
  import type { FormValues } from '@wix/forms/components';
10
11
  import type { BookResult, SelectedPaymentOption } from './book-action/types.js';
11
12
  export type { SelectedPaymentOption } from './book-action/types.js';
@@ -56,7 +57,11 @@ export interface ServiceSelection {
56
57
  rangeTimeSlots?: ServiceSelectionTimeSlot[];
57
58
  /** Number of participants for this service selection */
58
59
  totalParticipants?: number;
60
+ /** Date & time pricing rules to record on the booking (at most five). */
61
+ priceChoices?: ServiceChoice[];
59
62
  }
63
+ /** Rules priced for the old dates don't follow the slot to new ones. */
64
+ export declare function applySelectionUpdates(item: ServiceSelection, updates: Partial<Omit<ServiceSelection, 'instanceId'>>): ServiceSelection;
60
65
  /**
61
66
  * BookingService actions - setters only, no API calls
62
67
  */
@@ -27,6 +27,17 @@ function getClientTimezone() {
27
27
  ? Intl.DateTimeFormat().resolvedOptions().timeZone
28
28
  : undefined;
29
29
  }
30
+ const datesOf = (selection) => JSON.stringify([selection.timeSlot, ...(selection.rangeTimeSlots ?? [])].map((slot) => [
31
+ slot?.startDate,
32
+ slot?.endDate,
33
+ ]));
34
+ /** Rules priced for the old dates don't follow the slot to new ones. */
35
+ export function applySelectionUpdates(item, updates) {
36
+ const updated = { ...item, ...updates };
37
+ return datesOf(updated) !== datesOf(item) && !('priceChoices' in updates)
38
+ ? { ...updated, priceChoices: undefined }
39
+ : updated;
40
+ }
30
41
  /**
31
42
  * Service definition for Booking
32
43
  */
@@ -114,7 +125,9 @@ export const BookingService = implementService.withConfig()(BookingServiceDefini
114
125
  const current = serviceSelectionsSignal.get();
115
126
  // If no instanceId provided, update the first item (index 0)
116
127
  const targetId = instanceId ?? current[0]?.instanceId;
117
- const updated = current.map((item) => item.instanceId === targetId ? { ...item, ...updates } : item);
128
+ const updated = current.map((item) => item.instanceId === targetId
129
+ ? applySelectionUpdates(item, updates)
130
+ : item);
118
131
  serviceSelectionsSignal.set(updated);
119
132
  },
120
133
  removeItem(instanceId) {
@@ -40,9 +40,9 @@ export interface AppliedAdditionalFee {
40
40
  /** The service's additional fee ID. */
41
41
  feeId?: string;
42
42
  /** Units the fee was charged for (1 for a per-reservation fee). */
43
- units?: number;
43
+ units?: number | null;
44
44
  /** The fee amount for this line. */
45
- amount?: number;
45
+ amount?: number | null;
46
46
  }
47
47
  /**
48
48
  * `PriceInfo` with the additional-fee fields `previewPrice` serves, which the
@@ -162,7 +162,7 @@ async function buildLineItemWithPreview(item, totalParticipants, selectedPayment
162
162
  serviceId: item.service._id,
163
163
  localStartDate: slot.localStartDate,
164
164
  localEndDate: slot.localEndDate,
165
- numberOfParticipants: totalParticipants,
165
+ serviceChoices: [{ numberOfParticipants: totalParticipants }],
166
166
  ...(item.timeZone ? { timeZone: item.timeZone } : {}),
167
167
  }));
168
168
  const priceInfo = await getPreviewedPrice(bookingLineItems).catch(() => null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -37,10 +37,10 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@wix/auto_sdk_bookings_availability-time-slots": "^1.0.244",
40
- "@wix/auto_sdk_bookings_bookings": "^1.0.192",
40
+ "@wix/auto_sdk_bookings_bookings": "^1.0.262",
41
41
  "@wix/auto_sdk_bookings_catalog-search": "^1.0.2",
42
42
  "@wix/auto_sdk_bookings_event-time-slots": "^1.0.112",
43
- "@wix/auto_sdk_bookings_pricing": "^1.0.87",
43
+ "@wix/auto_sdk_bookings_pricing": "^1.0.117",
44
44
  "@wix/auto_sdk_bookings_services": "^1.0.265",
45
45
  "@wix/auto_sdk_ecom_cart-v-2": "^1.0.86",
46
46
  "@wix/forms": "^1.0.384",
@@ -91,5 +91,5 @@
91
91
  "groupId": "com.wixpress.headless-components"
92
92
  }
93
93
  },
94
- "falconPackageHash": "025aaf3ecf64a7ef23fcc40e8cad3993079c8c4a92038520589a77a2"
94
+ "falconPackageHash": "4cfe5a2f1743c1743eb4892fd20c8ed27a7e6b69813c2727bb0f1100"
95
95
  }