@uptrademedia/site-kit 1.0.25 → 1.0.26
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/dist/index.d.mts +43 -13
- package/dist/index.d.ts +43 -13
- package/dist/index.js +98 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -704,8 +704,10 @@ interface BookingResult {
|
|
|
704
704
|
};
|
|
705
705
|
}
|
|
706
706
|
interface BookingWidgetProps {
|
|
707
|
-
/** Organization slug (
|
|
708
|
-
orgSlug
|
|
707
|
+
/** Organization slug – required for public (unauthenticated) mode, optional with apiKey */
|
|
708
|
+
orgSlug?: string;
|
|
709
|
+
/** API key – when provided, uses authenticated /sync/widget/* endpoints (no orgSlug needed) */
|
|
710
|
+
apiKey?: string;
|
|
709
711
|
/** API base URL - defaults to https://api.uptrademedia.com */
|
|
710
712
|
apiUrl?: string;
|
|
711
713
|
/** Specific booking type slug to show (optional - shows all if not provided) */
|
|
@@ -741,44 +743,72 @@ interface SyncWidgetConfig {
|
|
|
741
743
|
timezone: string;
|
|
742
744
|
}
|
|
743
745
|
|
|
744
|
-
declare function BookingWidget({ orgSlug, apiUrl, bookingTypeSlug, timezone: propTimezone, className, daysToShow, onBookingComplete, onError, hideTypeSelector, styles, }: BookingWidgetProps): react_jsx_runtime.JSX.Element;
|
|
746
|
+
declare function BookingWidget({ orgSlug, apiKey: propApiKey, apiUrl: propApiUrl, bookingTypeSlug, timezone: propTimezone, className, daysToShow, onBookingComplete, onError, hideTypeSelector, styles, }: BookingWidgetProps): react_jsx_runtime.JSX.Element;
|
|
745
747
|
|
|
746
748
|
/**
|
|
747
749
|
* Sync API Functions - Client-side API calls for booking widget
|
|
750
|
+
*
|
|
751
|
+
* Two modes:
|
|
752
|
+
* 1. API-key flow (preferred): Uses x-api-key header → /sync/widget/* endpoints.
|
|
753
|
+
* Project is resolved server-side from the key. No orgSlug needed.
|
|
754
|
+
* 2. Public/orgSlug flow (legacy): Uses /sync/public/:org/* endpoints. No auth.
|
|
748
755
|
*/
|
|
749
756
|
|
|
750
757
|
/**
|
|
751
|
-
* Fetch
|
|
758
|
+
* Fetch booking types.
|
|
759
|
+
* - With apiKey → GET /sync/widget/types
|
|
760
|
+
* - With orgSlug → GET /sync/public/:org/types
|
|
752
761
|
*/
|
|
753
|
-
declare function fetchBookingTypes(orgSlug
|
|
762
|
+
declare function fetchBookingTypes(orgSlug?: string, apiUrl?: string, apiKey?: string): Promise<BookingType[]>;
|
|
754
763
|
/**
|
|
755
764
|
* Fetch booking type details
|
|
756
765
|
*/
|
|
757
|
-
declare function fetchBookingTypeDetails(
|
|
766
|
+
declare function fetchBookingTypeDetails(typeSlug: string, orgSlug?: string, apiUrl?: string, apiKey?: string): Promise<BookingType>;
|
|
758
767
|
/**
|
|
759
768
|
* Fetch available time slots for a specific date
|
|
760
769
|
*/
|
|
761
|
-
declare function fetchAvailability(
|
|
762
|
-
apiUrl?: string, timezone?: string, hostId?: string): Promise<TimeSlot[]>;
|
|
770
|
+
declare function fetchAvailability(typeSlug: string, date: string, // YYYY-MM-DD format
|
|
771
|
+
orgSlug?: string, apiUrl?: string, apiKey?: string, timezone?: string, hostId?: string): Promise<TimeSlot[]>;
|
|
763
772
|
/**
|
|
764
773
|
* Hold a time slot temporarily (5-10 minutes)
|
|
765
774
|
*/
|
|
766
|
-
declare function createSlotHold(
|
|
775
|
+
declare function createSlotHold(holdData: {
|
|
776
|
+
bookingType: string;
|
|
777
|
+
slotStart: string;
|
|
778
|
+
slotEnd: string;
|
|
779
|
+
hostId: string;
|
|
780
|
+
sessionId: string;
|
|
781
|
+
guestEmail?: string;
|
|
782
|
+
}, apiUrl?: string, apiKey?: string): Promise<SlotHold>;
|
|
767
783
|
/**
|
|
768
784
|
* Release a slot hold
|
|
769
785
|
*/
|
|
770
|
-
declare function releaseSlotHold(holdId: string, apiUrl?: string): Promise<void>;
|
|
786
|
+
declare function releaseSlotHold(holdId: string, apiUrl?: string, apiKey?: string): Promise<void>;
|
|
771
787
|
/**
|
|
772
788
|
* Create a booking
|
|
773
789
|
*/
|
|
774
|
-
declare function createBooking(
|
|
790
|
+
declare function createBooking(bookingData: {
|
|
791
|
+
bookingType: string;
|
|
792
|
+
scheduledAt: string;
|
|
793
|
+
hostId: string;
|
|
794
|
+
name: string;
|
|
795
|
+
email: string;
|
|
796
|
+
phone?: string;
|
|
797
|
+
company?: string;
|
|
798
|
+
message?: string;
|
|
799
|
+
source: string;
|
|
800
|
+
timezone?: string;
|
|
801
|
+
holdId?: string;
|
|
802
|
+
sessionId?: string;
|
|
803
|
+
sourceUrl?: string;
|
|
804
|
+
}, apiUrl?: string, apiKey?: string): Promise<BookingResult>;
|
|
775
805
|
/**
|
|
776
806
|
* Get available dates for a month (helper for calendar view)
|
|
777
807
|
* Returns dates that have at least one available slot
|
|
778
808
|
*/
|
|
779
|
-
declare function fetchAvailableDates(
|
|
809
|
+
declare function fetchAvailableDates(typeSlug: string, startDate: string, // YYYY-MM-DD
|
|
780
810
|
endDate: string, // YYYY-MM-DD
|
|
781
|
-
apiUrl?: string, timezone?: string): Promise<string[]>;
|
|
811
|
+
orgSlug?: string, apiUrl?: string, apiKey?: string, timezone?: string): Promise<string[]>;
|
|
782
812
|
/**
|
|
783
813
|
* Detect user's timezone
|
|
784
814
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -704,8 +704,10 @@ interface BookingResult {
|
|
|
704
704
|
};
|
|
705
705
|
}
|
|
706
706
|
interface BookingWidgetProps {
|
|
707
|
-
/** Organization slug (
|
|
708
|
-
orgSlug
|
|
707
|
+
/** Organization slug – required for public (unauthenticated) mode, optional with apiKey */
|
|
708
|
+
orgSlug?: string;
|
|
709
|
+
/** API key – when provided, uses authenticated /sync/widget/* endpoints (no orgSlug needed) */
|
|
710
|
+
apiKey?: string;
|
|
709
711
|
/** API base URL - defaults to https://api.uptrademedia.com */
|
|
710
712
|
apiUrl?: string;
|
|
711
713
|
/** Specific booking type slug to show (optional - shows all if not provided) */
|
|
@@ -741,44 +743,72 @@ interface SyncWidgetConfig {
|
|
|
741
743
|
timezone: string;
|
|
742
744
|
}
|
|
743
745
|
|
|
744
|
-
declare function BookingWidget({ orgSlug, apiUrl, bookingTypeSlug, timezone: propTimezone, className, daysToShow, onBookingComplete, onError, hideTypeSelector, styles, }: BookingWidgetProps): react_jsx_runtime.JSX.Element;
|
|
746
|
+
declare function BookingWidget({ orgSlug, apiKey: propApiKey, apiUrl: propApiUrl, bookingTypeSlug, timezone: propTimezone, className, daysToShow, onBookingComplete, onError, hideTypeSelector, styles, }: BookingWidgetProps): react_jsx_runtime.JSX.Element;
|
|
745
747
|
|
|
746
748
|
/**
|
|
747
749
|
* Sync API Functions - Client-side API calls for booking widget
|
|
750
|
+
*
|
|
751
|
+
* Two modes:
|
|
752
|
+
* 1. API-key flow (preferred): Uses x-api-key header → /sync/widget/* endpoints.
|
|
753
|
+
* Project is resolved server-side from the key. No orgSlug needed.
|
|
754
|
+
* 2. Public/orgSlug flow (legacy): Uses /sync/public/:org/* endpoints. No auth.
|
|
748
755
|
*/
|
|
749
756
|
|
|
750
757
|
/**
|
|
751
|
-
* Fetch
|
|
758
|
+
* Fetch booking types.
|
|
759
|
+
* - With apiKey → GET /sync/widget/types
|
|
760
|
+
* - With orgSlug → GET /sync/public/:org/types
|
|
752
761
|
*/
|
|
753
|
-
declare function fetchBookingTypes(orgSlug
|
|
762
|
+
declare function fetchBookingTypes(orgSlug?: string, apiUrl?: string, apiKey?: string): Promise<BookingType[]>;
|
|
754
763
|
/**
|
|
755
764
|
* Fetch booking type details
|
|
756
765
|
*/
|
|
757
|
-
declare function fetchBookingTypeDetails(
|
|
766
|
+
declare function fetchBookingTypeDetails(typeSlug: string, orgSlug?: string, apiUrl?: string, apiKey?: string): Promise<BookingType>;
|
|
758
767
|
/**
|
|
759
768
|
* Fetch available time slots for a specific date
|
|
760
769
|
*/
|
|
761
|
-
declare function fetchAvailability(
|
|
762
|
-
apiUrl?: string, timezone?: string, hostId?: string): Promise<TimeSlot[]>;
|
|
770
|
+
declare function fetchAvailability(typeSlug: string, date: string, // YYYY-MM-DD format
|
|
771
|
+
orgSlug?: string, apiUrl?: string, apiKey?: string, timezone?: string, hostId?: string): Promise<TimeSlot[]>;
|
|
763
772
|
/**
|
|
764
773
|
* Hold a time slot temporarily (5-10 minutes)
|
|
765
774
|
*/
|
|
766
|
-
declare function createSlotHold(
|
|
775
|
+
declare function createSlotHold(holdData: {
|
|
776
|
+
bookingType: string;
|
|
777
|
+
slotStart: string;
|
|
778
|
+
slotEnd: string;
|
|
779
|
+
hostId: string;
|
|
780
|
+
sessionId: string;
|
|
781
|
+
guestEmail?: string;
|
|
782
|
+
}, apiUrl?: string, apiKey?: string): Promise<SlotHold>;
|
|
767
783
|
/**
|
|
768
784
|
* Release a slot hold
|
|
769
785
|
*/
|
|
770
|
-
declare function releaseSlotHold(holdId: string, apiUrl?: string): Promise<void>;
|
|
786
|
+
declare function releaseSlotHold(holdId: string, apiUrl?: string, apiKey?: string): Promise<void>;
|
|
771
787
|
/**
|
|
772
788
|
* Create a booking
|
|
773
789
|
*/
|
|
774
|
-
declare function createBooking(
|
|
790
|
+
declare function createBooking(bookingData: {
|
|
791
|
+
bookingType: string;
|
|
792
|
+
scheduledAt: string;
|
|
793
|
+
hostId: string;
|
|
794
|
+
name: string;
|
|
795
|
+
email: string;
|
|
796
|
+
phone?: string;
|
|
797
|
+
company?: string;
|
|
798
|
+
message?: string;
|
|
799
|
+
source: string;
|
|
800
|
+
timezone?: string;
|
|
801
|
+
holdId?: string;
|
|
802
|
+
sessionId?: string;
|
|
803
|
+
sourceUrl?: string;
|
|
804
|
+
}, apiUrl?: string, apiKey?: string): Promise<BookingResult>;
|
|
775
805
|
/**
|
|
776
806
|
* Get available dates for a month (helper for calendar view)
|
|
777
807
|
* Returns dates that have at least one available slot
|
|
778
808
|
*/
|
|
779
|
-
declare function fetchAvailableDates(
|
|
809
|
+
declare function fetchAvailableDates(typeSlug: string, startDate: string, // YYYY-MM-DD
|
|
780
810
|
endDate: string, // YYYY-MM-DD
|
|
781
|
-
apiUrl?: string, timezone?: string): Promise<string[]>;
|
|
811
|
+
orgSlug?: string, apiUrl?: string, apiKey?: string, timezone?: string): Promise<string[]>;
|
|
782
812
|
/**
|
|
783
813
|
* Detect user's timezone
|
|
784
814
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1821,70 +1821,89 @@ ${moduleConfigs.join("\n")}
|
|
|
1821
1821
|
|
|
1822
1822
|
// src/sync/api.ts
|
|
1823
1823
|
var DEFAULT_API_URL = "https://api.uptrademedia.com";
|
|
1824
|
-
|
|
1825
|
-
const
|
|
1824
|
+
function getApiConfig3() {
|
|
1825
|
+
const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || DEFAULT_API_URL : DEFAULT_API_URL;
|
|
1826
|
+
const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
|
|
1827
|
+
return { apiUrl, apiKey };
|
|
1828
|
+
}
|
|
1829
|
+
function buildHeaders(apiKey, isPost = false) {
|
|
1830
|
+
const headers = {};
|
|
1831
|
+
if (isPost) headers["Content-Type"] = "application/json";
|
|
1832
|
+
if (apiKey) headers["x-api-key"] = apiKey;
|
|
1833
|
+
return headers;
|
|
1834
|
+
}
|
|
1835
|
+
async function fetchBookingTypes(orgSlug, apiUrl, apiKey) {
|
|
1836
|
+
const cfg = getApiConfig3();
|
|
1837
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1838
|
+
const key = apiKey || cfg.apiKey;
|
|
1839
|
+
const endpoint = key ? `${url}/sync/widget/types` : `${url}/sync/public/${orgSlug}/types`;
|
|
1840
|
+
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1826
1841
|
if (!response.ok) {
|
|
1827
1842
|
throw new Error(`Failed to fetch booking types: ${response.statusText}`);
|
|
1828
1843
|
}
|
|
1829
1844
|
const data = await response.json();
|
|
1830
1845
|
return data.types || [];
|
|
1831
1846
|
}
|
|
1832
|
-
async function fetchBookingTypeDetails(
|
|
1833
|
-
const
|
|
1847
|
+
async function fetchBookingTypeDetails(typeSlug, orgSlug, apiUrl, apiKey) {
|
|
1848
|
+
const cfg = getApiConfig3();
|
|
1849
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1850
|
+
const key = apiKey || cfg.apiKey;
|
|
1851
|
+
const endpoint = key ? `${url}/sync/widget/types/${typeSlug}` : `${url}/sync/public/${orgSlug}/types/${typeSlug}`;
|
|
1852
|
+
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1834
1853
|
if (!response.ok) {
|
|
1835
1854
|
throw new Error(`Failed to fetch booking type: ${response.statusText}`);
|
|
1836
1855
|
}
|
|
1837
1856
|
return response.json();
|
|
1838
1857
|
}
|
|
1839
|
-
async function fetchAvailability(
|
|
1858
|
+
async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezone, hostId) {
|
|
1859
|
+
const cfg = getApiConfig3();
|
|
1860
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1861
|
+
const key = apiKey || cfg.apiKey;
|
|
1840
1862
|
const params = new URLSearchParams({ date });
|
|
1841
1863
|
if (timezone) params.append("timezone", timezone);
|
|
1842
1864
|
if (hostId) params.append("hostId", hostId);
|
|
1843
|
-
const
|
|
1844
|
-
|
|
1845
|
-
);
|
|
1865
|
+
const endpoint = key ? `${url}/sync/widget/availability/${typeSlug}?${params}` : `${url}/sync/public/${orgSlug}/availability/${typeSlug}?${params}`;
|
|
1866
|
+
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1846
1867
|
if (!response.ok) {
|
|
1847
1868
|
throw new Error(`Failed to fetch availability: ${response.statusText}`);
|
|
1848
1869
|
}
|
|
1849
1870
|
const data = await response.json();
|
|
1850
1871
|
return data.slots || [];
|
|
1851
1872
|
}
|
|
1852
|
-
async function createSlotHold(
|
|
1853
|
-
const
|
|
1873
|
+
async function createSlotHold(holdData, apiUrl, apiKey) {
|
|
1874
|
+
const cfg = getApiConfig3();
|
|
1875
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1876
|
+
const key = apiKey || cfg.apiKey;
|
|
1877
|
+
const endpoint = key ? `${url}/sync/widget/hold` : `${url}/sync/public/hold`;
|
|
1878
|
+
const response = await fetch(endpoint, {
|
|
1854
1879
|
method: "POST",
|
|
1855
|
-
headers:
|
|
1856
|
-
body: JSON.stringify(
|
|
1857
|
-
booking_type_id: bookingTypeId,
|
|
1858
|
-
start_time: startTime,
|
|
1859
|
-
host_id: hostId,
|
|
1860
|
-
guest_timezone: guestTimezone
|
|
1861
|
-
})
|
|
1880
|
+
headers: buildHeaders(key, true),
|
|
1881
|
+
body: JSON.stringify(holdData)
|
|
1862
1882
|
});
|
|
1863
1883
|
if (!response.ok) {
|
|
1864
1884
|
throw new Error(`Failed to hold slot: ${response.statusText}`);
|
|
1865
1885
|
}
|
|
1866
1886
|
return response.json();
|
|
1867
1887
|
}
|
|
1868
|
-
async function releaseSlotHold(holdId, apiUrl
|
|
1869
|
-
|
|
1870
|
-
|
|
1888
|
+
async function releaseSlotHold(holdId, apiUrl, apiKey) {
|
|
1889
|
+
const cfg = getApiConfig3();
|
|
1890
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1891
|
+
const key = apiKey || cfg.apiKey;
|
|
1892
|
+
const endpoint = key ? `${url}/sync/widget/hold/${holdId}` : `${url}/sync/public/hold/${holdId}`;
|
|
1893
|
+
await fetch(endpoint, {
|
|
1894
|
+
method: "DELETE",
|
|
1895
|
+
headers: buildHeaders(key)
|
|
1871
1896
|
});
|
|
1872
1897
|
}
|
|
1873
|
-
async function createBooking(
|
|
1874
|
-
const
|
|
1898
|
+
async function createBooking(bookingData, apiUrl, apiKey) {
|
|
1899
|
+
const cfg = getApiConfig3();
|
|
1900
|
+
const url = apiUrl || cfg.apiUrl;
|
|
1901
|
+
const key = apiKey || cfg.apiKey;
|
|
1902
|
+
const endpoint = key ? `${url}/sync/widget/booking` : `${url}/sync/public/booking`;
|
|
1903
|
+
const response = await fetch(endpoint, {
|
|
1875
1904
|
method: "POST",
|
|
1876
|
-
headers:
|
|
1877
|
-
body: JSON.stringify(
|
|
1878
|
-
booking_type_id: bookingTypeId,
|
|
1879
|
-
start_time: startTime,
|
|
1880
|
-
guest_name: guest.name,
|
|
1881
|
-
guest_email: guest.email,
|
|
1882
|
-
guest_phone: guest.phone,
|
|
1883
|
-
guest_notes: guest.notes,
|
|
1884
|
-
timezone,
|
|
1885
|
-
host_id: hostId,
|
|
1886
|
-
hold_id: holdId
|
|
1887
|
-
})
|
|
1905
|
+
headers: buildHeaders(key, true),
|
|
1906
|
+
body: JSON.stringify(bookingData)
|
|
1888
1907
|
});
|
|
1889
1908
|
if (!response.ok) {
|
|
1890
1909
|
const errorData = await response.json().catch(() => ({}));
|
|
@@ -1892,7 +1911,7 @@ async function createBooking(bookingTypeId, startTime, guest, timezone, hostId,
|
|
|
1892
1911
|
}
|
|
1893
1912
|
return response.json();
|
|
1894
1913
|
}
|
|
1895
|
-
async function fetchAvailableDates(
|
|
1914
|
+
async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl, apiKey, timezone) {
|
|
1896
1915
|
const availableDates = [];
|
|
1897
1916
|
const start = new Date(startDate);
|
|
1898
1917
|
const end = new Date(endDate);
|
|
@@ -1900,7 +1919,7 @@ async function fetchAvailableDates(orgSlug, typeSlug, startDate, endDate, apiUrl
|
|
|
1900
1919
|
while (current <= end) {
|
|
1901
1920
|
const dateStr = current.toISOString().split("T")[0];
|
|
1902
1921
|
try {
|
|
1903
|
-
const slots = await fetchAvailability(
|
|
1922
|
+
const slots = await fetchAvailability(typeSlug, dateStr, orgSlug, apiUrl, apiKey, timezone);
|
|
1904
1923
|
if (slots.some((s) => s.available)) {
|
|
1905
1924
|
availableDates.push(dateStr);
|
|
1906
1925
|
}
|
|
@@ -2023,7 +2042,8 @@ function SpinnerIcon() {
|
|
|
2023
2042
|
}
|
|
2024
2043
|
function BookingWidget({
|
|
2025
2044
|
orgSlug,
|
|
2026
|
-
|
|
2045
|
+
apiKey: propApiKey,
|
|
2046
|
+
apiUrl: propApiUrl,
|
|
2027
2047
|
bookingTypeSlug,
|
|
2028
2048
|
timezone: propTimezone,
|
|
2029
2049
|
className = "",
|
|
@@ -2033,6 +2053,8 @@ function BookingWidget({
|
|
|
2033
2053
|
hideTypeSelector = false,
|
|
2034
2054
|
styles: styles2 = {}
|
|
2035
2055
|
}) {
|
|
2056
|
+
const apiKey = propApiKey || (typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0);
|
|
2057
|
+
const apiUrl = propApiUrl || (typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ : void 0) || DEFAULT_API_URL2;
|
|
2036
2058
|
const [step, setStep] = React3.useState(bookingTypeSlug ? "datetime" : "type");
|
|
2037
2059
|
const [loading, setLoading] = React3.useState(false);
|
|
2038
2060
|
const [slotsLoading, setSlotsLoading] = React3.useState(false);
|
|
@@ -2072,7 +2094,7 @@ function BookingWidget({
|
|
|
2072
2094
|
React3.useEffect(() => {
|
|
2073
2095
|
if (bookingTypeSlug) {
|
|
2074
2096
|
setLoading(true);
|
|
2075
|
-
fetchBookingTypeDetails(orgSlug,
|
|
2097
|
+
fetchBookingTypeDetails(bookingTypeSlug, orgSlug, apiUrl, apiKey).then((type) => {
|
|
2076
2098
|
setSelectedType(type);
|
|
2077
2099
|
setStep("datetime");
|
|
2078
2100
|
}).catch((err) => {
|
|
@@ -2081,12 +2103,12 @@ function BookingWidget({
|
|
|
2081
2103
|
}).finally(() => setLoading(false));
|
|
2082
2104
|
} else {
|
|
2083
2105
|
setLoading(true);
|
|
2084
|
-
fetchBookingTypes(orgSlug, apiUrl).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
|
|
2106
|
+
fetchBookingTypes(orgSlug, apiUrl, apiKey).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
|
|
2085
2107
|
setError(err.message);
|
|
2086
2108
|
onError?.(err);
|
|
2087
2109
|
}).finally(() => setLoading(false));
|
|
2088
2110
|
}
|
|
2089
|
-
}, [orgSlug, bookingTypeSlug, apiUrl, onError]);
|
|
2111
|
+
}, [orgSlug, apiKey, bookingTypeSlug, apiUrl, onError]);
|
|
2090
2112
|
React3.useEffect(() => {
|
|
2091
2113
|
if (!selectedDate || !selectedType) return;
|
|
2092
2114
|
const dateStr = selectedDate.toISOString().split("T")[0];
|
|
@@ -2094,22 +2116,32 @@ function BookingWidget({
|
|
|
2094
2116
|
setSlots([]);
|
|
2095
2117
|
setSelectedSlot(null);
|
|
2096
2118
|
setConfirmedSlot(false);
|
|
2097
|
-
fetchAvailability(
|
|
2119
|
+
fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
|
|
2098
2120
|
setError(err.message);
|
|
2099
2121
|
onError?.(err);
|
|
2100
2122
|
}).finally(() => setSlotsLoading(false));
|
|
2101
|
-
}, [selectedDate, selectedType, orgSlug, apiUrl, timezone, onError]);
|
|
2123
|
+
}, [selectedDate, selectedType, orgSlug, apiKey, apiUrl, timezone, onError]);
|
|
2102
2124
|
const handleSlotSelect = React3.useCallback((slot) => {
|
|
2103
2125
|
setSelectedSlot(slot);
|
|
2104
2126
|
setConfirmedSlot(false);
|
|
2105
2127
|
}, []);
|
|
2106
2128
|
const handleSlotConfirm = React3.useCallback(async () => {
|
|
2107
2129
|
if (!selectedType || !selectedSlot) return;
|
|
2108
|
-
if (hold) await releaseSlotHold(hold.holdId, apiUrl).catch(() => {
|
|
2130
|
+
if (hold) await releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
|
|
2109
2131
|
});
|
|
2110
2132
|
setLoading(true);
|
|
2111
2133
|
try {
|
|
2112
|
-
const newHold = await createSlotHold(
|
|
2134
|
+
const newHold = await createSlotHold(
|
|
2135
|
+
{
|
|
2136
|
+
bookingType: selectedType.slug,
|
|
2137
|
+
slotStart: selectedSlot.start,
|
|
2138
|
+
slotEnd: selectedSlot.end,
|
|
2139
|
+
hostId: selectedSlot.hostId || "",
|
|
2140
|
+
sessionId: `bw-${Date.now()}`
|
|
2141
|
+
},
|
|
2142
|
+
apiUrl,
|
|
2143
|
+
apiKey
|
|
2144
|
+
);
|
|
2113
2145
|
setHold(newHold);
|
|
2114
2146
|
setConfirmedSlot(true);
|
|
2115
2147
|
setStep("form");
|
|
@@ -2119,14 +2151,31 @@ function BookingWidget({
|
|
|
2119
2151
|
} finally {
|
|
2120
2152
|
setLoading(false);
|
|
2121
2153
|
}
|
|
2122
|
-
}, [selectedType, selectedSlot, hold, timezone, apiUrl, onError]);
|
|
2154
|
+
}, [selectedType, selectedSlot, hold, timezone, apiUrl, apiKey, onError]);
|
|
2123
2155
|
const handleBookingSubmit = React3.useCallback(async (e) => {
|
|
2124
2156
|
e.preventDefault();
|
|
2125
2157
|
if (!selectedType || !selectedSlot) return;
|
|
2126
2158
|
setSubmitting(true);
|
|
2127
2159
|
setError(null);
|
|
2128
2160
|
try {
|
|
2129
|
-
const result = await createBooking(
|
|
2161
|
+
const result = await createBooking(
|
|
2162
|
+
{
|
|
2163
|
+
bookingType: selectedType.slug,
|
|
2164
|
+
scheduledAt: selectedSlot.start,
|
|
2165
|
+
hostId: selectedSlot.hostId || "",
|
|
2166
|
+
name: guestInfo.name,
|
|
2167
|
+
email: guestInfo.email,
|
|
2168
|
+
phone: guestInfo.phone,
|
|
2169
|
+
message: guestInfo.notes,
|
|
2170
|
+
source: "main-site",
|
|
2171
|
+
timezone,
|
|
2172
|
+
holdId: hold?.holdId,
|
|
2173
|
+
sessionId: `bw-${Date.now()}`,
|
|
2174
|
+
sourceUrl: typeof window !== "undefined" ? window.location.href : void 0
|
|
2175
|
+
},
|
|
2176
|
+
apiUrl,
|
|
2177
|
+
apiKey
|
|
2178
|
+
);
|
|
2130
2179
|
setBookingResult(result);
|
|
2131
2180
|
setStep("success");
|
|
2132
2181
|
onBookingComplete?.(result);
|
|
@@ -2136,13 +2185,13 @@ function BookingWidget({
|
|
|
2136
2185
|
} finally {
|
|
2137
2186
|
setSubmitting(false);
|
|
2138
2187
|
}
|
|
2139
|
-
}, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, onBookingComplete, onError]);
|
|
2188
|
+
}, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, apiKey, onBookingComplete, onError]);
|
|
2140
2189
|
React3.useEffect(() => {
|
|
2141
2190
|
return () => {
|
|
2142
|
-
if (hold) releaseSlotHold(hold.holdId, apiUrl).catch(() => {
|
|
2191
|
+
if (hold) releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
|
|
2143
2192
|
});
|
|
2144
2193
|
};
|
|
2145
|
-
}, [hold, apiUrl]);
|
|
2194
|
+
}, [hold, apiUrl, apiKey]);
|
|
2146
2195
|
const canGoPrev = viewMonth.getFullYear() > today.getFullYear() || viewMonth.getMonth() > today.getMonth();
|
|
2147
2196
|
const canGoNext = viewMonth < maxDate;
|
|
2148
2197
|
const goMonth = (dir) => {
|