@wix/headless-bookings 0.0.104 → 0.0.106
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/__mocks__/booking/booking-client-service.js +25 -20
- package/cjs/dist/__mocks__/booking/booking-mocks.js +28 -20
- package/cjs/dist/__mocks__/payment/payment-mocks.js +6 -3
- package/cjs/dist/__mocks__/services/services-mocks.js +79 -74
- package/cjs/dist/__mocks__/time-slots/time-slots-client-service.js +39 -33
- package/cjs/dist/__mocks__/time-slots/time-slots-core.js +43 -33
- package/cjs/dist/__mocks__/time-slots/time-slots-mocks.js +18 -13
- package/cjs/dist/api/create-booking/index.js +6 -3
- package/cjs/dist/api/create-checkout/index.js +9 -4
- package/cjs/dist/api/create-order/index.js +6 -3
- package/cjs/dist/api/fetch-availability/index.js +18 -15
- package/cjs/dist/api/index.js +24 -7
- package/cjs/dist/api/query-categories/index.js +6 -3
- package/cjs/dist/api/query-locations/index.js +9 -5
- package/cjs/dist/api/query-services/index.js +24 -17
- package/cjs/dist/react/booking/Book.js +51 -12
- package/cjs/dist/react/booking/Booking.js +68 -26
- package/cjs/dist/react/booking/BookingItem.d.ts +2 -0
- package/cjs/dist/react/booking/BookingItem.js +57 -16
- package/cjs/dist/react/booking-form/BookingForm.js +63 -21
- package/cjs/dist/react/core/booking/Book.js +14 -11
- package/cjs/dist/react/core/booking/Booking.d.ts +3 -1
- package/cjs/dist/react/core/booking/Booking.js +38 -25
- package/cjs/dist/react/core/booking-form/BookingForm.js +63 -26
- package/cjs/dist/react/core/location/Location.js +60 -21
- package/cjs/dist/react/core/location-list/LocationList.js +15 -10
- package/cjs/dist/react/core/payment/Payment.js +41 -30
- package/cjs/dist/react/core/service/Service.js +28 -19
- package/cjs/dist/react/core/service/ServiceMediaCover.js +7 -4
- package/cjs/dist/react/core/service/ServiceMediaGallery.js +7 -4
- package/cjs/dist/react/core/service/ServiceMediaMain.js +7 -4
- package/cjs/dist/react/core/service-list/ServiceList.js +12 -8
- package/cjs/dist/react/core/service-list/ServiceListFilter.js +9 -6
- package/cjs/dist/react/core/staff-member/StaffMember.js +20 -14
- package/cjs/dist/react/core/staff-member-list/StaffMemberList.js +19 -14
- package/cjs/dist/react/core/time-slot-list/TimeSlot.js +41 -28
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +21 -15
- package/cjs/dist/react/index.js +49 -13
- package/cjs/dist/react/location/Location.js +76 -36
- package/cjs/dist/react/location/LocationList.js +70 -31
- package/cjs/dist/react/payment/Payment.js +87 -48
- package/cjs/dist/react/service/Service.js +197 -158
- package/cjs/dist/react/service/ServiceMedia.js +56 -17
- package/cjs/dist/react/service-list/ServiceList.js +71 -32
- package/cjs/dist/react/staff-member/StaffMember.js +61 -20
- package/cjs/dist/react/staff-member/StaffMemberList.js +68 -29
- package/cjs/dist/react/time-slot-list/TimeSlot.js +95 -56
- package/cjs/dist/react/time-slot-list/TimeSlotList.js +87 -48
- package/cjs/dist/services/booking/book-action/bookAction.js +21 -18
- package/cjs/dist/services/booking/book-action/buildBookingRequest.js +18 -15
- package/cjs/dist/services/booking/book-action/buildCheckoutRequest.js +8 -5
- package/cjs/dist/services/booking/book-action/canBook.js +4 -1
- package/cjs/dist/services/booking/book-action/index.js +15 -6
- package/cjs/dist/services/booking/book-action/isCheckoutRequired.js +4 -1
- package/cjs/dist/services/booking/book-action/types.js +5 -2
- package/cjs/dist/services/booking/booking.js +11 -8
- package/cjs/dist/services/booking-form/booking-form.js +26 -18
- package/cjs/dist/services/booking-form/utils.js +10 -4
- package/cjs/dist/services/constants.js +6 -3
- package/cjs/dist/services/index.js +48 -10
- package/cjs/dist/services/location-list/location-list.def.js +7 -5
- package/cjs/dist/services/location-list/location-list.js +31 -23
- package/cjs/dist/services/payment/payment.def.js +5 -2
- package/cjs/dist/services/payment/payment.js +22 -17
- package/cjs/dist/services/service/service.js +33 -29
- package/cjs/dist/services/service-list/service-list.js +22 -18
- package/cjs/dist/services/staff-member-list/staff-member-list.def.js +5 -2
- package/cjs/dist/services/staff-member-list/staff-member-list.js +16 -10
- package/cjs/dist/services/time-slot-list/index.js +12 -3
- package/cjs/dist/services/time-slot-list/time-slot-list.def.js +8 -5
- package/cjs/dist/services/time-slot-list/time-slot-list.js +24 -19
- package/cjs/dist/services/time-slot-list/time-slot.js +9 -6
- package/cjs/dist/utils/dateAndTime.js +7 -2
- package/cjs/dist/utils/guid.js +4 -1
- package/cjs/dist/utils/index.js +5 -1
- package/cjs/dist/utils/money.js +6 -2
- package/cjs/dist/utils/navigation.js +6 -3
- package/dist/react/booking/BookingItem.d.ts +2 -0
- package/dist/react/booking/BookingItem.js +2 -2
- package/dist/react/core/booking/Booking.d.ts +3 -1
- package/dist/react/core/booking/Booking.js +3 -2
- package/package.json +3 -3
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* TimeSlotList Service Implementation
|
|
3
4
|
* Manages time slot fetching, selection, and state
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TimeSlotListService = exports.getStaffName = void 0;
|
|
8
|
+
exports.loadTimeSlotListConfig = loadTimeSlotListConfig;
|
|
9
|
+
const services_definitions_1 = require("@wix/services-definitions");
|
|
10
|
+
const signals_1 = require("@wix/services-definitions/core-services/signals");
|
|
11
|
+
const time_slot_list_def_js_1 = require("./time-slot-list.def.js");
|
|
12
|
+
const auto_sdk_bookings_event_time_slots_1 = require("@wix/auto_sdk_bookings_event-time-slots");
|
|
13
|
+
const index_js_1 = require("../../api/fetch-availability/index.js");
|
|
14
|
+
const booking_js_1 = require("../booking/booking.js");
|
|
11
15
|
// ============================================================================
|
|
12
16
|
// Helpers
|
|
13
17
|
// ============================================================================
|
|
@@ -20,22 +24,23 @@ const getClientTimezone = () => {
|
|
|
20
24
|
* Helper to get staff member name from time slots by ID
|
|
21
25
|
* @internal - exported for testing
|
|
22
26
|
*/
|
|
23
|
-
|
|
27
|
+
const getStaffName = (staffMemberId, slots) => {
|
|
24
28
|
return (slots
|
|
25
29
|
.flatMap((slot) => slot.availableResources[0].resources)
|
|
26
30
|
.find((r) => r._id === staffMemberId)?.name ?? undefined);
|
|
27
31
|
};
|
|
32
|
+
exports.getStaffName = getStaffName;
|
|
28
33
|
// ============================================================================
|
|
29
34
|
// Service Implementation
|
|
30
35
|
// ============================================================================
|
|
31
|
-
|
|
32
|
-
const signalsService = getService(SignalsServiceDefinition);
|
|
33
|
-
const bookingService = getService(BookingServiceDefinition);
|
|
36
|
+
exports.TimeSlotListService = services_definitions_1.implementService.withConfig()(time_slot_list_def_js_1.TimeSlotListServiceDefinition, ({ getService, config }) => {
|
|
37
|
+
const signalsService = getService(signals_1.SignalsServiceDefinition);
|
|
38
|
+
const bookingService = getService(booking_js_1.BookingServiceDefinition);
|
|
34
39
|
const timeSlotsSignal = signalsService.signal(config.timeSlots || []);
|
|
35
40
|
const isLoadingSignal = signalsService.signal(false);
|
|
36
41
|
const errorSignal = signalsService.signal(null);
|
|
37
42
|
const hasMoreSignal = signalsService.signal(false);
|
|
38
|
-
const viewModeSignal = signalsService.signal(ViewMode.CLASSIC);
|
|
43
|
+
const viewModeSignal = signalsService.signal(time_slot_list_def_js_1.ViewMode.CLASSIC);
|
|
39
44
|
const dateRangeSignal = signalsService.signal({
|
|
40
45
|
start: config.startDate,
|
|
41
46
|
end: config.endDate,
|
|
@@ -56,8 +61,8 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
56
61
|
const getFilters = () => {
|
|
57
62
|
const baseFilters = config.filters ?? {};
|
|
58
63
|
const selectedLocation = bookingService.location.peek();
|
|
59
|
-
const isCustomOrCustomerLocation = selectedLocation?.type === LocationType.CUSTOM ||
|
|
60
|
-
selectedLocation?.type === LocationType.CUSTOMER;
|
|
64
|
+
const isCustomOrCustomerLocation = selectedLocation?.type === auto_sdk_bookings_event_time_slots_1.LocationType.CUSTOM ||
|
|
65
|
+
selectedLocation?.type === auto_sdk_bookings_event_time_slots_1.LocationType.CUSTOMER;
|
|
61
66
|
const location = selectedLocation
|
|
62
67
|
? {
|
|
63
68
|
id: isCustomOrCustomerLocation ? undefined : selectedLocation._id,
|
|
@@ -75,7 +80,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
75
80
|
cursorSignal.set(undefined);
|
|
76
81
|
timeSlotsSignal.set([]);
|
|
77
82
|
try {
|
|
78
|
-
const response = await fetchAvailability({
|
|
83
|
+
const response = await (0, index_js_1.fetchAvailability)({
|
|
79
84
|
services: getServices(),
|
|
80
85
|
timeZone: bookingService.timezone.peek(),
|
|
81
86
|
viewMode: viewModeSignal.peek(),
|
|
@@ -109,7 +114,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
109
114
|
? [
|
|
110
115
|
{
|
|
111
116
|
_id: preSelectedStaffMemberIdSignal.peek(),
|
|
112
|
-
name: getStaffName(preSelectedStaffMemberIdSignal.peek(), timeSlotsSignal.peek()),
|
|
117
|
+
name: (0, exports.getStaffName)(preSelectedStaffMemberIdSignal.peek(), timeSlotsSignal.peek()),
|
|
113
118
|
},
|
|
114
119
|
]
|
|
115
120
|
: [];
|
|
@@ -138,7 +143,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
138
143
|
const resources = [
|
|
139
144
|
{
|
|
140
145
|
_id: staffMemberId,
|
|
141
|
-
name: getStaffName(staffMemberId, timeSlotsSignal.peek()),
|
|
146
|
+
name: (0, exports.getStaffName)(staffMemberId, timeSlotsSignal.peek()),
|
|
142
147
|
},
|
|
143
148
|
];
|
|
144
149
|
bookingService.actions.updateItem({
|
|
@@ -170,7 +175,7 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
170
175
|
isLoadingSignal.set(true);
|
|
171
176
|
errorSignal.set(null);
|
|
172
177
|
try {
|
|
173
|
-
const response = await fetchAvailability({
|
|
178
|
+
const response = await (0, index_js_1.fetchAvailability)({
|
|
174
179
|
services: getServices(),
|
|
175
180
|
fromLocalDate: dateRangeSignal.peek().start,
|
|
176
181
|
toLocalDate: dateRangeSignal.peek().end,
|
|
@@ -256,9 +261,9 @@ export const TimeSlotListService = implementService.withConfig()(TimeSlotListSer
|
|
|
256
261
|
* const timeSlotListConfig = loadResult.config;
|
|
257
262
|
* ```
|
|
258
263
|
*/
|
|
259
|
-
|
|
264
|
+
async function loadTimeSlotListConfig(options) {
|
|
260
265
|
try {
|
|
261
|
-
const response = await fetchAvailability({
|
|
266
|
+
const response = await (0, index_js_1.fetchAvailability)({
|
|
262
267
|
services: options.services || [],
|
|
263
268
|
fromLocalDate: options.startDate,
|
|
264
269
|
toLocalDate: options.endDate,
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* TimeSlot Service
|
|
3
4
|
* Manages individual time slot data
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TimeSlotService = exports.TimeSlotServiceDefinition = void 0;
|
|
8
|
+
const services_definitions_1 = require("@wix/services-definitions");
|
|
9
|
+
const signals_1 = require("@wix/services-definitions/core-services/signals");
|
|
10
|
+
const constants_js_1 = require("../constants.js");
|
|
8
11
|
/**
|
|
9
12
|
* Service definition for TimeSlot
|
|
10
13
|
*/
|
|
11
|
-
|
|
14
|
+
exports.TimeSlotServiceDefinition = (0, services_definitions_1.defineService)(constants_js_1.ClientServiceIds.timeSlot);
|
|
12
15
|
/**
|
|
13
16
|
* Implementation of TimeSlotService
|
|
14
17
|
*/
|
|
15
|
-
|
|
16
|
-
const signalsService = getService(SignalsServiceDefinition);
|
|
18
|
+
exports.TimeSlotService = services_definitions_1.implementService.withConfig()(exports.TimeSlotServiceDefinition, ({ getService, config }) => {
|
|
19
|
+
const signalsService = getService(signals_1.SignalsServiceDefinition);
|
|
17
20
|
const timeSlotSignal = signalsService.signal(config.timeSlot);
|
|
18
21
|
return {
|
|
19
22
|
timeSlotSignal,
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDuration = exports.formatDate = void 0;
|
|
4
|
+
const formatDate = (date) => {
|
|
2
5
|
return date.toLocaleDateString(undefined, {
|
|
3
6
|
year: 'numeric',
|
|
4
7
|
month: 'short',
|
|
5
8
|
day: 'numeric',
|
|
6
9
|
});
|
|
7
10
|
};
|
|
8
|
-
|
|
11
|
+
exports.formatDate = formatDate;
|
|
12
|
+
const formatDuration = (minutes) => {
|
|
9
13
|
if (minutes < 60) {
|
|
10
14
|
return `${minutes} min`;
|
|
11
15
|
}
|
|
@@ -16,3 +20,4 @@ export const formatDuration = (minutes) => {
|
|
|
16
20
|
}
|
|
17
21
|
return `${hours}h ${mins}m`;
|
|
18
22
|
};
|
|
23
|
+
exports.formatDuration = formatDuration;
|
package/cjs/dist/utils/guid.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* ID generation utilities
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateLineItemId = generateLineItemId;
|
|
4
7
|
/**
|
|
5
8
|
* Generates a unique line item ID in Ecom's GUID format
|
|
6
9
|
*/
|
|
7
|
-
|
|
10
|
+
function generateLineItemId() {
|
|
8
11
|
const s4 = () => Math.floor((1 + Math.random()) * 0x10000)
|
|
9
12
|
.toString(16)
|
|
10
13
|
.substring(1);
|
package/cjs/dist/utils/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Bookings Utilities
|
|
3
4
|
* Exports utility functions for the bookings package
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.navigateToCheckout = void 0;
|
|
8
|
+
var navigation_js_1 = require("./navigation.js");
|
|
9
|
+
Object.defineProperty(exports, "navigateToCheckout", { enumerable: true, get: function () { return navigation_js_1.navigateToCheckout; } });
|
package/cjs/dist/utils/money.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Money utility functions for converting between SDK Money types and MoneyData
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.convertToMoneyData = convertToMoneyData;
|
|
7
|
+
exports.convertMultiCurrencyPriceToMoneyData = convertMultiCurrencyPriceToMoneyData;
|
|
4
8
|
/**
|
|
5
9
|
* Converts SDK Money format to MoneyData format
|
|
6
10
|
*
|
|
@@ -13,7 +17,7 @@
|
|
|
13
17
|
* // Returns: { amount: 25.50, currency: "USD" }
|
|
14
18
|
* ```
|
|
15
19
|
*/
|
|
16
|
-
|
|
20
|
+
function convertToMoneyData(sdkMoney) {
|
|
17
21
|
if (!sdkMoney)
|
|
18
22
|
return null;
|
|
19
23
|
const priceValue = sdkMoney.value;
|
|
@@ -40,7 +44,7 @@ export function convertToMoneyData(sdkMoney) {
|
|
|
40
44
|
* @param currency - The currency code (from response level)
|
|
41
45
|
* @returns MoneyData object or null if conversion fails
|
|
42
46
|
*/
|
|
43
|
-
|
|
47
|
+
function convertMultiCurrencyPriceToMoneyData(price, currency) {
|
|
44
48
|
if (!price?.amount)
|
|
45
49
|
return null;
|
|
46
50
|
const parsed = parseFloat(price.amount);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.navigateToCheckout = navigateToCheckout;
|
|
4
|
+
const redirects_1 = require("@wix/redirects");
|
|
5
|
+
async function navigateToCheckout({ checkoutId, navigationInfo, }) {
|
|
6
|
+
const { redirectSession } = await redirects_1.redirects.createRedirectSession({
|
|
4
7
|
ecomCheckout: { checkoutId },
|
|
5
8
|
callbacks: {
|
|
6
9
|
postFlowUrl: navigationInfo.postFlowUrl,
|
|
@@ -54,6 +54,8 @@ export interface StaffNameProps extends Omit<React.HTMLAttributes<HTMLElement>,
|
|
|
54
54
|
children?: AsChildChildren<{
|
|
55
55
|
name: string;
|
|
56
56
|
}>;
|
|
57
|
+
/** Label to display when no specific staff member is assigned */
|
|
58
|
+
anyStaffLabel?: string;
|
|
57
59
|
}
|
|
58
60
|
/**
|
|
59
61
|
* Displays the staff member's name from the current booking item.
|
|
@@ -60,8 +60,8 @@ TimeSlot.displayName = 'BookingItem.TimeSlot';
|
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
62
|
export const StaffName = React.forwardRef((props, ref) => {
|
|
63
|
-
const { asChild, children, ...rest } = props;
|
|
64
|
-
return (_jsx(CoreBooking.BookingItemInfo, { children: ({ staffName }) => {
|
|
63
|
+
const { asChild, children, anyStaffLabel, ...rest } = props;
|
|
64
|
+
return (_jsx(CoreBooking.BookingItemInfo, { anyStaffLabel: anyStaffLabel, children: ({ staffName }) => {
|
|
65
65
|
if (!staffName)
|
|
66
66
|
return null;
|
|
67
67
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, ...rest, "data-testid": TestIds.bookingItemStaffName, customElement: children, customElementProps: { name: staffName }, children: _jsx("span", { children: staffName }) }));
|
|
@@ -98,12 +98,14 @@ export declare function BookingItemProvider(props: BookingItemProviderProps): Re
|
|
|
98
98
|
* Props for BookingItemInfo render prop component
|
|
99
99
|
*/
|
|
100
100
|
export interface BookingItemInfoProps {
|
|
101
|
+
/** Label to display when no specific staff member is assigned */
|
|
102
|
+
anyStaffLabel?: string;
|
|
101
103
|
children: (data: {
|
|
102
104
|
/** SDK Service object */
|
|
103
105
|
service: Service;
|
|
104
106
|
/** Adapted SDK TimeSlot (or null if no time slot selected) */
|
|
105
107
|
timeSlot: TimeSlot | null;
|
|
106
|
-
/** First staff member's name,
|
|
108
|
+
/** First staff member's name, or anyStaffLabel if none */
|
|
107
109
|
staffName: string;
|
|
108
110
|
/** Unique identifier for this booking instance */
|
|
109
111
|
instanceId: string;
|
|
@@ -159,9 +159,10 @@ export function BookingItemProvider(props) {
|
|
|
159
159
|
* ```
|
|
160
160
|
*/
|
|
161
161
|
export function BookingItemInfo(props) {
|
|
162
|
+
const { anyStaffLabel = '', children } = props;
|
|
162
163
|
const item = useBookingItemContext();
|
|
163
|
-
const staffName = item.staff?.[0]?.name ||
|
|
164
|
-
return
|
|
164
|
+
const staffName = item.staff?.[0]?.name || anyStaffLabel;
|
|
165
|
+
return children({
|
|
165
166
|
service: item.service,
|
|
166
167
|
timeSlot: item.timeSlot,
|
|
167
168
|
staffName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.106",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@wix/auto_sdk_ecom_checkout": "^1.0.104",
|
|
39
39
|
"@wix/form-public": "^0.104.0",
|
|
40
40
|
"@wix/headless-forms": "0.0.33",
|
|
41
|
-
"@wix/headless-media": "0.0.
|
|
41
|
+
"@wix/headless-media": "0.0.21",
|
|
42
42
|
"@wix/headless-utils": "0.0.8",
|
|
43
43
|
"@wix/services-definitions": "^1.0.1",
|
|
44
44
|
"@wix/services-manager-react": "^1.0.3",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"groupId": "com.wixpress.headless-components"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "e7cfdaed5bb7cf719ed0a005656bcacdc15bfe241b54e27ca0f90738"
|
|
76
76
|
}
|