@wix/headless-bookings 0.0.8 → 0.0.10

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.
@@ -3,8 +3,8 @@
3
3
  * Provides low-level access to BookingService via render props and service setup
4
4
  */
5
5
  import React from 'react';
6
- import { type BookingServiceConfig } from '../../../services/booking/booking.js';
7
- import type { services, availabilityTimeSlots } from '@wix/bookings';
6
+ import { type BookingServiceConfig, type ServiceSelection } from '../../../services/booking/booking.js';
7
+ import type { availabilityTimeSlots } from '@wix/bookings';
8
8
  /**
9
9
  * Props for Booking.Root component
10
10
  */
@@ -33,7 +33,7 @@ export declare function Root(props: RootProps): React.ReactNode;
33
33
  */
34
34
  export interface DataProps {
35
35
  children: (data: {
36
- selectedServices: services.Service[];
36
+ selectedServices: ServiceSelection[];
37
37
  selectedTimeSlot: availabilityTimeSlots.TimeSlot | null;
38
38
  }) => React.ReactNode;
39
39
  }
@@ -47,7 +47,7 @@ export interface DataProps {
47
47
  * <Booking.Data>
48
48
  * {({ selectedServices }) => (
49
49
  * selectedServices.length > 0 ? (
50
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
50
+ * <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
51
51
  * ) : (
52
52
  * <div>No services selected</div>
53
53
  * )
@@ -30,7 +30,7 @@ export function Root(props) {
30
30
  * <Booking.Data>
31
31
  * {({ selectedServices }) => (
32
32
  * selectedServices.length > 0 ? (
33
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
33
+ * <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
34
34
  * ) : (
35
35
  * <div>No services selected</div>
36
36
  * )
@@ -41,8 +41,8 @@ export function Root(props) {
41
41
  export function Data(props) {
42
42
  const { children } = props;
43
43
  const bookingService = useService(BookingServiceDefinition);
44
- const selectedServices = bookingService.selectedServices.get();
45
- const selectedTimeSlot = bookingService.selectedTimeSlot.get();
44
+ const selectedServices = bookingService.services.get();
45
+ const selectedTimeSlot = bookingService.timeSlot.get();
46
46
  return children({
47
47
  selectedServices,
48
48
  selectedTimeSlot,
@@ -1,19 +1,55 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { services, availabilityTimeSlots } from '@wix/bookings';
8
+ import type { FormValues } from '@wix/form-public';
9
+ /**
10
+ * ServiceSelection contains the service AND its related selections
11
+ */
12
+ export interface ServiceSelection {
13
+ service: services.Service;
14
+ /** Selected resources (staff members, rooms, etc.) */
15
+ resources?: availabilityTimeSlots.Resource[];
16
+ }
17
+ export interface Location {
18
+ id: string;
19
+ name?: string;
20
+ }
21
+ /**
22
+ * BookingService actions - setters only, no API calls
23
+ */
24
+ export interface BookingServiceActions {
25
+ setServices(services: ServiceSelection[]): void;
26
+ addService(service: ServiceSelection): void;
27
+ updateService(serviceId: string, updates: Partial<ServiceSelection>): void;
28
+ removeService(serviceId: string): void;
29
+ clearServices(): void;
30
+ setTimeSlot(slot: availabilityTimeSlots.TimeSlot | null): void;
31
+ clearTimeSlot(): void;
32
+ setLocation(location: Location | null): void;
33
+ clearLocation(): void;
34
+ setFormValues(values: FormValues | null): void;
35
+ clearFormValues(): void;
36
+ clearAll(): void;
37
+ }
8
38
  /**
9
39
  * Booking Service interface
10
- * Note: This is NOT an "API" service - it only exposes signals for state storage
40
+ * Pure state management - no API calls
11
41
  */
12
42
  export interface BookingService {
13
- /** Signal containing the currently selected services (can be multiple) */
14
- selectedServices: Signal<services.Service[]>;
43
+ /** Signal containing the currently selected services with their selections */
44
+ services: Signal<ServiceSelection[]>;
15
45
  /** Signal containing the currently selected time slot */
16
- selectedTimeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
46
+ timeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
47
+ /** Signal containing the selected location (derived from timeSlot) */
48
+ location: Signal<Location | null>;
49
+ /** Signal containing the form values */
50
+ formValues: Signal<FormValues | null>;
51
+ /** Actions for modifying booking state */
52
+ actions: BookingServiceActions;
17
53
  }
18
54
  /**
19
55
  * Service definition for Booking
@@ -25,12 +61,15 @@ export declare const BookingServiceDefinition: string & {
25
61
  } & BookingService;
26
62
  /**
27
63
  * Configuration interface for BookingService
64
+ * Note: location is NOT in config - it's derived internally from timeSlot
28
65
  */
29
66
  export interface BookingServiceConfig {
30
- /** Optional initial services to pre-populate (default: empty array) */
31
- initialServices?: services.Service[];
32
- /** Optional initial time slot to pre-populate (default: null) */
67
+ /** Optional initial services to pre-populate */
68
+ initialServices?: ServiceSelection[];
69
+ /** Optional initial time slot to pre-populate */
33
70
  initialTimeSlot?: availabilityTimeSlots.TimeSlot | null;
71
+ /** Optional initial form values */
72
+ initialFormValues?: FormValues | null;
34
73
  }
35
74
  /**
36
75
  * Implementation of BookingService
@@ -44,20 +83,16 @@ export interface BookingServiceConfig {
44
83
  * const bookingConfig = await loadBookingServiceConfig();
45
84
  *
46
85
  * // Wrap app with provider
47
- * <Booking.Root bookingServiceConfig={bookingConfig}>
86
+ * <Booking.Root config={bookingConfig}>
48
87
  * {children}
49
88
  * </Booking.Root>
50
89
  *
51
90
  * // In any page - access booking data
52
91
  * <Booking.Data>
53
- * {({ selectedServices }) => (
54
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
92
+ * {({ services, timeSlot, location, formValues, actions }) => (
93
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
55
94
  * )}
56
95
  * </Booking.Data>
57
- *
58
- * // Modify booking data (via action to be added later)
59
- * const booking = useService(BookingServiceDefinition);
60
- * booking.selectedServices.set([...currentServices, newService]);
61
96
  * ```
62
97
  */
63
98
  export declare const BookingService: import("@wix/services-definitions").ServiceFactory<string & {
@@ -65,21 +100,3 @@ export declare const BookingService: import("@wix/services-definitions").Service
65
100
  __config: {};
66
101
  isServiceDefinition?: boolean;
67
102
  } & BookingService, BookingServiceConfig>;
68
- /**
69
- * Load configuration for BookingService
70
- *
71
- * This function is called during SSR to initialize the service.
72
- * Currently returns null state - can be extended to load from API in future.
73
- *
74
- * @returns Promise resolving to BookingServiceConfig
75
- *
76
- * @example
77
- * ```astro
78
- * ---
79
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
80
- *
81
- * const bookingConfig = await loadBookingServiceConfig();
82
- * ---
83
- * ```
84
- */
85
- export declare function loadBookingServiceConfig(): Promise<BookingServiceConfig>;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
@@ -9,6 +9,9 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
9
9
  * Service definition for Booking
10
10
  */
11
11
  export const BookingServiceDefinition = defineService('booking');
12
+ // ============================================================================
13
+ // Service Implementation
14
+ // ============================================================================
12
15
  /**
13
16
  * Implementation of BookingService
14
17
  *
@@ -21,54 +24,85 @@ export const BookingServiceDefinition = defineService('booking');
21
24
  * const bookingConfig = await loadBookingServiceConfig();
22
25
  *
23
26
  * // Wrap app with provider
24
- * <Booking.Root bookingServiceConfig={bookingConfig}>
27
+ * <Booking.Root config={bookingConfig}>
25
28
  * {children}
26
29
  * </Booking.Root>
27
30
  *
28
31
  * // In any page - access booking data
29
32
  * <Booking.Data>
30
- * {({ selectedServices }) => (
31
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
33
+ * {({ services, timeSlot, location, formValues, actions }) => (
34
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
32
35
  * )}
33
36
  * </Booking.Data>
34
- *
35
- * // Modify booking data (via action to be added later)
36
- * const booking = useService(BookingServiceDefinition);
37
- * booking.selectedServices.set([...currentServices, newService]);
38
37
  * ```
39
38
  */
40
39
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
41
40
  const signalsService = getService(SignalsServiceDefinition);
42
- // Initialize selectedServices signal with config or empty array
43
- const selectedServices = signalsService.signal(config.initialServices || []);
44
- // Initialize selectedTimeSlot signal with config or null
45
- const selectedTimeSlot = signalsService.signal(config.initialTimeSlot || null);
46
- return {
47
- selectedServices,
48
- selectedTimeSlot,
41
+ // Initialize signals with config values
42
+ const servicesSignal = signalsService.signal(config.initialServices || []);
43
+ const timeSlotSignal = signalsService.signal(config.initialTimeSlot || null);
44
+ // Location is derived internally - initialize as null
45
+ const locationSignal = signalsService.signal(null);
46
+ const formValuesSignal = signalsService.signal(config.initialFormValues || null);
47
+ // ========================================================================
48
+ // Actions Implementation
49
+ // ========================================================================
50
+ const actions = {
51
+ // Services actions
52
+ setServices(newServices) {
53
+ servicesSignal.set(newServices);
54
+ },
55
+ addService(service) {
56
+ const current = servicesSignal.get();
57
+ servicesSignal.set([...current, service]);
58
+ },
59
+ updateService(serviceId, updates) {
60
+ const current = servicesSignal.get();
61
+ const updated = current.map((s) => s.service._id === serviceId ? { ...s, ...updates } : s);
62
+ servicesSignal.set(updated);
63
+ },
64
+ removeService(serviceId) {
65
+ const current = servicesSignal.get();
66
+ const filtered = current.filter((s) => s.service._id !== serviceId);
67
+ servicesSignal.set(filtered);
68
+ },
69
+ clearServices() {
70
+ servicesSignal.set([]);
71
+ },
72
+ // Time Slot actions
73
+ setTimeSlot(slot) {
74
+ timeSlotSignal.set(slot);
75
+ },
76
+ clearTimeSlot() {
77
+ timeSlotSignal.set(null);
78
+ },
79
+ // Location actions
80
+ setLocation(location) {
81
+ locationSignal.set(location);
82
+ },
83
+ clearLocation() {
84
+ locationSignal.set(null);
85
+ },
86
+ // Form Values actions
87
+ setFormValues(values) {
88
+ formValuesSignal.set(values);
89
+ },
90
+ clearFormValues() {
91
+ formValuesSignal.set(null);
92
+ },
93
+ // Clear all
94
+ clearAll() {
95
+ servicesSignal.set([]);
96
+ timeSlotSignal.set(null);
97
+ locationSignal.set(null);
98
+ formValuesSignal.set(null);
99
+ },
49
100
  };
50
- });
51
- /**
52
- * Load configuration for BookingService
53
- *
54
- * This function is called during SSR to initialize the service.
55
- * Currently returns null state - can be extended to load from API in future.
56
- *
57
- * @returns Promise resolving to BookingServiceConfig
58
- *
59
- * @example
60
- * ```astro
61
- * ---
62
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
63
- *
64
- * const bookingConfig = await loadBookingServiceConfig();
65
- * ---
66
- * ```
67
- */
68
- export async function loadBookingServiceConfig() {
69
- // Future: Load persisted selections from API by selection ID
70
101
  return {
71
- initialServices: [],
72
- initialTimeSlot: null,
102
+ services: servicesSignal,
103
+ timeSlot: timeSlotSignal,
104
+ location: locationSignal,
105
+ formValues: formValuesSignal,
106
+ actions,
73
107
  };
74
- }
108
+ });
@@ -3,4 +3,4 @@
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, type ServiceServiceAPI, type ServiceServiceConfig, loadServiceServiceConfig, type SuccessServiceServiceConfigResult, type NotFoundServiceServiceConfigResult, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, type BookingServiceConfig, loadBookingServiceConfig, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type ServiceSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
@@ -3,4 +3,4 @@
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, loadServiceServiceConfig, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, loadBookingServiceConfig, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, } from './booking/booking.js';
@@ -5,7 +5,7 @@
5
5
  import { defineService, implementService } from '@wix/services-definitions';
6
6
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
7
7
  import { getServiceById, getServiceBySlug, } from '../../api/query-service/index.js';
8
- import { BookingServiceDefinition } from '../booking/booking.js';
8
+ import { BookingServiceDefinition, } from '../booking/booking.js';
9
9
  /**
10
10
  * Service definition for the Service service.
11
11
  * This defines the contract that the ServiceService must implement.
@@ -73,21 +73,20 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
73
73
  // Action methods for booking
74
74
  const select = () => {
75
75
  const currentService = service.get();
76
- bookingService.selectedServices.set([currentService]);
76
+ const selection = { service: currentService };
77
+ bookingService.services.set([selection]);
77
78
  };
78
79
  const add = () => {
79
80
  const currentService = service.get();
80
- const selectedServices = bookingService.selectedServices.get();
81
- bookingService.selectedServices.set([
82
- ...selectedServices,
83
- currentService,
84
- ]);
81
+ const selections = bookingService.services.get();
82
+ const selection = { service: currentService };
83
+ bookingService.services.set([...selections, selection]);
85
84
  };
86
85
  const remove = () => {
87
86
  const currentService = service.get();
88
- const selectedServices = bookingService.selectedServices.get();
89
- const filtered = selectedServices.filter((s) => s._id !== currentService._id);
90
- bookingService.selectedServices.set(filtered);
87
+ const selections = bookingService.services.get();
88
+ const filtered = selections.filter((s) => s.service._id !== currentService._id);
89
+ bookingService.services.set(filtered);
91
90
  };
92
91
  return {
93
92
  service,
@@ -3,8 +3,8 @@
3
3
  * Provides low-level access to BookingService via render props and service setup
4
4
  */
5
5
  import React from 'react';
6
- import { type BookingServiceConfig } from '../../../services/booking/booking.js';
7
- import type { services, availabilityTimeSlots } from '@wix/bookings';
6
+ import { type BookingServiceConfig, type ServiceSelection } from '../../../services/booking/booking.js';
7
+ import type { availabilityTimeSlots } from '@wix/bookings';
8
8
  /**
9
9
  * Props for Booking.Root component
10
10
  */
@@ -33,7 +33,7 @@ export declare function Root(props: RootProps): React.ReactNode;
33
33
  */
34
34
  export interface DataProps {
35
35
  children: (data: {
36
- selectedServices: services.Service[];
36
+ selectedServices: ServiceSelection[];
37
37
  selectedTimeSlot: availabilityTimeSlots.TimeSlot | null;
38
38
  }) => React.ReactNode;
39
39
  }
@@ -47,7 +47,7 @@ export interface DataProps {
47
47
  * <Booking.Data>
48
48
  * {({ selectedServices }) => (
49
49
  * selectedServices.length > 0 ? (
50
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
50
+ * <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
51
51
  * ) : (
52
52
  * <div>No services selected</div>
53
53
  * )
@@ -30,7 +30,7 @@ export function Root(props) {
30
30
  * <Booking.Data>
31
31
  * {({ selectedServices }) => (
32
32
  * selectedServices.length > 0 ? (
33
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
33
+ * <div>{selectedServices.map(s => s.service.name).join(', ')}</div>
34
34
  * ) : (
35
35
  * <div>No services selected</div>
36
36
  * )
@@ -41,8 +41,8 @@ export function Root(props) {
41
41
  export function Data(props) {
42
42
  const { children } = props;
43
43
  const bookingService = useService(BookingServiceDefinition);
44
- const selectedServices = bookingService.selectedServices.get();
45
- const selectedTimeSlot = bookingService.selectedTimeSlot.get();
44
+ const selectedServices = bookingService.services.get();
45
+ const selectedTimeSlot = bookingService.timeSlot.get();
46
46
  return children({
47
47
  selectedServices,
48
48
  selectedTimeSlot,
@@ -1,19 +1,55 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { type Signal } from '@wix/services-definitions/core-services/signals';
7
7
  import type { services, availabilityTimeSlots } from '@wix/bookings';
8
+ import type { FormValues } from '@wix/form-public';
9
+ /**
10
+ * ServiceSelection contains the service AND its related selections
11
+ */
12
+ export interface ServiceSelection {
13
+ service: services.Service;
14
+ /** Selected resources (staff members, rooms, etc.) */
15
+ resources?: availabilityTimeSlots.Resource[];
16
+ }
17
+ export interface Location {
18
+ id: string;
19
+ name?: string;
20
+ }
21
+ /**
22
+ * BookingService actions - setters only, no API calls
23
+ */
24
+ export interface BookingServiceActions {
25
+ setServices(services: ServiceSelection[]): void;
26
+ addService(service: ServiceSelection): void;
27
+ updateService(serviceId: string, updates: Partial<ServiceSelection>): void;
28
+ removeService(serviceId: string): void;
29
+ clearServices(): void;
30
+ setTimeSlot(slot: availabilityTimeSlots.TimeSlot | null): void;
31
+ clearTimeSlot(): void;
32
+ setLocation(location: Location | null): void;
33
+ clearLocation(): void;
34
+ setFormValues(values: FormValues | null): void;
35
+ clearFormValues(): void;
36
+ clearAll(): void;
37
+ }
8
38
  /**
9
39
  * Booking Service interface
10
- * Note: This is NOT an "API" service - it only exposes signals for state storage
40
+ * Pure state management - no API calls
11
41
  */
12
42
  export interface BookingService {
13
- /** Signal containing the currently selected services (can be multiple) */
14
- selectedServices: Signal<services.Service[]>;
43
+ /** Signal containing the currently selected services with their selections */
44
+ services: Signal<ServiceSelection[]>;
15
45
  /** Signal containing the currently selected time slot */
16
- selectedTimeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
46
+ timeSlot: Signal<availabilityTimeSlots.TimeSlot | null>;
47
+ /** Signal containing the selected location (derived from timeSlot) */
48
+ location: Signal<Location | null>;
49
+ /** Signal containing the form values */
50
+ formValues: Signal<FormValues | null>;
51
+ /** Actions for modifying booking state */
52
+ actions: BookingServiceActions;
17
53
  }
18
54
  /**
19
55
  * Service definition for Booking
@@ -25,12 +61,15 @@ export declare const BookingServiceDefinition: string & {
25
61
  } & BookingService;
26
62
  /**
27
63
  * Configuration interface for BookingService
64
+ * Note: location is NOT in config - it's derived internally from timeSlot
28
65
  */
29
66
  export interface BookingServiceConfig {
30
- /** Optional initial services to pre-populate (default: empty array) */
31
- initialServices?: services.Service[];
32
- /** Optional initial time slot to pre-populate (default: null) */
67
+ /** Optional initial services to pre-populate */
68
+ initialServices?: ServiceSelection[];
69
+ /** Optional initial time slot to pre-populate */
33
70
  initialTimeSlot?: availabilityTimeSlots.TimeSlot | null;
71
+ /** Optional initial form values */
72
+ initialFormValues?: FormValues | null;
34
73
  }
35
74
  /**
36
75
  * Implementation of BookingService
@@ -44,20 +83,16 @@ export interface BookingServiceConfig {
44
83
  * const bookingConfig = await loadBookingServiceConfig();
45
84
  *
46
85
  * // Wrap app with provider
47
- * <Booking.Root bookingServiceConfig={bookingConfig}>
86
+ * <Booking.Root config={bookingConfig}>
48
87
  * {children}
49
88
  * </Booking.Root>
50
89
  *
51
90
  * // In any page - access booking data
52
91
  * <Booking.Data>
53
- * {({ selectedServices }) => (
54
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
92
+ * {({ services, timeSlot, location, formValues, actions }) => (
93
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
55
94
  * )}
56
95
  * </Booking.Data>
57
- *
58
- * // Modify booking data (via action to be added later)
59
- * const booking = useService(BookingServiceDefinition);
60
- * booking.selectedServices.set([...currentServices, newService]);
61
96
  * ```
62
97
  */
63
98
  export declare const BookingService: import("@wix/services-definitions").ServiceFactory<string & {
@@ -65,21 +100,3 @@ export declare const BookingService: import("@wix/services-definitions").Service
65
100
  __config: {};
66
101
  isServiceDefinition?: boolean;
67
102
  } & BookingService, BookingServiceConfig>;
68
- /**
69
- * Load configuration for BookingService
70
- *
71
- * This function is called during SSR to initialize the service.
72
- * Currently returns null state - can be extended to load from API in future.
73
- *
74
- * @returns Promise resolving to BookingServiceConfig
75
- *
76
- * @example
77
- * ```astro
78
- * ---
79
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
80
- *
81
- * const bookingConfig = await loadBookingServiceConfig();
82
- * ---
83
- * ```
84
- */
85
- export declare function loadBookingServiceConfig(): Promise<BookingServiceConfig>;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Booking Service - Global booking store
3
- * Manages booking flow state (selected service, and future: time slot, payment option, participants)
3
+ * Manages booking flow state (selected services, time slot, location, form values)
4
4
  * Persists across page navigation in SPA until page refresh
5
5
  */
6
6
  import { defineService, implementService } from '@wix/services-definitions';
@@ -9,6 +9,9 @@ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-servic
9
9
  * Service definition for Booking
10
10
  */
11
11
  export const BookingServiceDefinition = defineService('booking');
12
+ // ============================================================================
13
+ // Service Implementation
14
+ // ============================================================================
12
15
  /**
13
16
  * Implementation of BookingService
14
17
  *
@@ -21,54 +24,85 @@ export const BookingServiceDefinition = defineService('booking');
21
24
  * const bookingConfig = await loadBookingServiceConfig();
22
25
  *
23
26
  * // Wrap app with provider
24
- * <Booking.Root bookingServiceConfig={bookingConfig}>
27
+ * <Booking.Root config={bookingConfig}>
25
28
  * {children}
26
29
  * </Booking.Root>
27
30
  *
28
31
  * // In any page - access booking data
29
32
  * <Booking.Data>
30
- * {({ selectedServices }) => (
31
- * <div>{selectedServices.map(s => s.name).join(', ')}</div>
33
+ * {({ services, timeSlot, location, formValues, actions }) => (
34
+ * <div>{services.map(s => s.service.name).join(', ')}</div>
32
35
  * )}
33
36
  * </Booking.Data>
34
- *
35
- * // Modify booking data (via action to be added later)
36
- * const booking = useService(BookingServiceDefinition);
37
- * booking.selectedServices.set([...currentServices, newService]);
38
37
  * ```
39
38
  */
40
39
  export const BookingService = implementService.withConfig()(BookingServiceDefinition, ({ getService, config }) => {
41
40
  const signalsService = getService(SignalsServiceDefinition);
42
- // Initialize selectedServices signal with config or empty array
43
- const selectedServices = signalsService.signal(config.initialServices || []);
44
- // Initialize selectedTimeSlot signal with config or null
45
- const selectedTimeSlot = signalsService.signal(config.initialTimeSlot || null);
46
- return {
47
- selectedServices,
48
- selectedTimeSlot,
41
+ // Initialize signals with config values
42
+ const servicesSignal = signalsService.signal(config.initialServices || []);
43
+ const timeSlotSignal = signalsService.signal(config.initialTimeSlot || null);
44
+ // Location is derived internally - initialize as null
45
+ const locationSignal = signalsService.signal(null);
46
+ const formValuesSignal = signalsService.signal(config.initialFormValues || null);
47
+ // ========================================================================
48
+ // Actions Implementation
49
+ // ========================================================================
50
+ const actions = {
51
+ // Services actions
52
+ setServices(newServices) {
53
+ servicesSignal.set(newServices);
54
+ },
55
+ addService(service) {
56
+ const current = servicesSignal.get();
57
+ servicesSignal.set([...current, service]);
58
+ },
59
+ updateService(serviceId, updates) {
60
+ const current = servicesSignal.get();
61
+ const updated = current.map((s) => s.service._id === serviceId ? { ...s, ...updates } : s);
62
+ servicesSignal.set(updated);
63
+ },
64
+ removeService(serviceId) {
65
+ const current = servicesSignal.get();
66
+ const filtered = current.filter((s) => s.service._id !== serviceId);
67
+ servicesSignal.set(filtered);
68
+ },
69
+ clearServices() {
70
+ servicesSignal.set([]);
71
+ },
72
+ // Time Slot actions
73
+ setTimeSlot(slot) {
74
+ timeSlotSignal.set(slot);
75
+ },
76
+ clearTimeSlot() {
77
+ timeSlotSignal.set(null);
78
+ },
79
+ // Location actions
80
+ setLocation(location) {
81
+ locationSignal.set(location);
82
+ },
83
+ clearLocation() {
84
+ locationSignal.set(null);
85
+ },
86
+ // Form Values actions
87
+ setFormValues(values) {
88
+ formValuesSignal.set(values);
89
+ },
90
+ clearFormValues() {
91
+ formValuesSignal.set(null);
92
+ },
93
+ // Clear all
94
+ clearAll() {
95
+ servicesSignal.set([]);
96
+ timeSlotSignal.set(null);
97
+ locationSignal.set(null);
98
+ formValuesSignal.set(null);
99
+ },
49
100
  };
50
- });
51
- /**
52
- * Load configuration for BookingService
53
- *
54
- * This function is called during SSR to initialize the service.
55
- * Currently returns null state - can be extended to load from API in future.
56
- *
57
- * @returns Promise resolving to BookingServiceConfig
58
- *
59
- * @example
60
- * ```astro
61
- * ---
62
- * import { loadBookingServiceConfig } from '@wix/headless-bookings/services';
63
- *
64
- * const bookingConfig = await loadBookingServiceConfig();
65
- * ---
66
- * ```
67
- */
68
- export async function loadBookingServiceConfig() {
69
- // Future: Load persisted selections from API by selection ID
70
101
  return {
71
- initialServices: [],
72
- initialTimeSlot: null,
102
+ services: servicesSignal,
103
+ timeSlot: timeSlotSignal,
104
+ location: locationSignal,
105
+ formValues: formValuesSignal,
106
+ actions,
73
107
  };
74
- }
108
+ });
@@ -3,4 +3,4 @@
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, type ServiceServiceAPI, type ServiceServiceConfig, loadServiceServiceConfig, type SuccessServiceServiceConfigResult, type NotFoundServiceServiceConfigResult, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, type BookingServiceConfig, loadBookingServiceConfig, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, type BookingServiceConfig, type ServiceSelection, type Location, type BookingServiceActions, } from './booking/booking.js';
@@ -3,4 +3,4 @@
3
3
  * Main export file for all service definitions and implementations
4
4
  */
5
5
  export { ServiceService, ServiceServiceDefinition, loadServiceServiceConfig, } from './service/service.js';
6
- export { BookingService, BookingServiceDefinition, loadBookingServiceConfig, } from './booking/booking.js';
6
+ export { BookingService, BookingServiceDefinition, } from './booking/booking.js';
@@ -5,7 +5,7 @@
5
5
  import { defineService, implementService } from '@wix/services-definitions';
6
6
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
7
7
  import { getServiceById, getServiceBySlug, } from '../../api/query-service/index.js';
8
- import { BookingServiceDefinition } from '../booking/booking.js';
8
+ import { BookingServiceDefinition, } from '../booking/booking.js';
9
9
  /**
10
10
  * Service definition for the Service service.
11
11
  * This defines the contract that the ServiceService must implement.
@@ -73,21 +73,20 @@ export const ServiceService = implementService.withConfig()(ServiceServiceDefini
73
73
  // Action methods for booking
74
74
  const select = () => {
75
75
  const currentService = service.get();
76
- bookingService.selectedServices.set([currentService]);
76
+ const selection = { service: currentService };
77
+ bookingService.services.set([selection]);
77
78
  };
78
79
  const add = () => {
79
80
  const currentService = service.get();
80
- const selectedServices = bookingService.selectedServices.get();
81
- bookingService.selectedServices.set([
82
- ...selectedServices,
83
- currentService,
84
- ]);
81
+ const selections = bookingService.services.get();
82
+ const selection = { service: currentService };
83
+ bookingService.services.set([...selections, selection]);
85
84
  };
86
85
  const remove = () => {
87
86
  const currentService = service.get();
88
- const selectedServices = bookingService.selectedServices.get();
89
- const filtered = selectedServices.filter((s) => s._id !== currentService._id);
90
- bookingService.selectedServices.set(filtered);
87
+ const selections = bookingService.services.get();
88
+ const filtered = selections.filter((s) => s.service._id !== currentService._id);
89
+ bookingService.services.set(filtered);
91
90
  };
92
91
  return {
93
92
  service,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-bookings",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -34,8 +34,9 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@wix/bookings": "^1.0.122",
37
- "@wix/headless-media": "0.0.17",
38
- "@wix/headless-utils": "0.0.7",
37
+ "@wix/form-public": "^0.64.0",
38
+ "@wix/headless-media": "0.0.18",
39
+ "@wix/headless-utils": "0.0.8",
39
40
  "@wix/services-definitions": "^0.1.4",
40
41
  "@wix/services-manager-react": "^0.1.26"
41
42
  },
@@ -67,5 +68,5 @@
67
68
  "groupId": "com.wixpress.headless-components"
68
69
  }
69
70
  },
70
- "falconPackageHash": "381d7fff89ddacd4d77c4967f65578268963890159ac44ffc0f58d9b"
71
+ "falconPackageHash": "3c91261634a562523b329f6e6e240b0e4e0e81b18b3d55fbcd7f53ff"
71
72
  }