@wix/headless-bookings 0.0.87 → 0.0.89
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/booking/Booking.d.ts +36 -117
- package/cjs/dist/react/booking/Booking.js +40 -109
- package/cjs/dist/react/booking/BookingItem.d.ts +64 -0
- package/cjs/dist/react/booking/BookingItem.js +71 -0
- package/cjs/dist/react/core/payment/Payment.d.ts +3 -3
- package/cjs/dist/react/core/payment/Payment.js +4 -4
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.d.ts +2 -0
- package/cjs/dist/react/core/time-slot-list/TimeSlotList.js +3 -0
- package/cjs/dist/react/index.d.ts +1 -0
- package/cjs/dist/react/index.js +1 -0
- package/cjs/dist/react/payment/Payment.d.ts +3 -46
- package/cjs/dist/react/payment/Payment.js +4 -37
- package/cjs/dist/react/service/Service.d.ts +0 -2
- package/cjs/dist/react/service/Service.js +3 -3
- package/cjs/dist/react/service/ServiceMedia.d.ts +1 -63
- package/cjs/dist/react/service/ServiceMedia.js +1 -60
- package/cjs/dist/react/time-slot-list/TimeSlot.d.ts +21 -6
- package/cjs/dist/react/time-slot-list/TimeSlot.js +34 -14
- package/cjs/dist/react/time-slot-list/TimeSlotList.d.ts +3 -49
- package/cjs/dist/react/time-slot-list/TimeSlotList.js +24 -21
- package/cjs/dist/services/payment/payment.d.ts +2 -2
- package/cjs/dist/services/payment/payment.def.d.ts +1 -1
- package/cjs/dist/services/payment/payment.js +11 -11
- package/dist/react/booking/Booking.d.ts +36 -117
- package/dist/react/booking/Booking.js +40 -109
- package/dist/react/booking/BookingItem.d.ts +64 -0
- package/dist/react/booking/BookingItem.js +71 -0
- package/dist/react/core/payment/Payment.d.ts +3 -3
- package/dist/react/core/payment/Payment.js +4 -4
- package/dist/react/core/time-slot-list/TimeSlotList.d.ts +2 -0
- package/dist/react/core/time-slot-list/TimeSlotList.js +3 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/react/payment/Payment.d.ts +3 -46
- package/dist/react/payment/Payment.js +4 -37
- package/dist/react/service/Service.d.ts +0 -2
- package/dist/react/service/Service.js +3 -3
- package/dist/react/service/ServiceMedia.d.ts +1 -63
- package/dist/react/service/ServiceMedia.js +1 -60
- package/dist/react/time-slot-list/TimeSlot.d.ts +21 -6
- package/dist/react/time-slot-list/TimeSlot.js +34 -14
- package/dist/react/time-slot-list/TimeSlotList.d.ts +3 -49
- package/dist/react/time-slot-list/TimeSlotList.js +24 -21
- package/dist/services/payment/payment.d.ts +2 -2
- package/dist/services/payment/payment.def.d.ts +1 -1
- package/dist/services/payment/payment.js +11 -11
- package/package.json +2 -2
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* the necessary context. There is no public TimeSlot.Root - context is managed internally.
|
|
7
7
|
*/
|
|
8
8
|
import React from 'react';
|
|
9
|
+
import { type DateData } from '@wix/headless-components/react';
|
|
9
10
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
10
11
|
import type { TimeSlot as TimeSlotType } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
11
12
|
import * as CoreTimeSlot from '../core/time-slot-list/TimeSlot.js';
|
|
@@ -46,9 +47,10 @@ export declare enum TestIds {
|
|
|
46
47
|
timeSlotStaffMemberActionSelect = "time-slot-staff-member-action-select"
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
49
|
-
* Props for TimeSlot.StartDate component
|
|
50
|
+
* Props for TimeSlot.StartDate component.
|
|
51
|
+
* Inherits formatting options from DateData (dateTimeFormatOptions, locale).
|
|
50
52
|
*/
|
|
51
|
-
export interface StartDateProps {
|
|
53
|
+
export interface StartDateProps extends Omit<DateData, 'date'> {
|
|
52
54
|
asChild?: boolean;
|
|
53
55
|
children?: AsChildChildren<{
|
|
54
56
|
startDate: Date;
|
|
@@ -65,7 +67,13 @@ export interface StartDateProps {
|
|
|
65
67
|
* // Default usage - displays "10:00 AM"
|
|
66
68
|
* <TimeSlot.StartDate className="text-foreground" />
|
|
67
69
|
*
|
|
68
|
-
* // With custom
|
|
70
|
+
* // With custom date format
|
|
71
|
+
* <TimeSlot.StartDate
|
|
72
|
+
* className="text-foreground"
|
|
73
|
+
* dateTimeFormatOptions={{ weekday: 'long', month: 'long', day: 'numeric' }}
|
|
74
|
+
* />
|
|
75
|
+
*
|
|
76
|
+
* // With custom formatting via asChild
|
|
69
77
|
* <TimeSlot.StartDate asChild>
|
|
70
78
|
* {({ startDate }) => (
|
|
71
79
|
* <span>{formatTime(startDate)}</span>
|
|
@@ -75,9 +83,10 @@ export interface StartDateProps {
|
|
|
75
83
|
*/
|
|
76
84
|
export declare const StartDate: React.ForwardRefExoticComponent<StartDateProps & React.RefAttributes<HTMLElement>>;
|
|
77
85
|
/**
|
|
78
|
-
* Props for TimeSlot.EndDate component
|
|
86
|
+
* Props for TimeSlot.EndDate component.
|
|
87
|
+
* Inherits formatting options from DateData (dateTimeFormatOptions, locale).
|
|
79
88
|
*/
|
|
80
|
-
export interface EndDateProps {
|
|
89
|
+
export interface EndDateProps extends Omit<DateData, 'date'> {
|
|
81
90
|
asChild?: boolean;
|
|
82
91
|
children?: AsChildChildren<{
|
|
83
92
|
endDate: Date;
|
|
@@ -94,7 +103,13 @@ export interface EndDateProps {
|
|
|
94
103
|
* // Default usage - displays "11:00 AM"
|
|
95
104
|
* <TimeSlot.EndDate className="text-foreground" />
|
|
96
105
|
*
|
|
97
|
-
* // With custom
|
|
106
|
+
* // With custom date format
|
|
107
|
+
* <TimeSlot.EndDate
|
|
108
|
+
* className="text-foreground"
|
|
109
|
+
* dateTimeFormatOptions={{ weekday: 'long', month: 'long', day: 'numeric' }}
|
|
110
|
+
* />
|
|
111
|
+
*
|
|
112
|
+
* // With custom formatting via asChild
|
|
98
113
|
* <TimeSlot.EndDate asChild>
|
|
99
114
|
* {({ endDate }) => (
|
|
100
115
|
* <span>{formatTime(endDate)}</span>
|
|
@@ -7,7 +7,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
7
|
* the necessary context. There is no public TimeSlot.Root - context is managed internally.
|
|
8
8
|
*/
|
|
9
9
|
import React from 'react';
|
|
10
|
-
import { GenericList } from '@wix/headless-components/react';
|
|
10
|
+
import { GenericList, Date, } from '@wix/headless-components/react';
|
|
11
11
|
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
12
12
|
import * as CoreTimeSlot from '../core/time-slot-list/TimeSlot.js';
|
|
13
13
|
/**
|
|
@@ -56,7 +56,13 @@ export var TestIds;
|
|
|
56
56
|
* // Default usage - displays "10:00 AM"
|
|
57
57
|
* <TimeSlot.StartDate className="text-foreground" />
|
|
58
58
|
*
|
|
59
|
-
* // With custom
|
|
59
|
+
* // With custom date format
|
|
60
|
+
* <TimeSlot.StartDate
|
|
61
|
+
* className="text-foreground"
|
|
62
|
+
* dateTimeFormatOptions={{ weekday: 'long', month: 'long', day: 'numeric' }}
|
|
63
|
+
* />
|
|
64
|
+
*
|
|
65
|
+
* // With custom formatting via asChild
|
|
60
66
|
* <TimeSlot.StartDate asChild>
|
|
61
67
|
* {({ startDate }) => (
|
|
62
68
|
* <span>{formatTime(startDate)}</span>
|
|
@@ -65,11 +71,15 @@ export var TestIds;
|
|
|
65
71
|
* ```
|
|
66
72
|
*/
|
|
67
73
|
export const StartDate = React.forwardRef((props, ref) => {
|
|
68
|
-
const { asChild, children, className } = props;
|
|
69
|
-
return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
const { asChild, children, className, dateTimeFormatOptions, locale } = props;
|
|
75
|
+
return (_jsx(CoreTimeSlot.Info, { children: ({ startDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotStartDate, customElement: children, customElementProps: { startDate }, children: _jsx(Date, { date: {
|
|
76
|
+
date: startDate,
|
|
77
|
+
locale,
|
|
78
|
+
dateTimeFormatOptions: dateTimeFormatOptions ?? {
|
|
79
|
+
hour: '2-digit',
|
|
80
|
+
minute: '2-digit',
|
|
81
|
+
},
|
|
82
|
+
} }) })) }));
|
|
73
83
|
});
|
|
74
84
|
StartDate.displayName = 'TimeSlot.StartDate';
|
|
75
85
|
/**
|
|
@@ -82,7 +92,13 @@ StartDate.displayName = 'TimeSlot.StartDate';
|
|
|
82
92
|
* // Default usage - displays "11:00 AM"
|
|
83
93
|
* <TimeSlot.EndDate className="text-foreground" />
|
|
84
94
|
*
|
|
85
|
-
* // With custom
|
|
95
|
+
* // With custom date format
|
|
96
|
+
* <TimeSlot.EndDate
|
|
97
|
+
* className="text-foreground"
|
|
98
|
+
* dateTimeFormatOptions={{ weekday: 'long', month: 'long', day: 'numeric' }}
|
|
99
|
+
* />
|
|
100
|
+
*
|
|
101
|
+
* // With custom formatting via asChild
|
|
86
102
|
* <TimeSlot.EndDate asChild>
|
|
87
103
|
* {({ endDate }) => (
|
|
88
104
|
* <span>{formatTime(endDate)}</span>
|
|
@@ -91,11 +107,15 @@ StartDate.displayName = 'TimeSlot.StartDate';
|
|
|
91
107
|
* ```
|
|
92
108
|
*/
|
|
93
109
|
export const EndDate = React.forwardRef((props, ref) => {
|
|
94
|
-
const { asChild, children, className } = props;
|
|
95
|
-
return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
110
|
+
const { asChild, children, className, dateTimeFormatOptions, locale } = props;
|
|
111
|
+
return (_jsx(CoreTimeSlot.Info, { children: ({ endDate }) => (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotEndDate, customElement: children, customElementProps: { endDate }, children: _jsx(Date, { date: {
|
|
112
|
+
date: endDate,
|
|
113
|
+
locale,
|
|
114
|
+
dateTimeFormatOptions: dateTimeFormatOptions ?? {
|
|
115
|
+
hour: '2-digit',
|
|
116
|
+
minute: '2-digit',
|
|
117
|
+
},
|
|
118
|
+
} }) })) }));
|
|
99
119
|
});
|
|
100
120
|
EndDate.displayName = 'TimeSlot.EndDate';
|
|
101
121
|
/**
|
|
@@ -168,7 +188,7 @@ export const Select = React.forwardRef((props, ref) => {
|
|
|
168
188
|
disabled: !bookable,
|
|
169
189
|
isSelected,
|
|
170
190
|
bookable,
|
|
171
|
-
}, children: _jsx("button", { onClick: handleClick, disabled: !bookable, children: label }) }));
|
|
191
|
+
}, children: _jsx("button", { onClick: handleClick, disabled: !bookable, children: children || label }) }));
|
|
172
192
|
} }));
|
|
173
193
|
});
|
|
174
194
|
Select.displayName = 'TimeSlot.Actions.Select';
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { ListVariant } from '@wix/headless-components/react';
|
|
7
7
|
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
8
|
-
import type { TimeSlot as TimeSlotType } from '@wix/auto_sdk_bookings_availability-time-slots';
|
|
9
8
|
import type { TimeSlotListServiceConfig } from '../../services/time-slot-list/time-slot-list.def.js';
|
|
10
9
|
export type { StartDateProps as TimeSlotStartDateProps, EndDateProps as TimeSlotEndDateProps, DurationProps as TimeSlotDurationProps, SelectProps as TimeSlotSelectProps, LocationNameProps as TimeSlotLocationNameProps, StaffMembersProps as TimeSlotStaffMembersProps, StaffMemberRepeaterProps as TimeSlotStaffMemberRepeaterProps, StaffMemberNameProps as TimeSlotStaffMemberNameProps, SelectStaffMemberProps as TimeSlotSelectStaffMemberProps, ClearStaffSelectionProps as TimeSlotClearStaffSelectionProps, } from './TimeSlot.js';
|
|
11
10
|
/**
|
|
@@ -120,32 +119,11 @@ export interface TimeSlotsProps {
|
|
|
120
119
|
* ```
|
|
121
120
|
*/
|
|
122
121
|
export declare const TimeSlots: React.ForwardRefExoticComponent<TimeSlotsProps & React.RefAttributes<HTMLElement>>;
|
|
123
|
-
/**
|
|
124
|
-
* Data provided to TimeSlotRepeater function children
|
|
125
|
-
*/
|
|
126
|
-
export interface TimeSlotRepeaterChildProps {
|
|
127
|
-
/** Whether the slot is currently selected */
|
|
128
|
-
isSelected: boolean;
|
|
129
|
-
/** Whether the slot can be booked */
|
|
130
|
-
bookable: boolean;
|
|
131
|
-
/** Start date/time as Date (constructed from the raw localStartDate string) */
|
|
132
|
-
startDate: Date;
|
|
133
|
-
/** End date/time as Date (constructed from the raw localEndDate string) */
|
|
134
|
-
endDate: Date;
|
|
135
|
-
/** Duration in minutes */
|
|
136
|
-
durationInMinutes: number;
|
|
137
|
-
/** The raw time slot data */
|
|
138
|
-
timeSlot: TimeSlotType;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Children type for TimeSlotRepeater - can be ReactNode or function
|
|
142
|
-
*/
|
|
143
|
-
type TimeSlotRepeaterChildren = React.ReactNode | ((props: TimeSlotRepeaterChildProps) => React.ReactNode);
|
|
144
122
|
/**
|
|
145
123
|
* Props for TimeSlotList.TimeSlotRepeater component
|
|
146
124
|
*/
|
|
147
125
|
export interface TimeSlotRepeaterProps {
|
|
148
|
-
children:
|
|
126
|
+
children: React.ReactNode;
|
|
149
127
|
}
|
|
150
128
|
export declare const TimeSlotRepeater: React.ForwardRefExoticComponent<TimeSlotRepeaterProps & React.RefAttributes<HTMLElement>>;
|
|
151
129
|
/**
|
|
@@ -193,36 +171,12 @@ export interface DateRangeInputProps {
|
|
|
193
171
|
startDate: Date;
|
|
194
172
|
endDate: Date;
|
|
195
173
|
onChange: (start: Date, end: Date) => void;
|
|
174
|
+
/** IANA timezone string for the time slots (e.g., "America/New_York") */
|
|
175
|
+
timezone: string | undefined;
|
|
196
176
|
}>;
|
|
197
177
|
/** CSS classes to apply to the container */
|
|
198
178
|
className?: string;
|
|
199
179
|
}
|
|
200
|
-
/**
|
|
201
|
-
* Date range input for setting the start and end date filter.
|
|
202
|
-
* Uses the core DateRange component to access service data.
|
|
203
|
-
* Both dates are set together and trigger a single fetch.
|
|
204
|
-
*
|
|
205
|
-
* Default rendering provides two native date inputs.
|
|
206
|
-
*
|
|
207
|
-
* @component
|
|
208
|
-
* @example
|
|
209
|
-
* ```tsx
|
|
210
|
-
* // Default usage - renders two date inputs
|
|
211
|
-
* <TimeSlotList.DateRange.Input className="flex gap-2" />
|
|
212
|
-
*
|
|
213
|
-
* // With asChild for custom rendering
|
|
214
|
-
* <TimeSlotList.DateRange.Input asChild>
|
|
215
|
-
* {({ startDate, endDate, onChange }) => (
|
|
216
|
-
* <MyDateRangePicker
|
|
217
|
-
* start={startDate}
|
|
218
|
-
* end={endDate}
|
|
219
|
-
* onRangeChange={(start, end) => onChange(start, end)}
|
|
220
|
-
* />
|
|
221
|
-
* )}
|
|
222
|
-
* </TimeSlotList.DateRange.Input>
|
|
223
|
-
* ```
|
|
224
|
-
*/
|
|
225
|
-
export declare const DateRangeInput: React.ForwardRefExoticComponent<DateRangeInputProps & React.RefAttributes<HTMLElement>>;
|
|
226
180
|
/**
|
|
227
181
|
* DateRange namespace for TimeSlotList date range filter
|
|
228
182
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* TimeSlotList - High-level component for displaying time slot list information
|
|
4
4
|
* Provides components for displaying timezone and time slot data
|
|
@@ -6,6 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { GenericList } from '@wix/headless-components/react';
|
|
8
8
|
import { AsChildSlot } from '@wix/headless-utils/react';
|
|
9
|
+
import { startOfDay, endOfDay, parse, format } from 'date-fns';
|
|
9
10
|
import * as CoreTimeSlotList from '../core/time-slot-list/TimeSlotList.js';
|
|
10
11
|
import * as CoreTimeSlot from '../core/time-slot-list/TimeSlot.js';
|
|
11
12
|
import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, Actions as TimeSlotActions, Location, StaffMembers, StaffMemberRepeater, StaffMember, Root as TimeSlotRoot, } from './TimeSlot.js';
|
|
@@ -14,9 +15,19 @@ import { StartDate as TimeSlotStartDate, EndDate as TimeSlotEndDate, Duration, A
|
|
|
14
15
|
// ============================================================================
|
|
15
16
|
/**
|
|
16
17
|
* Converts a Date to ISO date string format (YYYY-MM-DD) for input[type="date"]
|
|
18
|
+
* Uses the specified timezone or falls back to local timezone
|
|
17
19
|
*/
|
|
18
|
-
function toISODateString(date) {
|
|
19
|
-
|
|
20
|
+
function toISODateString(date, timezone) {
|
|
21
|
+
if (timezone) {
|
|
22
|
+
const formatter = new Intl.DateTimeFormat('en-CA', {
|
|
23
|
+
timeZone: timezone,
|
|
24
|
+
year: 'numeric',
|
|
25
|
+
month: '2-digit',
|
|
26
|
+
day: '2-digit',
|
|
27
|
+
});
|
|
28
|
+
return formatter.format(date);
|
|
29
|
+
}
|
|
30
|
+
return format(date, 'yyyy-MM-dd');
|
|
20
31
|
}
|
|
21
32
|
/**
|
|
22
33
|
* TimeSlot with required id field for GenericList
|
|
@@ -117,34 +128,22 @@ export const TimeSlots = React.forwardRef((props, ref) => {
|
|
|
117
128
|
TimeSlots.displayName = 'TimeSlotList.TimeSlots';
|
|
118
129
|
/**
|
|
119
130
|
* Internal component that wraps each time slot item with context provider.
|
|
120
|
-
* Supports both ReactNode and function children patterns.
|
|
121
131
|
*/
|
|
122
132
|
const TimeSlotItemWrapper = ({ timeSlot, children, }) => {
|
|
123
|
-
return (_jsx(TimeSlotRoot, { timeSlot: timeSlot, children: _jsx(CoreTimeSlot.Info, { children: (props) => (_jsx("div", { "data-testid": TestIds.timeSlotListTimeSlot, "data-bookable": props.bookable, "data-selected": props.isSelected, children:
|
|
133
|
+
return (_jsx(TimeSlotRoot, { timeSlot: timeSlot, children: _jsx(CoreTimeSlot.Info, { children: (props) => (_jsx("div", { "data-testid": TestIds.timeSlotListTimeSlot, "data-bookable": props.bookable, "data-selected": props.isSelected, children: children })) }) }));
|
|
124
134
|
};
|
|
125
135
|
/**
|
|
126
|
-
* Repeater component that renders each time slot.
|
|
136
|
+
* Repeater component that renders TimeSlot.Root for each time slot.
|
|
127
137
|
* Follows Repeater Level pattern and uses GenericList.Repeater for consistency.
|
|
128
|
-
* Automatically provides TimeSlot context to children.
|
|
129
138
|
*
|
|
130
139
|
* @component
|
|
131
140
|
* @example
|
|
132
141
|
* ```tsx
|
|
133
|
-
* // Standard usage with nested components
|
|
134
142
|
* <TimeSlotList.TimeSlotRepeater>
|
|
135
143
|
* <TimeSlot.StartDate />
|
|
136
144
|
* <TimeSlot.Duration />
|
|
137
145
|
* <TimeSlot.Actions.Select />
|
|
138
146
|
* </TimeSlotList.TimeSlotRepeater>
|
|
139
|
-
*
|
|
140
|
-
* // Function children pattern - all data available directly
|
|
141
|
-
* <TimeSlotList.TimeSlotRepeater>
|
|
142
|
-
* {({ isSelected, bookable, startDate }) => (
|
|
143
|
-
* <button disabled={!bookable} className={isSelected ? 'selected' : ''}>
|
|
144
|
-
* {formatTime(startDate)}
|
|
145
|
-
* </button>
|
|
146
|
-
* )}
|
|
147
|
-
* </TimeSlotList.TimeSlotRepeater>
|
|
148
147
|
* ```
|
|
149
148
|
*/
|
|
150
149
|
const generateSlotKey = (timeSlot) => {
|
|
@@ -152,7 +151,7 @@ const generateSlotKey = (timeSlot) => {
|
|
|
152
151
|
};
|
|
153
152
|
export const TimeSlotRepeater = React.forwardRef((props, ref) => {
|
|
154
153
|
const { children } = props;
|
|
155
|
-
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item: timeSlot }) => (_jsx(TimeSlotItemWrapper, { timeSlot: timeSlot, children:
|
|
154
|
+
return (_jsx(GenericList.Repeater, { ref: ref, itemWrapper: ({ item: timeSlot, children: itemChildren }) => (_jsx(TimeSlotItemWrapper, { timeSlot: timeSlot, children: itemChildren }, generateSlotKey(timeSlot))), children: children }));
|
|
156
155
|
});
|
|
157
156
|
TimeSlotRepeater.displayName = 'TimeSlotList.TimeSlotRepeater';
|
|
158
157
|
/**
|
|
@@ -203,14 +202,18 @@ export const Actions = {
|
|
|
203
202
|
* </TimeSlotList.DateRange.Input>
|
|
204
203
|
* ```
|
|
205
204
|
*/
|
|
206
|
-
|
|
205
|
+
const DateRangeInput = React.forwardRef((props, ref) => {
|
|
207
206
|
const { asChild, children, className, ...otherProps } = props;
|
|
208
|
-
return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange }) => {
|
|
209
|
-
const defaultContent = (
|
|
207
|
+
return (_jsx(CoreTimeSlotList.DateRange, { children: ({ startDate, endDate, setDateRange, timezone }) => {
|
|
208
|
+
const defaultContent = (_jsx("input", { ref: ref, type: "date", className: className, "data-testid": TestIds.timeSlotListDateRangeInput, value: toISODateString(startDate, timezone), required: true, onChange: (e) => {
|
|
209
|
+
const date = parse(e.target.value, 'yyyy-MM-dd', new Date());
|
|
210
|
+
setDateRange(startOfDay(date), endOfDay(date));
|
|
211
|
+
} }));
|
|
210
212
|
return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.timeSlotListDateRangeInput, customElement: children, customElementProps: {
|
|
211
213
|
startDate,
|
|
212
214
|
endDate,
|
|
213
215
|
onChange: setDateRange,
|
|
216
|
+
timezone,
|
|
214
217
|
}, ...otherProps, children: defaultContent }));
|
|
215
218
|
} }));
|
|
216
219
|
});
|
|
@@ -24,9 +24,9 @@ export type ErrorPaymentConfigResult = {
|
|
|
24
24
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
25
25
|
*
|
|
26
26
|
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
27
|
-
* @param params.
|
|
27
|
+
* @param params.totalParticipants - Number of participants (default: 1)
|
|
28
28
|
*/
|
|
29
29
|
export declare function loadPaymentConfig(params: {
|
|
30
30
|
pricingServiceSelections: PricingServiceSelection[];
|
|
31
|
-
|
|
31
|
+
totalParticipants?: number;
|
|
32
32
|
}): Promise<SuccessPaymentConfigResult | ErrorPaymentConfigResult>;
|
|
@@ -53,7 +53,7 @@ export interface PaymentServiceInternalConfig extends PaymentServiceConfig {
|
|
|
53
53
|
/** Booking services for lazy loading (internal use) */
|
|
54
54
|
pricingServiceSelections?: PricingServiceSelection[];
|
|
55
55
|
/** Number of participants for lazy loading (internal use) */
|
|
56
|
-
|
|
56
|
+
totalParticipants?: number;
|
|
57
57
|
}
|
|
58
58
|
export interface PaymentServiceAPI {
|
|
59
59
|
paymentDetailsSignal: Signal<PaymentDetails | null>;
|
|
@@ -36,15 +36,15 @@ function getPaymentOption(service, hasDeposit) {
|
|
|
36
36
|
}
|
|
37
37
|
return 'FULL_PAYMENT_ONLINE';
|
|
38
38
|
}
|
|
39
|
-
function buildLineItem(service,
|
|
39
|
+
function buildLineItem(service, totalParticipants, lineItemId) {
|
|
40
40
|
// Get fixed price from service
|
|
41
41
|
const servicePrice = service.payment?.fixed?.price?.value;
|
|
42
|
-
const price = Number(servicePrice || 0) *
|
|
42
|
+
const price = Number(servicePrice || 0) * totalParticipants;
|
|
43
43
|
// Get deposit if configured
|
|
44
44
|
const depositValue = service.payment?.fixed?.deposit?.value;
|
|
45
45
|
const hasDeposit = !!depositValue && Number(depositValue) > 0;
|
|
46
46
|
const deposit = hasDeposit
|
|
47
|
-
? Number(depositValue) *
|
|
47
|
+
? Number(depositValue) * totalParticipants
|
|
48
48
|
: undefined;
|
|
49
49
|
// Get payment option from service configuration (pass hasDeposit for correct API behavior)
|
|
50
50
|
const paymentOption = getPaymentOption(service, hasDeposit);
|
|
@@ -60,13 +60,13 @@ function buildLineItem(service, numberOfParticipants, lineItemId) {
|
|
|
60
60
|
paymentOption,
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
async function calculatePaymentDetails(pricingServiceSelections,
|
|
63
|
+
async function calculatePaymentDetails(pricingServiceSelections, totalParticipants) {
|
|
64
64
|
// Ensure all booking services have a lineItemId
|
|
65
65
|
const data = pricingServiceSelections.map((selection) => ({
|
|
66
66
|
...selection,
|
|
67
67
|
lineItemId: selection.lineItemId || generateLineItemId(),
|
|
68
68
|
}));
|
|
69
|
-
const lineItems = data.map((item) => buildLineItem(item.service,
|
|
69
|
+
const lineItems = data.map((item) => buildLineItem(item.service, totalParticipants, item.lineItemId));
|
|
70
70
|
const response = await calculateTotals({
|
|
71
71
|
lineItems,
|
|
72
72
|
});
|
|
@@ -96,7 +96,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
96
96
|
const isLoadingSignal = signalsService.signal(false);
|
|
97
97
|
const errorSignal = signalsService.signal(null);
|
|
98
98
|
// Internal calculate function
|
|
99
|
-
const calculate = async (pricingServiceSelections,
|
|
99
|
+
const calculate = async (pricingServiceSelections, totalParticipants) => {
|
|
100
100
|
if (!pricingServiceSelections.length) {
|
|
101
101
|
paymentDetailsSignal.set(null);
|
|
102
102
|
return;
|
|
@@ -104,7 +104,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
104
104
|
isLoadingSignal.set(true);
|
|
105
105
|
errorSignal.set(null);
|
|
106
106
|
try {
|
|
107
|
-
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections,
|
|
107
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, totalParticipants);
|
|
108
108
|
paymentDetailsSignal.set(paymentDetails);
|
|
109
109
|
}
|
|
110
110
|
catch (error) {
|
|
@@ -124,7 +124,7 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
124
124
|
}
|
|
125
125
|
// Mode 2: Lazy loading - pricingServiceSelections provided via internal config
|
|
126
126
|
else if (config.pricingServiceSelections?.length) {
|
|
127
|
-
void calculate(config.pricingServiceSelections, config.
|
|
127
|
+
void calculate(config.pricingServiceSelections, config.totalParticipants ?? 1);
|
|
128
128
|
}
|
|
129
129
|
// Mode 3: Reactive - observe BookingService signals (client-side only)
|
|
130
130
|
else if (typeof window !== 'undefined' && bookingService) {
|
|
@@ -159,18 +159,18 @@ export const PaymentService = implementService.withConfig()(PaymentServiceDefini
|
|
|
159
159
|
* Calls the pricing APIs and returns pre-calculated payment details.
|
|
160
160
|
*
|
|
161
161
|
* @param params.pricingServiceSelections - Pricing service selections for calculation
|
|
162
|
-
* @param params.
|
|
162
|
+
* @param params.totalParticipants - Number of participants (default: 1)
|
|
163
163
|
*/
|
|
164
164
|
export async function loadPaymentConfig(params) {
|
|
165
165
|
try {
|
|
166
|
-
const { pricingServiceSelections,
|
|
166
|
+
const { pricingServiceSelections, totalParticipants = 1 } = params;
|
|
167
167
|
if (!pricingServiceSelections.length) {
|
|
168
168
|
return {
|
|
169
169
|
type: 'success',
|
|
170
170
|
config: { paymentDetails: undefined },
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
-
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections,
|
|
173
|
+
const paymentDetails = await calculatePaymentDetails(pricingServiceSelections, totalParticipants);
|
|
174
174
|
return {
|
|
175
175
|
type: 'success',
|
|
176
176
|
config: { paymentDetails },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-bookings",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.89",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"groupId": "com.wixpress.headless-components"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "57a07a8154bb7def020ba4429b5e58f59af1a8c7e7451b13e715d4a4"
|
|
76
76
|
}
|