@cimplify/sdk 0.18.0 → 0.20.0
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/advanced.d.mts +2 -2
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.js +21 -21
- package/dist/advanced.mjs +2 -2
- package/dist/{chunk-RYQ5IPWX.js → chunk-2BSYTQAY.js} +18 -28
- package/dist/{chunk-KTTQC5HG.mjs → chunk-676BJ3EU.mjs} +43 -8
- package/dist/{chunk-2JI47EYJ.mjs → chunk-7KH2XJIW.mjs} +67 -12
- package/dist/{chunk-MJECWMOY.js → chunk-AVVLN353.js} +76 -40
- package/dist/{chunk-FTL2SXCG.mjs → chunk-HG7GG3TT.mjs} +18 -28
- package/dist/{chunk-DYKFSV77.js → chunk-KSN3RJFL.js} +86 -30
- package/dist/{client-BFFfuzJr.d.mts → client-D4E9aJy7.d.mts} +141 -7
- package/dist/{client-B1UtuyOg.d.ts → client-VyO6Bqz2.d.ts} +141 -7
- package/dist/index.d.mts +38 -5
- package/dist/index.d.ts +38 -5
- package/dist/index.js +101 -97
- package/dist/index.mjs +3 -3
- package/dist/{payment-D9FTaOse.d.mts → payment-CKqMU4xT.d.mts} +1052 -934
- package/dist/{payment-D9FTaOse.d.ts → payment-CKqMU4xT.d.ts} +1052 -934
- package/dist/{price-BD1iioLh.d.ts → price-BqV_DjjQ.d.mts} +1 -1
- package/dist/{price-9JsPuknm.d.mts → price-e4beObLZ.d.ts} +1 -1
- package/dist/react.d.mts +463 -11
- package/dist/react.d.ts +463 -11
- package/dist/react.js +1630 -113
- package/dist/react.mjs +1566 -65
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +28 -28
- package/dist/utils.mjs +1 -1
- package/package.json +2 -2
- package/registry/availability-badge.json +1 -1
- package/registry/booking-page.json +1 -1
- package/registry/bundle-selector.json +1 -1
- package/registry/cart-summary.json +1 -1
- package/registry/composite-selector.json +1 -1
- package/registry/order-summary.json +1 -1
- package/registry/product-customizer.json +1 -1
- package/registry/search-input.json +1 -1
- package/registry/service-card.json +1 -1
- package/registry/variant-selector.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { getVariantDisplayName, createCimplifyClient } from './chunk-
|
|
3
|
-
export { getVariantDisplayName } from './chunk-
|
|
4
|
-
import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-
|
|
5
|
-
import { isSupportedCurrency, formatPrice, parsePrice, isOnSale, getDiscountPercentage, getBasePrice } from './chunk-
|
|
2
|
+
import { getVariantDisplayName, createCimplifyClient } from './chunk-676BJ3EU.mjs';
|
|
3
|
+
export { getVariantDisplayName } from './chunk-676BJ3EU.mjs';
|
|
4
|
+
import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-7KH2XJIW.mjs';
|
|
5
|
+
import { isSupportedCurrency, formatPrice, parsePrice, isOnSale, getDiscountPercentage, getBasePrice } from './chunk-HG7GG3TT.mjs';
|
|
6
6
|
import React3, { createContext, useContext, useState, useEffect, useRef, useMemo, useSyncExternalStore, useCallback, useId } from 'react';
|
|
7
7
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
8
8
|
import { NumberField } from '@base-ui/react/number-field';
|
|
@@ -532,7 +532,12 @@ function mapServerCart(serverCart) {
|
|
|
532
532
|
specialInstructions: item.special_instructions,
|
|
533
533
|
scheduledStart: item.scheduled_start || void 0,
|
|
534
534
|
scheduledEnd: item.scheduled_end || void 0,
|
|
535
|
-
staffId: item.staff_id || void 0
|
|
535
|
+
staffId: item.staff_id || void 0,
|
|
536
|
+
lineType: item.line_type,
|
|
537
|
+
confirmationCode: item.confirmation_code || void 0,
|
|
538
|
+
serviceStatus: item.service_status || void 0,
|
|
539
|
+
bundleResolved: item.bundle_resolved || void 0,
|
|
540
|
+
compositeResolved: item.composite_resolved || void 0
|
|
536
541
|
});
|
|
537
542
|
});
|
|
538
543
|
return {
|
|
@@ -2089,7 +2094,7 @@ function useOrder(orderId, options = {}) {
|
|
|
2089
2094
|
return () => {
|
|
2090
2095
|
window.clearInterval(timer);
|
|
2091
2096
|
};
|
|
2092
|
-
}, [enabled, load, normalizedOrderId
|
|
2097
|
+
}, [enabled, load, normalizedOrderId, poll, pollInterval]);
|
|
2093
2098
|
const refetch = useCallback(async () => {
|
|
2094
2099
|
orderCache.delete(cacheKey);
|
|
2095
2100
|
await load(true);
|
|
@@ -3989,6 +3994,682 @@ function useBookings(options = {}) {
|
|
|
3989
3994
|
);
|
|
3990
3995
|
return { bookings, isLoading, error, refetch, cancelBooking };
|
|
3991
3996
|
}
|
|
3997
|
+
var definitionsCache = /* @__PURE__ */ new Map();
|
|
3998
|
+
var definitionsInflight = /* @__PURE__ */ new Map();
|
|
3999
|
+
function buildCacheKey(client, namespace) {
|
|
4000
|
+
return `attr_defs_${client.getPublicKey() || "__demo__"}${namespace ? `_${namespace}` : ""}`;
|
|
4001
|
+
}
|
|
4002
|
+
function useAttributeDefinitions(options = {}) {
|
|
4003
|
+
const context = useOptionalCimplifyClient();
|
|
4004
|
+
const client = options.client ?? context?.client;
|
|
4005
|
+
if (!client) {
|
|
4006
|
+
throw new Error(
|
|
4007
|
+
"useAttributeDefinitions must be used within CimplifyProvider or passed { client }."
|
|
4008
|
+
);
|
|
4009
|
+
}
|
|
4010
|
+
const enabled = options.enabled ?? true;
|
|
4011
|
+
const namespace = options.namespace;
|
|
4012
|
+
const cacheKey = useMemo(() => buildCacheKey(client, namespace), [client, namespace]);
|
|
4013
|
+
const cached = definitionsCache.get(cacheKey);
|
|
4014
|
+
const [definitions, setDefinitions] = useState(cached ?? []);
|
|
4015
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4016
|
+
const [error, setError] = useState(null);
|
|
4017
|
+
const load = useCallback(
|
|
4018
|
+
async (force = false) => {
|
|
4019
|
+
if (!enabled) {
|
|
4020
|
+
setIsLoading(false);
|
|
4021
|
+
return;
|
|
4022
|
+
}
|
|
4023
|
+
setError(null);
|
|
4024
|
+
if (!force) {
|
|
4025
|
+
const cachedDefs = definitionsCache.get(cacheKey);
|
|
4026
|
+
if (cachedDefs) {
|
|
4027
|
+
setDefinitions(cachedDefs);
|
|
4028
|
+
setIsLoading(false);
|
|
4029
|
+
return;
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
setIsLoading(true);
|
|
4033
|
+
try {
|
|
4034
|
+
const existing = definitionsInflight.get(cacheKey);
|
|
4035
|
+
const promise = existing ?? (async () => {
|
|
4036
|
+
const result = await client.catalogue.getAttributeDefinitions(namespace);
|
|
4037
|
+
if (!result.ok) {
|
|
4038
|
+
throw result.error;
|
|
4039
|
+
}
|
|
4040
|
+
return result.value;
|
|
4041
|
+
})();
|
|
4042
|
+
if (!existing) {
|
|
4043
|
+
definitionsInflight.set(
|
|
4044
|
+
cacheKey,
|
|
4045
|
+
promise.finally(() => {
|
|
4046
|
+
definitionsInflight.delete(cacheKey);
|
|
4047
|
+
})
|
|
4048
|
+
);
|
|
4049
|
+
}
|
|
4050
|
+
const value = await promise;
|
|
4051
|
+
definitionsCache.set(cacheKey, value);
|
|
4052
|
+
setDefinitions(value);
|
|
4053
|
+
} catch (loadError) {
|
|
4054
|
+
setError(loadError);
|
|
4055
|
+
} finally {
|
|
4056
|
+
setIsLoading(false);
|
|
4057
|
+
}
|
|
4058
|
+
},
|
|
4059
|
+
[cacheKey, client, enabled]
|
|
4060
|
+
);
|
|
4061
|
+
useEffect(() => {
|
|
4062
|
+
void load(false);
|
|
4063
|
+
}, [load]);
|
|
4064
|
+
const refetch = useCallback(async () => {
|
|
4065
|
+
definitionsCache.delete(cacheKey);
|
|
4066
|
+
await load(true);
|
|
4067
|
+
}, [cacheKey, load]);
|
|
4068
|
+
return { definitions, isLoading, error, refetch };
|
|
4069
|
+
}
|
|
4070
|
+
var facetsCache = /* @__PURE__ */ new Map();
|
|
4071
|
+
var facetsInflight = /* @__PURE__ */ new Map();
|
|
4072
|
+
function usePropertyFacets(options = {}) {
|
|
4073
|
+
const context = useOptionalCimplifyClient();
|
|
4074
|
+
const client = options.client ?? context?.client;
|
|
4075
|
+
if (!client) {
|
|
4076
|
+
throw new Error(
|
|
4077
|
+
"usePropertyFacets must be used within CimplifyProvider or passed { client }."
|
|
4078
|
+
);
|
|
4079
|
+
}
|
|
4080
|
+
const enabled = options.enabled ?? true;
|
|
4081
|
+
const cacheKey = useMemo(
|
|
4082
|
+
() => `facets_${client.getPublicKey() || "__demo__"}_${options.category_id ?? ""}_${options.product_type ?? ""}`,
|
|
4083
|
+
[client, options.category_id, options.product_type]
|
|
4084
|
+
);
|
|
4085
|
+
const cached = facetsCache.get(cacheKey);
|
|
4086
|
+
const [facets, setFacets] = useState(cached ?? []);
|
|
4087
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4088
|
+
const [error, setError] = useState(null);
|
|
4089
|
+
const load = useCallback(
|
|
4090
|
+
async (force = false) => {
|
|
4091
|
+
if (!enabled) {
|
|
4092
|
+
setIsLoading(false);
|
|
4093
|
+
return;
|
|
4094
|
+
}
|
|
4095
|
+
setError(null);
|
|
4096
|
+
if (!force) {
|
|
4097
|
+
const cachedFacets = facetsCache.get(cacheKey);
|
|
4098
|
+
if (cachedFacets) {
|
|
4099
|
+
setFacets(cachedFacets);
|
|
4100
|
+
setIsLoading(false);
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
setIsLoading(true);
|
|
4105
|
+
try {
|
|
4106
|
+
const existing = facetsInflight.get(cacheKey);
|
|
4107
|
+
const promise = existing ?? (async () => {
|
|
4108
|
+
const result = await client.catalogue.getPropertyFacets({
|
|
4109
|
+
category_id: options.category_id,
|
|
4110
|
+
product_type: options.product_type
|
|
4111
|
+
});
|
|
4112
|
+
if (!result.ok) {
|
|
4113
|
+
throw result.error;
|
|
4114
|
+
}
|
|
4115
|
+
return result.value;
|
|
4116
|
+
})();
|
|
4117
|
+
if (!existing) {
|
|
4118
|
+
facetsInflight.set(
|
|
4119
|
+
cacheKey,
|
|
4120
|
+
promise.finally(() => {
|
|
4121
|
+
facetsInflight.delete(cacheKey);
|
|
4122
|
+
})
|
|
4123
|
+
);
|
|
4124
|
+
}
|
|
4125
|
+
const value = await promise;
|
|
4126
|
+
facetsCache.set(cacheKey, value);
|
|
4127
|
+
setFacets(value);
|
|
4128
|
+
} catch (loadError) {
|
|
4129
|
+
setError(loadError);
|
|
4130
|
+
} finally {
|
|
4131
|
+
setIsLoading(false);
|
|
4132
|
+
}
|
|
4133
|
+
},
|
|
4134
|
+
[cacheKey, client, enabled, options.category_id, options.product_type]
|
|
4135
|
+
);
|
|
4136
|
+
useEffect(() => {
|
|
4137
|
+
void load(false);
|
|
4138
|
+
}, [load]);
|
|
4139
|
+
const refetch = useCallback(async () => {
|
|
4140
|
+
facetsCache.delete(cacheKey);
|
|
4141
|
+
await load(true);
|
|
4142
|
+
}, [cacheKey, load]);
|
|
4143
|
+
return { facets, isLoading, error, refetch };
|
|
4144
|
+
}
|
|
4145
|
+
function useBillingPlans(productId, options = {}) {
|
|
4146
|
+
const context = useOptionalCimplifyClient();
|
|
4147
|
+
const client = options.client ?? context?.client;
|
|
4148
|
+
if (!client) {
|
|
4149
|
+
throw new Error("useBillingPlans must be used within CimplifyProvider or passed { client }.");
|
|
4150
|
+
}
|
|
4151
|
+
const enabled = options.enabled ?? true;
|
|
4152
|
+
const requestIdRef = useRef(0);
|
|
4153
|
+
const [plans, setPlans] = useState([]);
|
|
4154
|
+
const [isLoading, setIsLoading] = useState(enabled && !!productId);
|
|
4155
|
+
const [error, setError] = useState(null);
|
|
4156
|
+
const customerId = options.customerId;
|
|
4157
|
+
const quantity = options.quantity;
|
|
4158
|
+
const orderValue = options.orderValue;
|
|
4159
|
+
const load = useCallback(
|
|
4160
|
+
async (force = false) => {
|
|
4161
|
+
if (!enabled || !productId) {
|
|
4162
|
+
setPlans([]);
|
|
4163
|
+
setIsLoading(false);
|
|
4164
|
+
return;
|
|
4165
|
+
}
|
|
4166
|
+
const nextRequestId = ++requestIdRef.current;
|
|
4167
|
+
setError(null);
|
|
4168
|
+
setIsLoading(true);
|
|
4169
|
+
try {
|
|
4170
|
+
const result = await client.catalogue.getEligibleBillingPlans(productId, {
|
|
4171
|
+
customer_id: customerId,
|
|
4172
|
+
quantity,
|
|
4173
|
+
order_value: orderValue
|
|
4174
|
+
});
|
|
4175
|
+
if (!result.ok) {
|
|
4176
|
+
throw result.error;
|
|
4177
|
+
}
|
|
4178
|
+
if (nextRequestId === requestIdRef.current) {
|
|
4179
|
+
setPlans(result.value);
|
|
4180
|
+
setError(null);
|
|
4181
|
+
}
|
|
4182
|
+
} catch (loadError) {
|
|
4183
|
+
if (nextRequestId === requestIdRef.current) {
|
|
4184
|
+
setError(loadError);
|
|
4185
|
+
}
|
|
4186
|
+
} finally {
|
|
4187
|
+
if (nextRequestId === requestIdRef.current) {
|
|
4188
|
+
setIsLoading(false);
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
},
|
|
4192
|
+
[client, enabled, productId, customerId, quantity, orderValue]
|
|
4193
|
+
);
|
|
4194
|
+
useEffect(() => {
|
|
4195
|
+
void load(false);
|
|
4196
|
+
}, [load]);
|
|
4197
|
+
const refetch = useCallback(async () => {
|
|
4198
|
+
await load(true);
|
|
4199
|
+
}, [load]);
|
|
4200
|
+
const subscriptionPlans = useMemo(
|
|
4201
|
+
() => plans.filter((p) => p.plan_type === "subscription"),
|
|
4202
|
+
[plans]
|
|
4203
|
+
);
|
|
4204
|
+
const installmentPlans = useMemo(
|
|
4205
|
+
() => plans.filter((p) => p.plan_type === "installment"),
|
|
4206
|
+
[plans]
|
|
4207
|
+
);
|
|
4208
|
+
return { plans, subscriptionPlans, installmentPlans, isLoading, error, refetch };
|
|
4209
|
+
}
|
|
4210
|
+
function findMatchingVariant(variants, selections) {
|
|
4211
|
+
const axisCount = Object.keys(selections).length;
|
|
4212
|
+
if (axisCount === 0) return null;
|
|
4213
|
+
return variants.find((v) => {
|
|
4214
|
+
const sel = v.axis_selections;
|
|
4215
|
+
if (!sel) return false;
|
|
4216
|
+
return Object.entries(selections).every(([axisId, valueId]) => sel[axisId] === valueId);
|
|
4217
|
+
}) ?? null;
|
|
4218
|
+
}
|
|
4219
|
+
function computeAvailableValues(variants, axes, selections) {
|
|
4220
|
+
const result = {};
|
|
4221
|
+
for (const axis of axes) {
|
|
4222
|
+
const otherSelections = Object.entries(selections).filter(([id]) => id !== axis.id);
|
|
4223
|
+
const candidates = variants.filter((v) => {
|
|
4224
|
+
const sel = v.axis_selections;
|
|
4225
|
+
if (!sel) return false;
|
|
4226
|
+
return otherSelections.every(([axisId, valueId]) => sel[axisId] === valueId);
|
|
4227
|
+
});
|
|
4228
|
+
const available = /* @__PURE__ */ new Set();
|
|
4229
|
+
for (const v of candidates) {
|
|
4230
|
+
const val = v.axis_selections?.[axis.id];
|
|
4231
|
+
if (val) available.add(val);
|
|
4232
|
+
}
|
|
4233
|
+
result[axis.id] = available;
|
|
4234
|
+
}
|
|
4235
|
+
return result;
|
|
4236
|
+
}
|
|
4237
|
+
function useVariantSelector(options) {
|
|
4238
|
+
const { variants, axes } = options;
|
|
4239
|
+
const [selectedValues, setSelectedValues] = useState({});
|
|
4240
|
+
const selectValue = useCallback(
|
|
4241
|
+
(axisId, valueId) => {
|
|
4242
|
+
setSelectedValues((prev) => {
|
|
4243
|
+
if (prev[axisId] === valueId) {
|
|
4244
|
+
const next = { ...prev };
|
|
4245
|
+
delete next[axisId];
|
|
4246
|
+
return next;
|
|
4247
|
+
}
|
|
4248
|
+
return { ...prev, [axisId]: valueId };
|
|
4249
|
+
});
|
|
4250
|
+
},
|
|
4251
|
+
[]
|
|
4252
|
+
);
|
|
4253
|
+
const reset = useCallback(() => setSelectedValues({}), []);
|
|
4254
|
+
const selectedVariant = useMemo(
|
|
4255
|
+
() => findMatchingVariant(variants, selectedValues),
|
|
4256
|
+
[variants, selectedValues]
|
|
4257
|
+
);
|
|
4258
|
+
const variantImage = useMemo(
|
|
4259
|
+
() => selectedVariant?.images?.[0] ?? null,
|
|
4260
|
+
[selectedVariant]
|
|
4261
|
+
);
|
|
4262
|
+
const availableValues = useMemo(
|
|
4263
|
+
() => computeAvailableValues(variants, axes, selectedValues),
|
|
4264
|
+
[variants, axes, selectedValues]
|
|
4265
|
+
);
|
|
4266
|
+
return {
|
|
4267
|
+
selectedValues,
|
|
4268
|
+
selectedVariant,
|
|
4269
|
+
variantImage,
|
|
4270
|
+
availableValues,
|
|
4271
|
+
selectValue,
|
|
4272
|
+
reset
|
|
4273
|
+
};
|
|
4274
|
+
}
|
|
4275
|
+
var activityStateCache = /* @__PURE__ */ new Map();
|
|
4276
|
+
var activityStateInflight = /* @__PURE__ */ new Map();
|
|
4277
|
+
function buildActivityStateCacheKey(client) {
|
|
4278
|
+
return JSON.stringify({ key: client.getPublicKey(), type: "activity_state" });
|
|
4279
|
+
}
|
|
4280
|
+
function useActivityState(options = {}) {
|
|
4281
|
+
const context = useOptionalCimplifyClient();
|
|
4282
|
+
const client = options.client ?? context?.client;
|
|
4283
|
+
if (!client) {
|
|
4284
|
+
throw new Error("useActivityState must be used within CimplifyProvider or passed { client }.");
|
|
4285
|
+
}
|
|
4286
|
+
const enabled = options.enabled ?? true;
|
|
4287
|
+
const cacheKey = useMemo(() => buildActivityStateCacheKey(client), [client]);
|
|
4288
|
+
const cached = activityStateCache.get(cacheKey);
|
|
4289
|
+
const [state, setState] = useState(cached ?? null);
|
|
4290
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4291
|
+
const [error, setError] = useState(null);
|
|
4292
|
+
const load = useCallback(
|
|
4293
|
+
async (force = false) => {
|
|
4294
|
+
if (!enabled) {
|
|
4295
|
+
setIsLoading(false);
|
|
4296
|
+
return;
|
|
4297
|
+
}
|
|
4298
|
+
setError(null);
|
|
4299
|
+
if (!force) {
|
|
4300
|
+
const cachedState = activityStateCache.get(cacheKey);
|
|
4301
|
+
if (cachedState) {
|
|
4302
|
+
setState(cachedState);
|
|
4303
|
+
setIsLoading(false);
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
4306
|
+
}
|
|
4307
|
+
setIsLoading(true);
|
|
4308
|
+
try {
|
|
4309
|
+
const existing = activityStateInflight.get(cacheKey);
|
|
4310
|
+
const promise = existing ?? (async () => {
|
|
4311
|
+
const result = await client.activity.getState();
|
|
4312
|
+
if (!result.ok) {
|
|
4313
|
+
throw result.error;
|
|
4314
|
+
}
|
|
4315
|
+
return result.value;
|
|
4316
|
+
})();
|
|
4317
|
+
if (!existing) {
|
|
4318
|
+
activityStateInflight.set(
|
|
4319
|
+
cacheKey,
|
|
4320
|
+
promise.finally(() => {
|
|
4321
|
+
activityStateInflight.delete(cacheKey);
|
|
4322
|
+
})
|
|
4323
|
+
);
|
|
4324
|
+
}
|
|
4325
|
+
const value = await promise;
|
|
4326
|
+
activityStateCache.set(cacheKey, value);
|
|
4327
|
+
setState(value);
|
|
4328
|
+
} catch (loadError) {
|
|
4329
|
+
setError(loadError);
|
|
4330
|
+
} finally {
|
|
4331
|
+
setIsLoading(false);
|
|
4332
|
+
}
|
|
4333
|
+
},
|
|
4334
|
+
[cacheKey, client, enabled]
|
|
4335
|
+
);
|
|
4336
|
+
useEffect(() => {
|
|
4337
|
+
void load(false);
|
|
4338
|
+
}, [load]);
|
|
4339
|
+
const refetch = useCallback(async () => {
|
|
4340
|
+
activityStateCache.delete(cacheKey);
|
|
4341
|
+
await load(true);
|
|
4342
|
+
}, [cacheKey, load]);
|
|
4343
|
+
const dismissMessage = useCallback(
|
|
4344
|
+
async (code) => {
|
|
4345
|
+
const result = await client.activity.dismissMessage(code);
|
|
4346
|
+
if (!result.ok) {
|
|
4347
|
+
setError(result.error);
|
|
4348
|
+
return;
|
|
4349
|
+
}
|
|
4350
|
+
setState((prev) => {
|
|
4351
|
+
if (!prev) return prev;
|
|
4352
|
+
return { ...prev, messages: result.value.messages };
|
|
4353
|
+
});
|
|
4354
|
+
activityStateCache.delete(cacheKey);
|
|
4355
|
+
await load(true);
|
|
4356
|
+
},
|
|
4357
|
+
[cacheKey, client, load]
|
|
4358
|
+
);
|
|
4359
|
+
const messages = state?.messages ?? [];
|
|
4360
|
+
const intent = state?.intent ?? "";
|
|
4361
|
+
return { state, messages, intent, isLoading, error, refetch, dismissMessage };
|
|
4362
|
+
}
|
|
4363
|
+
var recommendationsCache = /* @__PURE__ */ new Map();
|
|
4364
|
+
var recommendationsInflight = /* @__PURE__ */ new Map();
|
|
4365
|
+
function buildRecommendationsCacheKey(client, locationId, limit) {
|
|
4366
|
+
return JSON.stringify({
|
|
4367
|
+
key: client.getPublicKey(),
|
|
4368
|
+
type: "recommendations",
|
|
4369
|
+
location_id: locationId,
|
|
4370
|
+
limit
|
|
4371
|
+
});
|
|
4372
|
+
}
|
|
4373
|
+
function useRecommendations(options = {}) {
|
|
4374
|
+
const context = useOptionalCimplifyClient();
|
|
4375
|
+
const client = options.client ?? context?.client;
|
|
4376
|
+
if (!client) {
|
|
4377
|
+
throw new Error(
|
|
4378
|
+
"useRecommendations must be used within CimplifyProvider or passed { client }."
|
|
4379
|
+
);
|
|
4380
|
+
}
|
|
4381
|
+
const enabled = options.enabled ?? true;
|
|
4382
|
+
const locationId = options.locationId ?? client.getLocationId() ?? void 0;
|
|
4383
|
+
const limit = options.limit;
|
|
4384
|
+
const previousLocationIdRef = useRef(locationId);
|
|
4385
|
+
const cacheKey = useMemo(
|
|
4386
|
+
() => buildRecommendationsCacheKey(client, locationId, limit),
|
|
4387
|
+
[client, locationId, limit]
|
|
4388
|
+
);
|
|
4389
|
+
const cached = recommendationsCache.get(cacheKey);
|
|
4390
|
+
const [response, setResponse] = useState(cached ?? null);
|
|
4391
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4392
|
+
const [error, setError] = useState(null);
|
|
4393
|
+
useEffect(() => {
|
|
4394
|
+
if (previousLocationIdRef.current !== locationId) {
|
|
4395
|
+
recommendationsCache.clear();
|
|
4396
|
+
recommendationsInflight.clear();
|
|
4397
|
+
previousLocationIdRef.current = locationId;
|
|
4398
|
+
}
|
|
4399
|
+
}, [locationId]);
|
|
4400
|
+
const load = useCallback(
|
|
4401
|
+
async (force = false) => {
|
|
4402
|
+
if (!enabled) {
|
|
4403
|
+
setIsLoading(false);
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
setError(null);
|
|
4407
|
+
if (!force) {
|
|
4408
|
+
const cachedResponse = recommendationsCache.get(cacheKey);
|
|
4409
|
+
if (cachedResponse) {
|
|
4410
|
+
setResponse(cachedResponse);
|
|
4411
|
+
setIsLoading(false);
|
|
4412
|
+
return;
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4415
|
+
setIsLoading(true);
|
|
4416
|
+
try {
|
|
4417
|
+
const existing = recommendationsInflight.get(cacheKey);
|
|
4418
|
+
const promise = existing ?? (async () => {
|
|
4419
|
+
const result = await client.activity.getRecommendations({
|
|
4420
|
+
location_id: locationId,
|
|
4421
|
+
limit
|
|
4422
|
+
});
|
|
4423
|
+
if (!result.ok) {
|
|
4424
|
+
throw result.error;
|
|
4425
|
+
}
|
|
4426
|
+
return result.value;
|
|
4427
|
+
})();
|
|
4428
|
+
if (!existing) {
|
|
4429
|
+
recommendationsInflight.set(
|
|
4430
|
+
cacheKey,
|
|
4431
|
+
promise.finally(() => {
|
|
4432
|
+
recommendationsInflight.delete(cacheKey);
|
|
4433
|
+
})
|
|
4434
|
+
);
|
|
4435
|
+
}
|
|
4436
|
+
const value = await promise;
|
|
4437
|
+
recommendationsCache.set(cacheKey, value);
|
|
4438
|
+
setResponse(value);
|
|
4439
|
+
} catch (loadError) {
|
|
4440
|
+
setError(loadError);
|
|
4441
|
+
} finally {
|
|
4442
|
+
setIsLoading(false);
|
|
4443
|
+
}
|
|
4444
|
+
},
|
|
4445
|
+
[cacheKey, client, enabled, locationId, limit]
|
|
4446
|
+
);
|
|
4447
|
+
useEffect(() => {
|
|
4448
|
+
void load(false);
|
|
4449
|
+
}, [load]);
|
|
4450
|
+
const refetch = useCallback(async () => {
|
|
4451
|
+
recommendationsCache.delete(cacheKey);
|
|
4452
|
+
await load(true);
|
|
4453
|
+
}, [cacheKey, load]);
|
|
4454
|
+
const recommendations = response?.recommendations ?? [];
|
|
4455
|
+
const intent = response?.intent ?? "";
|
|
4456
|
+
return { recommendations, intent, isLoading, error, refetch };
|
|
4457
|
+
}
|
|
4458
|
+
var deliveryFeeCache = /* @__PURE__ */ new Map();
|
|
4459
|
+
function buildDeliveryFeeCacheKey(client, latitude, longitude, country) {
|
|
4460
|
+
return JSON.stringify({
|
|
4461
|
+
key: client.getPublicKey(),
|
|
4462
|
+
lat: latitude,
|
|
4463
|
+
lng: longitude,
|
|
4464
|
+
country
|
|
4465
|
+
});
|
|
4466
|
+
}
|
|
4467
|
+
function useDeliveryFee(options) {
|
|
4468
|
+
const context = useOptionalCimplifyClient();
|
|
4469
|
+
const client = options.client ?? context?.client;
|
|
4470
|
+
if (!client) {
|
|
4471
|
+
throw new Error("useDeliveryFee must be used within CimplifyProvider or passed { client }.");
|
|
4472
|
+
}
|
|
4473
|
+
const enabled = options.enabled ?? true;
|
|
4474
|
+
const { latitude, longitude, country } = options;
|
|
4475
|
+
const cacheKey = useMemo(
|
|
4476
|
+
() => buildDeliveryFeeCacheKey(client, latitude, longitude, country),
|
|
4477
|
+
[client, latitude, longitude, country]
|
|
4478
|
+
);
|
|
4479
|
+
const cached = deliveryFeeCache.get(cacheKey);
|
|
4480
|
+
const [fee, setFee] = useState(cached ?? null);
|
|
4481
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4482
|
+
const [error, setError] = useState(null);
|
|
4483
|
+
const requestIdRef = useRef(0);
|
|
4484
|
+
const load = useCallback(
|
|
4485
|
+
async (force = false) => {
|
|
4486
|
+
if (!enabled) {
|
|
4487
|
+
setIsLoading(false);
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
setError(null);
|
|
4491
|
+
if (!force) {
|
|
4492
|
+
const cachedFee = deliveryFeeCache.get(cacheKey);
|
|
4493
|
+
if (cachedFee) {
|
|
4494
|
+
setFee(cachedFee);
|
|
4495
|
+
setIsLoading(false);
|
|
4496
|
+
return;
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
setIsLoading(true);
|
|
4500
|
+
const currentRequestId = ++requestIdRef.current;
|
|
4501
|
+
try {
|
|
4502
|
+
const result = await client.delivery.getFee(latitude, longitude, country);
|
|
4503
|
+
if (currentRequestId !== requestIdRef.current) return;
|
|
4504
|
+
if (!result.ok) {
|
|
4505
|
+
throw result.error;
|
|
4506
|
+
}
|
|
4507
|
+
deliveryFeeCache.set(cacheKey, result.value);
|
|
4508
|
+
setFee(result.value);
|
|
4509
|
+
} catch (loadError) {
|
|
4510
|
+
if (currentRequestId !== requestIdRef.current) return;
|
|
4511
|
+
setError(loadError);
|
|
4512
|
+
} finally {
|
|
4513
|
+
if (currentRequestId === requestIdRef.current) {
|
|
4514
|
+
setIsLoading(false);
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
},
|
|
4518
|
+
[cacheKey, client, country, enabled, latitude, longitude]
|
|
4519
|
+
);
|
|
4520
|
+
useEffect(() => {
|
|
4521
|
+
void load(false);
|
|
4522
|
+
}, [load]);
|
|
4523
|
+
const refetch = useCallback(async () => {
|
|
4524
|
+
deliveryFeeCache.delete(cacheKey);
|
|
4525
|
+
await load(true);
|
|
4526
|
+
}, [cacheKey, load]);
|
|
4527
|
+
return { fee, isLoading, error, refetch };
|
|
4528
|
+
}
|
|
4529
|
+
var fxRateCache = /* @__PURE__ */ new Map();
|
|
4530
|
+
var fxRateInflight = /* @__PURE__ */ new Map();
|
|
4531
|
+
function buildFxRateCacheKey(client, from, to) {
|
|
4532
|
+
return JSON.stringify({ key: client.getPublicKey(), from, to });
|
|
4533
|
+
}
|
|
4534
|
+
function useFxRate(options) {
|
|
4535
|
+
const context = useOptionalCimplifyClient();
|
|
4536
|
+
const client = options.client ?? context?.client;
|
|
4537
|
+
if (!client) {
|
|
4538
|
+
throw new Error("useFxRate must be used within CimplifyProvider or passed { client }.");
|
|
4539
|
+
}
|
|
4540
|
+
const enabled = options.enabled ?? true;
|
|
4541
|
+
const { from, to } = options;
|
|
4542
|
+
const cacheKey = useMemo(
|
|
4543
|
+
() => buildFxRateCacheKey(client, from, to),
|
|
4544
|
+
[client, from, to]
|
|
4545
|
+
);
|
|
4546
|
+
const cached = fxRateCache.get(cacheKey);
|
|
4547
|
+
const [rate, setRate] = useState(cached ?? null);
|
|
4548
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4549
|
+
const [error, setError] = useState(null);
|
|
4550
|
+
const load = useCallback(
|
|
4551
|
+
async (force = false) => {
|
|
4552
|
+
if (!enabled) {
|
|
4553
|
+
setIsLoading(false);
|
|
4554
|
+
return;
|
|
4555
|
+
}
|
|
4556
|
+
setError(null);
|
|
4557
|
+
if (!force) {
|
|
4558
|
+
const cachedRate = fxRateCache.get(cacheKey);
|
|
4559
|
+
if (cachedRate) {
|
|
4560
|
+
setRate(cachedRate);
|
|
4561
|
+
setIsLoading(false);
|
|
4562
|
+
return;
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
4565
|
+
setIsLoading(true);
|
|
4566
|
+
try {
|
|
4567
|
+
const existing = fxRateInflight.get(cacheKey);
|
|
4568
|
+
const promise = existing ?? (async () => {
|
|
4569
|
+
const result = await client.fx.getRate(from, to);
|
|
4570
|
+
if (!result.ok) {
|
|
4571
|
+
throw result.error;
|
|
4572
|
+
}
|
|
4573
|
+
return result.value;
|
|
4574
|
+
})();
|
|
4575
|
+
if (!existing) {
|
|
4576
|
+
fxRateInflight.set(
|
|
4577
|
+
cacheKey,
|
|
4578
|
+
promise.finally(() => {
|
|
4579
|
+
fxRateInflight.delete(cacheKey);
|
|
4580
|
+
})
|
|
4581
|
+
);
|
|
4582
|
+
}
|
|
4583
|
+
const value = await promise;
|
|
4584
|
+
fxRateCache.set(cacheKey, value);
|
|
4585
|
+
setRate(value);
|
|
4586
|
+
} catch (loadError) {
|
|
4587
|
+
setError(loadError);
|
|
4588
|
+
} finally {
|
|
4589
|
+
setIsLoading(false);
|
|
4590
|
+
}
|
|
4591
|
+
},
|
|
4592
|
+
[cacheKey, client, enabled, from, to]
|
|
4593
|
+
);
|
|
4594
|
+
useEffect(() => {
|
|
4595
|
+
void load(false);
|
|
4596
|
+
}, [load]);
|
|
4597
|
+
const refetch = useCallback(async () => {
|
|
4598
|
+
fxRateCache.delete(cacheKey);
|
|
4599
|
+
await load(true);
|
|
4600
|
+
}, [cacheKey, load]);
|
|
4601
|
+
return { rate, isLoading, error, refetch };
|
|
4602
|
+
}
|
|
4603
|
+
var bootstrapCache = /* @__PURE__ */ new Map();
|
|
4604
|
+
var bootstrapInflight = /* @__PURE__ */ new Map();
|
|
4605
|
+
function buildBootstrapCacheKey(client) {
|
|
4606
|
+
return JSON.stringify({ key: client.getPublicKey(), type: "bootstrap" });
|
|
4607
|
+
}
|
|
4608
|
+
function useBootstrap(options = {}) {
|
|
4609
|
+
const context = useOptionalCimplifyClient();
|
|
4610
|
+
const client = options.client ?? context?.client;
|
|
4611
|
+
if (!client) {
|
|
4612
|
+
throw new Error("useBootstrap must be used within CimplifyProvider or passed { client }.");
|
|
4613
|
+
}
|
|
4614
|
+
const enabled = options.enabled ?? true;
|
|
4615
|
+
const cacheKey = useMemo(() => buildBootstrapCacheKey(client), [client]);
|
|
4616
|
+
const cached = bootstrapCache.get(cacheKey);
|
|
4617
|
+
const [bootstrap, setBootstrap] = useState(cached ?? null);
|
|
4618
|
+
const [isLoading, setIsLoading] = useState(enabled && !cached);
|
|
4619
|
+
const [error, setError] = useState(null);
|
|
4620
|
+
const load = useCallback(
|
|
4621
|
+
async (force = false) => {
|
|
4622
|
+
if (!enabled) {
|
|
4623
|
+
setIsLoading(false);
|
|
4624
|
+
return;
|
|
4625
|
+
}
|
|
4626
|
+
setError(null);
|
|
4627
|
+
if (!force) {
|
|
4628
|
+
const cachedBootstrap = bootstrapCache.get(cacheKey);
|
|
4629
|
+
if (cachedBootstrap) {
|
|
4630
|
+
setBootstrap(cachedBootstrap);
|
|
4631
|
+
setIsLoading(false);
|
|
4632
|
+
return;
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
setIsLoading(true);
|
|
4636
|
+
try {
|
|
4637
|
+
const existing = bootstrapInflight.get(cacheKey);
|
|
4638
|
+
const promise = existing ?? (async () => {
|
|
4639
|
+
const result = await client.business.getBootstrap();
|
|
4640
|
+
if (!result.ok) {
|
|
4641
|
+
throw result.error;
|
|
4642
|
+
}
|
|
4643
|
+
return result.value;
|
|
4644
|
+
})();
|
|
4645
|
+
if (!existing) {
|
|
4646
|
+
bootstrapInflight.set(
|
|
4647
|
+
cacheKey,
|
|
4648
|
+
promise.finally(() => {
|
|
4649
|
+
bootstrapInflight.delete(cacheKey);
|
|
4650
|
+
})
|
|
4651
|
+
);
|
|
4652
|
+
}
|
|
4653
|
+
const value = await promise;
|
|
4654
|
+
bootstrapCache.set(cacheKey, value);
|
|
4655
|
+
setBootstrap(value);
|
|
4656
|
+
} catch (loadError) {
|
|
4657
|
+
setError(loadError);
|
|
4658
|
+
} finally {
|
|
4659
|
+
setIsLoading(false);
|
|
4660
|
+
}
|
|
4661
|
+
},
|
|
4662
|
+
[cacheKey, client, enabled]
|
|
4663
|
+
);
|
|
4664
|
+
useEffect(() => {
|
|
4665
|
+
void load(false);
|
|
4666
|
+
}, [load]);
|
|
4667
|
+
const refetch = useCallback(async () => {
|
|
4668
|
+
bootstrapCache.delete(cacheKey);
|
|
4669
|
+
await load(true);
|
|
4670
|
+
}, [cacheKey, load]);
|
|
4671
|
+
return { bootstrap, isLoading, error, refetch };
|
|
4672
|
+
}
|
|
3992
4673
|
var ElementsContext = createContext({
|
|
3993
4674
|
elements: null,
|
|
3994
4675
|
isReady: false
|
|
@@ -4732,6 +5413,17 @@ function getComponentPrice(component, selectedVariantId) {
|
|
|
4732
5413
|
if (!selectedAdj) return parsePrice(component.effective_price);
|
|
4733
5414
|
return parsePrice(component.effective_price) - parsePrice(bakedAdj?.price_adjustment ?? "0") + parsePrice(selectedAdj.price_adjustment);
|
|
4734
5415
|
}
|
|
5416
|
+
function formatDuration(minutes, unit) {
|
|
5417
|
+
if (unit === "hours" || !unit && minutes >= 60 && minutes % 60 === 0) {
|
|
5418
|
+
const h = Math.round(minutes / 60);
|
|
5419
|
+
return `${h}h`;
|
|
5420
|
+
}
|
|
5421
|
+
if (unit === "days" || unit === "nights") {
|
|
5422
|
+
const d = Math.round(minutes / 1440);
|
|
5423
|
+
return `${d}${unit === "nights" ? "n" : "d"}`;
|
|
5424
|
+
}
|
|
5425
|
+
return `${minutes}min`;
|
|
5426
|
+
}
|
|
4735
5427
|
function BundleComponentCard({
|
|
4736
5428
|
component,
|
|
4737
5429
|
selectedVariantId,
|
|
@@ -4777,6 +5469,43 @@ function BundleComponentCard({
|
|
|
4777
5469
|
className: cn("text-sm", classNames?.componentName),
|
|
4778
5470
|
children: component.product_name
|
|
4779
5471
|
}
|
|
5472
|
+
),
|
|
5473
|
+
component.product_type === "service" && /* @__PURE__ */ jsxs(
|
|
5474
|
+
"span",
|
|
5475
|
+
{
|
|
5476
|
+
"data-cimplify-bundle-type-badge": "service",
|
|
5477
|
+
className: cn(
|
|
5478
|
+
"text-[10px] uppercase tracking-wider font-medium text-blue-600",
|
|
5479
|
+
classNames?.typeBadge,
|
|
5480
|
+
classNames?.serviceBadge
|
|
5481
|
+
),
|
|
5482
|
+
children: [
|
|
5483
|
+
/* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", className: "inline-block w-3 h-3 mr-0.5 -mt-px", "aria-hidden": "true", children: [
|
|
5484
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
5485
|
+
/* @__PURE__ */ jsx("path", { d: "M8 4v4l2.5 1.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
5486
|
+
] }),
|
|
5487
|
+
"Service",
|
|
5488
|
+
component.duration_minutes != null && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5489
|
+
" \xB7 ",
|
|
5490
|
+
formatDuration(component.duration_minutes, component.duration_unit)
|
|
5491
|
+
] })
|
|
5492
|
+
]
|
|
5493
|
+
}
|
|
5494
|
+
),
|
|
5495
|
+
component.product_type === "digital" && /* @__PURE__ */ jsxs(
|
|
5496
|
+
"span",
|
|
5497
|
+
{
|
|
5498
|
+
"data-cimplify-bundle-type-badge": "digital",
|
|
5499
|
+
className: cn(
|
|
5500
|
+
"text-[10px] uppercase tracking-wider font-medium text-violet-600",
|
|
5501
|
+
classNames?.typeBadge,
|
|
5502
|
+
classNames?.digitalBadge
|
|
5503
|
+
),
|
|
5504
|
+
children: [
|
|
5505
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", className: "inline-block w-3 h-3 mr-0.5 -mt-px", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M9 2L4 9h4l-1 5 5-7H8l1-5z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
5506
|
+
"Digital"
|
|
5507
|
+
]
|
|
5508
|
+
}
|
|
4780
5509
|
)
|
|
4781
5510
|
] }),
|
|
4782
5511
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: /* @__PURE__ */ jsx(Price, { amount: displayPrice }) })
|
|
@@ -5101,6 +5830,39 @@ function CompositeSelector({
|
|
|
5101
5830
|
children: displayName
|
|
5102
5831
|
}
|
|
5103
5832
|
),
|
|
5833
|
+
component.product_type === "service" && /* @__PURE__ */ jsxs(
|
|
5834
|
+
"span",
|
|
5835
|
+
{
|
|
5836
|
+
"data-cimplify-composite-type-badge": "service",
|
|
5837
|
+
className: cn(
|
|
5838
|
+
"text-[10px] uppercase tracking-wider font-medium text-blue-600",
|
|
5839
|
+
classNames?.typeBadge,
|
|
5840
|
+
classNames?.serviceBadge
|
|
5841
|
+
),
|
|
5842
|
+
children: [
|
|
5843
|
+
/* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", className: "inline-block w-3 h-3 mr-0.5 -mt-px", "aria-hidden": "true", children: [
|
|
5844
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
5845
|
+
/* @__PURE__ */ jsx("path", { d: "M8 4v4l2.5 1.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
5846
|
+
] }),
|
|
5847
|
+
"Service"
|
|
5848
|
+
]
|
|
5849
|
+
}
|
|
5850
|
+
),
|
|
5851
|
+
component.product_type === "digital" && /* @__PURE__ */ jsxs(
|
|
5852
|
+
"span",
|
|
5853
|
+
{
|
|
5854
|
+
"data-cimplify-composite-type-badge": "digital",
|
|
5855
|
+
className: cn(
|
|
5856
|
+
"text-[10px] uppercase tracking-wider font-medium text-violet-600",
|
|
5857
|
+
classNames?.typeBadge,
|
|
5858
|
+
classNames?.digitalBadge
|
|
5859
|
+
),
|
|
5860
|
+
children: [
|
|
5861
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", className: "inline-block w-3 h-3 mr-0.5 -mt-px", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M9 2L4 9h4l-1 5 5-7H8l1-5z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
5862
|
+
"Digital"
|
|
5863
|
+
]
|
|
5864
|
+
}
|
|
5865
|
+
),
|
|
5104
5866
|
component.is_popular && /* @__PURE__ */ jsx(
|
|
5105
5867
|
"span",
|
|
5106
5868
|
{
|
|
@@ -5265,6 +6027,7 @@ function CompositeSelector({
|
|
|
5265
6027
|
function ProductCustomizer({
|
|
5266
6028
|
product,
|
|
5267
6029
|
onAddToCart,
|
|
6030
|
+
showSpecialInstructions = true,
|
|
5268
6031
|
className,
|
|
5269
6032
|
classNames
|
|
5270
6033
|
}) {
|
|
@@ -5280,10 +6043,13 @@ function ProductCustomizer({
|
|
|
5280
6043
|
const [bundleSelections, setBundleSelections] = useState([]);
|
|
5281
6044
|
const [bundleTotalPrice, setBundleTotalPrice] = useState(null);
|
|
5282
6045
|
const [bundleReady, setBundleReady] = useState(false);
|
|
6046
|
+
const [specialInstructions, setSpecialInstructions] = useState("");
|
|
5283
6047
|
const cart = useCart();
|
|
5284
6048
|
const productType = product.type || "product";
|
|
5285
6049
|
const isComposite = productType === "composite";
|
|
5286
6050
|
const isBundle = productType === "bundle";
|
|
6051
|
+
const isDigital = productType === "digital";
|
|
6052
|
+
const isService = productType === "service";
|
|
5287
6053
|
const isStandard = !isComposite && !isBundle;
|
|
5288
6054
|
const hasVariants = isStandard && product.variants && product.variants.length > 0;
|
|
5289
6055
|
const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;
|
|
@@ -5300,6 +6066,7 @@ function ProductCustomizer({
|
|
|
5300
6066
|
setBundleSelections([]);
|
|
5301
6067
|
setBundleTotalPrice(null);
|
|
5302
6068
|
setBundleReady(false);
|
|
6069
|
+
setSpecialInstructions("");
|
|
5303
6070
|
}, [product.id]);
|
|
5304
6071
|
const selectedAddOnOptions = useMemo(() => {
|
|
5305
6072
|
if (!product.add_ons) return [];
|
|
@@ -5396,7 +6163,8 @@ function ProductCustomizer({
|
|
|
5396
6163
|
default_price: opt.default_price
|
|
5397
6164
|
})) : void 0,
|
|
5398
6165
|
compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : void 0,
|
|
5399
|
-
bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : void 0
|
|
6166
|
+
bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : void 0,
|
|
6167
|
+
specialInstructions: specialInstructions.trim() || void 0
|
|
5400
6168
|
};
|
|
5401
6169
|
try {
|
|
5402
6170
|
if (onAddToCart) {
|
|
@@ -5457,6 +6225,43 @@ function ProductCustomizer({
|
|
|
5457
6225
|
onOptionsChange: setSelectedAddOnOptionIds
|
|
5458
6226
|
}
|
|
5459
6227
|
),
|
|
6228
|
+
product.deposit_type && product.deposit_type !== "none" && product.deposit_amount && /* @__PURE__ */ jsx("div", { "data-cimplify-customizer-deposit": true, className: cn("text-sm text-muted-foreground", classNames?.depositInfo), children: product.deposit_type === "fixed" ? /* @__PURE__ */ jsxs("span", { children: [
|
|
6229
|
+
"Deposit required: ",
|
|
6230
|
+
/* @__PURE__ */ jsx(Price, { amount: product.deposit_amount })
|
|
6231
|
+
] }) : /* @__PURE__ */ jsxs("span", { children: [
|
|
6232
|
+
"Deposit required: ",
|
|
6233
|
+
parsePrice(product.deposit_amount),
|
|
6234
|
+
"%"
|
|
6235
|
+
] }) }),
|
|
6236
|
+
product.allergies && product.allergies.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-customizer-allergens": true, className: cn("flex flex-wrap gap-1.5", classNames?.allergens), children: product.allergies.map((allergen) => /* @__PURE__ */ jsx(
|
|
6237
|
+
"span",
|
|
6238
|
+
{
|
|
6239
|
+
"data-cimplify-allergen-tag": true,
|
|
6240
|
+
className: "inline-block text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground",
|
|
6241
|
+
children: allergen
|
|
6242
|
+
},
|
|
6243
|
+
allergen
|
|
6244
|
+
)) }),
|
|
6245
|
+
isService && product.duration_minutes != null && /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer-duration": true, className: cn("text-sm text-muted-foreground", classNames?.duration), children: [
|
|
6246
|
+
"Duration: ",
|
|
6247
|
+
product.duration_minutes,
|
|
6248
|
+
" ",
|
|
6249
|
+
product.duration_unit ?? "minutes"
|
|
6250
|
+
] }),
|
|
6251
|
+
showSpecialInstructions && !isDigital && /* @__PURE__ */ jsx("div", { "data-cimplify-customizer-special-instructions": true, children: /* @__PURE__ */ jsx(
|
|
6252
|
+
"textarea",
|
|
6253
|
+
{
|
|
6254
|
+
value: specialInstructions,
|
|
6255
|
+
onChange: (e) => setSpecialInstructions(e.target.value),
|
|
6256
|
+
placeholder: "Special instructions (e.g., no onions, extra sauce)",
|
|
6257
|
+
rows: 2,
|
|
6258
|
+
"data-cimplify-customizer-textarea": true,
|
|
6259
|
+
className: cn(
|
|
6260
|
+
"w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-none",
|
|
6261
|
+
classNames?.specialInstructions
|
|
6262
|
+
)
|
|
6263
|
+
}
|
|
6264
|
+
) }),
|
|
5460
6265
|
/* @__PURE__ */ jsxs(
|
|
5461
6266
|
"div",
|
|
5462
6267
|
{
|
|
@@ -5591,7 +6396,8 @@ function ProductImageGallery({
|
|
|
5591
6396
|
function CartLineItemRow({
|
|
5592
6397
|
item,
|
|
5593
6398
|
onRemove,
|
|
5594
|
-
onQuantityChange
|
|
6399
|
+
onQuantityChange,
|
|
6400
|
+
classNames
|
|
5595
6401
|
}) {
|
|
5596
6402
|
const { unitPrice } = useProductPrice({
|
|
5597
6403
|
product: item.product,
|
|
@@ -5600,18 +6406,60 @@ function CartLineItemRow({
|
|
|
5600
6406
|
});
|
|
5601
6407
|
const hasComposite = item.compositeSelections && item.compositeSelections.length > 0;
|
|
5602
6408
|
const hasBundle = item.bundleSelections && item.bundleSelections.length > 0;
|
|
5603
|
-
return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item": true, children: [
|
|
6409
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item": true, className: classNames?.item, children: [
|
|
5604
6410
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-info": true, children: [
|
|
5605
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-name": true, children: item.product.name }),
|
|
6411
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
|
|
5606
6412
|
item.variant && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-variant": true, children: getVariantDisplayName(item.variant, item.product.name) }),
|
|
5607
6413
|
item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
|
|
5608
6414
|
"+ ",
|
|
5609
6415
|
item.addOnOptions.map((opt) => opt.name).join(", ")
|
|
5610
6416
|
] }),
|
|
5611
6417
|
(hasComposite || hasBundle) && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-badge": true, children: hasComposite ? "Custom" : "Bundle" }),
|
|
5612
|
-
/* @__PURE__ */ jsx(
|
|
6418
|
+
item.specialInstructions && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-instructions": true, className: "text-xs text-muted-foreground", children: item.specialInstructions }),
|
|
6419
|
+
(item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-service-info": true, className: classNames?.serviceInfo, children: [
|
|
6420
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
6421
|
+
"\u{1F4C5}",
|
|
6422
|
+
" ",
|
|
6423
|
+
new Date(item.scheduledStart).toLocaleDateString(),
|
|
6424
|
+
" at ",
|
|
6425
|
+
new Date(item.scheduledStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
|
6426
|
+
] }),
|
|
6427
|
+
item.confirmationCode && /* @__PURE__ */ jsxs("span", { children: [
|
|
6428
|
+
"Confirmation: ",
|
|
6429
|
+
item.confirmationCode
|
|
6430
|
+
] }),
|
|
6431
|
+
item.serviceStatus && /* @__PURE__ */ jsx("span", { "data-status": item.serviceStatus, children: item.serviceStatus })
|
|
6432
|
+
] }),
|
|
6433
|
+
(item.lineType === "digital" || item.product.type === "digital") && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-digital-info": true, className: classNames?.digitalInfo, children: /* @__PURE__ */ jsxs("span", { children: [
|
|
6434
|
+
"\u26A1",
|
|
6435
|
+
" Instant digital delivery"
|
|
6436
|
+
] }) }),
|
|
6437
|
+
item.bundleResolved && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-bundle-breakdown": true, className: classNames?.bundleBreakdown, children: item.bundleResolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
|
|
6438
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
6439
|
+
sel.quantity,
|
|
6440
|
+
"\xD7 ",
|
|
6441
|
+
sel.product_name
|
|
6442
|
+
] }),
|
|
6443
|
+
sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
|
|
6444
|
+
" \u2014 ",
|
|
6445
|
+
new Date(sel.scheduling.scheduled_start).toLocaleDateString()
|
|
6446
|
+
] }),
|
|
6447
|
+
sel.product_type === "digital" && /* @__PURE__ */ jsx("span", { children: " \u2014 Digital" })
|
|
6448
|
+
] }, sel.component_id)) }),
|
|
6449
|
+
item.compositeResolved && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-composite-breakdown": true, className: classNames?.compositeBreakdown, children: item.compositeResolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
|
|
6450
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
6451
|
+
sel.quantity,
|
|
6452
|
+
"\xD7 ",
|
|
6453
|
+
sel.component_name
|
|
6454
|
+
] }),
|
|
6455
|
+
sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
|
|
6456
|
+
" \u2014 ",
|
|
6457
|
+
new Date(sel.scheduling.scheduled_start).toLocaleDateString()
|
|
6458
|
+
] })
|
|
6459
|
+
] }, sel.component_id)) }),
|
|
6460
|
+
/* @__PURE__ */ jsx(Price, { amount: unitPrice, className: classNames?.itemPrice })
|
|
5613
6461
|
] }),
|
|
5614
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-controls": true, children: [
|
|
6462
|
+
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-controls": true, className: classNames?.quantity, children: [
|
|
5615
6463
|
/* @__PURE__ */ jsx(
|
|
5616
6464
|
QuantitySelector,
|
|
5617
6465
|
{
|
|
@@ -5626,6 +6474,7 @@ function CartLineItemRow({
|
|
|
5626
6474
|
type: "button",
|
|
5627
6475
|
onClick: () => onRemove(item.id),
|
|
5628
6476
|
"data-cimplify-cart-item-remove": true,
|
|
6477
|
+
className: classNames?.removeButton,
|
|
5629
6478
|
"aria-label": `Remove ${item.product.name}`,
|
|
5630
6479
|
children: "Remove"
|
|
5631
6480
|
}
|
|
@@ -5634,13 +6483,18 @@ function CartLineItemRow({
|
|
|
5634
6483
|
] });
|
|
5635
6484
|
}
|
|
5636
6485
|
function CartSummary({
|
|
6486
|
+
cart: serverCart,
|
|
5637
6487
|
onCheckout,
|
|
5638
6488
|
onItemRemove,
|
|
5639
6489
|
onQuantityChange,
|
|
5640
6490
|
emptyMessage = "Your cart is empty",
|
|
5641
|
-
className
|
|
6491
|
+
className,
|
|
6492
|
+
classNames
|
|
5642
6493
|
}) {
|
|
5643
6494
|
const { items, itemCount, subtotal, tax, total, isEmpty, removeItem, updateQuantity } = useCart();
|
|
6495
|
+
const deliveryFee = serverCart?.delivery_fee;
|
|
6496
|
+
const serviceCharge = serverCart?.service_charge;
|
|
6497
|
+
const totalDiscounts = serverCart?.total_discounts;
|
|
5644
6498
|
const handleRemove = (itemId) => {
|
|
5645
6499
|
if (onItemRemove) {
|
|
5646
6500
|
onItemRemove(itemId);
|
|
@@ -5655,18 +6509,19 @@ function CartSummary({
|
|
|
5655
6509
|
void updateQuantity(itemId, qty);
|
|
5656
6510
|
}
|
|
5657
6511
|
};
|
|
5658
|
-
return /* @__PURE__ */ jsx("div", { "data-cimplify-cart-summary": true, className, children: isEmpty ? /* @__PURE__ */ jsx("div", { "data-cimplify-cart-empty": true, children: /* @__PURE__ */ jsx("p", { children: emptyMessage }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6512
|
+
return /* @__PURE__ */ jsx("div", { "data-cimplify-cart-summary": true, className: cn(className, classNames?.root), children: isEmpty ? /* @__PURE__ */ jsx("div", { "data-cimplify-cart-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsx("p", { children: emptyMessage }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5659
6513
|
/* @__PURE__ */ jsx("div", { "data-cimplify-cart-items": true, children: items.map((item) => /* @__PURE__ */ jsx(
|
|
5660
6514
|
CartLineItemRow,
|
|
5661
6515
|
{
|
|
5662
6516
|
item,
|
|
5663
6517
|
onRemove: handleRemove,
|
|
5664
|
-
onQuantityChange: handleQuantityChange
|
|
6518
|
+
onQuantityChange: handleQuantityChange,
|
|
6519
|
+
classNames
|
|
5665
6520
|
},
|
|
5666
6521
|
item.id
|
|
5667
6522
|
)) }),
|
|
5668
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-totals": true, children: [
|
|
5669
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-subtotal": true, children: [
|
|
6523
|
+
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-totals": true, className: classNames?.totals, children: [
|
|
6524
|
+
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-subtotal": true, className: classNames?.subtotal, children: [
|
|
5670
6525
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
5671
6526
|
"Subtotal (",
|
|
5672
6527
|
itemCount,
|
|
@@ -5676,11 +6531,23 @@ function CartSummary({
|
|
|
5676
6531
|
] }),
|
|
5677
6532
|
/* @__PURE__ */ jsx(Price, { amount: subtotal })
|
|
5678
6533
|
] }),
|
|
5679
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-
|
|
6534
|
+
totalDiscounts != null && parsePrice(totalDiscounts) > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-discount": true, className: classNames?.discount, children: [
|
|
6535
|
+
/* @__PURE__ */ jsx("span", { children: "Discount" }),
|
|
6536
|
+
/* @__PURE__ */ jsx(Price, { amount: totalDiscounts, prefix: "-" })
|
|
6537
|
+
] }),
|
|
6538
|
+
deliveryFee != null && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-delivery-fee": true, className: classNames?.deliveryFee, children: [
|
|
6539
|
+
/* @__PURE__ */ jsx("span", { children: "Delivery fee" }),
|
|
6540
|
+
parsePrice(deliveryFee) > 0 ? /* @__PURE__ */ jsx(Price, { amount: deliveryFee }) : /* @__PURE__ */ jsx("span", { children: "Free delivery" })
|
|
6541
|
+
] }),
|
|
6542
|
+
serviceCharge != null && parsePrice(serviceCharge) > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-service-charge": true, className: classNames?.serviceCharge, children: [
|
|
6543
|
+
/* @__PURE__ */ jsx("span", { children: "Service charge" }),
|
|
6544
|
+
/* @__PURE__ */ jsx(Price, { amount: serviceCharge })
|
|
6545
|
+
] }),
|
|
6546
|
+
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-tax": true, className: classNames?.tax, children: [
|
|
5680
6547
|
/* @__PURE__ */ jsx("span", { children: "Tax" }),
|
|
5681
6548
|
/* @__PURE__ */ jsx(Price, { amount: tax })
|
|
5682
6549
|
] }),
|
|
5683
|
-
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-total": true, children: [
|
|
6550
|
+
/* @__PURE__ */ jsxs("div", { "data-cimplify-cart-total": true, className: classNames?.total, children: [
|
|
5684
6551
|
/* @__PURE__ */ jsx("span", { children: "Total" }),
|
|
5685
6552
|
/* @__PURE__ */ jsx(Price, { amount: total })
|
|
5686
6553
|
] })
|
|
@@ -5691,6 +6558,7 @@ function CartSummary({
|
|
|
5691
6558
|
type: "button",
|
|
5692
6559
|
onClick: onCheckout,
|
|
5693
6560
|
"data-cimplify-cart-checkout": true,
|
|
6561
|
+
className: classNames?.checkout,
|
|
5694
6562
|
children: "Proceed to Checkout"
|
|
5695
6563
|
}
|
|
5696
6564
|
)
|
|
@@ -5700,21 +6568,26 @@ function AvailabilityBadge({
|
|
|
5700
6568
|
product,
|
|
5701
6569
|
isAvailable,
|
|
5702
6570
|
isInStock,
|
|
6571
|
+
stockQuantity,
|
|
6572
|
+
lowStockThreshold = 5,
|
|
6573
|
+
locationId,
|
|
5703
6574
|
className,
|
|
5704
6575
|
classNames
|
|
5705
6576
|
}) {
|
|
5706
6577
|
if (product.is_tracked !== true) {
|
|
5707
6578
|
return null;
|
|
5708
6579
|
}
|
|
5709
|
-
const outOfStock = isInStock === false || isAvailable === false;
|
|
5710
|
-
const
|
|
6580
|
+
const outOfStock = isInStock === false || isAvailable === false || stockQuantity !== void 0 && stockQuantity <= 0;
|
|
6581
|
+
const isLowStock = !outOfStock && stockQuantity !== void 0 && stockQuantity > 0 && stockQuantity <= lowStockThreshold;
|
|
6582
|
+
const stockState = outOfStock ? "out_of_stock" : isLowStock ? "low_stock" : "in_stock";
|
|
5711
6583
|
const label = outOfStock ? "Out of Stock" : "In Stock";
|
|
5712
6584
|
return /* @__PURE__ */ jsxs(
|
|
5713
6585
|
"span",
|
|
5714
6586
|
{
|
|
5715
6587
|
"data-cimplify-availability-badge": true,
|
|
5716
6588
|
"data-stock-state": stockState,
|
|
5717
|
-
|
|
6589
|
+
...locationId ? { "data-location-id": locationId } : void 0,
|
|
6590
|
+
className: cn(className, classNames?.root, isLowStock && classNames?.lowStock),
|
|
5718
6591
|
style: { display: "inline-flex", alignItems: "center", gap: "0.375rem" },
|
|
5719
6592
|
children: [
|
|
5720
6593
|
/* @__PURE__ */ jsx(
|
|
@@ -5730,7 +6603,12 @@ function AvailabilityBadge({
|
|
|
5730
6603
|
}
|
|
5731
6604
|
}
|
|
5732
6605
|
),
|
|
5733
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-availability-label": true, className: classNames?.label, children: label })
|
|
6606
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-availability-label": true, className: classNames?.label, children: label }),
|
|
6607
|
+
stockQuantity !== void 0 && isLowStock && /* @__PURE__ */ jsxs("span", { "data-cimplify-availability-stock-count": true, className: classNames?.stockCount, children: [
|
|
6608
|
+
"Only ",
|
|
6609
|
+
stockQuantity,
|
|
6610
|
+
" left"
|
|
6611
|
+
] })
|
|
5734
6612
|
]
|
|
5735
6613
|
}
|
|
5736
6614
|
);
|
|
@@ -6199,10 +7077,16 @@ function SearchInput({
|
|
|
6199
7077
|
onResultClick,
|
|
6200
7078
|
renderResult,
|
|
6201
7079
|
showResults = true,
|
|
7080
|
+
categoryId,
|
|
7081
|
+
categoryName,
|
|
6202
7082
|
className,
|
|
6203
7083
|
classNames
|
|
6204
7084
|
}) {
|
|
6205
|
-
const
|
|
7085
|
+
const mergedOptions = useMemo(
|
|
7086
|
+
() => categoryId ? { ...searchOptions, category: categoryId } : searchOptions ?? {},
|
|
7087
|
+
[searchOptions, categoryId]
|
|
7088
|
+
);
|
|
7089
|
+
const { results, isLoading, query, setQuery, clear } = useSearch(mergedOptions);
|
|
6206
7090
|
const handleValueChange = useCallback(
|
|
6207
7091
|
(value) => {
|
|
6208
7092
|
setQuery(value);
|
|
@@ -6255,6 +7139,10 @@ function SearchInput({
|
|
|
6255
7139
|
}
|
|
6256
7140
|
)
|
|
6257
7141
|
] }),
|
|
7142
|
+
categoryId && /* @__PURE__ */ jsxs("div", { "data-cimplify-search-category-filter": true, className: classNames?.categoryFilter, children: [
|
|
7143
|
+
"Filtered by: ",
|
|
7144
|
+
categoryName || categoryId
|
|
7145
|
+
] }),
|
|
6258
7146
|
showResults && query.length > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-search-results": true, className: classNames?.results, children: [
|
|
6259
7147
|
isLoading && /* @__PURE__ */ jsx("div", { "data-cimplify-search-loading": true, className: classNames?.loading, "aria-busy": "true", children: "Searching..." }),
|
|
6260
7148
|
!isLoading && results.length === 0 && query.length >= 2 && /* @__PURE__ */ jsx("div", { "data-cimplify-search-empty": true, className: classNames?.empty, children: "No results found" }),
|
|
@@ -6265,7 +7153,21 @@ function SearchInput({
|
|
|
6265
7153
|
onClick: () => onResultClick?.(product),
|
|
6266
7154
|
"data-cimplify-search-result": true,
|
|
6267
7155
|
className: classNames?.resultItem,
|
|
6268
|
-
|
|
7156
|
+
style: !renderResult ? { display: "flex", alignItems: "center", gap: "0.5rem", width: "100%" } : void 0,
|
|
7157
|
+
children: renderResult ? renderResult(product) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7158
|
+
(product.images?.[0] || product.image_url) && /* @__PURE__ */ jsx(
|
|
7159
|
+
"img",
|
|
7160
|
+
{
|
|
7161
|
+
src: product.images?.[0] || product.image_url,
|
|
7162
|
+
alt: "",
|
|
7163
|
+
"data-cimplify-search-result-image": true,
|
|
7164
|
+
className: classNames?.resultImage,
|
|
7165
|
+
style: { width: "2rem", height: "2rem", objectFit: "cover", borderRadius: "0.25rem", flexShrink: 0 }
|
|
7166
|
+
}
|
|
7167
|
+
),
|
|
7168
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-search-result-name": true, className: classNames?.resultName, style: { flex: 1, textAlign: "left" }, children: product.name }),
|
|
7169
|
+
product.default_price !== void 0 && /* @__PURE__ */ jsx("span", { "data-cimplify-search-result-price": true, className: classNames?.resultPrice, style: { flexShrink: 0 }, children: formatPrice(product.default_price) })
|
|
7170
|
+
] })
|
|
6269
7171
|
},
|
|
6270
7172
|
product.id
|
|
6271
7173
|
))
|
|
@@ -6604,6 +7506,12 @@ var STATUS_LABELS = {
|
|
|
6604
7506
|
cancelled: "Cancelled",
|
|
6605
7507
|
refunded: "Refunded"
|
|
6606
7508
|
};
|
|
7509
|
+
var PAYMENT_STATE_LABELS = {
|
|
7510
|
+
not_paid: "Not Paid",
|
|
7511
|
+
paid: "Paid",
|
|
7512
|
+
partially_refunded: "Partially Refunded",
|
|
7513
|
+
refunded: "Refunded"
|
|
7514
|
+
};
|
|
6607
7515
|
function OrderSummary({
|
|
6608
7516
|
order: orderProp,
|
|
6609
7517
|
orderId,
|
|
@@ -6645,8 +7553,25 @@ function OrderSummary({
|
|
|
6645
7553
|
className: classNames?.status,
|
|
6646
7554
|
children: STATUS_LABELS[order.status] ?? order.status
|
|
6647
7555
|
}
|
|
7556
|
+
),
|
|
7557
|
+
order.payment_state && /* @__PURE__ */ jsx(
|
|
7558
|
+
"span",
|
|
7559
|
+
{
|
|
7560
|
+
"data-cimplify-order-payment-state": true,
|
|
7561
|
+
"data-payment-state": order.payment_state,
|
|
7562
|
+
className: classNames?.paymentState,
|
|
7563
|
+
children: PAYMENT_STATE_LABELS[order.payment_state] ?? order.payment_state
|
|
7564
|
+
}
|
|
6648
7565
|
)
|
|
6649
7566
|
] }),
|
|
7567
|
+
order.order_type === "pickup" && order.pickup_time && /* @__PURE__ */ jsx("div", { "data-cimplify-order-fulfillment": true, className: classNames?.fulfillmentDetails, children: /* @__PURE__ */ jsxs("span", { children: [
|
|
7568
|
+
"Pickup time: ",
|
|
7569
|
+
new Date(order.pickup_time).toLocaleString()
|
|
7570
|
+
] }) }),
|
|
7571
|
+
order.order_type === "dine-in" && order.table_number && /* @__PURE__ */ jsx("div", { "data-cimplify-order-fulfillment": true, className: classNames?.fulfillmentDetails, children: /* @__PURE__ */ jsxs("span", { children: [
|
|
7572
|
+
"Table: ",
|
|
7573
|
+
order.table_number
|
|
7574
|
+
] }) }),
|
|
6650
7575
|
/* @__PURE__ */ jsx("time", { "data-cimplify-order-date": true, dateTime: order.created_at, children: new Date(order.created_at).toLocaleDateString(void 0, {
|
|
6651
7576
|
year: "numeric",
|
|
6652
7577
|
month: "long",
|
|
@@ -6658,6 +7583,10 @@ function OrderSummary({
|
|
|
6658
7583
|
order.customer_name && /* @__PURE__ */ jsx("span", { "data-cimplify-order-customer-name": true, children: order.customer_name }),
|
|
6659
7584
|
order.customer_email && /* @__PURE__ */ jsx("span", { "data-cimplify-order-customer-email": true, children: order.customer_email })
|
|
6660
7585
|
] }),
|
|
7586
|
+
order.delivery_address && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-delivery-address": true, className: classNames?.deliveryAddress, children: [
|
|
7587
|
+
/* @__PURE__ */ jsx("span", { children: "Delivery address" }),
|
|
7588
|
+
/* @__PURE__ */ jsx("p", { children: order.delivery_address })
|
|
7589
|
+
] }),
|
|
6661
7590
|
/* @__PURE__ */ jsx("div", { "data-cimplify-order-items": true, className: classNames?.items, children: order.items.map(
|
|
6662
7591
|
(item) => renderLineItem ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderLineItem(item) }, item.id) : /* @__PURE__ */ jsxs("div", { "data-cimplify-order-line-item": true, className: classNames?.lineItem, children: [
|
|
6663
7592
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-order-line-info": true, children: [
|
|
@@ -6667,14 +7596,75 @@ function OrderSummary({
|
|
|
6667
7596
|
] }),
|
|
6668
7597
|
/* @__PURE__ */ jsx("span", { "data-cimplify-order-line-key": true, children: item.line_key })
|
|
6669
7598
|
] }),
|
|
6670
|
-
/* @__PURE__ */ jsx(Price, { amount: item.price })
|
|
7599
|
+
/* @__PURE__ */ jsx(Price, { amount: item.price }),
|
|
7600
|
+
item.fulfillment_type === "digital" && item.fulfillment_id && /* @__PURE__ */ jsx(
|
|
7601
|
+
"a",
|
|
7602
|
+
{
|
|
7603
|
+
href: item.fulfillment_id,
|
|
7604
|
+
target: "_blank",
|
|
7605
|
+
rel: "noopener noreferrer",
|
|
7606
|
+
"data-cimplify-order-line-download": true,
|
|
7607
|
+
className: "text-sm text-primary underline",
|
|
7608
|
+
children: "Download"
|
|
7609
|
+
}
|
|
7610
|
+
),
|
|
7611
|
+
item.configuration.type === "service" && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-service-info": true, className: classNames?.serviceInfo, children: [
|
|
7612
|
+
item.configuration.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
|
|
7613
|
+
"\u{1F4C5}",
|
|
7614
|
+
" ",
|
|
7615
|
+
new Date(item.configuration.scheduled_start).toLocaleDateString(),
|
|
7616
|
+
" at ",
|
|
7617
|
+
new Date(item.configuration.scheduled_start).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
|
7618
|
+
] }),
|
|
7619
|
+
item.configuration.confirmation_code && /* @__PURE__ */ jsxs("span", { children: [
|
|
7620
|
+
"Confirmation: ",
|
|
7621
|
+
item.configuration.confirmation_code
|
|
7622
|
+
] }),
|
|
7623
|
+
item.configuration.service_status && /* @__PURE__ */ jsx("span", { "data-status": item.configuration.service_status, children: item.configuration.service_status })
|
|
7624
|
+
] }),
|
|
7625
|
+
item.configuration.type === "digital" && /* @__PURE__ */ jsx("div", { "data-cimplify-order-digital-info": true, className: classNames?.digitalInfo, children: /* @__PURE__ */ jsxs("span", { children: [
|
|
7626
|
+
"\u26A1",
|
|
7627
|
+
" Instant digital delivery"
|
|
7628
|
+
] }) }),
|
|
7629
|
+
item.configuration.type === "bundle" && item.configuration.resolved && /* @__PURE__ */ jsx("div", { "data-cimplify-order-bundle-breakdown": true, className: classNames?.bundleBreakdown, children: item.configuration.resolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
|
|
7630
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7631
|
+
sel.quantity,
|
|
7632
|
+
"\xD7 ",
|
|
7633
|
+
sel.product_name
|
|
7634
|
+
] }),
|
|
7635
|
+
sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
|
|
7636
|
+
" \u2014 ",
|
|
7637
|
+
new Date(sel.scheduling.scheduled_start).toLocaleDateString()
|
|
7638
|
+
] }),
|
|
7639
|
+
sel.product_type === "digital" && /* @__PURE__ */ jsx("span", { children: " \u2014 Digital" })
|
|
7640
|
+
] }, sel.component_id)) }),
|
|
7641
|
+
item.configuration.type === "composite" && item.configuration.resolved && /* @__PURE__ */ jsx("div", { "data-cimplify-order-composite-breakdown": true, className: classNames?.compositeBreakdown, children: item.configuration.resolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
|
|
7642
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7643
|
+
sel.quantity,
|
|
7644
|
+
"\xD7 ",
|
|
7645
|
+
sel.component_name
|
|
7646
|
+
] }),
|
|
7647
|
+
sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
|
|
7648
|
+
" \u2014 ",
|
|
7649
|
+
new Date(sel.scheduling.scheduled_start).toLocaleDateString()
|
|
7650
|
+
] }),
|
|
7651
|
+
/* @__PURE__ */ jsx(Price, { amount: sel.unit_price })
|
|
7652
|
+
] }, sel.component_id)) })
|
|
6671
7653
|
] }, item.id)
|
|
6672
7654
|
) }),
|
|
7655
|
+
order.customer_notes && order.customer_notes.length > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-notes": true, className: classNames?.notes, children: [
|
|
7656
|
+
/* @__PURE__ */ jsx("span", { children: "Notes" }),
|
|
7657
|
+
order.customer_notes.map((note, index) => /* @__PURE__ */ jsx("p", { "data-cimplify-order-note": true, children: note }, index))
|
|
7658
|
+
] }),
|
|
6673
7659
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-order-totals": true, className: classNames?.totals, children: [
|
|
6674
7660
|
order.total_discount != null && parsePrice(order.total_discount) !== 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-discount": true, children: [
|
|
6675
7661
|
/* @__PURE__ */ jsx("span", { children: "Discount" }),
|
|
6676
7662
|
/* @__PURE__ */ jsx(Price, { amount: order.total_discount, prefix: "-" })
|
|
6677
7663
|
] }),
|
|
7664
|
+
order.delivery_fee != null && parsePrice(order.delivery_fee) > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-delivery-fee": true, children: [
|
|
7665
|
+
/* @__PURE__ */ jsx("span", { children: "Delivery fee" }),
|
|
7666
|
+
/* @__PURE__ */ jsx(Price, { amount: order.delivery_fee })
|
|
7667
|
+
] }),
|
|
6678
7668
|
order.service_charge != null && parsePrice(order.service_charge) !== 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-order-service-charge": true, children: [
|
|
6679
7669
|
/* @__PURE__ */ jsx("span", { children: "Service charge" }),
|
|
6680
7670
|
/* @__PURE__ */ jsx(Price, { amount: order.service_charge })
|
|
@@ -6695,6 +7685,7 @@ function OrderSummary({
|
|
|
6695
7685
|
target: "_blank",
|
|
6696
7686
|
rel: "noopener noreferrer",
|
|
6697
7687
|
"data-cimplify-order-tracking": true,
|
|
7688
|
+
className: classNames?.trackingLink,
|
|
6698
7689
|
children: "Track your order"
|
|
6699
7690
|
}
|
|
6700
7691
|
)
|
|
@@ -7360,6 +8351,23 @@ function BookingList({
|
|
|
7360
8351
|
booking.order_id
|
|
7361
8352
|
)) });
|
|
7362
8353
|
}
|
|
8354
|
+
|
|
8355
|
+
// src/react/utils/format-duration.ts
|
|
8356
|
+
var UNIT_LABELS = {
|
|
8357
|
+
minutes: { singular: "min", plural: "min" },
|
|
8358
|
+
hours: { singular: "hr", plural: "hrs" },
|
|
8359
|
+
days: { singular: "day", plural: "days" },
|
|
8360
|
+
nights: { singular: "night", plural: "nights" },
|
|
8361
|
+
weeks: { singular: "week", plural: "weeks" },
|
|
8362
|
+
months: { singular: "month", plural: "months" },
|
|
8363
|
+
years: { singular: "year", plural: "years" }
|
|
8364
|
+
};
|
|
8365
|
+
function formatDuration2(value, unit) {
|
|
8366
|
+
const resolved = unit ?? "minutes";
|
|
8367
|
+
const labels = UNIT_LABELS[resolved];
|
|
8368
|
+
const label = value === 1 ? labels.singular : labels.plural;
|
|
8369
|
+
return `${value} ${label}`;
|
|
8370
|
+
}
|
|
7363
8371
|
var ASPECT_STYLES3 = {
|
|
7364
8372
|
square: { aspectRatio: "1/1" },
|
|
7365
8373
|
"4/3": { aspectRatio: "4/3" },
|
|
@@ -7421,10 +8429,7 @@ function ServiceCard({
|
|
|
7421
8429
|
}
|
|
7422
8430
|
),
|
|
7423
8431
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-service-card-meta": true, className: classNames?.meta, children: [
|
|
7424
|
-
/* @__PURE__ */
|
|
7425
|
-
service.duration_minutes,
|
|
7426
|
-
" min"
|
|
7427
|
-
] }),
|
|
8432
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-service-card-duration": true, className: classNames?.duration, children: formatDuration2(service.duration_minutes, service.duration_unit) }),
|
|
7428
8433
|
service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-price": true, className: classNames?.price, children: /* @__PURE__ */ jsx(Price, { amount: service.price }) })
|
|
7429
8434
|
] })
|
|
7430
8435
|
] }),
|
|
@@ -8194,16 +9199,21 @@ function DealsPage({
|
|
|
8194
9199
|
}
|
|
8195
9200
|
function BookingPage({
|
|
8196
9201
|
service,
|
|
9202
|
+
product,
|
|
8197
9203
|
staff,
|
|
8198
9204
|
participantCount,
|
|
8199
9205
|
title,
|
|
8200
9206
|
onBooked,
|
|
8201
9207
|
onBack,
|
|
9208
|
+
existingBooking,
|
|
9209
|
+
onRescheduled,
|
|
8202
9210
|
showPrice = true,
|
|
8203
9211
|
className,
|
|
8204
9212
|
classNames
|
|
8205
9213
|
}) {
|
|
8206
9214
|
const { addItem } = useCart();
|
|
9215
|
+
const { client } = useCimplifyClient();
|
|
9216
|
+
const isReschedule = existingBooking !== void 0;
|
|
8207
9217
|
const [step, setStep] = useState("select-slot");
|
|
8208
9218
|
const [selectedSlot, setSelectedSlot] = useState(null);
|
|
8209
9219
|
const [selectedDate, setSelectedDate] = useState(null);
|
|
@@ -8211,6 +9221,11 @@ function BookingPage({
|
|
|
8211
9221
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
8212
9222
|
const [error, setError] = useState(null);
|
|
8213
9223
|
const hasStaffStep = staff && staff.length > 0;
|
|
9224
|
+
const depositType = product?.deposit_type;
|
|
9225
|
+
const depositAmount = product?.deposit_amount;
|
|
9226
|
+
const hasDeposit = depositType !== void 0 && depositType !== "none" && depositAmount !== void 0 && parsePrice(depositAmount) !== 0;
|
|
9227
|
+
const cancellationMinutes = product?.cancellation_window_minutes;
|
|
9228
|
+
const noShowFee = product?.no_show_fee;
|
|
8214
9229
|
const handleSlotSelect = useCallback(
|
|
8215
9230
|
(slot, date) => {
|
|
8216
9231
|
setSelectedSlot(slot);
|
|
@@ -8243,34 +9258,51 @@ function BookingPage({
|
|
|
8243
9258
|
setIsSubmitting(true);
|
|
8244
9259
|
setError(null);
|
|
8245
9260
|
try {
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
9261
|
+
if (isReschedule && existingBooking) {
|
|
9262
|
+
const serviceItem = existingBooking.service_items[0];
|
|
9263
|
+
const result = await client.scheduling.rescheduleBooking({
|
|
9264
|
+
order_id: existingBooking.order_id,
|
|
9265
|
+
line_item_id: serviceItem?.service_id ?? existingBooking.order_id,
|
|
9266
|
+
new_start_time: selectedSlot.start_time,
|
|
9267
|
+
new_end_time: selectedSlot.end_time,
|
|
9268
|
+
new_staff_id: selectedStaffId || void 0,
|
|
9269
|
+
reschedule_type: "customer"
|
|
9270
|
+
});
|
|
9271
|
+
if (!result.ok) {
|
|
9272
|
+
throw result.error;
|
|
9273
|
+
}
|
|
9274
|
+
onRescheduled?.(existingBooking, selectedSlot);
|
|
9275
|
+
} else {
|
|
9276
|
+
const serviceProduct = {
|
|
9277
|
+
id: service.product_id || service.id,
|
|
9278
|
+
business_id: service.business_id || "",
|
|
9279
|
+
category_id: service.category_id || void 0,
|
|
9280
|
+
name: service.name,
|
|
9281
|
+
slug: service.id,
|
|
9282
|
+
description: service.description || void 0,
|
|
9283
|
+
image_url: service.image_url || void 0,
|
|
9284
|
+
default_price: service.price || "0",
|
|
9285
|
+
type: "service",
|
|
9286
|
+
inventory_type: "none",
|
|
9287
|
+
variant_strategy: "fetch_all",
|
|
9288
|
+
is_active: service.is_available,
|
|
9289
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9290
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9291
|
+
};
|
|
9292
|
+
await addItem(serviceProduct, 1, {
|
|
9293
|
+
scheduledStart: selectedSlot.start_time,
|
|
9294
|
+
scheduledEnd: selectedSlot.end_time,
|
|
9295
|
+
staffId: selectedStaffId || void 0
|
|
9296
|
+
});
|
|
9297
|
+
onBooked?.(selectedSlot, selectedStaffId);
|
|
9298
|
+
}
|
|
8268
9299
|
} catch (err) {
|
|
8269
|
-
|
|
9300
|
+
const fallbackMessage = isReschedule ? "Failed to reschedule booking" : "Failed to add booking to cart";
|
|
9301
|
+
setError(err instanceof Error ? err.message : fallbackMessage);
|
|
8270
9302
|
} finally {
|
|
8271
9303
|
setIsSubmitting(false);
|
|
8272
9304
|
}
|
|
8273
|
-
}, [selectedSlot, selectedDate, selectedStaffId, service, addItem, onBooked]);
|
|
9305
|
+
}, [selectedSlot, selectedDate, selectedStaffId, service, addItem, onBooked, isReschedule, existingBooking, client, onRescheduled]);
|
|
8274
9306
|
return /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page": true, className: cn(className, classNames?.root), children: [
|
|
8275
9307
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page-header": true, className: classNames?.header, children: [
|
|
8276
9308
|
onBack && step === "select-slot" && /* @__PURE__ */ jsx(
|
|
@@ -8293,15 +9325,29 @@ function BookingPage({
|
|
|
8293
9325
|
children: "Back"
|
|
8294
9326
|
}
|
|
8295
9327
|
),
|
|
8296
|
-
/* @__PURE__ */ jsx("h1", { "data-cimplify-booking-page-title": true, className: classNames?.title, children: title || `Book ${service.name}` })
|
|
9328
|
+
/* @__PURE__ */ jsx("h1", { "data-cimplify-booking-page-title": true, className: classNames?.title, children: title || (isReschedule ? "Reschedule Booking" : `Book ${service.name}`) })
|
|
8297
9329
|
] }),
|
|
9330
|
+
isReschedule && existingBooking && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-reschedule-info": true, className: classNames?.rescheduleInfo, children: /* @__PURE__ */ jsxs("span", { children: [
|
|
9331
|
+
"Rescheduling booking from ",
|
|
9332
|
+
new Date(existingBooking.service_items[0]?.scheduled_start ?? existingBooking.created_at).toLocaleDateString()
|
|
9333
|
+
] }) }),
|
|
8298
9334
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-booking-service-info": true, className: classNames?.serviceInfo, children: [
|
|
8299
9335
|
/* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-name": true, children: service.name }),
|
|
8300
|
-
/* @__PURE__ */
|
|
8301
|
-
|
|
8302
|
-
|
|
9336
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-duration": true, children: formatDuration2(service.duration_minutes, service.duration_unit) }),
|
|
9337
|
+
service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-price": true, children: /* @__PURE__ */ jsx(Price, { amount: service.price }) }),
|
|
9338
|
+
hasDeposit && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-deposit-info": true, className: classNames?.depositInfo, children: [
|
|
9339
|
+
"Deposit: ",
|
|
9340
|
+
depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount })
|
|
9341
|
+
] }),
|
|
9342
|
+
cancellationMinutes !== void 0 && cancellationMinutes > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-cancellation-policy": true, className: classNames?.cancellationPolicy, children: [
|
|
9343
|
+
"Free cancellation up to ",
|
|
9344
|
+
cancellationMinutes >= 60 ? `${Math.floor(cancellationMinutes / 60)} hour${Math.floor(cancellationMinutes / 60) !== 1 ? "s" : ""}` : `${cancellationMinutes} minute${cancellationMinutes !== 1 ? "s" : ""}`,
|
|
9345
|
+
" before"
|
|
8303
9346
|
] }),
|
|
8304
|
-
|
|
9347
|
+
noShowFee !== void 0 && parsePrice(noShowFee) !== 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-no-show-fee": true, className: classNames?.cancellationPolicy, children: [
|
|
9348
|
+
"No-show fee: ",
|
|
9349
|
+
/* @__PURE__ */ jsx(Price, { amount: noShowFee })
|
|
9350
|
+
] })
|
|
8305
9351
|
] }),
|
|
8306
9352
|
error && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-error": true, className: classNames?.error, children: error }),
|
|
8307
9353
|
step === "select-slot" && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-slot", className: classNames?.step, children: [
|
|
@@ -8348,10 +9394,7 @@ function BookingPage({
|
|
|
8348
9394
|
] }),
|
|
8349
9395
|
/* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
|
|
8350
9396
|
/* @__PURE__ */ jsx("span", { children: "Duration" }),
|
|
8351
|
-
/* @__PURE__ */
|
|
8352
|
-
service.duration_minutes,
|
|
8353
|
-
" min"
|
|
8354
|
-
] })
|
|
9397
|
+
/* @__PURE__ */ jsx("span", { children: formatDuration2(service.duration_minutes, service.duration_unit) })
|
|
8355
9398
|
] }),
|
|
8356
9399
|
selectedStaffId && staff && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
|
|
8357
9400
|
/* @__PURE__ */ jsx("span", { children: "Provider" }),
|
|
@@ -8360,6 +9403,10 @@ function BookingPage({
|
|
|
8360
9403
|
(selectedSlot.price || service.price) && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
|
|
8361
9404
|
/* @__PURE__ */ jsx("span", { children: "Price" }),
|
|
8362
9405
|
/* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(Price, { amount: selectedSlot.price || service.price }) })
|
|
9406
|
+
] }),
|
|
9407
|
+
hasDeposit && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: cn(classNames?.summaryRow, classNames?.depositInfo), children: [
|
|
9408
|
+
/* @__PURE__ */ jsx("span", { children: "Deposit" }),
|
|
9409
|
+
/* @__PURE__ */ jsx("span", { children: depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount }) })
|
|
8363
9410
|
] })
|
|
8364
9411
|
] }),
|
|
8365
9412
|
/* @__PURE__ */ jsx(
|
|
@@ -8370,7 +9417,7 @@ function BookingPage({
|
|
|
8370
9417
|
disabled: isSubmitting,
|
|
8371
9418
|
"data-cimplify-booking-confirm": true,
|
|
8372
9419
|
className: classNames?.confirmButton,
|
|
8373
|
-
children: isSubmitting ? "Adding to cart\u2026" : "
|
|
9420
|
+
children: isSubmitting ? isReschedule ? "Rescheduling\u2026" : "Adding to cart\u2026" : isReschedule ? "Reschedule" : "Confirm Booking"
|
|
8374
9421
|
}
|
|
8375
9422
|
)
|
|
8376
9423
|
] })
|
|
@@ -8462,5 +9509,459 @@ function BookingsPage({
|
|
|
8462
9509
|
) })
|
|
8463
9510
|
] });
|
|
8464
9511
|
}
|
|
9512
|
+
function LocationPicker({
|
|
9513
|
+
locations: locationsProp,
|
|
9514
|
+
currentLocation: currentLocationProp,
|
|
9515
|
+
onLocationChange,
|
|
9516
|
+
renderLocation,
|
|
9517
|
+
emptyMessage,
|
|
9518
|
+
className,
|
|
9519
|
+
classNames
|
|
9520
|
+
}) {
|
|
9521
|
+
const {
|
|
9522
|
+
locations: fetched,
|
|
9523
|
+
currentLocation: fetchedCurrent,
|
|
9524
|
+
setCurrentLocation,
|
|
9525
|
+
isLoading
|
|
9526
|
+
} = useLocations();
|
|
9527
|
+
const locations = locationsProp ?? fetched;
|
|
9528
|
+
const currentLocation = currentLocationProp ?? fetchedCurrent;
|
|
9529
|
+
const handleSelect = (location) => {
|
|
9530
|
+
if (onLocationChange) {
|
|
9531
|
+
onLocationChange(location);
|
|
9532
|
+
} else {
|
|
9533
|
+
setCurrentLocation(location);
|
|
9534
|
+
}
|
|
9535
|
+
};
|
|
9536
|
+
if (isLoading && locations.length === 0) {
|
|
9537
|
+
return /* @__PURE__ */ jsx(
|
|
9538
|
+
"div",
|
|
9539
|
+
{
|
|
9540
|
+
"data-cimplify-location-picker": true,
|
|
9541
|
+
"aria-busy": "true",
|
|
9542
|
+
className: cn(className, classNames?.root, classNames?.loading)
|
|
9543
|
+
}
|
|
9544
|
+
);
|
|
9545
|
+
}
|
|
9546
|
+
if (locations.length <= 1) {
|
|
9547
|
+
return null;
|
|
9548
|
+
}
|
|
9549
|
+
if (locations.length === 0) {
|
|
9550
|
+
return /* @__PURE__ */ jsx(
|
|
9551
|
+
"div",
|
|
9552
|
+
{
|
|
9553
|
+
"data-cimplify-location-picker": true,
|
|
9554
|
+
"data-empty": true,
|
|
9555
|
+
className: cn(className, classNames?.root, classNames?.empty),
|
|
9556
|
+
children: /* @__PURE__ */ jsx("p", { children: emptyMessage ?? "No locations available" })
|
|
9557
|
+
}
|
|
9558
|
+
);
|
|
9559
|
+
}
|
|
9560
|
+
return /* @__PURE__ */ jsx("div", { "data-cimplify-location-picker": true, className: cn(className, classNames?.root), children: locations.map((location) => {
|
|
9561
|
+
const isActive = currentLocation?.id === location.id;
|
|
9562
|
+
return /* @__PURE__ */ jsx(
|
|
9563
|
+
"button",
|
|
9564
|
+
{
|
|
9565
|
+
type: "button",
|
|
9566
|
+
onClick: () => handleSelect(location),
|
|
9567
|
+
"data-cimplify-location-item": true,
|
|
9568
|
+
"data-active": isActive || void 0,
|
|
9569
|
+
"aria-pressed": isActive,
|
|
9570
|
+
className: cn(classNames?.item, isActive && classNames?.activeItem),
|
|
9571
|
+
children: renderLocation ? renderLocation(location, isActive) : /* @__PURE__ */ jsx("span", { children: location.name })
|
|
9572
|
+
},
|
|
9573
|
+
location.id
|
|
9574
|
+
);
|
|
9575
|
+
}) });
|
|
9576
|
+
}
|
|
9577
|
+
function RecommendationCarousel({
|
|
9578
|
+
recommendations: recommendationsProp,
|
|
9579
|
+
locationId,
|
|
9580
|
+
limit,
|
|
9581
|
+
onProductClick,
|
|
9582
|
+
renderProduct,
|
|
9583
|
+
emptyMessage,
|
|
9584
|
+
className,
|
|
9585
|
+
classNames
|
|
9586
|
+
}) {
|
|
9587
|
+
const { recommendations: fetched, isLoading } = useRecommendations({
|
|
9588
|
+
locationId,
|
|
9589
|
+
limit,
|
|
9590
|
+
enabled: recommendationsProp === void 0
|
|
9591
|
+
});
|
|
9592
|
+
const recommendations = recommendationsProp ?? fetched;
|
|
9593
|
+
if (isLoading && recommendations.length === 0) {
|
|
9594
|
+
return /* @__PURE__ */ jsx(
|
|
9595
|
+
"div",
|
|
9596
|
+
{
|
|
9597
|
+
"data-cimplify-recommendation-carousel": true,
|
|
9598
|
+
"aria-busy": "true",
|
|
9599
|
+
className: cn(className, classNames?.root, classNames?.loading)
|
|
9600
|
+
}
|
|
9601
|
+
);
|
|
9602
|
+
}
|
|
9603
|
+
if (recommendations.length === 0) {
|
|
9604
|
+
return null;
|
|
9605
|
+
}
|
|
9606
|
+
return /* @__PURE__ */ jsx(
|
|
9607
|
+
"div",
|
|
9608
|
+
{
|
|
9609
|
+
"data-cimplify-recommendation-carousel": true,
|
|
9610
|
+
className: cn(className, classNames?.root),
|
|
9611
|
+
style: { display: "flex", overflowX: "auto", gap: "1rem" },
|
|
9612
|
+
children: recommendations.map((rec, index) => {
|
|
9613
|
+
const productId = rec.product?.id ?? String(index);
|
|
9614
|
+
return /* @__PURE__ */ jsx(
|
|
9615
|
+
"button",
|
|
9616
|
+
{
|
|
9617
|
+
type: "button",
|
|
9618
|
+
onClick: () => onProductClick?.(rec),
|
|
9619
|
+
"data-cimplify-recommendation-item": true,
|
|
9620
|
+
className: classNames?.item,
|
|
9621
|
+
style: { flexShrink: 0 },
|
|
9622
|
+
children: renderProduct ? renderProduct(rec) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9623
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-recommendation-name": true, children: rec.product?.name ?? rec.product?.id ?? "Product" }),
|
|
9624
|
+
rec.reason && /* @__PURE__ */ jsx("span", { "data-cimplify-recommendation-reason": true, className: classNames?.reason, children: rec.reason })
|
|
9625
|
+
] })
|
|
9626
|
+
},
|
|
9627
|
+
String(productId)
|
|
9628
|
+
);
|
|
9629
|
+
})
|
|
9630
|
+
}
|
|
9631
|
+
);
|
|
9632
|
+
}
|
|
9633
|
+
function SessionMessageBanner({
|
|
9634
|
+
messages: messagesProp,
|
|
9635
|
+
onDismiss,
|
|
9636
|
+
renderMessage,
|
|
9637
|
+
className,
|
|
9638
|
+
classNames
|
|
9639
|
+
}) {
|
|
9640
|
+
const { messages: fetched, isLoading, dismissMessage } = useActivityState({
|
|
9641
|
+
enabled: messagesProp === void 0
|
|
9642
|
+
});
|
|
9643
|
+
const messages = messagesProp ?? fetched;
|
|
9644
|
+
const handleDismiss = async (code) => {
|
|
9645
|
+
if (onDismiss) {
|
|
9646
|
+
onDismiss(code);
|
|
9647
|
+
} else {
|
|
9648
|
+
await dismissMessage(code);
|
|
9649
|
+
}
|
|
9650
|
+
};
|
|
9651
|
+
if (isLoading && messages.length === 0) {
|
|
9652
|
+
return /* @__PURE__ */ jsx(
|
|
9653
|
+
"div",
|
|
9654
|
+
{
|
|
9655
|
+
"data-cimplify-session-message-banner": true,
|
|
9656
|
+
"aria-busy": "true",
|
|
9657
|
+
className: cn(className, classNames?.root)
|
|
9658
|
+
}
|
|
9659
|
+
);
|
|
9660
|
+
}
|
|
9661
|
+
if (messages.length === 0) {
|
|
9662
|
+
return null;
|
|
9663
|
+
}
|
|
9664
|
+
return /* @__PURE__ */ jsx("div", { "data-cimplify-session-message-banner": true, className: cn(className, classNames?.root), children: messages.map((msg) => /* @__PURE__ */ jsx(
|
|
9665
|
+
"div",
|
|
9666
|
+
{
|
|
9667
|
+
"data-cimplify-session-message": true,
|
|
9668
|
+
"data-level": msg.level,
|
|
9669
|
+
className: classNames?.message,
|
|
9670
|
+
children: renderMessage ? renderMessage(msg) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9671
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-session-message-text": true, className: classNames?.text, children: msg.text }),
|
|
9672
|
+
msg.dismissible && /* @__PURE__ */ jsx(
|
|
9673
|
+
"button",
|
|
9674
|
+
{
|
|
9675
|
+
type: "button",
|
|
9676
|
+
onClick: () => void handleDismiss(msg.code),
|
|
9677
|
+
"data-cimplify-session-message-dismiss": true,
|
|
9678
|
+
className: classNames?.dismissButton,
|
|
9679
|
+
"aria-label": "Dismiss message",
|
|
9680
|
+
children: "\xD7"
|
|
9681
|
+
}
|
|
9682
|
+
)
|
|
9683
|
+
] })
|
|
9684
|
+
},
|
|
9685
|
+
msg.code
|
|
9686
|
+
)) });
|
|
9687
|
+
}
|
|
9688
|
+
function RecentlyViewed({
|
|
9689
|
+
limit,
|
|
9690
|
+
onProductClick,
|
|
9691
|
+
renderProduct,
|
|
9692
|
+
emptyMessage,
|
|
9693
|
+
className,
|
|
9694
|
+
classNames
|
|
9695
|
+
}) {
|
|
9696
|
+
const { state, isLoading } = useActivityState();
|
|
9697
|
+
const rawViewed = state?.activity?.viewed_products ?? [];
|
|
9698
|
+
const viewed = limit ? rawViewed.slice(0, limit) : rawViewed;
|
|
9699
|
+
if (isLoading && viewed.length === 0) {
|
|
9700
|
+
return /* @__PURE__ */ jsx(
|
|
9701
|
+
"div",
|
|
9702
|
+
{
|
|
9703
|
+
"data-cimplify-recently-viewed": true,
|
|
9704
|
+
"aria-busy": "true",
|
|
9705
|
+
className: cn(className, classNames?.root, classNames?.loading)
|
|
9706
|
+
}
|
|
9707
|
+
);
|
|
9708
|
+
}
|
|
9709
|
+
if (viewed.length === 0) {
|
|
9710
|
+
return null;
|
|
9711
|
+
}
|
|
9712
|
+
return /* @__PURE__ */ jsx("div", { "data-cimplify-recently-viewed": true, className: cn(className, classNames?.root), children: viewed.map((product) => /* @__PURE__ */ jsx(
|
|
9713
|
+
"button",
|
|
9714
|
+
{
|
|
9715
|
+
type: "button",
|
|
9716
|
+
onClick: () => onProductClick?.(product),
|
|
9717
|
+
"data-cimplify-recently-viewed-item": true,
|
|
9718
|
+
className: classNames?.item,
|
|
9719
|
+
children: renderProduct ? renderProduct(product) : /* @__PURE__ */ jsx("span", { children: product.product_name ?? product.product_id })
|
|
9720
|
+
},
|
|
9721
|
+
product.product_id
|
|
9722
|
+
)) });
|
|
9723
|
+
}
|
|
9724
|
+
var FREQUENCY_LABELS = {
|
|
9725
|
+
weekly: "Weekly",
|
|
9726
|
+
monthly: "Monthly",
|
|
9727
|
+
quarterly: "Quarterly",
|
|
9728
|
+
annually: "Annually"
|
|
9729
|
+
};
|
|
9730
|
+
function formatMarkup(plan) {
|
|
9731
|
+
if (!plan.markup_type || plan.markup_amount == null) return null;
|
|
9732
|
+
if (plan.markup_type === "percentage") return `+${plan.markup_amount}%`;
|
|
9733
|
+
return null;
|
|
9734
|
+
}
|
|
9735
|
+
function BillingPlanSelector({
|
|
9736
|
+
productId,
|
|
9737
|
+
plans: plansProp,
|
|
9738
|
+
onPlanSelect,
|
|
9739
|
+
selectedPlanId,
|
|
9740
|
+
showOneTimePurchase = false,
|
|
9741
|
+
oneTimePurchaseLabel = "One-time purchase",
|
|
9742
|
+
renderPlan,
|
|
9743
|
+
className,
|
|
9744
|
+
classNames
|
|
9745
|
+
}) {
|
|
9746
|
+
const { plans: fetched, isLoading } = useBillingPlans(productId, {
|
|
9747
|
+
enabled: plansProp === void 0
|
|
9748
|
+
});
|
|
9749
|
+
const plans = plansProp ?? fetched;
|
|
9750
|
+
if (isLoading && plans.length === 0) {
|
|
9751
|
+
return /* @__PURE__ */ jsx(
|
|
9752
|
+
"div",
|
|
9753
|
+
{
|
|
9754
|
+
"data-cimplify-billing-plan-selector": true,
|
|
9755
|
+
"aria-busy": "true",
|
|
9756
|
+
className: cn(className, classNames?.root, classNames?.loading)
|
|
9757
|
+
}
|
|
9758
|
+
);
|
|
9759
|
+
}
|
|
9760
|
+
if (plans.length === 0 && !showOneTimePurchase) {
|
|
9761
|
+
return null;
|
|
9762
|
+
}
|
|
9763
|
+
const isOneTimePurchaseSelected = selectedPlanId === null;
|
|
9764
|
+
return /* @__PURE__ */ jsxs("div", { "data-cimplify-billing-plan-selector": true, className: cn(className, classNames?.root), children: [
|
|
9765
|
+
showOneTimePurchase && /* @__PURE__ */ jsx(
|
|
9766
|
+
"button",
|
|
9767
|
+
{
|
|
9768
|
+
type: "button",
|
|
9769
|
+
onClick: () => onPlanSelect?.(null),
|
|
9770
|
+
"data-cimplify-billing-plan": true,
|
|
9771
|
+
"data-plan-type": "one-time",
|
|
9772
|
+
"data-active": isOneTimePurchaseSelected || void 0,
|
|
9773
|
+
"aria-pressed": isOneTimePurchaseSelected,
|
|
9774
|
+
className: cn(
|
|
9775
|
+
classNames?.plan,
|
|
9776
|
+
isOneTimePurchaseSelected && classNames?.activePlan
|
|
9777
|
+
),
|
|
9778
|
+
children: /* @__PURE__ */ jsx("span", { "data-cimplify-billing-frequency": true, className: classNames?.frequency, children: oneTimePurchaseLabel })
|
|
9779
|
+
}
|
|
9780
|
+
),
|
|
9781
|
+
plans.map((plan) => {
|
|
9782
|
+
const isActive = selectedPlanId === plan.id;
|
|
9783
|
+
const markup = formatMarkup(plan);
|
|
9784
|
+
return /* @__PURE__ */ jsx(
|
|
9785
|
+
"button",
|
|
9786
|
+
{
|
|
9787
|
+
type: "button",
|
|
9788
|
+
onClick: () => onPlanSelect?.(plan),
|
|
9789
|
+
"data-cimplify-billing-plan": true,
|
|
9790
|
+
"data-plan-type": plan.plan_type,
|
|
9791
|
+
"data-active": isActive || void 0,
|
|
9792
|
+
"aria-pressed": isActive,
|
|
9793
|
+
className: cn(classNames?.plan, isActive && classNames?.activePlan),
|
|
9794
|
+
children: renderPlan ? renderPlan(plan, isActive) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9795
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-billing-frequency": true, className: classNames?.frequency, children: FREQUENCY_LABELS[plan.frequency] }),
|
|
9796
|
+
markup && /* @__PURE__ */ jsx("span", { "data-cimplify-billing-markup": true, className: classNames?.price, children: markup }),
|
|
9797
|
+
plan.markup_type === "fixed" && plan.markup_amount != null && /* @__PURE__ */ jsxs("span", { "data-cimplify-billing-markup": true, className: classNames?.price, children: [
|
|
9798
|
+
"+",
|
|
9799
|
+
/* @__PURE__ */ jsx(Price, { amount: plan.markup_amount })
|
|
9800
|
+
] }),
|
|
9801
|
+
plan.trial_days > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-billing-trial": true, className: classNames?.trialBadge, children: [
|
|
9802
|
+
plan.trial_days,
|
|
9803
|
+
"-day trial"
|
|
9804
|
+
] }),
|
|
9805
|
+
plan.setup_fee > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-billing-setup-fee": true, className: classNames?.setupFee, children: [
|
|
9806
|
+
"Setup fee: ",
|
|
9807
|
+
/* @__PURE__ */ jsx(Price, { amount: plan.setup_fee })
|
|
9808
|
+
] }),
|
|
9809
|
+
plan.plan_type === "installment" && plan.installment_periods != null && /* @__PURE__ */ jsxs("span", { "data-cimplify-billing-periods": true, children: [
|
|
9810
|
+
plan.installment_periods,
|
|
9811
|
+
" payments"
|
|
9812
|
+
] })
|
|
9813
|
+
] })
|
|
9814
|
+
},
|
|
9815
|
+
plan.id
|
|
9816
|
+
);
|
|
9817
|
+
})
|
|
9818
|
+
] });
|
|
9819
|
+
}
|
|
9820
|
+
function DeliveryEstimate({
|
|
9821
|
+
latitude,
|
|
9822
|
+
longitude,
|
|
9823
|
+
country,
|
|
9824
|
+
onFeeCalculated,
|
|
9825
|
+
className,
|
|
9826
|
+
classNames
|
|
9827
|
+
}) {
|
|
9828
|
+
const context = useOptionalCimplifyClient();
|
|
9829
|
+
const client = context?.client ?? null;
|
|
9830
|
+
const [result, setResult] = useState(null);
|
|
9831
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
9832
|
+
const [error, setError] = useState(null);
|
|
9833
|
+
const requestIdRef = useRef(0);
|
|
9834
|
+
useEffect(() => {
|
|
9835
|
+
if (!client) return;
|
|
9836
|
+
const nextRequestId = ++requestIdRef.current;
|
|
9837
|
+
setIsLoading(true);
|
|
9838
|
+
setError(null);
|
|
9839
|
+
void (async () => {
|
|
9840
|
+
const res = await client.delivery.getFee(latitude, longitude, country);
|
|
9841
|
+
if (nextRequestId !== requestIdRef.current) return;
|
|
9842
|
+
if (!res.ok) {
|
|
9843
|
+
setError(res.error);
|
|
9844
|
+
setResult(null);
|
|
9845
|
+
setIsLoading(false);
|
|
9846
|
+
return;
|
|
9847
|
+
}
|
|
9848
|
+
setResult(res.value);
|
|
9849
|
+
setError(null);
|
|
9850
|
+
setIsLoading(false);
|
|
9851
|
+
onFeeCalculated?.(res.value);
|
|
9852
|
+
})();
|
|
9853
|
+
}, [client, latitude, longitude, country]);
|
|
9854
|
+
if (!client) {
|
|
9855
|
+
return null;
|
|
9856
|
+
}
|
|
9857
|
+
if (isLoading) {
|
|
9858
|
+
return /* @__PURE__ */ jsx(
|
|
9859
|
+
"div",
|
|
9860
|
+
{
|
|
9861
|
+
"data-cimplify-delivery-estimate": true,
|
|
9862
|
+
"data-serviceable": "false",
|
|
9863
|
+
"aria-busy": "true",
|
|
9864
|
+
className: cn(className, classNames?.root, classNames?.loading)
|
|
9865
|
+
}
|
|
9866
|
+
);
|
|
9867
|
+
}
|
|
9868
|
+
if (error) {
|
|
9869
|
+
return /* @__PURE__ */ jsx(
|
|
9870
|
+
"div",
|
|
9871
|
+
{
|
|
9872
|
+
"data-cimplify-delivery-estimate": true,
|
|
9873
|
+
"data-serviceable": "false",
|
|
9874
|
+
className: cn(className, classNames?.root, classNames?.error),
|
|
9875
|
+
children: /* @__PURE__ */ jsx("span", { children: error.message })
|
|
9876
|
+
}
|
|
9877
|
+
);
|
|
9878
|
+
}
|
|
9879
|
+
if (!result || !result.serviceable) {
|
|
9880
|
+
return /* @__PURE__ */ jsx(
|
|
9881
|
+
"div",
|
|
9882
|
+
{
|
|
9883
|
+
"data-cimplify-delivery-estimate": true,
|
|
9884
|
+
"data-serviceable": "false",
|
|
9885
|
+
className: cn(className, classNames?.root, classNames?.notServiceable),
|
|
9886
|
+
children: /* @__PURE__ */ jsx("span", { children: "Not serviceable" })
|
|
9887
|
+
}
|
|
9888
|
+
);
|
|
9889
|
+
}
|
|
9890
|
+
return /* @__PURE__ */ jsxs(
|
|
9891
|
+
"div",
|
|
9892
|
+
{
|
|
9893
|
+
"data-cimplify-delivery-estimate": true,
|
|
9894
|
+
"data-serviceable": "true",
|
|
9895
|
+
className: cn(className, classNames?.root),
|
|
9896
|
+
children: [
|
|
9897
|
+
result.fee != null && /* @__PURE__ */ jsx("span", { "data-cimplify-delivery-fee": true, className: classNames?.fee, children: /* @__PURE__ */ jsx(Price, { amount: result.fee }) }),
|
|
9898
|
+
result.currency && /* @__PURE__ */ jsx("span", { "data-cimplify-delivery-currency": true, className: classNames?.currency, children: result.currency })
|
|
9899
|
+
]
|
|
9900
|
+
}
|
|
9901
|
+
);
|
|
9902
|
+
}
|
|
9903
|
+
function CurrencySelector({
|
|
9904
|
+
currencies,
|
|
9905
|
+
currentCurrency,
|
|
9906
|
+
onCurrencyChange,
|
|
9907
|
+
showRate = false,
|
|
9908
|
+
baseCurrency,
|
|
9909
|
+
renderCurrency,
|
|
9910
|
+
className,
|
|
9911
|
+
classNames
|
|
9912
|
+
}) {
|
|
9913
|
+
const context = useOptionalCimplifyClient();
|
|
9914
|
+
const client = context?.client ?? null;
|
|
9915
|
+
const [rates, setRates] = useState({});
|
|
9916
|
+
const [isLoadingRates, setIsLoadingRates] = useState(false);
|
|
9917
|
+
const requestIdRef = useRef(0);
|
|
9918
|
+
useEffect(() => {
|
|
9919
|
+
if (!showRate || !baseCurrency || !client) return;
|
|
9920
|
+
const targets = currencies.filter((c) => c !== baseCurrency);
|
|
9921
|
+
if (targets.length === 0) return;
|
|
9922
|
+
const nextRequestId = ++requestIdRef.current;
|
|
9923
|
+
setIsLoadingRates(true);
|
|
9924
|
+
void (async () => {
|
|
9925
|
+
const fetched = {};
|
|
9926
|
+
await Promise.all(
|
|
9927
|
+
targets.map(async (currency) => {
|
|
9928
|
+
const res = await client.fx.getRate(baseCurrency, currency);
|
|
9929
|
+
if (res.ok) {
|
|
9930
|
+
fetched[currency] = res.value;
|
|
9931
|
+
}
|
|
9932
|
+
})
|
|
9933
|
+
);
|
|
9934
|
+
if (nextRequestId !== requestIdRef.current) return;
|
|
9935
|
+
setRates(fetched);
|
|
9936
|
+
setIsLoadingRates(false);
|
|
9937
|
+
})();
|
|
9938
|
+
}, [client, showRate, baseCurrency, currencies]);
|
|
9939
|
+
if (currencies.length <= 1) {
|
|
9940
|
+
return null;
|
|
9941
|
+
}
|
|
9942
|
+
return /* @__PURE__ */ jsx("div", { "data-cimplify-currency-selector": true, className: cn(className, classNames?.root), children: currencies.map((currency) => {
|
|
9943
|
+
const isActive = currentCurrency === currency;
|
|
9944
|
+
const rate = rates[currency] ?? null;
|
|
9945
|
+
return /* @__PURE__ */ jsx(
|
|
9946
|
+
"button",
|
|
9947
|
+
{
|
|
9948
|
+
type: "button",
|
|
9949
|
+
onClick: () => onCurrencyChange?.(currency),
|
|
9950
|
+
"data-cimplify-currency-option": true,
|
|
9951
|
+
"data-active": isActive || void 0,
|
|
9952
|
+
"aria-pressed": isActive,
|
|
9953
|
+
className: cn(
|
|
9954
|
+
classNames?.option,
|
|
9955
|
+
isActive && classNames?.activeOption
|
|
9956
|
+
),
|
|
9957
|
+
children: renderCurrency ? renderCurrency(currency, isActive, rate) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9958
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-currency-label": true, className: classNames?.label, children: currency }),
|
|
9959
|
+
showRate && baseCurrency && currency !== baseCurrency && /* @__PURE__ */ jsx("span", { "data-cimplify-currency-rate": true, className: classNames?.rate, children: isLoadingRates ? "..." : rate ? `1 ${baseCurrency} = ${rate.rate.toFixed(4)} ${currency}` : null })
|
|
9960
|
+
] })
|
|
9961
|
+
},
|
|
9962
|
+
currency
|
|
9963
|
+
);
|
|
9964
|
+
}) });
|
|
9965
|
+
}
|
|
8465
9966
|
|
|
8466
|
-
export { Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BookingCard, BookingList, BookingPage, BookingsPage, BundleSelector, CartPage, CartSummary, CataloguePage, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyCheckout, CimplifyProvider, CollectionPage, CompositeSelector, DateSlotPicker, DealBanner, DealsPage, DiscountInput, ElementsProvider, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, QuantitySelector, SaleBadge, SearchInput, SearchPage, ServiceCard, ServiceGrid, SlotPicker, StaffPicker, StoreNav, VariantSelector, cn, useAds, useAvailableSlots, useBookings, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useElements, useElementsReady, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, useQuote, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount };
|
|
9967
|
+
export { Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleSelector, CartPage, CartSummary, CataloguePage, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyCheckout, CimplifyProvider, CollectionPage, CompositeSelector, CurrencySelector, DateSlotPicker, DealBanner, DealsPage, DeliveryEstimate, DiscountInput, ElementsProvider, LocationPicker, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, QuantitySelector, RecentlyViewed, RecommendationCarousel, SaleBadge, SearchInput, SearchPage, ServiceCard, ServiceGrid, SessionMessageBanner, SlotPicker, StaffPicker, StoreNav, VariantSelector, cn, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|