@cimplify/sdk 0.27.0 → 0.29.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/{chunk-4JSRPSNA.js → chunk-R4AKAGZQ.js} +162 -0
- package/dist/{chunk-MISITC47.mjs → chunk-REXW2PET.mjs} +159 -1
- package/dist/{index-DBM89ktY.d.ts → index-Cjfczg2W.d.ts} +2 -2
- package/dist/{index-2JxW7TuQ.d.mts → index-D4-b5OZO.d.mts} +2 -2
- package/dist/{index-BAu-zmIP.d.ts → index-DijjnO-u.d.mts} +73 -2
- package/dist/{index-DT-24csu.d.mts → index-DwvzjdGi.d.ts} +73 -2
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +25 -9
- package/dist/index.mjs +1 -1
- package/dist/{payment-5a21yzi7.d.mts → payment-BeLHpQMo.d.mts} +155 -1
- package/dist/{payment-5a21yzi7.d.ts → payment-BeLHpQMo.d.ts} +155 -1
- package/dist/{price-BS0Z5Oi9.d.ts → price-C6gfys5B.d.ts} +1 -1
- package/dist/{price-CGPMlQUk.d.mts → price-Dvl1p9AM.d.mts} +1 -1
- package/dist/react.d.mts +86 -4
- package/dist/react.d.ts +86 -4
- package/dist/react.js +1583 -340
- package/dist/react.mjs +1260 -24
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +3 -3
- package/dist/utils.d.ts +3 -3
- package/package.json +1 -1
- package/registry/cart-summary.json +1 -1
- package/registry/product-card.json +1 -1
- package/registry/product-customizer.json +1 -1
- package/registry/product-page.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkR4AKAGZQ_js = require('./chunk-R4AKAGZQ.js');
|
|
5
5
|
var chunk2CGA3MUW_js = require('./chunk-2CGA3MUW.js');
|
|
6
6
|
var chunkPEDLCL72_js = require('./chunk-PEDLCL72.js');
|
|
7
|
-
var
|
|
7
|
+
var React10 = require('react');
|
|
8
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
9
|
var clsx = require('clsx');
|
|
10
10
|
var tailwindMerge = require('tailwind-merge');
|
|
@@ -20,7 +20,7 @@ var tabs = require('@base-ui/react/tabs');
|
|
|
20
20
|
|
|
21
21
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
22
|
|
|
23
|
-
var
|
|
23
|
+
var React10__default = /*#__PURE__*/_interopDefault(React10);
|
|
24
24
|
|
|
25
25
|
// src/ads/identity.ts
|
|
26
26
|
var COOKIE_NAME = "_cimplify_uid";
|
|
@@ -197,7 +197,7 @@ function deriveAdsApiUrl() {
|
|
|
197
197
|
}
|
|
198
198
|
return "https://api.cimplify.io";
|
|
199
199
|
}
|
|
200
|
-
var AdContext =
|
|
200
|
+
var AdContext = React10.createContext({
|
|
201
201
|
siteId: null,
|
|
202
202
|
config: null,
|
|
203
203
|
isLoading: true,
|
|
@@ -205,7 +205,7 @@ var AdContext = React3.createContext({
|
|
|
205
205
|
apiBase: "https://api.cimplify.io"
|
|
206
206
|
});
|
|
207
207
|
function useAds() {
|
|
208
|
-
return
|
|
208
|
+
return React10.useContext(AdContext);
|
|
209
209
|
}
|
|
210
210
|
function AdProvider({
|
|
211
211
|
siteId,
|
|
@@ -214,10 +214,10 @@ function AdProvider({
|
|
|
214
214
|
children
|
|
215
215
|
}) {
|
|
216
216
|
const resolvedApiBase = apiBase || deriveAdsApiUrl();
|
|
217
|
-
const [config, setConfig] =
|
|
218
|
-
const [isLoading, setIsLoading] =
|
|
219
|
-
const [identity, setIdentity] =
|
|
220
|
-
|
|
217
|
+
const [config, setConfig] = React10.useState(null);
|
|
218
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
219
|
+
const [identity, setIdentity] = React10.useState(null);
|
|
220
|
+
React10.useEffect(() => {
|
|
221
221
|
const userIdentity = getUserIdentity(authenticatedAccountId);
|
|
222
222
|
setIdentity(userIdentity);
|
|
223
223
|
fetch(`${resolvedApiBase}/ads/config/${siteId}`).then((r) => r.json()).then((data) => {
|
|
@@ -240,11 +240,11 @@ function Ad({
|
|
|
240
240
|
onClick
|
|
241
241
|
}) {
|
|
242
242
|
const { siteId, config, isLoading, identity, apiBase } = useAds();
|
|
243
|
-
const [ad, setAd] =
|
|
244
|
-
const [error, setError] =
|
|
245
|
-
const impressionTracked =
|
|
246
|
-
const containerRef =
|
|
247
|
-
|
|
243
|
+
const [ad, setAd] = React10.useState(null);
|
|
244
|
+
const [error, setError] = React10.useState(false);
|
|
245
|
+
const impressionTracked = React10.useRef(false);
|
|
246
|
+
const containerRef = React10.useRef(null);
|
|
247
|
+
React10.useEffect(() => {
|
|
248
248
|
if (isLoading || !config?.enabled || !siteId || !identity) return;
|
|
249
249
|
const path = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
250
250
|
const referrer = typeof document !== "undefined" ? document.referrer : "";
|
|
@@ -287,7 +287,7 @@ function Ad({
|
|
|
287
287
|
}
|
|
288
288
|
}).catch(() => setError(true));
|
|
289
289
|
}, [siteId, config, isLoading, slot, identity, apiBase]);
|
|
290
|
-
|
|
290
|
+
React10.useEffect(() => {
|
|
291
291
|
if (!ad || impressionTracked.current || typeof window === "undefined" || !identity) return;
|
|
292
292
|
const observer = new IntersectionObserver(
|
|
293
293
|
([entry]) => {
|
|
@@ -570,7 +570,8 @@ function mapServerCart(serverCart) {
|
|
|
570
570
|
confirmationCode: item.confirmation_code || void 0,
|
|
571
571
|
serviceStatus: item.service_status || void 0,
|
|
572
572
|
bundleResolved: item.bundle_resolved || void 0,
|
|
573
|
-
compositeResolved: item.composite_resolved || void 0
|
|
573
|
+
compositeResolved: item.composite_resolved || void 0,
|
|
574
|
+
customerInputs: item.customer_inputs || void 0
|
|
574
575
|
});
|
|
575
576
|
});
|
|
576
577
|
return {
|
|
@@ -790,7 +791,8 @@ function createCartStore(params) {
|
|
|
790
791
|
scheduled_start: normalizedOptions.scheduledStart,
|
|
791
792
|
scheduled_end: normalizedOptions.scheduledEnd,
|
|
792
793
|
staff_id: normalizedOptions.staffId,
|
|
793
|
-
resource_id: normalizedOptions.resourceId
|
|
794
|
+
resource_id: normalizedOptions.resourceId,
|
|
795
|
+
customer_inputs: normalizedOptions.customerInputs
|
|
794
796
|
});
|
|
795
797
|
if (!result.ok) {
|
|
796
798
|
throw result.error;
|
|
@@ -981,7 +983,7 @@ function useCart(options = {}) {
|
|
|
981
983
|
const locationId = options.locationId ?? client.getLocationId();
|
|
982
984
|
const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
|
|
983
985
|
const currency = options.currency ?? context?.currency ?? "USD";
|
|
984
|
-
const store =
|
|
986
|
+
const store = React10.useMemo(
|
|
985
987
|
() => getOrCreateStore({
|
|
986
988
|
client,
|
|
987
989
|
locationId,
|
|
@@ -990,53 +992,53 @@ function useCart(options = {}) {
|
|
|
990
992
|
}),
|
|
991
993
|
[client, currency, isDemoMode, locationId]
|
|
992
994
|
);
|
|
993
|
-
const snapshot =
|
|
995
|
+
const snapshot = React10.useSyncExternalStore(
|
|
994
996
|
store.subscribe,
|
|
995
997
|
store.getSnapshot,
|
|
996
998
|
store.getSnapshot
|
|
997
999
|
);
|
|
998
|
-
|
|
1000
|
+
React10.useEffect(() => {
|
|
999
1001
|
void store.initialize();
|
|
1000
1002
|
}, [store]);
|
|
1001
|
-
const addItem =
|
|
1003
|
+
const addItem = React10.useCallback(
|
|
1002
1004
|
async (product, quantity, addOptions) => {
|
|
1003
1005
|
await store.addItem(product, quantity, addOptions);
|
|
1004
1006
|
},
|
|
1005
1007
|
[store]
|
|
1006
1008
|
);
|
|
1007
|
-
const removeItem =
|
|
1009
|
+
const removeItem = React10.useCallback(
|
|
1008
1010
|
async (itemId) => {
|
|
1009
1011
|
await store.removeItem(itemId);
|
|
1010
1012
|
},
|
|
1011
1013
|
[store]
|
|
1012
1014
|
);
|
|
1013
|
-
const updateQuantity =
|
|
1015
|
+
const updateQuantity = React10.useCallback(
|
|
1014
1016
|
async (itemId, quantity) => {
|
|
1015
1017
|
await store.updateQuantity(itemId, quantity);
|
|
1016
1018
|
},
|
|
1017
1019
|
[store]
|
|
1018
1020
|
);
|
|
1019
|
-
const clearCart =
|
|
1021
|
+
const clearCart = React10.useCallback(async () => {
|
|
1020
1022
|
await store.clearCart();
|
|
1021
1023
|
}, [store]);
|
|
1022
|
-
const sync =
|
|
1024
|
+
const sync = React10.useCallback(async () => {
|
|
1023
1025
|
try {
|
|
1024
1026
|
await store.sync();
|
|
1025
1027
|
} catch (syncError) {
|
|
1026
1028
|
throw syncError;
|
|
1027
1029
|
}
|
|
1028
1030
|
}, [store]);
|
|
1029
|
-
const reorder =
|
|
1031
|
+
const reorder = React10.useCallback(
|
|
1030
1032
|
async (orderId) => {
|
|
1031
1033
|
return store.reorder(orderId);
|
|
1032
1034
|
},
|
|
1033
1035
|
[store]
|
|
1034
1036
|
);
|
|
1035
|
-
const itemCount =
|
|
1037
|
+
const itemCount = React10.useMemo(
|
|
1036
1038
|
() => snapshot.items.reduce((sum, item) => sum + item.quantity, 0),
|
|
1037
1039
|
[snapshot.items]
|
|
1038
1040
|
);
|
|
1039
|
-
return
|
|
1041
|
+
return React10.useMemo(() => ({
|
|
1040
1042
|
items: snapshot.items,
|
|
1041
1043
|
itemCount,
|
|
1042
1044
|
subtotal: snapshot.subtotal,
|
|
@@ -1061,7 +1063,7 @@ var DEFAULT_COUNTRY = "US";
|
|
|
1061
1063
|
function createDefaultClient() {
|
|
1062
1064
|
const processRef = globalThis.process;
|
|
1063
1065
|
const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
|
|
1064
|
-
return
|
|
1066
|
+
return chunkR4AKAGZQ_js.createCimplifyClient({ publicKey: envPublicKey });
|
|
1065
1067
|
}
|
|
1066
1068
|
function getStoredLocationId() {
|
|
1067
1069
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
@@ -1118,30 +1120,30 @@ function resolveInitialLocation(locations) {
|
|
|
1118
1120
|
}
|
|
1119
1121
|
return locations[0];
|
|
1120
1122
|
}
|
|
1121
|
-
var CimplifyClientContext =
|
|
1122
|
-
var CimplifyStateContext =
|
|
1123
|
+
var CimplifyClientContext = React10.createContext(null);
|
|
1124
|
+
var CimplifyStateContext = React10.createContext(null);
|
|
1123
1125
|
function CimplifyProvider({
|
|
1124
1126
|
client,
|
|
1125
1127
|
children,
|
|
1126
1128
|
onLocationChange
|
|
1127
1129
|
}) {
|
|
1128
|
-
const resolvedClient =
|
|
1129
|
-
const onLocationChangeRef =
|
|
1130
|
-
const [business, setBusiness] =
|
|
1131
|
-
const [locations, setLocations] =
|
|
1132
|
-
const [currentLocation, setCurrentLocationState] =
|
|
1133
|
-
const [isReady, setIsReady] =
|
|
1134
|
-
|
|
1130
|
+
const resolvedClient = React10.useMemo(() => client ?? createDefaultClient(), [client]);
|
|
1131
|
+
const onLocationChangeRef = React10.useRef(onLocationChange);
|
|
1132
|
+
const [business, setBusiness] = React10.useState(null);
|
|
1133
|
+
const [locations, setLocations] = React10.useState([]);
|
|
1134
|
+
const [currentLocation, setCurrentLocationState] = React10.useState(null);
|
|
1135
|
+
const [isReady, setIsReady] = React10.useState(false);
|
|
1136
|
+
React10.useEffect(() => {
|
|
1135
1137
|
onLocationChangeRef.current = onLocationChange;
|
|
1136
1138
|
}, [onLocationChange]);
|
|
1137
1139
|
const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
|
|
1138
1140
|
const baseCurrency = business?.default_currency || DEFAULT_CURRENCY;
|
|
1139
|
-
const [displayCurrencyOverride, setDisplayCurrencyOverride] =
|
|
1141
|
+
const [displayCurrencyOverride, setDisplayCurrencyOverride] = React10.useState(
|
|
1140
1142
|
() => getStoredDisplayCurrency()
|
|
1141
1143
|
);
|
|
1142
|
-
const [fxRate, setFxRate] =
|
|
1144
|
+
const [fxRate, setFxRate] = React10.useState(null);
|
|
1143
1145
|
const displayCurrency = displayCurrencyOverride && displayCurrencyOverride !== baseCurrency ? displayCurrencyOverride : baseCurrency;
|
|
1144
|
-
const setDisplayCurrency =
|
|
1146
|
+
const setDisplayCurrency = React10.useCallback(
|
|
1145
1147
|
(currency) => {
|
|
1146
1148
|
const normalized = currency?.trim().toUpperCase() || null;
|
|
1147
1149
|
if (normalized && !chunkPEDLCL72_js.isSupportedCurrency(normalized)) {
|
|
@@ -1155,7 +1157,7 @@ function CimplifyProvider({
|
|
|
1155
1157
|
},
|
|
1156
1158
|
[baseCurrency]
|
|
1157
1159
|
);
|
|
1158
|
-
|
|
1160
|
+
React10.useEffect(() => {
|
|
1159
1161
|
if (displayCurrency === baseCurrency || isDemoMode) {
|
|
1160
1162
|
setFxRate(null);
|
|
1161
1163
|
return;
|
|
@@ -1180,7 +1182,7 @@ function CimplifyProvider({
|
|
|
1180
1182
|
clearInterval(intervalId);
|
|
1181
1183
|
};
|
|
1182
1184
|
}, [resolvedClient, baseCurrency, displayCurrency, isDemoMode]);
|
|
1183
|
-
const convertPrice =
|
|
1185
|
+
const convertPrice = React10.useCallback(
|
|
1184
1186
|
(amount) => {
|
|
1185
1187
|
const num = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
1186
1188
|
if (isNaN(num)) return 0;
|
|
@@ -1189,7 +1191,7 @@ function CimplifyProvider({
|
|
|
1189
1191
|
},
|
|
1190
1192
|
[fxRate, displayCurrency, baseCurrency]
|
|
1191
1193
|
);
|
|
1192
|
-
const setCurrentLocation =
|
|
1194
|
+
const setCurrentLocation = React10.useCallback(
|
|
1193
1195
|
(location) => {
|
|
1194
1196
|
const previousLocationId = resolvedClient.getLocationId();
|
|
1195
1197
|
if (previousLocationId && previousLocationId !== location.id) {
|
|
@@ -1202,7 +1204,7 @@ function CimplifyProvider({
|
|
|
1202
1204
|
},
|
|
1203
1205
|
[resolvedClient]
|
|
1204
1206
|
);
|
|
1205
|
-
|
|
1207
|
+
React10.useEffect(() => {
|
|
1206
1208
|
let cancelled = false;
|
|
1207
1209
|
async function bootstrap() {
|
|
1208
1210
|
setIsReady(false);
|
|
@@ -1258,7 +1260,7 @@ function CimplifyProvider({
|
|
|
1258
1260
|
cancelled = true;
|
|
1259
1261
|
};
|
|
1260
1262
|
}, [resolvedClient, isDemoMode]);
|
|
1261
|
-
const clientContextValue =
|
|
1263
|
+
const clientContextValue = React10.useMemo(
|
|
1262
1264
|
() => ({
|
|
1263
1265
|
client: resolvedClient,
|
|
1264
1266
|
business,
|
|
@@ -1278,7 +1280,7 @@ function CimplifyProvider({
|
|
|
1278
1280
|
isDemoMode
|
|
1279
1281
|
]
|
|
1280
1282
|
);
|
|
1281
|
-
const stateContextValue =
|
|
1283
|
+
const stateContextValue = React10.useMemo(
|
|
1282
1284
|
() => ({
|
|
1283
1285
|
currentLocation,
|
|
1284
1286
|
setCurrentLocation,
|
|
@@ -1299,20 +1301,20 @@ function CimplifyProvider({
|
|
|
1299
1301
|
return /* @__PURE__ */ jsxRuntime.jsx(CimplifyClientContext.Provider, { value: clientContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(CimplifyStateContext.Provider, { value: stateContextValue, children }) });
|
|
1300
1302
|
}
|
|
1301
1303
|
function useCimplify() {
|
|
1302
|
-
const clientContext =
|
|
1303
|
-
const stateContext =
|
|
1304
|
+
const clientContext = React10.useContext(CimplifyClientContext);
|
|
1305
|
+
const stateContext = React10.useContext(CimplifyStateContext);
|
|
1304
1306
|
if (!clientContext || !stateContext) {
|
|
1305
1307
|
throw new Error("useCimplify must be used within CimplifyProvider");
|
|
1306
1308
|
}
|
|
1307
|
-
return
|
|
1309
|
+
return React10.useMemo(
|
|
1308
1310
|
() => ({ ...clientContext, ...stateContext }),
|
|
1309
1311
|
[clientContext, stateContext]
|
|
1310
1312
|
);
|
|
1311
1313
|
}
|
|
1312
1314
|
function useOptionalCimplify() {
|
|
1313
|
-
const clientContext =
|
|
1314
|
-
const stateContext =
|
|
1315
|
-
return
|
|
1315
|
+
const clientContext = React10.useContext(CimplifyClientContext);
|
|
1316
|
+
const stateContext = React10.useContext(CimplifyStateContext);
|
|
1317
|
+
return React10.useMemo(() => {
|
|
1316
1318
|
if (!clientContext || !stateContext) {
|
|
1317
1319
|
return null;
|
|
1318
1320
|
}
|
|
@@ -1320,14 +1322,14 @@ function useOptionalCimplify() {
|
|
|
1320
1322
|
}, [clientContext, stateContext]);
|
|
1321
1323
|
}
|
|
1322
1324
|
function useCimplifyClient() {
|
|
1323
|
-
const context =
|
|
1325
|
+
const context = React10.useContext(CimplifyClientContext);
|
|
1324
1326
|
if (!context) {
|
|
1325
1327
|
throw new Error("useCimplifyClient must be used within CimplifyProvider");
|
|
1326
1328
|
}
|
|
1327
1329
|
return context;
|
|
1328
1330
|
}
|
|
1329
1331
|
function useOptionalCimplifyClient() {
|
|
1330
|
-
return
|
|
1332
|
+
return React10.useContext(CimplifyClientContext);
|
|
1331
1333
|
}
|
|
1332
1334
|
var SPACE = { sm: 8};
|
|
1333
1335
|
function shellColors(isDark, primaryColor) {
|
|
@@ -1385,36 +1387,36 @@ function CimplifyCheckout({
|
|
|
1385
1387
|
demoMode,
|
|
1386
1388
|
className
|
|
1387
1389
|
}) {
|
|
1388
|
-
const resolvedOrderTypes =
|
|
1390
|
+
const resolvedOrderTypes = React10.useMemo(
|
|
1389
1391
|
() => orderTypes && orderTypes.length > 0 ? orderTypes : ["pickup", "delivery"],
|
|
1390
1392
|
[orderTypes]
|
|
1391
1393
|
);
|
|
1392
|
-
const resolvedDefaultOrderType =
|
|
1394
|
+
const resolvedDefaultOrderType = React10.useMemo(() => {
|
|
1393
1395
|
if (defaultOrderType && resolvedOrderTypes.includes(defaultOrderType)) {
|
|
1394
1396
|
return defaultOrderType;
|
|
1395
1397
|
}
|
|
1396
1398
|
return resolvedOrderTypes[0] || "pickup";
|
|
1397
1399
|
}, [defaultOrderType, resolvedOrderTypes]);
|
|
1398
|
-
const [orderType, setOrderType] =
|
|
1399
|
-
const [status, setStatus] =
|
|
1400
|
-
const [statusText, setStatusText] =
|
|
1401
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1402
|
-
const [isInitializing, setIsInitializing] =
|
|
1403
|
-
const [errorMessage, setErrorMessage] =
|
|
1404
|
-
const [resolvedBusinessId, setResolvedBusinessId] =
|
|
1405
|
-
const [resolvedCartId, setResolvedCartId] =
|
|
1406
|
-
const [resolvedCart, setResolvedCart] =
|
|
1407
|
-
const checkoutMountRef =
|
|
1408
|
-
const elementsRef =
|
|
1409
|
-
const activeCheckoutRef =
|
|
1410
|
-
const initialAppearanceRef =
|
|
1411
|
-
const hasWarnedInlineAppearanceRef =
|
|
1412
|
-
const isMountedRef =
|
|
1413
|
-
const demoRunRef =
|
|
1400
|
+
const [orderType, setOrderType] = React10.useState(resolvedDefaultOrderType);
|
|
1401
|
+
const [status, setStatus] = React10.useState(null);
|
|
1402
|
+
const [statusText, setStatusText] = React10.useState("");
|
|
1403
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
1404
|
+
const [isInitializing, setIsInitializing] = React10.useState(false);
|
|
1405
|
+
const [errorMessage, setErrorMessage] = React10.useState(null);
|
|
1406
|
+
const [resolvedBusinessId, setResolvedBusinessId] = React10.useState(businessId ?? null);
|
|
1407
|
+
const [resolvedCartId, setResolvedCartId] = React10.useState(cartId ?? null);
|
|
1408
|
+
const [resolvedCart, setResolvedCart] = React10.useState(null);
|
|
1409
|
+
const checkoutMountRef = React10.useRef(null);
|
|
1410
|
+
const elementsRef = React10.useRef(null);
|
|
1411
|
+
const activeCheckoutRef = React10.useRef(null);
|
|
1412
|
+
const initialAppearanceRef = React10.useRef(appearance);
|
|
1413
|
+
const hasWarnedInlineAppearanceRef = React10.useRef(false);
|
|
1414
|
+
const isMountedRef = React10.useRef(true);
|
|
1415
|
+
const demoRunRef = React10.useRef(0);
|
|
1414
1416
|
const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
|
|
1415
1417
|
const isTestMode = client.isTestMode();
|
|
1416
1418
|
const cimplifyCtx = useOptionalCimplify();
|
|
1417
|
-
const fxOptions =
|
|
1419
|
+
const fxOptions = React10.useMemo(() => {
|
|
1418
1420
|
if (!cimplifyCtx?.fxRate) return void 0;
|
|
1419
1421
|
if (cimplifyCtx.displayCurrency === cimplifyCtx.baseCurrency) return void 0;
|
|
1420
1422
|
return {
|
|
@@ -1422,30 +1424,30 @@ function CimplifyCheckout({
|
|
|
1422
1424
|
convertPrice: cimplifyCtx.convertPrice
|
|
1423
1425
|
};
|
|
1424
1426
|
}, [cimplifyCtx?.fxRate, cimplifyCtx?.displayCurrency, cimplifyCtx?.baseCurrency, cimplifyCtx?.convertPrice]);
|
|
1425
|
-
const fxOptionsRef =
|
|
1427
|
+
const fxOptionsRef = React10.useRef(fxOptions);
|
|
1426
1428
|
fxOptionsRef.current = fxOptions;
|
|
1427
|
-
const resolvedCartRef =
|
|
1429
|
+
const resolvedCartRef = React10.useRef(resolvedCart);
|
|
1428
1430
|
resolvedCartRef.current = resolvedCart;
|
|
1429
1431
|
const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
|
|
1430
1432
|
const isDark = appearance?.theme === "dark";
|
|
1431
|
-
const emitStatus =
|
|
1433
|
+
const emitStatus = React10__default.default.useEffectEvent(
|
|
1432
1434
|
(nextStatus, context = {}) => {
|
|
1433
1435
|
setStatus(nextStatus);
|
|
1434
1436
|
setStatusText(context.display_text || "");
|
|
1435
1437
|
onStatusChange?.(nextStatus, context);
|
|
1436
1438
|
}
|
|
1437
1439
|
);
|
|
1438
|
-
const fireError =
|
|
1440
|
+
const fireError = React10__default.default.useEffectEvent(
|
|
1439
1441
|
(error) => {
|
|
1440
1442
|
onError?.(error);
|
|
1441
1443
|
}
|
|
1442
1444
|
);
|
|
1443
|
-
|
|
1445
|
+
React10.useEffect(() => {
|
|
1444
1446
|
if (!resolvedOrderTypes.includes(orderType)) {
|
|
1445
1447
|
setOrderType(resolvedDefaultOrderType);
|
|
1446
1448
|
}
|
|
1447
1449
|
}, [resolvedOrderTypes, resolvedDefaultOrderType, orderType]);
|
|
1448
|
-
|
|
1450
|
+
React10.useEffect(() => {
|
|
1449
1451
|
if (appearance && appearance !== initialAppearanceRef.current && !hasWarnedInlineAppearanceRef.current) {
|
|
1450
1452
|
hasWarnedInlineAppearanceRef.current = true;
|
|
1451
1453
|
console.warn(
|
|
@@ -1453,7 +1455,7 @@ function CimplifyCheckout({
|
|
|
1453
1455
|
);
|
|
1454
1456
|
}
|
|
1455
1457
|
}, [appearance]);
|
|
1456
|
-
|
|
1458
|
+
React10.useEffect(() => {
|
|
1457
1459
|
let cancelled = false;
|
|
1458
1460
|
async function bootstrap() {
|
|
1459
1461
|
if (isDemoCheckout) {
|
|
@@ -1533,7 +1535,7 @@ function CimplifyCheckout({
|
|
|
1533
1535
|
cancelled = true;
|
|
1534
1536
|
};
|
|
1535
1537
|
}, [businessId, cartId, client, isDemoCheckout]);
|
|
1536
|
-
|
|
1538
|
+
React10.useEffect(() => {
|
|
1537
1539
|
return () => {
|
|
1538
1540
|
isMountedRef.current = false;
|
|
1539
1541
|
demoRunRef.current += 1;
|
|
@@ -1541,7 +1543,7 @@ function CimplifyCheckout({
|
|
|
1541
1543
|
activeCheckoutRef.current = null;
|
|
1542
1544
|
};
|
|
1543
1545
|
}, []);
|
|
1544
|
-
const handleSubmit =
|
|
1546
|
+
const handleSubmit = React10__default.default.useEffectEvent(async () => {
|
|
1545
1547
|
if (isSubmitting || isInitializing || !resolvedCartId) {
|
|
1546
1548
|
if (!resolvedCartId && !isInitializing) {
|
|
1547
1549
|
const message = "Your cart is empty. Add items before checkout.";
|
|
@@ -1622,7 +1624,7 @@ function CimplifyCheckout({
|
|
|
1622
1624
|
}
|
|
1623
1625
|
}
|
|
1624
1626
|
});
|
|
1625
|
-
|
|
1627
|
+
React10.useEffect(() => {
|
|
1626
1628
|
if (isDemoCheckout || !resolvedBusinessId) {
|
|
1627
1629
|
elementsRef.current = null;
|
|
1628
1630
|
return;
|
|
@@ -1669,7 +1671,7 @@ function CimplifyCheckout({
|
|
|
1669
1671
|
resolvedDefaultOrderType,
|
|
1670
1672
|
submitLabel
|
|
1671
1673
|
]);
|
|
1672
|
-
|
|
1674
|
+
React10.useEffect(() => {
|
|
1673
1675
|
if (!resolvedCart || !elementsRef.current) return;
|
|
1674
1676
|
const checkoutElement = elementsRef.current.getElement("checkout");
|
|
1675
1677
|
if (checkoutElement) {
|
|
@@ -1717,10 +1719,10 @@ function CimplifyAccount({
|
|
|
1717
1719
|
const context = useOptionalCimplify();
|
|
1718
1720
|
const client = clientProp ?? context?.client;
|
|
1719
1721
|
const resolvedLinkUrl = linkUrl || DEFAULT_LINK_URL;
|
|
1720
|
-
const iframeRef =
|
|
1721
|
-
const [height, setHeight] =
|
|
1722
|
-
const [isReady, setIsReady] =
|
|
1723
|
-
const iframeSrc =
|
|
1722
|
+
const iframeRef = React10.useRef(null);
|
|
1723
|
+
const [height, setHeight] = React10.useState(400);
|
|
1724
|
+
const [isReady, setIsReady] = React10.useState(false);
|
|
1725
|
+
const iframeSrc = React10.useMemo(() => {
|
|
1724
1726
|
const path = section ? `/elements/account/${section}` : "/elements/account";
|
|
1725
1727
|
const url = new URL(path, resolvedLinkUrl);
|
|
1726
1728
|
if (client) {
|
|
@@ -1729,7 +1731,7 @@ function CimplifyAccount({
|
|
|
1729
1731
|
}
|
|
1730
1732
|
return url.toString();
|
|
1731
1733
|
}, [resolvedLinkUrl, section, client]);
|
|
1732
|
-
|
|
1734
|
+
React10.useEffect(() => {
|
|
1733
1735
|
function handleMessage(event) {
|
|
1734
1736
|
if (!event.data || typeof event.data !== "object") return;
|
|
1735
1737
|
if (iframeRef.current?.contentWindow && event.source !== iframeRef.current.contentWindow) {
|
|
@@ -1831,9 +1833,9 @@ function createCachedQuery(config) {
|
|
|
1831
1833
|
}
|
|
1832
1834
|
const enabled = options.enabled ?? true;
|
|
1833
1835
|
const locationId = client.getLocationId();
|
|
1834
|
-
const previousLocationRef =
|
|
1835
|
-
const requestIdRef =
|
|
1836
|
-
const optionsRef =
|
|
1836
|
+
const previousLocationRef = React10.useRef(locationId);
|
|
1837
|
+
const requestIdRef = React10.useRef(0);
|
|
1838
|
+
const optionsRef = React10.useRef(options);
|
|
1837
1839
|
optionsRef.current = options;
|
|
1838
1840
|
if (config.locationSensitive && previousLocationRef.current !== locationId) {
|
|
1839
1841
|
cache.clear();
|
|
@@ -1843,10 +1845,10 @@ function createCachedQuery(config) {
|
|
|
1843
1845
|
sweep();
|
|
1844
1846
|
const cacheKey2 = config.key(client, options);
|
|
1845
1847
|
const cached = cache.get(cacheKey2);
|
|
1846
|
-
const [data, setData] =
|
|
1847
|
-
const [isLoading, setIsLoading] =
|
|
1848
|
-
const [error, setError] =
|
|
1849
|
-
const load =
|
|
1848
|
+
const [data, setData] = React10.useState(cached?.data ?? null);
|
|
1849
|
+
const [isLoading, setIsLoading] = React10.useState(enabled && !cached);
|
|
1850
|
+
const [error, setError] = React10.useState(null);
|
|
1851
|
+
const load = React10.useCallback(
|
|
1850
1852
|
async (force = false) => {
|
|
1851
1853
|
if (!enabled) {
|
|
1852
1854
|
setIsLoading(false);
|
|
@@ -1889,10 +1891,10 @@ function createCachedQuery(config) {
|
|
|
1889
1891
|
},
|
|
1890
1892
|
[cacheKey2, client, enabled]
|
|
1891
1893
|
);
|
|
1892
|
-
|
|
1894
|
+
React10.useEffect(() => {
|
|
1893
1895
|
void load(false);
|
|
1894
1896
|
}, [load]);
|
|
1895
|
-
const refetch =
|
|
1897
|
+
const refetch = React10.useCallback(async () => {
|
|
1896
1898
|
cache.delete(cacheKey2);
|
|
1897
1899
|
await load(true);
|
|
1898
1900
|
}, [cacheKey2, load]);
|
|
@@ -2022,25 +2024,25 @@ function useOrder(orderId, options = {}) {
|
|
|
2022
2024
|
if (!client) {
|
|
2023
2025
|
throw new Error("useOrder must be used within CimplifyProvider or passed { client }.");
|
|
2024
2026
|
}
|
|
2025
|
-
const normalizedOrderId =
|
|
2027
|
+
const normalizedOrderId = React10.useMemo(() => (orderId || "").trim(), [orderId]);
|
|
2026
2028
|
const enabled = options.enabled ?? true;
|
|
2027
2029
|
const poll = options.poll ?? false;
|
|
2028
2030
|
const pollInterval = options.pollInterval ?? 5e3;
|
|
2029
|
-
const requestIdRef =
|
|
2030
|
-
const previousStatusRef =
|
|
2031
|
-
const onStatusChangeRef =
|
|
2031
|
+
const requestIdRef = React10.useRef(0);
|
|
2032
|
+
const previousStatusRef = React10.useRef(null);
|
|
2033
|
+
const onStatusChangeRef = React10.useRef(options.onStatusChange);
|
|
2032
2034
|
onStatusChangeRef.current = options.onStatusChange;
|
|
2033
|
-
const cacheKey2 =
|
|
2035
|
+
const cacheKey2 = React10.useMemo(
|
|
2034
2036
|
() => buildOrderCacheKey(client, normalizedOrderId),
|
|
2035
2037
|
[client, normalizedOrderId]
|
|
2036
2038
|
);
|
|
2037
2039
|
const cached = orderCache.get(cacheKey2);
|
|
2038
|
-
const [order, setOrder] =
|
|
2039
|
-
const [isLoading, setIsLoading] =
|
|
2040
|
+
const [order, setOrder] = React10.useState(cached?.order ?? null);
|
|
2041
|
+
const [isLoading, setIsLoading] = React10.useState(
|
|
2040
2042
|
enabled && normalizedOrderId.length > 0 && !cached
|
|
2041
2043
|
);
|
|
2042
|
-
const [error, setError] =
|
|
2043
|
-
const load =
|
|
2044
|
+
const [error, setError] = React10.useState(null);
|
|
2045
|
+
const load = React10.useCallback(
|
|
2044
2046
|
async (force = false) => {
|
|
2045
2047
|
if (!enabled || normalizedOrderId.length === 0) {
|
|
2046
2048
|
setOrder(null);
|
|
@@ -2099,11 +2101,11 @@ function useOrder(orderId, options = {}) {
|
|
|
2099
2101
|
},
|
|
2100
2102
|
[cacheKey2, client, enabled, normalizedOrderId]
|
|
2101
2103
|
);
|
|
2102
|
-
|
|
2104
|
+
React10.useEffect(() => {
|
|
2103
2105
|
void load(false);
|
|
2104
2106
|
}, [load]);
|
|
2105
2107
|
const isTerminal = order ? TERMINAL_STATUSES.has(order.status) : false;
|
|
2106
|
-
|
|
2108
|
+
React10.useEffect(() => {
|
|
2107
2109
|
if (!poll || !enabled || normalizedOrderId.length === 0 || isTerminal) {
|
|
2108
2110
|
return;
|
|
2109
2111
|
}
|
|
@@ -2114,7 +2116,7 @@ function useOrder(orderId, options = {}) {
|
|
|
2114
2116
|
window.clearInterval(timer);
|
|
2115
2117
|
};
|
|
2116
2118
|
}, [enabled, isTerminal, load, normalizedOrderId, poll, pollInterval]);
|
|
2117
|
-
const refetch =
|
|
2119
|
+
const refetch = React10.useCallback(async () => {
|
|
2118
2120
|
orderCache.delete(cacheKey2);
|
|
2119
2121
|
await load(true);
|
|
2120
2122
|
}, [cacheKey2, load]);
|
|
@@ -2165,10 +2167,10 @@ function useLocations(options = {}) {
|
|
|
2165
2167
|
};
|
|
2166
2168
|
}
|
|
2167
2169
|
const client = options.client;
|
|
2168
|
-
const [locations, setLocations] =
|
|
2169
|
-
const [currentLocation, setCurrentLocationState] =
|
|
2170
|
-
const [isLoading, setIsLoading] =
|
|
2171
|
-
const setCurrentLocation =
|
|
2170
|
+
const [locations, setLocations] = React10.useState([]);
|
|
2171
|
+
const [currentLocation, setCurrentLocationState] = React10.useState(null);
|
|
2172
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
2173
|
+
const setCurrentLocation = React10.useCallback(
|
|
2172
2174
|
(location) => {
|
|
2173
2175
|
setCurrentLocationState(location);
|
|
2174
2176
|
if (client) {
|
|
@@ -2178,7 +2180,7 @@ function useLocations(options = {}) {
|
|
|
2178
2180
|
},
|
|
2179
2181
|
[client]
|
|
2180
2182
|
);
|
|
2181
|
-
|
|
2183
|
+
React10.useEffect(() => {
|
|
2182
2184
|
if (!client) {
|
|
2183
2185
|
setLocations([]);
|
|
2184
2186
|
setCurrentLocationState(null);
|
|
@@ -2282,14 +2284,14 @@ function useSearch(options = {}) {
|
|
|
2282
2284
|
const minLength = Math.max(0, options.minLength ?? 2);
|
|
2283
2285
|
const debounceMs = Math.max(0, options.debounceMs ?? 300);
|
|
2284
2286
|
const limit = Math.max(1, options.limit ?? 20);
|
|
2285
|
-
const [query, setQueryState] =
|
|
2286
|
-
const [results, setResults] =
|
|
2287
|
-
const [isLoading, setIsLoading] =
|
|
2288
|
-
const [error, setError] =
|
|
2289
|
-
const requestIdRef =
|
|
2290
|
-
const timerRef =
|
|
2287
|
+
const [query, setQueryState] = React10.useState("");
|
|
2288
|
+
const [results, setResults] = React10.useState([]);
|
|
2289
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
2290
|
+
const [error, setError] = React10.useState(null);
|
|
2291
|
+
const requestIdRef = React10.useRef(0);
|
|
2292
|
+
const timerRef = React10.useRef(null);
|
|
2291
2293
|
const tagsSignature = options.tags?.join(",") ?? "";
|
|
2292
|
-
|
|
2294
|
+
React10.useEffect(() => {
|
|
2293
2295
|
if (timerRef.current) {
|
|
2294
2296
|
clearTimeout(timerRef.current);
|
|
2295
2297
|
timerRef.current = null;
|
|
@@ -2344,10 +2346,10 @@ function useSearch(options = {}) {
|
|
|
2344
2346
|
}
|
|
2345
2347
|
};
|
|
2346
2348
|
}, [client, debounceMs, limit, minLength, options.category, options.taxonomy, tagsSignature, options.featured, options.in_stock, options.min_price, options.max_price, options.sort_by, options.sort_order, query]);
|
|
2347
|
-
const setQuery =
|
|
2349
|
+
const setQuery = React10.useCallback((nextQuery) => {
|
|
2348
2350
|
setQueryState(nextQuery);
|
|
2349
2351
|
}, []);
|
|
2350
|
-
const clear =
|
|
2352
|
+
const clear = React10.useCallback(() => {
|
|
2351
2353
|
requestIdRef.current += 1;
|
|
2352
2354
|
if (timerRef.current) {
|
|
2353
2355
|
clearTimeout(timerRef.current);
|
|
@@ -2438,34 +2440,34 @@ function useQuote(input, options = {}) {
|
|
|
2438
2440
|
const autoRefresh = options.autoRefresh ?? true;
|
|
2439
2441
|
const refreshBeforeExpiryMs = Math.max(0, options.refreshBeforeExpiryMs ?? 3e4);
|
|
2440
2442
|
const locationId = client.getLocationId();
|
|
2441
|
-
const requestIdRef =
|
|
2442
|
-
const debounceTimerRef =
|
|
2443
|
+
const requestIdRef = React10.useRef(0);
|
|
2444
|
+
const debounceTimerRef = React10.useRef(null);
|
|
2443
2445
|
const inputSignature = buildQuoteInputSignature(input);
|
|
2444
|
-
const normalizedInput =
|
|
2446
|
+
const normalizedInput = React10.useMemo(() => {
|
|
2445
2447
|
if (!input) {
|
|
2446
2448
|
return null;
|
|
2447
2449
|
}
|
|
2448
2450
|
const normalized = normalizeInput(input, locationId);
|
|
2449
2451
|
return normalized.product_id.length > 0 ? normalized : null;
|
|
2450
2452
|
}, [inputSignature, locationId]);
|
|
2451
|
-
const cacheKey2 =
|
|
2453
|
+
const cacheKey2 = React10.useMemo(
|
|
2452
2454
|
() => buildQuoteCacheKey(client, locationId, inputSignature),
|
|
2453
2455
|
[client, inputSignature, locationId]
|
|
2454
2456
|
);
|
|
2455
2457
|
const cached = quoteCache.get(cacheKey2);
|
|
2456
|
-
const [quote, setQuote] =
|
|
2457
|
-
const [isLoading, setIsLoading] =
|
|
2458
|
-
const [error, setError] =
|
|
2459
|
-
const [isExpired, setIsExpired] =
|
|
2460
|
-
const [messages, setMessages] =
|
|
2461
|
-
const quoteExpiryTimestamp =
|
|
2458
|
+
const [quote, setQuote] = React10.useState(cached?.quote ?? null);
|
|
2459
|
+
const [isLoading, setIsLoading] = React10.useState(enabled && normalizedInput !== null && !cached);
|
|
2460
|
+
const [error, setError] = React10.useState(null);
|
|
2461
|
+
const [isExpired, setIsExpired] = React10.useState(isQuoteExpired(cached?.quote ?? null));
|
|
2462
|
+
const [messages, setMessages] = React10.useState(cached?.quote?.ui_messages ?? []);
|
|
2463
|
+
const quoteExpiryTimestamp = React10.useMemo(() => {
|
|
2462
2464
|
if (!quote?.expires_at) {
|
|
2463
2465
|
return Number.NaN;
|
|
2464
2466
|
}
|
|
2465
2467
|
const expiresAt = Date.parse(quote.expires_at);
|
|
2466
2468
|
return Number.isFinite(expiresAt) ? expiresAt : Number.NaN;
|
|
2467
2469
|
}, [quote?.expires_at]);
|
|
2468
|
-
const load =
|
|
2470
|
+
const load = React10.useCallback(
|
|
2469
2471
|
async (force = false) => {
|
|
2470
2472
|
if (!enabled || !normalizedInput) {
|
|
2471
2473
|
setQuote(null);
|
|
@@ -2525,7 +2527,7 @@ function useQuote(input, options = {}) {
|
|
|
2525
2527
|
},
|
|
2526
2528
|
[cacheKey2, client, enabled, normalizedInput]
|
|
2527
2529
|
);
|
|
2528
|
-
|
|
2530
|
+
React10.useEffect(() => {
|
|
2529
2531
|
if (debounceTimerRef.current) {
|
|
2530
2532
|
clearTimeout(debounceTimerRef.current);
|
|
2531
2533
|
}
|
|
@@ -2544,7 +2546,7 @@ function useQuote(input, options = {}) {
|
|
|
2544
2546
|
}
|
|
2545
2547
|
};
|
|
2546
2548
|
}, [load, cacheKey2, enabled, normalizedInput]);
|
|
2547
|
-
const refresh =
|
|
2549
|
+
const refresh = React10.useCallback(async () => {
|
|
2548
2550
|
if (!enabled || !normalizedInput) {
|
|
2549
2551
|
return;
|
|
2550
2552
|
}
|
|
@@ -2581,7 +2583,7 @@ function useQuote(input, options = {}) {
|
|
|
2581
2583
|
}
|
|
2582
2584
|
}
|
|
2583
2585
|
}, [cacheKey2, client, enabled, load, normalizedInput, quote]);
|
|
2584
|
-
|
|
2586
|
+
React10.useEffect(() => {
|
|
2585
2587
|
if (!Number.isFinite(quoteExpiryTimestamp)) {
|
|
2586
2588
|
setIsExpired(false);
|
|
2587
2589
|
return;
|
|
@@ -2757,9 +2759,9 @@ function useValidateDiscount(options = {}) {
|
|
|
2757
2759
|
if (!client) {
|
|
2758
2760
|
throw new Error("useValidateDiscount must be used within CimplifyProvider or passed { client }.");
|
|
2759
2761
|
}
|
|
2760
|
-
const [isValidating, setIsValidating] =
|
|
2761
|
-
const [error, setError] =
|
|
2762
|
-
const validate =
|
|
2762
|
+
const [isValidating, setIsValidating] = React10.useState(false);
|
|
2763
|
+
const [error, setError] = React10.useState(null);
|
|
2764
|
+
const validate = React10.useCallback(
|
|
2763
2765
|
async (code, orderSubtotal, locationId) => {
|
|
2764
2766
|
setError(null);
|
|
2765
2767
|
setIsValidating(true);
|
|
@@ -2806,7 +2808,7 @@ function useProductPrice(input) {
|
|
|
2806
2808
|
compositePrice,
|
|
2807
2809
|
bundleTotalPrice
|
|
2808
2810
|
} = input;
|
|
2809
|
-
return
|
|
2811
|
+
return React10.useMemo(() => {
|
|
2810
2812
|
let unitPrice;
|
|
2811
2813
|
if (bundleTotalPrice != null) {
|
|
2812
2814
|
unitPrice = bundleTotalPrice;
|
|
@@ -2852,6 +2854,84 @@ function useOrders(options = {}) {
|
|
|
2852
2854
|
const { data, isLoading, error, refetch } = ordersQuery(options);
|
|
2853
2855
|
return { orders: data ?? [], isLoading, error, refetch };
|
|
2854
2856
|
}
|
|
2857
|
+
function useSubscriptions(options = {}) {
|
|
2858
|
+
const { client } = useCimplifyClient();
|
|
2859
|
+
const { status, enabled = true } = options;
|
|
2860
|
+
const [subscriptions, setSubscriptions] = React10.useState([]);
|
|
2861
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
2862
|
+
const [error, setError] = React10.useState(null);
|
|
2863
|
+
const fetch2 = React10.useCallback(async () => {
|
|
2864
|
+
if (!enabled) return;
|
|
2865
|
+
setIsLoading(true);
|
|
2866
|
+
setError(null);
|
|
2867
|
+
try {
|
|
2868
|
+
const result = await client.subscriptions.list();
|
|
2869
|
+
if (result.ok) {
|
|
2870
|
+
const filtered = status ? result.value.filter((s) => s.status === status) : result.value;
|
|
2871
|
+
setSubscriptions(filtered);
|
|
2872
|
+
} else {
|
|
2873
|
+
setError(result.error);
|
|
2874
|
+
}
|
|
2875
|
+
} catch (e) {
|
|
2876
|
+
setError(e);
|
|
2877
|
+
} finally {
|
|
2878
|
+
setIsLoading(false);
|
|
2879
|
+
}
|
|
2880
|
+
}, [client, enabled, status]);
|
|
2881
|
+
React10.useEffect(() => {
|
|
2882
|
+
void fetch2();
|
|
2883
|
+
}, [fetch2]);
|
|
2884
|
+
return { subscriptions, isLoading, error, refetch: fetch2 };
|
|
2885
|
+
}
|
|
2886
|
+
function useSubscription(id, options = {}) {
|
|
2887
|
+
const { client } = useCimplifyClient();
|
|
2888
|
+
const { enabled = true } = options;
|
|
2889
|
+
const normalizedId = (id || "").trim();
|
|
2890
|
+
const [subscription, setSubscription] = React10.useState(null);
|
|
2891
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
2892
|
+
const [error, setError] = React10.useState(null);
|
|
2893
|
+
const fetch2 = React10.useCallback(async () => {
|
|
2894
|
+
if (!enabled || !normalizedId) return;
|
|
2895
|
+
setIsLoading(true);
|
|
2896
|
+
setError(null);
|
|
2897
|
+
try {
|
|
2898
|
+
const result = await client.subscriptions.get(normalizedId);
|
|
2899
|
+
if (result.ok) {
|
|
2900
|
+
setSubscription(result.value);
|
|
2901
|
+
} else {
|
|
2902
|
+
setError(result.error);
|
|
2903
|
+
}
|
|
2904
|
+
} catch (e) {
|
|
2905
|
+
setError(e);
|
|
2906
|
+
} finally {
|
|
2907
|
+
setIsLoading(false);
|
|
2908
|
+
}
|
|
2909
|
+
}, [client, enabled, normalizedId]);
|
|
2910
|
+
React10.useEffect(() => {
|
|
2911
|
+
void fetch2();
|
|
2912
|
+
}, [fetch2]);
|
|
2913
|
+
const cancel = React10.useCallback(async (reason) => {
|
|
2914
|
+
if (!normalizedId) return;
|
|
2915
|
+
await client.subscriptions.cancel(normalizedId, reason);
|
|
2916
|
+
void fetch2();
|
|
2917
|
+
}, [client, normalizedId, fetch2]);
|
|
2918
|
+
const pause = React10.useCallback(async () => {
|
|
2919
|
+
if (!normalizedId) return;
|
|
2920
|
+
await client.subscriptions.pause(normalizedId);
|
|
2921
|
+
void fetch2();
|
|
2922
|
+
}, [client, normalizedId, fetch2]);
|
|
2923
|
+
const resume = React10.useCallback(async () => {
|
|
2924
|
+
if (!normalizedId) return;
|
|
2925
|
+
await client.subscriptions.resume(normalizedId);
|
|
2926
|
+
void fetch2();
|
|
2927
|
+
}, [client, normalizedId, fetch2]);
|
|
2928
|
+
const skipNext = React10.useCallback(async () => {
|
|
2929
|
+
if (!normalizedId) return;
|
|
2930
|
+
await client.subscriptions.skipNextRenewal(normalizedId);
|
|
2931
|
+
void fetch2();
|
|
2932
|
+
}, [client, normalizedId, fetch2]);
|
|
2933
|
+
return { subscription, isLoading, error, cancel, pause, resume, skipNext, refetch: fetch2 };
|
|
2934
|
+
}
|
|
2855
2935
|
|
|
2856
2936
|
// src/react/hooks/use-services.ts
|
|
2857
2937
|
var servicesQuery = createCachedQuery({
|
|
@@ -2949,7 +3029,7 @@ function useBookings(options = {}) {
|
|
|
2949
3029
|
const context = useOptionalCimplifyClient();
|
|
2950
3030
|
const client = options.client ?? context?.client;
|
|
2951
3031
|
const { data, isLoading, error, refetch } = bookingsQuery(options);
|
|
2952
|
-
const cancelBooking =
|
|
3032
|
+
const cancelBooking = React10.useCallback(
|
|
2953
3033
|
async (bookingId, reason) => {
|
|
2954
3034
|
if (!client) throw new Error("useBookings must be used within CimplifyProvider or passed { client }.");
|
|
2955
3035
|
const result = await client.scheduling.cancelBooking({
|
|
@@ -3005,14 +3085,14 @@ function useBillingPlans(productId, options = {}) {
|
|
|
3005
3085
|
throw new Error("useBillingPlans must be used within CimplifyProvider or passed { client }.");
|
|
3006
3086
|
}
|
|
3007
3087
|
const enabled = options.enabled ?? true;
|
|
3008
|
-
const requestIdRef =
|
|
3009
|
-
const [plans, setPlans] =
|
|
3010
|
-
const [isLoading, setIsLoading] =
|
|
3011
|
-
const [error, setError] =
|
|
3088
|
+
const requestIdRef = React10.useRef(0);
|
|
3089
|
+
const [plans, setPlans] = React10.useState([]);
|
|
3090
|
+
const [isLoading, setIsLoading] = React10.useState(enabled && !!productId);
|
|
3091
|
+
const [error, setError] = React10.useState(null);
|
|
3012
3092
|
const customerId = options.customerId;
|
|
3013
3093
|
const quantity = options.quantity;
|
|
3014
3094
|
const orderValue = options.orderValue;
|
|
3015
|
-
const load =
|
|
3095
|
+
const load = React10.useCallback(
|
|
3016
3096
|
async (force = false) => {
|
|
3017
3097
|
if (!enabled || !productId) {
|
|
3018
3098
|
setPlans([]);
|
|
@@ -3047,17 +3127,17 @@ function useBillingPlans(productId, options = {}) {
|
|
|
3047
3127
|
},
|
|
3048
3128
|
[client, enabled, productId, customerId, quantity, orderValue]
|
|
3049
3129
|
);
|
|
3050
|
-
|
|
3130
|
+
React10.useEffect(() => {
|
|
3051
3131
|
void load(false);
|
|
3052
3132
|
}, [load]);
|
|
3053
|
-
const refetch =
|
|
3133
|
+
const refetch = React10.useCallback(async () => {
|
|
3054
3134
|
await load(true);
|
|
3055
3135
|
}, [load]);
|
|
3056
|
-
const subscriptionPlans =
|
|
3136
|
+
const subscriptionPlans = React10.useMemo(
|
|
3057
3137
|
() => plans.filter((p) => p.plan_type === "subscription"),
|
|
3058
3138
|
[plans]
|
|
3059
3139
|
);
|
|
3060
|
-
const installmentPlans =
|
|
3140
|
+
const installmentPlans = React10.useMemo(
|
|
3061
3141
|
() => plans.filter((p) => p.plan_type === "installment"),
|
|
3062
3142
|
[plans]
|
|
3063
3143
|
);
|
|
@@ -3092,8 +3172,8 @@ function computeAvailableValues(variants, axes, selections) {
|
|
|
3092
3172
|
}
|
|
3093
3173
|
function useVariantSelector(options) {
|
|
3094
3174
|
const { variants, axes } = options;
|
|
3095
|
-
const [selectedValues, setSelectedValues] =
|
|
3096
|
-
const selectValue =
|
|
3175
|
+
const [selectedValues, setSelectedValues] = React10.useState({});
|
|
3176
|
+
const selectValue = React10.useCallback(
|
|
3097
3177
|
(axisId, valueId) => {
|
|
3098
3178
|
setSelectedValues((prev) => {
|
|
3099
3179
|
if (prev[axisId] === valueId) {
|
|
@@ -3106,16 +3186,16 @@ function useVariantSelector(options) {
|
|
|
3106
3186
|
},
|
|
3107
3187
|
[]
|
|
3108
3188
|
);
|
|
3109
|
-
const reset =
|
|
3110
|
-
const selectedVariant =
|
|
3189
|
+
const reset = React10.useCallback(() => setSelectedValues({}), []);
|
|
3190
|
+
const selectedVariant = React10.useMemo(
|
|
3111
3191
|
() => findMatchingVariant(variants, selectedValues),
|
|
3112
3192
|
[variants, selectedValues]
|
|
3113
3193
|
);
|
|
3114
|
-
const variantImage =
|
|
3194
|
+
const variantImage = React10.useMemo(
|
|
3115
3195
|
() => selectedVariant?.images?.[0] ?? null,
|
|
3116
3196
|
[selectedVariant]
|
|
3117
3197
|
);
|
|
3118
|
-
const availableValues =
|
|
3198
|
+
const availableValues = React10.useMemo(
|
|
3119
3199
|
() => computeAvailableValues(variants, axes, selectedValues),
|
|
3120
3200
|
[variants, axes, selectedValues]
|
|
3121
3201
|
);
|
|
@@ -3141,7 +3221,7 @@ function useActivityState(options = {}) {
|
|
|
3141
3221
|
const context = useOptionalCimplifyClient();
|
|
3142
3222
|
const client = options.client ?? context?.client;
|
|
3143
3223
|
const { data, isLoading, error, refetch } = activityStateQuery(options);
|
|
3144
|
-
const dismissMessage =
|
|
3224
|
+
const dismissMessage = React10.useCallback(
|
|
3145
3225
|
async (code) => {
|
|
3146
3226
|
if (!client) return;
|
|
3147
3227
|
const result = await client.activity.dismissMessage(code);
|
|
@@ -3235,15 +3315,15 @@ function useBootstrap(options = {}) {
|
|
|
3235
3315
|
const { data, isLoading, error, refetch } = bootstrapQuery(options);
|
|
3236
3316
|
return { bootstrap: data, isLoading, error, refetch };
|
|
3237
3317
|
}
|
|
3238
|
-
var ElementsContext =
|
|
3318
|
+
var ElementsContext = React10.createContext({
|
|
3239
3319
|
elements: null,
|
|
3240
3320
|
isReady: false
|
|
3241
3321
|
});
|
|
3242
3322
|
function useElements() {
|
|
3243
|
-
return
|
|
3323
|
+
return React10.useContext(ElementsContext).elements;
|
|
3244
3324
|
}
|
|
3245
3325
|
function useElementsReady() {
|
|
3246
|
-
return
|
|
3326
|
+
return React10.useContext(ElementsContext).isReady;
|
|
3247
3327
|
}
|
|
3248
3328
|
function ElementsProvider({
|
|
3249
3329
|
client,
|
|
@@ -3251,10 +3331,10 @@ function ElementsProvider({
|
|
|
3251
3331
|
options,
|
|
3252
3332
|
children
|
|
3253
3333
|
}) {
|
|
3254
|
-
const [elements, setElements] =
|
|
3255
|
-
const [isReady, setIsReady] =
|
|
3256
|
-
const initialOptionsRef =
|
|
3257
|
-
|
|
3334
|
+
const [elements, setElements] = React10.useState(null);
|
|
3335
|
+
const [isReady, setIsReady] = React10.useState(false);
|
|
3336
|
+
const initialOptionsRef = React10.useRef(options);
|
|
3337
|
+
React10.useEffect(() => {
|
|
3258
3338
|
let cancelled = false;
|
|
3259
3339
|
let instance = null;
|
|
3260
3340
|
setIsReady(false);
|
|
@@ -3295,20 +3375,20 @@ function AuthElement({
|
|
|
3295
3375
|
onRequiresOtp,
|
|
3296
3376
|
onError
|
|
3297
3377
|
}) {
|
|
3298
|
-
const containerRef =
|
|
3299
|
-
const elementRef =
|
|
3378
|
+
const containerRef = React10.useRef(null);
|
|
3379
|
+
const elementRef = React10.useRef(null);
|
|
3300
3380
|
const elements = useElements();
|
|
3301
|
-
const onReadyRef =
|
|
3302
|
-
const onAuthenticatedRef =
|
|
3303
|
-
const onRequiresOtpRef =
|
|
3304
|
-
const onErrorRef =
|
|
3305
|
-
|
|
3381
|
+
const onReadyRef = React10.useRef(onReady);
|
|
3382
|
+
const onAuthenticatedRef = React10.useRef(onAuthenticated);
|
|
3383
|
+
const onRequiresOtpRef = React10.useRef(onRequiresOtp);
|
|
3384
|
+
const onErrorRef = React10.useRef(onError);
|
|
3385
|
+
React10.useEffect(() => {
|
|
3306
3386
|
onReadyRef.current = onReady;
|
|
3307
3387
|
onAuthenticatedRef.current = onAuthenticated;
|
|
3308
3388
|
onRequiresOtpRef.current = onRequiresOtp;
|
|
3309
3389
|
onErrorRef.current = onError;
|
|
3310
3390
|
}, [onReady, onAuthenticated, onRequiresOtp, onError]);
|
|
3311
|
-
|
|
3391
|
+
React10.useEffect(() => {
|
|
3312
3392
|
if (!elements || !containerRef.current) return;
|
|
3313
3393
|
const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.AUTH, { prefillEmail });
|
|
3314
3394
|
elementRef.current = element;
|
|
@@ -3338,18 +3418,18 @@ function AddressElement({
|
|
|
3338
3418
|
onChange,
|
|
3339
3419
|
onError
|
|
3340
3420
|
}) {
|
|
3341
|
-
const containerRef =
|
|
3342
|
-
const elementRef =
|
|
3421
|
+
const containerRef = React10.useRef(null);
|
|
3422
|
+
const elementRef = React10.useRef(null);
|
|
3343
3423
|
const elements = useElements();
|
|
3344
|
-
const onReadyRef =
|
|
3345
|
-
const onChangeRef =
|
|
3346
|
-
const onErrorRef =
|
|
3347
|
-
|
|
3424
|
+
const onReadyRef = React10.useRef(onReady);
|
|
3425
|
+
const onChangeRef = React10.useRef(onChange);
|
|
3426
|
+
const onErrorRef = React10.useRef(onError);
|
|
3427
|
+
React10.useEffect(() => {
|
|
3348
3428
|
onReadyRef.current = onReady;
|
|
3349
3429
|
onChangeRef.current = onChange;
|
|
3350
3430
|
onErrorRef.current = onError;
|
|
3351
3431
|
}, [onReady, onChange, onError]);
|
|
3352
|
-
|
|
3432
|
+
React10.useEffect(() => {
|
|
3353
3433
|
if (!elements || !containerRef.current) return;
|
|
3354
3434
|
const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.ADDRESS, { mode });
|
|
3355
3435
|
elementRef.current = element;
|
|
@@ -3376,18 +3456,18 @@ function PaymentElement({
|
|
|
3376
3456
|
onChange,
|
|
3377
3457
|
onError
|
|
3378
3458
|
}) {
|
|
3379
|
-
const containerRef =
|
|
3380
|
-
const elementRef =
|
|
3459
|
+
const containerRef = React10.useRef(null);
|
|
3460
|
+
const elementRef = React10.useRef(null);
|
|
3381
3461
|
const elements = useElements();
|
|
3382
|
-
const onReadyRef =
|
|
3383
|
-
const onChangeRef =
|
|
3384
|
-
const onErrorRef =
|
|
3385
|
-
|
|
3462
|
+
const onReadyRef = React10.useRef(onReady);
|
|
3463
|
+
const onChangeRef = React10.useRef(onChange);
|
|
3464
|
+
const onErrorRef = React10.useRef(onError);
|
|
3465
|
+
React10.useEffect(() => {
|
|
3386
3466
|
onReadyRef.current = onReady;
|
|
3387
3467
|
onChangeRef.current = onChange;
|
|
3388
3468
|
onErrorRef.current = onError;
|
|
3389
3469
|
}, [onReady, onChange, onError]);
|
|
3390
|
-
|
|
3470
|
+
React10.useEffect(() => {
|
|
3391
3471
|
if (!elements || !containerRef.current) return;
|
|
3392
3472
|
const element = elements.create(chunk2CGA3MUW_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
|
|
3393
3473
|
elementRef.current = element;
|
|
@@ -3407,8 +3487,8 @@ function PaymentElement({
|
|
|
3407
3487
|
}
|
|
3408
3488
|
function useCheckout() {
|
|
3409
3489
|
const elements = useElements();
|
|
3410
|
-
const [isLoading, setIsLoading] =
|
|
3411
|
-
const submit =
|
|
3490
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
3491
|
+
const submit = React10.useCallback(
|
|
3412
3492
|
async (data) => {
|
|
3413
3493
|
if (!elements) {
|
|
3414
3494
|
return { success: false, error: { code: "NO_ELEMENTS", message: "Elements not initialized" } };
|
|
@@ -3422,7 +3502,7 @@ function useCheckout() {
|
|
|
3422
3502
|
},
|
|
3423
3503
|
[elements]
|
|
3424
3504
|
);
|
|
3425
|
-
const process =
|
|
3505
|
+
const process = React10.useCallback(
|
|
3426
3506
|
async (options) => {
|
|
3427
3507
|
if (!elements) {
|
|
3428
3508
|
return {
|
|
@@ -3516,13 +3596,13 @@ function VariantSelector({
|
|
|
3516
3596
|
className,
|
|
3517
3597
|
classNames
|
|
3518
3598
|
}) {
|
|
3519
|
-
const [axisSelections, setAxisSelections] =
|
|
3520
|
-
const initialized =
|
|
3521
|
-
const idPrefix =
|
|
3522
|
-
|
|
3599
|
+
const [axisSelections, setAxisSelections] = React10.useState({});
|
|
3600
|
+
const initialized = React10.useRef(false);
|
|
3601
|
+
const idPrefix = React10.useId();
|
|
3602
|
+
React10.useEffect(() => {
|
|
3523
3603
|
initialized.current = false;
|
|
3524
3604
|
}, [variants]);
|
|
3525
|
-
|
|
3605
|
+
React10.useEffect(() => {
|
|
3526
3606
|
if (initialized.current) return;
|
|
3527
3607
|
if (!variants || variants.length === 0) return;
|
|
3528
3608
|
const defaultVariant = variants.find((v) => v.is_default) || variants[0];
|
|
@@ -3537,7 +3617,7 @@ function VariantSelector({
|
|
|
3537
3617
|
setAxisSelections(initial);
|
|
3538
3618
|
}
|
|
3539
3619
|
}, [variants, onVariantChange]);
|
|
3540
|
-
|
|
3620
|
+
React10.useEffect(() => {
|
|
3541
3621
|
if (!initialized.current) return;
|
|
3542
3622
|
if (!variantAxes || variantAxes.length === 0) return;
|
|
3543
3623
|
const match = variants.find((v) => {
|
|
@@ -3657,7 +3737,7 @@ function VariantSelector({
|
|
|
3657
3737
|
{
|
|
3658
3738
|
"data-cimplify-variant-name": true,
|
|
3659
3739
|
className: cn("flex-1 min-w-0 text-sm", classNames?.name),
|
|
3660
|
-
children:
|
|
3740
|
+
children: chunkR4AKAGZQ_js.getVariantDisplayName(variant, productName)
|
|
3661
3741
|
}
|
|
3662
3742
|
),
|
|
3663
3743
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
|
|
@@ -3680,12 +3760,12 @@ function AddOnSelector({
|
|
|
3680
3760
|
className,
|
|
3681
3761
|
classNames
|
|
3682
3762
|
}) {
|
|
3683
|
-
const selectedSet =
|
|
3684
|
-
const isOptionSelected =
|
|
3763
|
+
const selectedSet = React10.useMemo(() => new Set(selectedOptions), [selectedOptions]);
|
|
3764
|
+
const isOptionSelected = React10.useCallback(
|
|
3685
3765
|
(optionId) => selectedSet.has(optionId),
|
|
3686
3766
|
[selectedSet]
|
|
3687
3767
|
);
|
|
3688
|
-
const handleCheckedChange =
|
|
3768
|
+
const handleCheckedChange = React10.useCallback(
|
|
3689
3769
|
(addOn, optionId, checked) => {
|
|
3690
3770
|
const isSelected = selectedSet.has(optionId);
|
|
3691
3771
|
if (addOn.is_mutually_exclusive || !addOn.is_multiple_allowed) {
|
|
@@ -3861,9 +3941,9 @@ function BundleSelector({
|
|
|
3861
3941
|
className,
|
|
3862
3942
|
classNames
|
|
3863
3943
|
}) {
|
|
3864
|
-
const [variantChoices, setVariantChoices] =
|
|
3865
|
-
const lastComponentIds =
|
|
3866
|
-
|
|
3944
|
+
const [variantChoices, setVariantChoices] = React10.useState({});
|
|
3945
|
+
const lastComponentIds = React10.useRef("");
|
|
3946
|
+
React10.useEffect(() => {
|
|
3867
3947
|
const ids = components.map((c) => c.id).sort().join();
|
|
3868
3948
|
if (ids === lastComponentIds.current) return;
|
|
3869
3949
|
lastComponentIds.current = ids;
|
|
@@ -3880,20 +3960,20 @@ function BundleSelector({
|
|
|
3880
3960
|
}
|
|
3881
3961
|
setVariantChoices(defaults);
|
|
3882
3962
|
}, [components]);
|
|
3883
|
-
const selections =
|
|
3963
|
+
const selections = React10.useMemo(() => {
|
|
3884
3964
|
return components.map((comp) => ({
|
|
3885
3965
|
component_id: comp.id,
|
|
3886
3966
|
variant_id: variantChoices[comp.id],
|
|
3887
3967
|
quantity: comp.quantity
|
|
3888
3968
|
}));
|
|
3889
3969
|
}, [components, variantChoices]);
|
|
3890
|
-
|
|
3970
|
+
React10.useEffect(() => {
|
|
3891
3971
|
onSelectionsChange(selections);
|
|
3892
3972
|
}, [selections, onSelectionsChange]);
|
|
3893
|
-
|
|
3973
|
+
React10.useEffect(() => {
|
|
3894
3974
|
onReady?.(components.length > 0 && selections.length > 0);
|
|
3895
3975
|
}, [components, selections, onReady]);
|
|
3896
|
-
const totalPrice =
|
|
3976
|
+
const totalPrice = React10.useMemo(() => {
|
|
3897
3977
|
if (pricingType === "fixed" && bundlePrice) {
|
|
3898
3978
|
return chunkPEDLCL72_js.parsePrice(bundlePrice);
|
|
3899
3979
|
}
|
|
@@ -3908,10 +3988,10 @@ function BundleSelector({
|
|
|
3908
3988
|
}
|
|
3909
3989
|
return componentsTotal;
|
|
3910
3990
|
}, [components, variantChoices, pricingType, bundlePrice, discountValue]);
|
|
3911
|
-
|
|
3991
|
+
React10.useEffect(() => {
|
|
3912
3992
|
onPriceChange?.(totalPrice);
|
|
3913
3993
|
}, [totalPrice, onPriceChange]);
|
|
3914
|
-
const handleVariantChange =
|
|
3994
|
+
const handleVariantChange = React10.useCallback(
|
|
3915
3995
|
(componentId, variantId) => {
|
|
3916
3996
|
setVariantChoices((prev) => ({ ...prev, [componentId]: variantId }));
|
|
3917
3997
|
},
|
|
@@ -3992,9 +4072,9 @@ function BundleComponentCard({
|
|
|
3992
4072
|
onVariantChange,
|
|
3993
4073
|
classNames
|
|
3994
4074
|
}) {
|
|
3995
|
-
const idPrefix =
|
|
4075
|
+
const idPrefix = React10.useId();
|
|
3996
4076
|
const showVariantPicker = component.allow_variant_choice && component.available_variants.length > 1;
|
|
3997
|
-
const displayPrice =
|
|
4077
|
+
const displayPrice = React10.useMemo(
|
|
3998
4078
|
() => getComponentPrice(component, selectedVariantId),
|
|
3999
4079
|
[component, selectedVariantId]
|
|
4000
4080
|
);
|
|
@@ -4142,11 +4222,11 @@ function CompositeSelector({
|
|
|
4142
4222
|
classNames
|
|
4143
4223
|
}) {
|
|
4144
4224
|
const { client } = useCimplifyClient();
|
|
4145
|
-
const [groupSelections, setGroupSelections] =
|
|
4146
|
-
const [priceResult, setPriceResult] =
|
|
4147
|
-
const [isPriceLoading, setIsPriceLoading] =
|
|
4148
|
-
const [priceError, setPriceError] =
|
|
4149
|
-
const selections =
|
|
4225
|
+
const [groupSelections, setGroupSelections] = React10.useState({});
|
|
4226
|
+
const [priceResult, setPriceResult] = React10.useState(null);
|
|
4227
|
+
const [isPriceLoading, setIsPriceLoading] = React10.useState(false);
|
|
4228
|
+
const [priceError, setPriceError] = React10.useState(false);
|
|
4229
|
+
const selections = React10.useMemo(() => {
|
|
4150
4230
|
const result = [];
|
|
4151
4231
|
for (const groupSels of Object.values(groupSelections)) {
|
|
4152
4232
|
for (const [componentId, qty] of Object.entries(groupSels)) {
|
|
@@ -4157,13 +4237,13 @@ function CompositeSelector({
|
|
|
4157
4237
|
}
|
|
4158
4238
|
return result;
|
|
4159
4239
|
}, [groupSelections]);
|
|
4160
|
-
|
|
4240
|
+
React10.useEffect(() => {
|
|
4161
4241
|
onSelectionsChange(selections);
|
|
4162
4242
|
}, [selections, onSelectionsChange]);
|
|
4163
|
-
|
|
4243
|
+
React10.useEffect(() => {
|
|
4164
4244
|
onPriceChange?.(priceResult);
|
|
4165
4245
|
}, [priceResult, onPriceChange]);
|
|
4166
|
-
const allGroupsSatisfied =
|
|
4246
|
+
const allGroupsSatisfied = React10.useMemo(() => {
|
|
4167
4247
|
for (const group of groups) {
|
|
4168
4248
|
const groupSels = groupSelections[group.id] || {};
|
|
4169
4249
|
const totalSelected = Object.values(groupSels).reduce((sum, q) => sum + q, 0);
|
|
@@ -4171,17 +4251,17 @@ function CompositeSelector({
|
|
|
4171
4251
|
}
|
|
4172
4252
|
return true;
|
|
4173
4253
|
}, [groups, groupSelections]);
|
|
4174
|
-
const sortedGroups =
|
|
4254
|
+
const sortedGroups = React10.useMemo(
|
|
4175
4255
|
() => [...groups].sort((a, b) => a.display_order - b.display_order).map((group) => ({
|
|
4176
4256
|
...group,
|
|
4177
4257
|
_sortedComponents: group.components.filter((component) => component.is_available && !component.is_archived).sort((a, b) => a.display_order - b.display_order)
|
|
4178
4258
|
})),
|
|
4179
4259
|
[groups]
|
|
4180
4260
|
);
|
|
4181
|
-
|
|
4261
|
+
React10.useEffect(() => {
|
|
4182
4262
|
onReady?.(allGroupsSatisfied);
|
|
4183
4263
|
}, [allGroupsSatisfied, onReady]);
|
|
4184
|
-
|
|
4264
|
+
React10.useEffect(() => {
|
|
4185
4265
|
if (skipPriceFetch || !allGroupsSatisfied || selections.length === 0) return;
|
|
4186
4266
|
let cancelled = false;
|
|
4187
4267
|
const timer = setTimeout(() => {
|
|
@@ -4208,7 +4288,7 @@ function CompositeSelector({
|
|
|
4208
4288
|
clearTimeout(timer);
|
|
4209
4289
|
};
|
|
4210
4290
|
}, [selections, allGroupsSatisfied, compositeId, client, skipPriceFetch]);
|
|
4211
|
-
const toggleComponent =
|
|
4291
|
+
const toggleComponent = React10.useCallback(
|
|
4212
4292
|
(group, component) => {
|
|
4213
4293
|
setGroupSelections((prev) => {
|
|
4214
4294
|
const groupSels = { ...prev[group.id] || {} };
|
|
@@ -4236,7 +4316,7 @@ function CompositeSelector({
|
|
|
4236
4316
|
},
|
|
4237
4317
|
[]
|
|
4238
4318
|
);
|
|
4239
|
-
const updateQuantity =
|
|
4319
|
+
const updateQuantity = React10.useCallback(
|
|
4240
4320
|
(group, componentId, newValue) => {
|
|
4241
4321
|
setGroupSelections((prev) => {
|
|
4242
4322
|
const groupSels = { ...prev[group.id] || {} };
|
|
@@ -4775,6 +4855,880 @@ function VolumePricing({
|
|
|
4775
4855
|
}
|
|
4776
4856
|
);
|
|
4777
4857
|
}
|
|
4858
|
+
function CustomerInputFields({
|
|
4859
|
+
fields,
|
|
4860
|
+
values,
|
|
4861
|
+
onChange,
|
|
4862
|
+
onFileUpload,
|
|
4863
|
+
className,
|
|
4864
|
+
classNames
|
|
4865
|
+
}) {
|
|
4866
|
+
const clientContext = useOptionalCimplifyClient();
|
|
4867
|
+
if (fields.length === 0) return null;
|
|
4868
|
+
const sorted = [...fields].sort((a, b) => a.display_order - b.display_order);
|
|
4869
|
+
const setValue = React10.useCallback(
|
|
4870
|
+
(fieldId, value) => {
|
|
4871
|
+
onChange({ ...values, [fieldId]: value });
|
|
4872
|
+
},
|
|
4873
|
+
[values, onChange]
|
|
4874
|
+
);
|
|
4875
|
+
const defaultFileUpload = React10.useCallback(
|
|
4876
|
+
async (file) => {
|
|
4877
|
+
if (onFileUpload) return onFileUpload(file, {});
|
|
4878
|
+
if (!clientContext?.client) throw new Error("No upload provider available");
|
|
4879
|
+
const result = await clientContext.client.uploads.upload(file);
|
|
4880
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
4881
|
+
return result.value.url;
|
|
4882
|
+
},
|
|
4883
|
+
[onFileUpload, clientContext]
|
|
4884
|
+
);
|
|
4885
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-customer-inputs": true, className: cn("space-y-4", className, classNames?.root), children: sorted.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4886
|
+
InputField,
|
|
4887
|
+
{
|
|
4888
|
+
field,
|
|
4889
|
+
value: values[field.id],
|
|
4890
|
+
onValueChange: (value) => setValue(field.id, value),
|
|
4891
|
+
onFileUpload: onFileUpload ?? (clientContext?.client ? (_file, _field) => defaultFileUpload(_file) : void 0),
|
|
4892
|
+
classNames
|
|
4893
|
+
},
|
|
4894
|
+
field.id
|
|
4895
|
+
)) });
|
|
4896
|
+
}
|
|
4897
|
+
function InputField({
|
|
4898
|
+
field,
|
|
4899
|
+
value,
|
|
4900
|
+
onValueChange,
|
|
4901
|
+
onFileUpload,
|
|
4902
|
+
classNames
|
|
4903
|
+
}) {
|
|
4904
|
+
const hasPriceAdjustment = field.price_adjustment != null && chunkPEDLCL72_js.parsePrice(field.price_adjustment) > 0;
|
|
4905
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customer-input": true, "data-field-type": field.field_type, className: classNames?.field, children: [
|
|
4906
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
|
|
4907
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: cn("text-sm font-semibold", classNames?.label), children: field.name }),
|
|
4908
|
+
field.is_required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs text-destructive", classNames?.required), children: "Required" }),
|
|
4909
|
+
hasPriceAdjustment && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-xs text-muted-foreground", classNames?.priceAdjustment), children: [
|
|
4910
|
+
"+",
|
|
4911
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: field.price_adjustment })
|
|
4912
|
+
] })
|
|
4913
|
+
] }),
|
|
4914
|
+
field.help_text && /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-xs text-muted-foreground mb-1.5", classNames?.helpText), children: field.help_text }),
|
|
4915
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4916
|
+
FieldInput,
|
|
4917
|
+
{
|
|
4918
|
+
field,
|
|
4919
|
+
value,
|
|
4920
|
+
onValueChange,
|
|
4921
|
+
onFileUpload,
|
|
4922
|
+
classNames
|
|
4923
|
+
}
|
|
4924
|
+
)
|
|
4925
|
+
] });
|
|
4926
|
+
}
|
|
4927
|
+
function FieldInput({
|
|
4928
|
+
field,
|
|
4929
|
+
value,
|
|
4930
|
+
onValueChange,
|
|
4931
|
+
onFileUpload,
|
|
4932
|
+
classNames
|
|
4933
|
+
}) {
|
|
4934
|
+
const inputClass = cn(
|
|
4935
|
+
"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",
|
|
4936
|
+
classNames?.input
|
|
4937
|
+
);
|
|
4938
|
+
switch (field.field_type) {
|
|
4939
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Text:
|
|
4940
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Url:
|
|
4941
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4942
|
+
"input",
|
|
4943
|
+
{
|
|
4944
|
+
type: field.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Url ? "url" : "text",
|
|
4945
|
+
value: typeof value === "string" ? value : "",
|
|
4946
|
+
onChange: (e) => onValueChange(e.target.value),
|
|
4947
|
+
placeholder: field.placeholder,
|
|
4948
|
+
required: field.is_required,
|
|
4949
|
+
maxLength: field.validation?.max_length ?? void 0,
|
|
4950
|
+
className: inputClass
|
|
4951
|
+
}
|
|
4952
|
+
);
|
|
4953
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Textarea:
|
|
4954
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4955
|
+
"textarea",
|
|
4956
|
+
{
|
|
4957
|
+
value: typeof value === "string" ? value : "",
|
|
4958
|
+
onChange: (e) => onValueChange(e.target.value),
|
|
4959
|
+
placeholder: field.placeholder,
|
|
4960
|
+
required: field.is_required,
|
|
4961
|
+
maxLength: field.validation?.max_length ?? void 0,
|
|
4962
|
+
rows: 3,
|
|
4963
|
+
className: cn(inputClass, "resize-none", classNames?.textarea)
|
|
4964
|
+
}
|
|
4965
|
+
);
|
|
4966
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Number:
|
|
4967
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4968
|
+
"input",
|
|
4969
|
+
{
|
|
4970
|
+
type: "number",
|
|
4971
|
+
value: typeof value === "number" ? value : "",
|
|
4972
|
+
onChange: (e) => onValueChange(e.target.value ? parseFloat(e.target.value) : void 0),
|
|
4973
|
+
placeholder: field.placeholder,
|
|
4974
|
+
required: field.is_required,
|
|
4975
|
+
min: field.validation?.min_value ?? void 0,
|
|
4976
|
+
max: field.validation?.max_value ?? void 0,
|
|
4977
|
+
className: inputClass
|
|
4978
|
+
}
|
|
4979
|
+
);
|
|
4980
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Select:
|
|
4981
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4982
|
+
"select",
|
|
4983
|
+
{
|
|
4984
|
+
value: typeof value === "string" ? value : "",
|
|
4985
|
+
onChange: (e) => onValueChange(e.target.value || void 0),
|
|
4986
|
+
required: field.is_required,
|
|
4987
|
+
className: cn(inputClass, classNames?.select),
|
|
4988
|
+
children: [
|
|
4989
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: field.placeholder || "Select..." }),
|
|
4990
|
+
(field.options || []).map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: opt }, opt))
|
|
4991
|
+
]
|
|
4992
|
+
}
|
|
4993
|
+
);
|
|
4994
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Radio:
|
|
4995
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.radioGroup), children: (field.options || []).map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4996
|
+
"label",
|
|
4997
|
+
{
|
|
4998
|
+
className: cn(
|
|
4999
|
+
"flex items-center gap-2 text-sm cursor-pointer",
|
|
5000
|
+
classNames?.radioOption
|
|
5001
|
+
),
|
|
5002
|
+
children: [
|
|
5003
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5004
|
+
"input",
|
|
5005
|
+
{
|
|
5006
|
+
type: "radio",
|
|
5007
|
+
name: field.id,
|
|
5008
|
+
value: opt,
|
|
5009
|
+
checked: value === opt,
|
|
5010
|
+
onChange: () => onValueChange(opt),
|
|
5011
|
+
className: "accent-primary"
|
|
5012
|
+
}
|
|
5013
|
+
),
|
|
5014
|
+
opt
|
|
5015
|
+
]
|
|
5016
|
+
},
|
|
5017
|
+
opt
|
|
5018
|
+
)) });
|
|
5019
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Checkbox:
|
|
5020
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cn("flex items-center gap-2 text-sm cursor-pointer", classNames?.checkboxLabel), children: [
|
|
5021
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5022
|
+
"input",
|
|
5023
|
+
{
|
|
5024
|
+
type: "checkbox",
|
|
5025
|
+
checked: value === true,
|
|
5026
|
+
onChange: (e) => onValueChange(e.target.checked),
|
|
5027
|
+
className: "accent-primary w-4 h-4"
|
|
5028
|
+
}
|
|
5029
|
+
),
|
|
5030
|
+
field.placeholder || field.name
|
|
5031
|
+
] });
|
|
5032
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Color:
|
|
5033
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5034
|
+
"input",
|
|
5035
|
+
{
|
|
5036
|
+
type: "color",
|
|
5037
|
+
value: typeof value === "string" ? value : "#000000",
|
|
5038
|
+
onChange: (e) => onValueChange(e.target.value),
|
|
5039
|
+
className: cn("w-12 h-10 rounded-md border border-input cursor-pointer", classNames?.colorInput)
|
|
5040
|
+
}
|
|
5041
|
+
);
|
|
5042
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Date:
|
|
5043
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5044
|
+
"input",
|
|
5045
|
+
{
|
|
5046
|
+
type: "date",
|
|
5047
|
+
value: typeof value === "string" ? value : "",
|
|
5048
|
+
onChange: (e) => onValueChange(e.target.value || void 0),
|
|
5049
|
+
required: field.is_required,
|
|
5050
|
+
className: inputClass
|
|
5051
|
+
}
|
|
5052
|
+
);
|
|
5053
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.File:
|
|
5054
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Image:
|
|
5055
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5056
|
+
FileUploadInput,
|
|
5057
|
+
{
|
|
5058
|
+
field,
|
|
5059
|
+
value,
|
|
5060
|
+
onValueChange,
|
|
5061
|
+
onFileUpload,
|
|
5062
|
+
classNames
|
|
5063
|
+
}
|
|
5064
|
+
);
|
|
5065
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Email:
|
|
5066
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5067
|
+
"input",
|
|
5068
|
+
{
|
|
5069
|
+
type: "email",
|
|
5070
|
+
value: typeof value === "string" ? value : "",
|
|
5071
|
+
onChange: (e) => onValueChange(e.target.value),
|
|
5072
|
+
placeholder: field.placeholder || "email@example.com",
|
|
5073
|
+
required: field.is_required,
|
|
5074
|
+
className: inputClass
|
|
5075
|
+
}
|
|
5076
|
+
);
|
|
5077
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.DateTime: {
|
|
5078
|
+
const dtLocalValue = typeof value === "string" && value.includes("T") ? value.slice(0, 16) : typeof value === "string" ? value : "";
|
|
5079
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5080
|
+
"input",
|
|
5081
|
+
{
|
|
5082
|
+
type: "datetime-local",
|
|
5083
|
+
value: dtLocalValue,
|
|
5084
|
+
onChange: (e) => {
|
|
5085
|
+
if (!e.target.value) {
|
|
5086
|
+
onValueChange(void 0);
|
|
5087
|
+
return;
|
|
5088
|
+
}
|
|
5089
|
+
const date = new Date(e.target.value);
|
|
5090
|
+
onValueChange(Number.isNaN(date.getTime()) ? e.target.value : date.toISOString());
|
|
5091
|
+
},
|
|
5092
|
+
required: field.is_required,
|
|
5093
|
+
className: inputClass
|
|
5094
|
+
}
|
|
5095
|
+
);
|
|
5096
|
+
}
|
|
5097
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Time:
|
|
5098
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5099
|
+
"input",
|
|
5100
|
+
{
|
|
5101
|
+
type: "time",
|
|
5102
|
+
value: typeof value === "string" ? value : "",
|
|
5103
|
+
onChange: (e) => onValueChange(e.target.value || void 0),
|
|
5104
|
+
required: field.is_required,
|
|
5105
|
+
className: inputClass
|
|
5106
|
+
}
|
|
5107
|
+
);
|
|
5108
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.MultiSelect:
|
|
5109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5110
|
+
MultiSelectInput,
|
|
5111
|
+
{
|
|
5112
|
+
field,
|
|
5113
|
+
value,
|
|
5114
|
+
onValueChange,
|
|
5115
|
+
classNames
|
|
5116
|
+
}
|
|
5117
|
+
);
|
|
5118
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.DateRange:
|
|
5119
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5120
|
+
DateRangeInput,
|
|
5121
|
+
{
|
|
5122
|
+
field,
|
|
5123
|
+
value,
|
|
5124
|
+
onValueChange,
|
|
5125
|
+
classNames,
|
|
5126
|
+
inputClass
|
|
5127
|
+
}
|
|
5128
|
+
);
|
|
5129
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Address:
|
|
5130
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5131
|
+
AddressInput,
|
|
5132
|
+
{
|
|
5133
|
+
field,
|
|
5134
|
+
value,
|
|
5135
|
+
onValueChange,
|
|
5136
|
+
classNames,
|
|
5137
|
+
inputClass
|
|
5138
|
+
}
|
|
5139
|
+
);
|
|
5140
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Location:
|
|
5141
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5142
|
+
LocationInput,
|
|
5143
|
+
{
|
|
5144
|
+
field,
|
|
5145
|
+
value,
|
|
5146
|
+
onValueChange,
|
|
5147
|
+
classNames,
|
|
5148
|
+
inputClass
|
|
5149
|
+
}
|
|
5150
|
+
);
|
|
5151
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Phone:
|
|
5152
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5153
|
+
PhoneInput,
|
|
5154
|
+
{
|
|
5155
|
+
field,
|
|
5156
|
+
value,
|
|
5157
|
+
onValueChange,
|
|
5158
|
+
classNames,
|
|
5159
|
+
inputClass
|
|
5160
|
+
}
|
|
5161
|
+
);
|
|
5162
|
+
case chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Signature:
|
|
5163
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5164
|
+
SignatureInput,
|
|
5165
|
+
{
|
|
5166
|
+
field,
|
|
5167
|
+
value,
|
|
5168
|
+
onValueChange,
|
|
5169
|
+
classNames
|
|
5170
|
+
}
|
|
5171
|
+
);
|
|
5172
|
+
default:
|
|
5173
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5174
|
+
"input",
|
|
5175
|
+
{
|
|
5176
|
+
type: "text",
|
|
5177
|
+
value: typeof value === "string" ? value : "",
|
|
5178
|
+
onChange: (e) => onValueChange(e.target.value),
|
|
5179
|
+
placeholder: field.placeholder,
|
|
5180
|
+
className: inputClass
|
|
5181
|
+
}
|
|
5182
|
+
);
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
function FileUploadInput({
|
|
5186
|
+
field,
|
|
5187
|
+
value,
|
|
5188
|
+
onValueChange,
|
|
5189
|
+
onFileUpload,
|
|
5190
|
+
classNames
|
|
5191
|
+
}) {
|
|
5192
|
+
const [isUploading, setIsUploading] = React10__default.default.useState(false);
|
|
5193
|
+
const fileUrl = typeof value === "string" ? value : void 0;
|
|
5194
|
+
const acceptedFormats = field.validation?.accepted_formats;
|
|
5195
|
+
const accept = acceptedFormats ? acceptedFormats.map((f) => `.${f}`).join(",") : field.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Image ? "image/*" : void 0;
|
|
5196
|
+
const handleFile = async (file) => {
|
|
5197
|
+
if (!onFileUpload) return;
|
|
5198
|
+
if (field.validation?.max_size_mb) {
|
|
5199
|
+
const maxBytes = field.validation.max_size_mb * 1024 * 1024;
|
|
5200
|
+
if (file.size > maxBytes) {
|
|
5201
|
+
return;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
setIsUploading(true);
|
|
5205
|
+
try {
|
|
5206
|
+
const url = await onFileUpload(file, field);
|
|
5207
|
+
onValueChange(url);
|
|
5208
|
+
} finally {
|
|
5209
|
+
setIsUploading(false);
|
|
5210
|
+
}
|
|
5211
|
+
};
|
|
5212
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.fileInput), children: fileUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
5213
|
+
field.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Image && /* @__PURE__ */ jsxRuntime.jsx("img", { src: fileUrl, alt: "Uploaded", className: "w-16 h-16 object-cover rounded-md border border-border" }),
|
|
5214
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground truncate", children: fileUrl.split("/").pop() }) }),
|
|
5215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5216
|
+
"button",
|
|
5217
|
+
{
|
|
5218
|
+
type: "button",
|
|
5219
|
+
onClick: () => onValueChange(void 0),
|
|
5220
|
+
className: "text-xs text-muted-foreground hover:text-destructive transition-colors",
|
|
5221
|
+
children: "Remove"
|
|
5222
|
+
}
|
|
5223
|
+
)
|
|
5224
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex flex-col items-center justify-center w-full h-24 border-2 border-dashed border-border rounded-lg cursor-pointer hover:border-primary/40 transition-colors", children: [
|
|
5225
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5226
|
+
"input",
|
|
5227
|
+
{
|
|
5228
|
+
type: "file",
|
|
5229
|
+
accept,
|
|
5230
|
+
onChange: (e) => {
|
|
5231
|
+
const file = e.target.files?.[0];
|
|
5232
|
+
if (file) void handleFile(file);
|
|
5233
|
+
},
|
|
5234
|
+
className: "hidden",
|
|
5235
|
+
disabled: isUploading
|
|
5236
|
+
}
|
|
5237
|
+
),
|
|
5238
|
+
isUploading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Uploading..." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5239
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: field.placeholder || `Upload ${field.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Image ? "image" : "file"}` }),
|
|
5240
|
+
acceptedFormats && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground/60 mt-1", children: [
|
|
5241
|
+
acceptedFormats.map((f) => f.toUpperCase()).join(", "),
|
|
5242
|
+
field.validation?.max_size_mb && ` \xB7 Max ${field.validation.max_size_mb}MB`
|
|
5243
|
+
] })
|
|
5244
|
+
] })
|
|
5245
|
+
] }) });
|
|
5246
|
+
}
|
|
5247
|
+
function MultiSelectInput({
|
|
5248
|
+
field,
|
|
5249
|
+
value,
|
|
5250
|
+
onValueChange,
|
|
5251
|
+
classNames
|
|
5252
|
+
}) {
|
|
5253
|
+
const selected = Array.isArray(value) ? value : [];
|
|
5254
|
+
const options = field.options || [];
|
|
5255
|
+
const maxSelections = field.validation?.max_selections;
|
|
5256
|
+
const toggle = (opt) => {
|
|
5257
|
+
const next = selected.includes(opt) ? selected.filter((s) => s !== opt) : maxSelections && selected.length >= maxSelections ? selected : [...selected, opt];
|
|
5258
|
+
onValueChange(next.length > 0 ? next : void 0);
|
|
5259
|
+
};
|
|
5260
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", classNames?.multiSelectGroup), children: [
|
|
5261
|
+
options.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5262
|
+
"label",
|
|
5263
|
+
{
|
|
5264
|
+
className: cn(
|
|
5265
|
+
"flex items-center gap-2 text-sm cursor-pointer",
|
|
5266
|
+
classNames?.multiSelectOption
|
|
5267
|
+
),
|
|
5268
|
+
children: [
|
|
5269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5270
|
+
"input",
|
|
5271
|
+
{
|
|
5272
|
+
type: "checkbox",
|
|
5273
|
+
checked: selected.includes(opt),
|
|
5274
|
+
onChange: () => toggle(opt),
|
|
5275
|
+
className: "accent-primary w-4 h-4"
|
|
5276
|
+
}
|
|
5277
|
+
),
|
|
5278
|
+
opt
|
|
5279
|
+
]
|
|
5280
|
+
},
|
|
5281
|
+
opt
|
|
5282
|
+
)),
|
|
5283
|
+
maxSelections && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
5284
|
+
selected.length,
|
|
5285
|
+
"/",
|
|
5286
|
+
maxSelections,
|
|
5287
|
+
" selected"
|
|
5288
|
+
] })
|
|
5289
|
+
] });
|
|
5290
|
+
}
|
|
5291
|
+
function DateRangeInput({
|
|
5292
|
+
field,
|
|
5293
|
+
value,
|
|
5294
|
+
onValueChange,
|
|
5295
|
+
classNames,
|
|
5296
|
+
inputClass
|
|
5297
|
+
}) {
|
|
5298
|
+
const range = value && typeof value === "object" ? value : {};
|
|
5299
|
+
const update = (key, v) => {
|
|
5300
|
+
const next = { ...range, [key]: v };
|
|
5301
|
+
onValueChange(next.start || next.end ? next : void 0);
|
|
5302
|
+
};
|
|
5303
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid grid-cols-2 gap-3", classNames?.dateRangeInput), children: [
|
|
5304
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5305
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "Start" }),
|
|
5306
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5307
|
+
"input",
|
|
5308
|
+
{
|
|
5309
|
+
type: "date",
|
|
5310
|
+
value: range.start || "",
|
|
5311
|
+
onChange: (e) => update("start", e.target.value),
|
|
5312
|
+
required: field.is_required,
|
|
5313
|
+
className: inputClass
|
|
5314
|
+
}
|
|
5315
|
+
)
|
|
5316
|
+
] }),
|
|
5317
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5318
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-xs text-muted-foreground mb-1 block", children: "End" }),
|
|
5319
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5320
|
+
"input",
|
|
5321
|
+
{
|
|
5322
|
+
type: "date",
|
|
5323
|
+
value: range.end || "",
|
|
5324
|
+
onChange: (e) => update("end", e.target.value),
|
|
5325
|
+
required: field.is_required,
|
|
5326
|
+
className: inputClass
|
|
5327
|
+
}
|
|
5328
|
+
)
|
|
5329
|
+
] })
|
|
5330
|
+
] });
|
|
5331
|
+
}
|
|
5332
|
+
function AddressInput({
|
|
5333
|
+
field,
|
|
5334
|
+
value,
|
|
5335
|
+
onValueChange,
|
|
5336
|
+
classNames,
|
|
5337
|
+
inputClass
|
|
5338
|
+
}) {
|
|
5339
|
+
const clientContext = useOptionalCimplifyClient();
|
|
5340
|
+
const addr = value && typeof value === "object" ? value : null;
|
|
5341
|
+
const [inputText, setInputText] = React10__default.default.useState(addr?.formatted_address ?? "");
|
|
5342
|
+
const [suggestions, setSuggestions] = React10__default.default.useState([]);
|
|
5343
|
+
const [isOpen, setIsOpen] = React10__default.default.useState(false);
|
|
5344
|
+
const [highlightedIndex, setHighlightedIndex] = React10__default.default.useState(-1);
|
|
5345
|
+
const debounceRef = React10__default.default.useRef(null);
|
|
5346
|
+
const seqRef = React10__default.default.useRef(0);
|
|
5347
|
+
const sessionTokenRef = React10__default.default.useRef(createSessionToken());
|
|
5348
|
+
const blurTimeoutRef = React10__default.default.useRef(null);
|
|
5349
|
+
React10__default.default.useEffect(() => {
|
|
5350
|
+
return () => {
|
|
5351
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5352
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
5353
|
+
seqRef.current += 1;
|
|
5354
|
+
};
|
|
5355
|
+
}, []);
|
|
5356
|
+
const fetchSuggestions = React10__default.default.useCallback(async (query) => {
|
|
5357
|
+
const client = clientContext?.client;
|
|
5358
|
+
if (!client || query.length < 3) {
|
|
5359
|
+
setSuggestions([]);
|
|
5360
|
+
setIsOpen(false);
|
|
5361
|
+
return;
|
|
5362
|
+
}
|
|
5363
|
+
const seq = ++seqRef.current;
|
|
5364
|
+
const result = await client.places.autocomplete(query, sessionTokenRef.current);
|
|
5365
|
+
if (seqRef.current !== seq) return;
|
|
5366
|
+
if (result.ok && result.value.predictions.length > 0) {
|
|
5367
|
+
setSuggestions(result.value.predictions);
|
|
5368
|
+
setHighlightedIndex(0);
|
|
5369
|
+
setIsOpen(true);
|
|
5370
|
+
} else {
|
|
5371
|
+
setSuggestions([]);
|
|
5372
|
+
setIsOpen(false);
|
|
5373
|
+
}
|
|
5374
|
+
}, [clientContext]);
|
|
5375
|
+
const handleInputChange = (nextValue) => {
|
|
5376
|
+
setInputText(nextValue);
|
|
5377
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5378
|
+
debounceRef.current = setTimeout(() => void fetchSuggestions(nextValue.trim()), 300);
|
|
5379
|
+
};
|
|
5380
|
+
const selectSuggestion = React10__default.default.useCallback(async (suggestion) => {
|
|
5381
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5382
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
5383
|
+
const fallback = suggestion.description.split(",")[0]?.trim() || suggestion.description;
|
|
5384
|
+
setInputText(fallback);
|
|
5385
|
+
setSuggestions([]);
|
|
5386
|
+
setIsOpen(false);
|
|
5387
|
+
const client = clientContext?.client;
|
|
5388
|
+
if (!client) return;
|
|
5389
|
+
const result = await client.places.details(suggestion.place_id, sessionTokenRef.current);
|
|
5390
|
+
sessionTokenRef.current = createSessionToken();
|
|
5391
|
+
if (result.ok) {
|
|
5392
|
+
const d = result.value;
|
|
5393
|
+
const addressValue = {
|
|
5394
|
+
formatted_address: d.formatted_address || fallback,
|
|
5395
|
+
street_address: d.street_address,
|
|
5396
|
+
apartment: d.apartment,
|
|
5397
|
+
city: d.city,
|
|
5398
|
+
region: d.region,
|
|
5399
|
+
postal_code: d.postal_code,
|
|
5400
|
+
country: d.country,
|
|
5401
|
+
latitude: d.latitude,
|
|
5402
|
+
longitude: d.longitude,
|
|
5403
|
+
place_id: d.place_id
|
|
5404
|
+
};
|
|
5405
|
+
setInputText(addressValue.formatted_address);
|
|
5406
|
+
onValueChange(addressValue);
|
|
5407
|
+
}
|
|
5408
|
+
}, [clientContext, onValueChange]);
|
|
5409
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2 relative", classNames?.addressInput), children: [
|
|
5410
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5411
|
+
"input",
|
|
5412
|
+
{
|
|
5413
|
+
type: "text",
|
|
5414
|
+
value: inputText,
|
|
5415
|
+
onChange: (e) => handleInputChange(e.target.value),
|
|
5416
|
+
onFocus: () => {
|
|
5417
|
+
if (suggestions.length > 0) setIsOpen(true);
|
|
5418
|
+
},
|
|
5419
|
+
onBlur: () => {
|
|
5420
|
+
blurTimeoutRef.current = setTimeout(() => setIsOpen(false), 120);
|
|
5421
|
+
},
|
|
5422
|
+
onKeyDown: (e) => {
|
|
5423
|
+
if (e.key === "Escape") {
|
|
5424
|
+
setIsOpen(false);
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5427
|
+
if (!isOpen || suggestions.length === 0) return;
|
|
5428
|
+
if (e.key === "ArrowDown") {
|
|
5429
|
+
e.preventDefault();
|
|
5430
|
+
setHighlightedIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
|
|
5431
|
+
} else if (e.key === "ArrowUp") {
|
|
5432
|
+
e.preventDefault();
|
|
5433
|
+
setHighlightedIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
|
|
5434
|
+
} else if (e.key === "Enter" && highlightedIndex >= 0) {
|
|
5435
|
+
e.preventDefault();
|
|
5436
|
+
void selectSuggestion(suggestions[highlightedIndex]);
|
|
5437
|
+
}
|
|
5438
|
+
},
|
|
5439
|
+
placeholder: field.placeholder || "Search for an address...",
|
|
5440
|
+
required: field.is_required,
|
|
5441
|
+
autoComplete: "off",
|
|
5442
|
+
"aria-autocomplete": "list",
|
|
5443
|
+
"aria-expanded": isOpen && suggestions.length > 0,
|
|
5444
|
+
className: inputClass
|
|
5445
|
+
}
|
|
5446
|
+
),
|
|
5447
|
+
isOpen && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", className: "absolute left-0 right-0 top-full z-20 mt-1 overflow-hidden rounded-md border border-border bg-background shadow-lg", children: suggestions.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5448
|
+
"button",
|
|
5449
|
+
{
|
|
5450
|
+
type: "button",
|
|
5451
|
+
role: "option",
|
|
5452
|
+
"aria-selected": i === highlightedIndex,
|
|
5453
|
+
onMouseDown: (e) => {
|
|
5454
|
+
e.preventDefault();
|
|
5455
|
+
void selectSuggestion(s);
|
|
5456
|
+
},
|
|
5457
|
+
className: cn("block w-full px-3 py-2.5 text-left text-sm transition-colors", i === highlightedIndex ? "bg-muted text-foreground" : "text-foreground hover:bg-muted/70"),
|
|
5458
|
+
children: s.description
|
|
5459
|
+
},
|
|
5460
|
+
s.place_id
|
|
5461
|
+
)) }),
|
|
5462
|
+
addr && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5463
|
+
"input",
|
|
5464
|
+
{
|
|
5465
|
+
type: "text",
|
|
5466
|
+
value: addr.apartment || "",
|
|
5467
|
+
onChange: (e) => onValueChange({ ...addr, apartment: e.target.value || void 0 }),
|
|
5468
|
+
placeholder: "Apt, suite, unit (optional)",
|
|
5469
|
+
className: inputClass
|
|
5470
|
+
}
|
|
5471
|
+
)
|
|
5472
|
+
] });
|
|
5473
|
+
}
|
|
5474
|
+
function LocationInput({
|
|
5475
|
+
field,
|
|
5476
|
+
value,
|
|
5477
|
+
onValueChange,
|
|
5478
|
+
classNames,
|
|
5479
|
+
inputClass
|
|
5480
|
+
}) {
|
|
5481
|
+
const clientContext = useOptionalCimplifyClient();
|
|
5482
|
+
const loc = value && typeof value === "object" ? value : null;
|
|
5483
|
+
const [inputText, setInputText] = React10__default.default.useState(loc?.label ?? "");
|
|
5484
|
+
const [suggestions, setSuggestions] = React10__default.default.useState([]);
|
|
5485
|
+
const [isOpen, setIsOpen] = React10__default.default.useState(false);
|
|
5486
|
+
const [highlightedIndex, setHighlightedIndex] = React10__default.default.useState(-1);
|
|
5487
|
+
const debounceRef = React10__default.default.useRef(null);
|
|
5488
|
+
const seqRef = React10__default.default.useRef(0);
|
|
5489
|
+
const sessionTokenRef = React10__default.default.useRef(createSessionToken());
|
|
5490
|
+
const blurTimeoutRef = React10__default.default.useRef(null);
|
|
5491
|
+
React10__default.default.useEffect(() => {
|
|
5492
|
+
return () => {
|
|
5493
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5494
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
5495
|
+
seqRef.current += 1;
|
|
5496
|
+
};
|
|
5497
|
+
}, []);
|
|
5498
|
+
const fetchSuggestions = React10__default.default.useCallback(async (query) => {
|
|
5499
|
+
const client = clientContext?.client;
|
|
5500
|
+
if (!client || query.length < 3) {
|
|
5501
|
+
setSuggestions([]);
|
|
5502
|
+
setIsOpen(false);
|
|
5503
|
+
return;
|
|
5504
|
+
}
|
|
5505
|
+
const seq = ++seqRef.current;
|
|
5506
|
+
const result = await client.places.autocomplete(query, sessionTokenRef.current);
|
|
5507
|
+
if (seqRef.current !== seq) return;
|
|
5508
|
+
if (result.ok && result.value.predictions.length > 0) {
|
|
5509
|
+
setSuggestions(result.value.predictions);
|
|
5510
|
+
setHighlightedIndex(0);
|
|
5511
|
+
setIsOpen(true);
|
|
5512
|
+
} else {
|
|
5513
|
+
setSuggestions([]);
|
|
5514
|
+
setIsOpen(false);
|
|
5515
|
+
}
|
|
5516
|
+
}, [clientContext]);
|
|
5517
|
+
const handleInputChange = (nextValue) => {
|
|
5518
|
+
setInputText(nextValue);
|
|
5519
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5520
|
+
debounceRef.current = setTimeout(() => void fetchSuggestions(nextValue.trim()), 300);
|
|
5521
|
+
};
|
|
5522
|
+
const selectSuggestion = React10__default.default.useCallback(async (suggestion) => {
|
|
5523
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
5524
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
5525
|
+
const label = suggestion.description.split(",")[0]?.trim() || suggestion.description;
|
|
5526
|
+
setInputText(label);
|
|
5527
|
+
setSuggestions([]);
|
|
5528
|
+
setIsOpen(false);
|
|
5529
|
+
const client = clientContext?.client;
|
|
5530
|
+
if (!client) return;
|
|
5531
|
+
const result = await client.places.details(suggestion.place_id, sessionTokenRef.current);
|
|
5532
|
+
sessionTokenRef.current = createSessionToken();
|
|
5533
|
+
if (result.ok) {
|
|
5534
|
+
const d = result.value;
|
|
5535
|
+
onValueChange({
|
|
5536
|
+
latitude: d.latitude,
|
|
5537
|
+
longitude: d.longitude,
|
|
5538
|
+
label: d.formatted_address || label
|
|
5539
|
+
});
|
|
5540
|
+
setInputText(d.formatted_address || label);
|
|
5541
|
+
}
|
|
5542
|
+
}, [clientContext, onValueChange]);
|
|
5543
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", classNames?.locationInput), children: [
|
|
5544
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5545
|
+
"input",
|
|
5546
|
+
{
|
|
5547
|
+
type: "text",
|
|
5548
|
+
value: inputText,
|
|
5549
|
+
onChange: (e) => handleInputChange(e.target.value),
|
|
5550
|
+
onFocus: () => {
|
|
5551
|
+
if (suggestions.length > 0) setIsOpen(true);
|
|
5552
|
+
},
|
|
5553
|
+
onBlur: () => {
|
|
5554
|
+
blurTimeoutRef.current = setTimeout(() => setIsOpen(false), 120);
|
|
5555
|
+
},
|
|
5556
|
+
onKeyDown: (e) => {
|
|
5557
|
+
if (e.key === "Escape") {
|
|
5558
|
+
setIsOpen(false);
|
|
5559
|
+
return;
|
|
5560
|
+
}
|
|
5561
|
+
if (!isOpen || suggestions.length === 0) return;
|
|
5562
|
+
if (e.key === "ArrowDown") {
|
|
5563
|
+
e.preventDefault();
|
|
5564
|
+
setHighlightedIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
|
|
5565
|
+
} else if (e.key === "ArrowUp") {
|
|
5566
|
+
e.preventDefault();
|
|
5567
|
+
setHighlightedIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
|
|
5568
|
+
} else if (e.key === "Enter" && highlightedIndex >= 0) {
|
|
5569
|
+
e.preventDefault();
|
|
5570
|
+
void selectSuggestion(suggestions[highlightedIndex]);
|
|
5571
|
+
}
|
|
5572
|
+
},
|
|
5573
|
+
placeholder: field.placeholder || "Search for a location...",
|
|
5574
|
+
required: field.is_required,
|
|
5575
|
+
autoComplete: "off",
|
|
5576
|
+
"aria-autocomplete": "list",
|
|
5577
|
+
"aria-expanded": isOpen && suggestions.length > 0,
|
|
5578
|
+
className: inputClass
|
|
5579
|
+
}
|
|
5580
|
+
),
|
|
5581
|
+
isOpen && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", className: "absolute left-0 right-0 top-full z-20 mt-1 overflow-hidden rounded-md border border-border bg-background shadow-lg", children: suggestions.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5582
|
+
"button",
|
|
5583
|
+
{
|
|
5584
|
+
type: "button",
|
|
5585
|
+
role: "option",
|
|
5586
|
+
"aria-selected": i === highlightedIndex,
|
|
5587
|
+
onMouseDown: (e) => {
|
|
5588
|
+
e.preventDefault();
|
|
5589
|
+
void selectSuggestion(s);
|
|
5590
|
+
},
|
|
5591
|
+
className: cn("block w-full px-3 py-2.5 text-left text-sm transition-colors", i === highlightedIndex ? "bg-muted text-foreground" : "text-foreground hover:bg-muted/70"),
|
|
5592
|
+
children: s.description
|
|
5593
|
+
},
|
|
5594
|
+
s.place_id
|
|
5595
|
+
)) }),
|
|
5596
|
+
loc && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
5597
|
+
loc.latitude.toFixed(4),
|
|
5598
|
+
", ",
|
|
5599
|
+
loc.longitude.toFixed(4)
|
|
5600
|
+
] })
|
|
5601
|
+
] });
|
|
5602
|
+
}
|
|
5603
|
+
function PhoneInput({
|
|
5604
|
+
field,
|
|
5605
|
+
value,
|
|
5606
|
+
onValueChange,
|
|
5607
|
+
classNames,
|
|
5608
|
+
inputClass
|
|
5609
|
+
}) {
|
|
5610
|
+
const phone = value && typeof value === "object" ? value : null;
|
|
5611
|
+
const [code, setCode] = React10__default.default.useState(phone?.country_code ?? "+1");
|
|
5612
|
+
const [number, setNumber] = React10__default.default.useState(phone?.number ?? "");
|
|
5613
|
+
const update = (nextCode, nextNumber) => {
|
|
5614
|
+
setCode(nextCode);
|
|
5615
|
+
setNumber(nextNumber);
|
|
5616
|
+
if (nextNumber) {
|
|
5617
|
+
onValueChange({
|
|
5618
|
+
country_code: nextCode,
|
|
5619
|
+
number: nextNumber,
|
|
5620
|
+
formatted: `${nextCode} ${nextNumber}`
|
|
5621
|
+
});
|
|
5622
|
+
} else {
|
|
5623
|
+
onValueChange(void 0);
|
|
5624
|
+
}
|
|
5625
|
+
};
|
|
5626
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-2", classNames?.phoneInput), children: [
|
|
5627
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5628
|
+
"input",
|
|
5629
|
+
{
|
|
5630
|
+
type: "text",
|
|
5631
|
+
value: code,
|
|
5632
|
+
onChange: (e) => update(e.target.value, number),
|
|
5633
|
+
placeholder: "+1",
|
|
5634
|
+
className: cn(inputClass, "w-20 shrink-0")
|
|
5635
|
+
}
|
|
5636
|
+
),
|
|
5637
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5638
|
+
"input",
|
|
5639
|
+
{
|
|
5640
|
+
type: "tel",
|
|
5641
|
+
value: number,
|
|
5642
|
+
onChange: (e) => update(code, e.target.value),
|
|
5643
|
+
placeholder: field.placeholder || "Phone number",
|
|
5644
|
+
required: field.is_required,
|
|
5645
|
+
className: inputClass
|
|
5646
|
+
}
|
|
5647
|
+
)
|
|
5648
|
+
] });
|
|
5649
|
+
}
|
|
5650
|
+
function SignatureInput({
|
|
5651
|
+
field,
|
|
5652
|
+
value,
|
|
5653
|
+
onValueChange,
|
|
5654
|
+
classNames
|
|
5655
|
+
}) {
|
|
5656
|
+
const sig = value && typeof value === "object" ? value : null;
|
|
5657
|
+
const canvasRef = React10__default.default.useRef(null);
|
|
5658
|
+
const isDrawing = React10__default.default.useRef(false);
|
|
5659
|
+
const getCtx = () => canvasRef.current?.getContext("2d") ?? null;
|
|
5660
|
+
const startDraw = (e) => {
|
|
5661
|
+
const ctx = getCtx();
|
|
5662
|
+
if (!ctx) return;
|
|
5663
|
+
isDrawing.current = true;
|
|
5664
|
+
const rect = canvasRef.current.getBoundingClientRect();
|
|
5665
|
+
ctx.beginPath();
|
|
5666
|
+
ctx.moveTo(e.clientX - rect.left, e.clientY - rect.top);
|
|
5667
|
+
canvasRef.current.setPointerCapture(e.pointerId);
|
|
5668
|
+
};
|
|
5669
|
+
const draw = (e) => {
|
|
5670
|
+
if (!isDrawing.current) return;
|
|
5671
|
+
const ctx = getCtx();
|
|
5672
|
+
if (!ctx) return;
|
|
5673
|
+
const rect = canvasRef.current.getBoundingClientRect();
|
|
5674
|
+
ctx.lineWidth = 2;
|
|
5675
|
+
ctx.lineCap = "round";
|
|
5676
|
+
const style = getComputedStyle(canvasRef.current);
|
|
5677
|
+
ctx.strokeStyle = style.color || "#000";
|
|
5678
|
+
ctx.lineTo(e.clientX - rect.left, e.clientY - rect.top);
|
|
5679
|
+
ctx.stroke();
|
|
5680
|
+
};
|
|
5681
|
+
const endDraw = () => {
|
|
5682
|
+
if (!isDrawing.current) return;
|
|
5683
|
+
isDrawing.current = false;
|
|
5684
|
+
const canvas = canvasRef.current;
|
|
5685
|
+
if (!canvas) return;
|
|
5686
|
+
onValueChange({
|
|
5687
|
+
data_url: canvas.toDataURL("image/png"),
|
|
5688
|
+
signer_name: sig?.signer_name
|
|
5689
|
+
});
|
|
5690
|
+
};
|
|
5691
|
+
const clear = () => {
|
|
5692
|
+
const canvas = canvasRef.current;
|
|
5693
|
+
if (!canvas) return;
|
|
5694
|
+
const ctx = canvas.getContext("2d");
|
|
5695
|
+
if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
5696
|
+
onValueChange(void 0);
|
|
5697
|
+
};
|
|
5698
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", classNames?.signatureCanvas), children: [
|
|
5699
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative rounded-md border border-input overflow-hidden", children: [
|
|
5700
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5701
|
+
"canvas",
|
|
5702
|
+
{
|
|
5703
|
+
ref: canvasRef,
|
|
5704
|
+
width: 400,
|
|
5705
|
+
height: 150,
|
|
5706
|
+
className: "w-full touch-none cursor-crosshair bg-background text-foreground",
|
|
5707
|
+
onPointerDown: startDraw,
|
|
5708
|
+
onPointerMove: draw,
|
|
5709
|
+
onPointerUp: endDraw,
|
|
5710
|
+
onPointerLeave: endDraw
|
|
5711
|
+
}
|
|
5712
|
+
),
|
|
5713
|
+
sig?.data_url && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5714
|
+
"button",
|
|
5715
|
+
{
|
|
5716
|
+
type: "button",
|
|
5717
|
+
onClick: clear,
|
|
5718
|
+
className: "absolute top-1.5 right-1.5 text-xs text-muted-foreground hover:text-destructive transition-colors",
|
|
5719
|
+
children: "Clear"
|
|
5720
|
+
}
|
|
5721
|
+
)
|
|
5722
|
+
] }),
|
|
5723
|
+
!sig?.data_url && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: field.placeholder || "Draw your signature above" })
|
|
5724
|
+
] });
|
|
5725
|
+
}
|
|
5726
|
+
function createSessionToken() {
|
|
5727
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
5728
|
+
return crypto.randomUUID();
|
|
5729
|
+
}
|
|
5730
|
+
return `places_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
5731
|
+
}
|
|
4778
5732
|
function ProductCustomizer({
|
|
4779
5733
|
product,
|
|
4780
5734
|
onAddToCart,
|
|
@@ -4782,20 +5736,21 @@ function ProductCustomizer({
|
|
|
4782
5736
|
className,
|
|
4783
5737
|
classNames
|
|
4784
5738
|
}) {
|
|
4785
|
-
const [quantity, setQuantity] =
|
|
4786
|
-
const [isAdded, setIsAdded] =
|
|
4787
|
-
const [isSubmitting, setIsSubmitting] =
|
|
4788
|
-
const [selectedVariantId, setSelectedVariantId] =
|
|
4789
|
-
const [selectedVariant, setSelectedVariant] =
|
|
4790
|
-
const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] =
|
|
4791
|
-
const [compositeSelections, setCompositeSelections] =
|
|
4792
|
-
const [compositePrice, setCompositePrice] =
|
|
4793
|
-
const [compositeReady, setCompositeReady] =
|
|
4794
|
-
const [bundleSelections, setBundleSelections] =
|
|
4795
|
-
const [bundleTotalPrice, setBundleTotalPrice] =
|
|
4796
|
-
const [bundleReady, setBundleReady] =
|
|
4797
|
-
const [selectedBillingPlan, setSelectedBillingPlan] =
|
|
4798
|
-
const [
|
|
5739
|
+
const [quantity, setQuantity] = React10.useState(product.min_order_quantity ?? 1);
|
|
5740
|
+
const [isAdded, setIsAdded] = React10.useState(false);
|
|
5741
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
5742
|
+
const [selectedVariantId, setSelectedVariantId] = React10.useState();
|
|
5743
|
+
const [selectedVariant, setSelectedVariant] = React10.useState();
|
|
5744
|
+
const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] = React10.useState([]);
|
|
5745
|
+
const [compositeSelections, setCompositeSelections] = React10.useState([]);
|
|
5746
|
+
const [compositePrice, setCompositePrice] = React10.useState(null);
|
|
5747
|
+
const [compositeReady, setCompositeReady] = React10.useState(false);
|
|
5748
|
+
const [bundleSelections, setBundleSelections] = React10.useState([]);
|
|
5749
|
+
const [bundleTotalPrice, setBundleTotalPrice] = React10.useState(null);
|
|
5750
|
+
const [bundleReady, setBundleReady] = React10.useState(false);
|
|
5751
|
+
const [selectedBillingPlan, setSelectedBillingPlan] = React10.useState(null);
|
|
5752
|
+
const [customerInputValues, setCustomerInputValues] = React10.useState({});
|
|
5753
|
+
const [specialInstructions, setSpecialInstructions] = React10.useState("");
|
|
4799
5754
|
const cart = useCart();
|
|
4800
5755
|
const productType = product.type || "product";
|
|
4801
5756
|
const isComposite = productType === "composite";
|
|
@@ -4805,7 +5760,7 @@ function ProductCustomizer({
|
|
|
4805
5760
|
const isStandard = !isComposite && !isBundle;
|
|
4806
5761
|
const hasVariants = isStandard && product.variants && product.variants.length > 0;
|
|
4807
5762
|
const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;
|
|
4808
|
-
|
|
5763
|
+
React10.useEffect(() => {
|
|
4809
5764
|
setQuantity(product.min_order_quantity ?? 1);
|
|
4810
5765
|
setIsAdded(false);
|
|
4811
5766
|
setIsSubmitting(false);
|
|
@@ -4819,9 +5774,10 @@ function ProductCustomizer({
|
|
|
4819
5774
|
setBundleTotalPrice(null);
|
|
4820
5775
|
setBundleReady(false);
|
|
4821
5776
|
setSelectedBillingPlan(null);
|
|
5777
|
+
setCustomerInputValues({});
|
|
4822
5778
|
setSpecialInstructions("");
|
|
4823
5779
|
}, [product.id, product.min_order_quantity]);
|
|
4824
|
-
const selectedAddOnOptions =
|
|
5780
|
+
const selectedAddOnOptions = React10.useMemo(() => {
|
|
4825
5781
|
if (!product.add_ons) return [];
|
|
4826
5782
|
const options = [];
|
|
4827
5783
|
for (const addOn of product.add_ons) {
|
|
@@ -4833,11 +5789,11 @@ function ProductCustomizer({
|
|
|
4833
5789
|
}
|
|
4834
5790
|
return options;
|
|
4835
5791
|
}, [product.add_ons, selectedAddOnOptionIds]);
|
|
4836
|
-
const normalizedAddOnOptionIds =
|
|
5792
|
+
const normalizedAddOnOptionIds = React10.useMemo(() => {
|
|
4837
5793
|
if (selectedAddOnOptionIds.length === 0) return [];
|
|
4838
5794
|
return Array.from(new Set(selectedAddOnOptionIds.map((id) => id.trim()).filter(Boolean))).sort();
|
|
4839
5795
|
}, [selectedAddOnOptionIds]);
|
|
4840
|
-
const localTotalPrice =
|
|
5796
|
+
const localTotalPrice = React10.useMemo(() => {
|
|
4841
5797
|
if (isComposite && compositePrice) {
|
|
4842
5798
|
return chunkPEDLCL72_js.parsePrice(compositePrice.final_price) * quantity;
|
|
4843
5799
|
}
|
|
@@ -4855,7 +5811,7 @@ function ProductCustomizer({
|
|
|
4855
5811
|
}
|
|
4856
5812
|
return price * quantity;
|
|
4857
5813
|
}, [product.default_price, selectedVariant, selectedAddOnOptions, quantity, isComposite, compositePrice, isBundle, bundleTotalPrice]);
|
|
4858
|
-
const requiredAddOnsSatisfied =
|
|
5814
|
+
const requiredAddOnsSatisfied = React10.useMemo(() => {
|
|
4859
5815
|
if (!product.add_ons) return true;
|
|
4860
5816
|
for (const addOn of product.add_ons) {
|
|
4861
5817
|
if (addOn.is_required) {
|
|
@@ -4870,7 +5826,7 @@ function ProductCustomizer({
|
|
|
4870
5826
|
}
|
|
4871
5827
|
return true;
|
|
4872
5828
|
}, [product.add_ons, selectedAddOnOptionIds]);
|
|
4873
|
-
const quoteInput =
|
|
5829
|
+
const quoteInput = React10.useMemo(
|
|
4874
5830
|
() => ({
|
|
4875
5831
|
productId: product.id,
|
|
4876
5832
|
quantity,
|
|
@@ -4881,12 +5837,20 @@ function ProductCustomizer({
|
|
|
4881
5837
|
}),
|
|
4882
5838
|
[product.id, quantity, selectedVariantId, normalizedAddOnOptionIds, isBundle, bundleSelections, isComposite, compositeSelections]
|
|
4883
5839
|
);
|
|
4884
|
-
const
|
|
5840
|
+
const requiredInputsSatisfied = React10.useMemo(() => {
|
|
5841
|
+
if (!product.input_fields || product.input_fields.length === 0) return true;
|
|
5842
|
+
return product.input_fields.every((field) => {
|
|
5843
|
+
if (!field.is_required) return true;
|
|
5844
|
+
const val = customerInputValues[field.id];
|
|
5845
|
+
return val !== void 0 && val !== "" && val !== null;
|
|
5846
|
+
});
|
|
5847
|
+
}, [product.input_fields, customerInputValues]);
|
|
5848
|
+
const quoteEnabled = isComposite ? compositeReady && requiredInputsSatisfied : isBundle ? bundleReady && requiredInputsSatisfied : requiredAddOnsSatisfied && requiredInputsSatisfied;
|
|
4885
5849
|
const { quote } = useQuote(quoteInput, {
|
|
4886
5850
|
enabled: quoteEnabled
|
|
4887
5851
|
});
|
|
4888
5852
|
const quoteId = quote?.quote_id;
|
|
4889
|
-
const quotedTotalPrice =
|
|
5853
|
+
const quotedTotalPrice = React10.useMemo(() => {
|
|
4890
5854
|
if (!quote) return void 0;
|
|
4891
5855
|
const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;
|
|
4892
5856
|
const perUnit = priceInfo.pre_tax_price;
|
|
@@ -4894,16 +5858,16 @@ function ProductCustomizer({
|
|
|
4894
5858
|
return chunkPEDLCL72_js.parsePrice(perUnit) * quantity;
|
|
4895
5859
|
}, [quote, quantity]);
|
|
4896
5860
|
const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;
|
|
4897
|
-
const handleVariantChange =
|
|
5861
|
+
const handleVariantChange = React10.useCallback(
|
|
4898
5862
|
(variantId, variant) => {
|
|
4899
5863
|
setSelectedVariantId(variantId);
|
|
4900
5864
|
setSelectedVariant(variant);
|
|
4901
5865
|
},
|
|
4902
5866
|
[]
|
|
4903
5867
|
);
|
|
4904
|
-
const addedTimerRef =
|
|
4905
|
-
|
|
4906
|
-
const handleAddToCart =
|
|
5868
|
+
const addedTimerRef = React10.useRef(void 0);
|
|
5869
|
+
React10.useEffect(() => () => clearTimeout(addedTimerRef.current), []);
|
|
5870
|
+
const handleAddToCart = React10.useCallback(async () => {
|
|
4907
5871
|
if (isSubmitting) return;
|
|
4908
5872
|
setIsSubmitting(true);
|
|
4909
5873
|
const options = {
|
|
@@ -4920,6 +5884,7 @@ function ProductCustomizer({
|
|
|
4920
5884
|
compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : void 0,
|
|
4921
5885
|
bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : void 0,
|
|
4922
5886
|
billingPlanId: selectedBillingPlan?.id,
|
|
5887
|
+
customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
|
|
4923
5888
|
specialInstructions: specialInstructions.trim() || void 0
|
|
4924
5889
|
};
|
|
4925
5890
|
try {
|
|
@@ -4938,7 +5903,7 @@ function ProductCustomizer({
|
|
|
4938
5903
|
} finally {
|
|
4939
5904
|
setIsSubmitting(false);
|
|
4940
5905
|
}
|
|
4941
|
-
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, specialInstructions, isSubmitting, onAddToCart, cart]);
|
|
5906
|
+
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isSubmitting, onAddToCart, cart]);
|
|
4942
5907
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
|
|
4943
5908
|
isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4944
5909
|
CompositeSelector,
|
|
@@ -4999,6 +5964,14 @@ function ProductCustomizer({
|
|
|
4999
5964
|
currentQuantity: quantity
|
|
5000
5965
|
}
|
|
5001
5966
|
),
|
|
5967
|
+
product.input_fields && product.input_fields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5968
|
+
CustomerInputFields,
|
|
5969
|
+
{
|
|
5970
|
+
fields: product.input_fields,
|
|
5971
|
+
values: customerInputValues,
|
|
5972
|
+
onChange: setCustomerInputValues
|
|
5973
|
+
}
|
|
5974
|
+
),
|
|
5002
5975
|
product.deposit_type && product.deposit_type !== "none" && product.deposit_amount && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-customizer-deposit": true, className: cn("text-sm text-muted-foreground", classNames?.depositInfo), children: product.deposit_type === "fixed" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5003
5976
|
"Deposit required: ",
|
|
5004
5977
|
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.deposit_amount })
|
|
@@ -5106,14 +6079,14 @@ function ProductImageGallery({
|
|
|
5106
6079
|
aspectRatio = "4/3",
|
|
5107
6080
|
className
|
|
5108
6081
|
}) {
|
|
5109
|
-
const normalizedImages =
|
|
6082
|
+
const normalizedImages = React10.useMemo(
|
|
5110
6083
|
() => images.filter(
|
|
5111
6084
|
(image) => typeof image === "string" && image.trim().length > 0
|
|
5112
6085
|
),
|
|
5113
6086
|
[images]
|
|
5114
6087
|
);
|
|
5115
|
-
const [selectedImage, setSelectedImage] =
|
|
5116
|
-
|
|
6088
|
+
const [selectedImage, setSelectedImage] = React10.useState(0);
|
|
6089
|
+
React10.useEffect(() => {
|
|
5117
6090
|
setSelectedImage(0);
|
|
5118
6091
|
}, [normalizedImages.length, productName]);
|
|
5119
6092
|
if (normalizedImages.length === 0) {
|
|
@@ -5193,13 +6166,17 @@ function CartLineItemRow({
|
|
|
5193
6166
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item": true, className: classNames?.item, children: [
|
|
5194
6167
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-item-info": true, children: [
|
|
5195
6168
|
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-name": true, className: classNames?.itemName, children: item.product.name }),
|
|
5196
|
-
item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children:
|
|
6169
|
+
item.variant && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-variant": true, children: chunkR4AKAGZQ_js.getVariantDisplayName(item.variant, item.product.name) }),
|
|
5197
6170
|
item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-cart-item-addons": true, children: [
|
|
5198
6171
|
"+ ",
|
|
5199
6172
|
item.addOnOptions.map((opt) => opt.name).join(", ")
|
|
5200
6173
|
] }),
|
|
5201
6174
|
(hasComposite || hasBundle) && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-badge": true, children: hasComposite ? "Custom" : "Bundle" }),
|
|
5202
6175
|
item.specialInstructions && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-item-instructions": true, className: "text-xs text-muted-foreground", children: item.specialInstructions }),
|
|
6176
|
+
item.customerInputs && item.customerInputs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-cart-customer-inputs": true, className: classNames?.customerInputs, children: item.customerInputs.map((input) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-input": true, children: [
|
|
6177
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-label": true, children: input.field_name }),
|
|
6178
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-cart-input-value": true, children: input.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.File || input.field_type === chunkR4AKAGZQ_js.INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
|
|
6179
|
+
] }, input.field_id)) }),
|
|
5203
6180
|
(item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-info": true, className: classNames?.serviceInfo, children: [
|
|
5204
6181
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5205
6182
|
"\u{1F4C5}",
|
|
@@ -5718,7 +6695,7 @@ function FoodProductCard({
|
|
|
5718
6695
|
const tags = product.tags || [];
|
|
5719
6696
|
const isSignature = product.metadata?.is_signature === true;
|
|
5720
6697
|
const isNew = product.metadata?.is_new === true;
|
|
5721
|
-
const isComposite = product.type ===
|
|
6698
|
+
const isComposite = product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Composite;
|
|
5722
6699
|
return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
|
|
5723
6700
|
/* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
|
|
5724
6701
|
isSignature && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 left-3 inline-flex items-center gap-1 text-[11px] font-semibold tracking-wide bg-amber-50 text-amber-700 border border-amber-200/60 px-2 py-0.5 rounded-md", children: [
|
|
@@ -5887,6 +6864,98 @@ function DigitalProductCard({
|
|
|
5887
6864
|
] })
|
|
5888
6865
|
] });
|
|
5889
6866
|
}
|
|
6867
|
+
function BundleProductCard({
|
|
6868
|
+
product,
|
|
6869
|
+
onQuickAdd,
|
|
6870
|
+
renderImage,
|
|
6871
|
+
renderLink,
|
|
6872
|
+
className
|
|
6873
|
+
}) {
|
|
6874
|
+
const image = product.image_url || product.images?.[0] || "";
|
|
6875
|
+
const components = product.components || [];
|
|
6876
|
+
const componentCount = components.length;
|
|
6877
|
+
const onSale = chunkPEDLCL72_js.isOnSale(product);
|
|
6878
|
+
const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
|
|
6879
|
+
const hasVariantChoice = components.some((c) => c.allow_variant_choice);
|
|
6880
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
|
|
6881
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
|
|
6882
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-3 left-3 text-[11px] font-semibold tracking-wide bg-indigo-50 text-indigo-700 border border-indigo-200/60 px-2 py-0.5 rounded-md", children: "Bundle" }),
|
|
6883
|
+
componentCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 right-3 text-[11px] font-semibold tracking-wide bg-background/90 backdrop-blur text-foreground px-2 py-0.5 rounded-md", children: [
|
|
6884
|
+
componentCount,
|
|
6885
|
+
" item",
|
|
6886
|
+
componentCount !== 1 ? "s" : ""
|
|
6887
|
+
] }),
|
|
6888
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6889
|
+
QuickAddButton,
|
|
6890
|
+
{
|
|
6891
|
+
onClick: () => onQuickAdd?.(product),
|
|
6892
|
+
className: "absolute bottom-3 right-3"
|
|
6893
|
+
}
|
|
6894
|
+
)
|
|
6895
|
+
] }),
|
|
6896
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3.5", children: [
|
|
6897
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14.5px] font-semibold text-foreground leading-snug tracking-tight truncate", children: product.name }),
|
|
6898
|
+
componentCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[11px] text-muted-foreground mt-1 truncate", children: [
|
|
6899
|
+
"Includes: ",
|
|
6900
|
+
components.map((c) => c.product_name || c.product_id).join(", ")
|
|
6901
|
+
] }),
|
|
6902
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2.5", children: [
|
|
6903
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-sm font-bold" }),
|
|
6904
|
+
onSale && product.bundle_price && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6905
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: chunkPEDLCL72_js.getBasePrice(product), className: "text-xs text-muted-foreground line-through" }),
|
|
6906
|
+
discount != null && discount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-semibold text-emerald-600", children: [
|
|
6907
|
+
"Save ",
|
|
6908
|
+
discount,
|
|
6909
|
+
"%"
|
|
6910
|
+
] })
|
|
6911
|
+
] })
|
|
6912
|
+
] }),
|
|
6913
|
+
hasVariantChoice && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mt-2 text-[10px] font-medium text-muted-foreground px-1.5 py-0.5 bg-muted rounded", children: "Customizable" })
|
|
6914
|
+
] })
|
|
6915
|
+
] });
|
|
6916
|
+
}
|
|
6917
|
+
function CompositeProductCard({
|
|
6918
|
+
product,
|
|
6919
|
+
onQuickAdd,
|
|
6920
|
+
renderImage,
|
|
6921
|
+
renderLink,
|
|
6922
|
+
className
|
|
6923
|
+
}) {
|
|
6924
|
+
const image = product.image_url || product.images?.[0] || "";
|
|
6925
|
+
const groups = product.groups || [];
|
|
6926
|
+
const groupCount = groups.length;
|
|
6927
|
+
groups.reduce((sum, g) => sum + g.components.length, 0);
|
|
6928
|
+
const tags = product.tags || [];
|
|
6929
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
|
|
6930
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
|
|
6931
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-3 left-3 text-[11px] font-semibold tracking-wide bg-violet-50 text-violet-700 border border-violet-200/60 px-2 py-0.5 rounded-md", children: "Build Your Own" }),
|
|
6932
|
+
groupCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 right-3 text-[11px] font-semibold tracking-wide bg-background/90 backdrop-blur text-foreground px-2 py-0.5 rounded-md", children: [
|
|
6933
|
+
groupCount,
|
|
6934
|
+
" choice",
|
|
6935
|
+
groupCount !== 1 ? "s" : ""
|
|
6936
|
+
] }),
|
|
6937
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6938
|
+
QuickAddButton,
|
|
6939
|
+
{
|
|
6940
|
+
onClick: () => onQuickAdd?.(product),
|
|
6941
|
+
className: "absolute bottom-3 right-3"
|
|
6942
|
+
}
|
|
6943
|
+
)
|
|
6944
|
+
] }),
|
|
6945
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3.5", children: [
|
|
6946
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14.5px] font-semibold text-foreground leading-snug tracking-tight truncate", children: product.name }),
|
|
6947
|
+
product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] text-muted-foreground mt-1 line-clamp-1", children: product.description }),
|
|
6948
|
+
groupCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-muted-foreground mt-1 truncate", children: groups.map((g) => g.name).join(" + ") }),
|
|
6949
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mt-2.5", children: [
|
|
6950
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-bold", children: [
|
|
6951
|
+
"From ",
|
|
6952
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price })
|
|
6953
|
+
] }),
|
|
6954
|
+
tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-muted-foreground px-1.5 py-0.5 bg-muted rounded", children: tags[0] })
|
|
6955
|
+
] })
|
|
6956
|
+
] })
|
|
6957
|
+
] });
|
|
6958
|
+
}
|
|
5890
6959
|
function formatDuration2(minutes, unit) {
|
|
5891
6960
|
if (unit && unit !== "minutes") return `${minutes} ${unit}`;
|
|
5892
6961
|
if (minutes >= 60) {
|
|
@@ -6348,6 +7417,8 @@ var CardVariant = /* @__PURE__ */ ((CardVariant2) => {
|
|
|
6348
7417
|
CardVariant2["Retail"] = "retail";
|
|
6349
7418
|
CardVariant2["Wholesale"] = "wholesale";
|
|
6350
7419
|
CardVariant2["Digital"] = "digital";
|
|
7420
|
+
CardVariant2["Bundle"] = "bundle";
|
|
7421
|
+
CardVariant2["Composite"] = "composite";
|
|
6351
7422
|
CardVariant2["Standard"] = "standard";
|
|
6352
7423
|
CardVariant2["Compact"] = "compact";
|
|
6353
7424
|
CardVariant2["Schedule"] = "schedule";
|
|
@@ -6372,22 +7443,30 @@ var BUILT_IN_CARDS = {
|
|
|
6372
7443
|
["rental" /* Rental */]: RentalServiceCard,
|
|
6373
7444
|
["accommodation" /* Accommodation */]: AccommodationCard,
|
|
6374
7445
|
["lease" /* Lease */]: LeaseServiceCard,
|
|
7446
|
+
["bundle" /* Bundle */]: BundleProductCard,
|
|
7447
|
+
["composite" /* Composite */]: CompositeProductCard,
|
|
6375
7448
|
["subscription" /* Subscription */]: SubscriptionCard
|
|
6376
7449
|
};
|
|
6377
|
-
var RENTAL_UNITS = /* @__PURE__ */ new Set([
|
|
6378
|
-
var LEASE_UNITS = /* @__PURE__ */ new Set([
|
|
7450
|
+
var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkR4AKAGZQ_js.DURATION_UNIT.Days, chunkR4AKAGZQ_js.DURATION_UNIT.Hours]);
|
|
7451
|
+
var LEASE_UNITS = /* @__PURE__ */ new Set([chunkR4AKAGZQ_js.DURATION_UNIT.Weeks, chunkR4AKAGZQ_js.DURATION_UNIT.Months, chunkR4AKAGZQ_js.DURATION_UNIT.Years]);
|
|
6379
7452
|
function resolveCardVariant(product) {
|
|
7453
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Bundle) {
|
|
7454
|
+
return "bundle" /* Bundle */;
|
|
7455
|
+
}
|
|
7456
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Composite) {
|
|
7457
|
+
return "composite" /* Composite */;
|
|
7458
|
+
}
|
|
6380
7459
|
if (product.quantity_pricing && product.quantity_pricing.length > 1) {
|
|
6381
7460
|
return "wholesale" /* Wholesale */;
|
|
6382
7461
|
}
|
|
6383
|
-
if (product.type ===
|
|
7462
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Digital) {
|
|
6384
7463
|
return "digital" /* Digital */;
|
|
6385
7464
|
}
|
|
6386
|
-
if (product.type ===
|
|
7465
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Service) {
|
|
6387
7466
|
if (product.duration_unit && RENTAL_UNITS.has(product.duration_unit)) {
|
|
6388
7467
|
return "rental" /* Rental */;
|
|
6389
7468
|
}
|
|
6390
|
-
if (product.duration_unit ===
|
|
7469
|
+
if (product.duration_unit === chunkR4AKAGZQ_js.DURATION_UNIT.Nights) {
|
|
6391
7470
|
return "accommodation" /* Accommodation */;
|
|
6392
7471
|
}
|
|
6393
7472
|
if (product.duration_unit && LEASE_UNITS.has(product.duration_unit)) {
|
|
@@ -6398,10 +7477,10 @@ function resolveCardVariant(product) {
|
|
|
6398
7477
|
}
|
|
6399
7478
|
return "standard" /* Standard */;
|
|
6400
7479
|
}
|
|
6401
|
-
if (product.render_hint ===
|
|
7480
|
+
if (product.render_hint === chunkR4AKAGZQ_js.RENDER_HINT.Food) {
|
|
6402
7481
|
return "food" /* Food */;
|
|
6403
7482
|
}
|
|
6404
|
-
if (product.render_hint ===
|
|
7483
|
+
if (product.render_hint === chunkR4AKAGZQ_js.RENDER_HINT.Physical) {
|
|
6405
7484
|
return "retail" /* Retail */;
|
|
6406
7485
|
}
|
|
6407
7486
|
return "retail" /* Retail */;
|
|
@@ -6422,22 +7501,22 @@ function ProductCard({
|
|
|
6422
7501
|
classNames
|
|
6423
7502
|
}) {
|
|
6424
7503
|
const mode = displayMode ?? product.display_mode ?? "card";
|
|
6425
|
-
const [isOpen, setIsOpen] =
|
|
6426
|
-
const [shouldFetch, setShouldFetch] =
|
|
7504
|
+
const [isOpen, setIsOpen] = React10.useState(false);
|
|
7505
|
+
const [shouldFetch, setShouldFetch] = React10.useState(false);
|
|
6427
7506
|
const { product: productDetails } = useProduct(
|
|
6428
7507
|
product.slug ?? product.id,
|
|
6429
7508
|
{ enabled: shouldFetch || isOpen }
|
|
6430
7509
|
);
|
|
6431
|
-
const handlePrefetch =
|
|
7510
|
+
const handlePrefetch = React10.useCallback(() => {
|
|
6432
7511
|
setShouldFetch(true);
|
|
6433
7512
|
}, []);
|
|
6434
|
-
const handleOpenChange =
|
|
7513
|
+
const handleOpenChange = React10.useCallback((open) => {
|
|
6435
7514
|
setIsOpen(open);
|
|
6436
7515
|
if (open) {
|
|
6437
7516
|
setShouldFetch(true);
|
|
6438
7517
|
}
|
|
6439
7518
|
}, []);
|
|
6440
|
-
const handleClose =
|
|
7519
|
+
const handleClose = React10.useCallback(() => {
|
|
6441
7520
|
setIsOpen(false);
|
|
6442
7521
|
}, []);
|
|
6443
7522
|
const imageUrl = product.image_url || product.images?.[0];
|
|
@@ -6566,13 +7645,13 @@ function ProductGrid({
|
|
|
6566
7645
|
className,
|
|
6567
7646
|
classNames
|
|
6568
7647
|
}) {
|
|
6569
|
-
const rawId =
|
|
7648
|
+
const rawId = React10__default.default.useId();
|
|
6570
7649
|
const gridId = `cimplify-grid-${rawId.replace(/:/g, "")}`;
|
|
6571
7650
|
const sm = columns?.sm ?? 1;
|
|
6572
7651
|
const md = columns?.md ?? 2;
|
|
6573
7652
|
const lg = columns?.lg ?? 3;
|
|
6574
7653
|
const xl = columns?.xl ?? 4;
|
|
6575
|
-
const css =
|
|
7654
|
+
const css = React10__default.default.useMemo(
|
|
6576
7655
|
() => [
|
|
6577
7656
|
`#${gridId}{display:grid;grid-template-columns:repeat(${sm},1fr);gap:1rem}`,
|
|
6578
7657
|
`@media(min-width:768px){#${gridId}{grid-template-columns:repeat(${md},1fr)}}`,
|
|
@@ -6650,12 +7729,12 @@ function SearchInput({
|
|
|
6650
7729
|
className,
|
|
6651
7730
|
classNames
|
|
6652
7731
|
}) {
|
|
6653
|
-
const mergedOptions =
|
|
7732
|
+
const mergedOptions = React10.useMemo(
|
|
6654
7733
|
() => categoryId ? { ...searchOptions, category: categoryId } : searchOptions ?? {},
|
|
6655
7734
|
[searchOptions, categoryId]
|
|
6656
7735
|
);
|
|
6657
7736
|
const { results, isLoading, query, setQuery, clear } = useSearch(mergedOptions);
|
|
6658
|
-
const handleValueChange =
|
|
7737
|
+
const handleValueChange = React10.useCallback(
|
|
6659
7738
|
(value) => {
|
|
6660
7739
|
setQuery(value);
|
|
6661
7740
|
},
|
|
@@ -6754,7 +7833,7 @@ function CategoryFilter({
|
|
|
6754
7833
|
classNames
|
|
6755
7834
|
}) {
|
|
6756
7835
|
const { categories, isLoading } = useCategories();
|
|
6757
|
-
const handleValueChange =
|
|
7836
|
+
const handleValueChange = React10.useCallback(
|
|
6758
7837
|
(value) => {
|
|
6759
7838
|
onSelect(value === ALL_VALUE ? null : String(value));
|
|
6760
7839
|
},
|
|
@@ -6821,10 +7900,10 @@ function DiscountInput({
|
|
|
6821
7900
|
className,
|
|
6822
7901
|
classNames
|
|
6823
7902
|
}) {
|
|
6824
|
-
const [code, setCode] =
|
|
6825
|
-
const [appliedValidation, setAppliedValidation] =
|
|
7903
|
+
const [code, setCode] = React10.useState("");
|
|
7904
|
+
const [appliedValidation, setAppliedValidation] = React10.useState(null);
|
|
6826
7905
|
const { validate, isValidating, error } = useValidateDiscount();
|
|
6827
|
-
const handleApply =
|
|
7906
|
+
const handleApply = React10.useCallback(async () => {
|
|
6828
7907
|
const trimmed = code.trim();
|
|
6829
7908
|
if (!trimmed) return;
|
|
6830
7909
|
const result = await validate(trimmed, orderSubtotal, locationId);
|
|
@@ -6837,12 +7916,12 @@ function DiscountInput({
|
|
|
6837
7916
|
}
|
|
6838
7917
|
}
|
|
6839
7918
|
}, [code, validate, orderSubtotal, locationId, onApply]);
|
|
6840
|
-
const handleClear =
|
|
7919
|
+
const handleClear = React10.useCallback(() => {
|
|
6841
7920
|
setCode("");
|
|
6842
7921
|
setAppliedValidation(null);
|
|
6843
7922
|
onClear?.();
|
|
6844
7923
|
}, [onClear]);
|
|
6845
|
-
const handleKeyDown =
|
|
7924
|
+
const handleKeyDown = React10.useCallback(
|
|
6846
7925
|
(e) => {
|
|
6847
7926
|
if (e.key === "Enter") {
|
|
6848
7927
|
void handleApply();
|
|
@@ -6933,7 +8012,7 @@ function CategoryGrid({
|
|
|
6933
8012
|
enabled: categoriesProp === void 0
|
|
6934
8013
|
});
|
|
6935
8014
|
const categories = categoriesProp ?? fetched;
|
|
6936
|
-
const rawId =
|
|
8015
|
+
const rawId = React10__default.default.useId();
|
|
6937
8016
|
const gridId = `cimplify-cat-grid-${rawId.replace(/:/g, "")}`;
|
|
6938
8017
|
const sm = columns?.sm ?? 2;
|
|
6939
8018
|
const md = columns?.md ?? 3;
|
|
@@ -7159,7 +8238,7 @@ function OrderSummary({
|
|
|
7159
8238
|
/* @__PURE__ */ jsxRuntime.jsx("p", { children: order.delivery_address })
|
|
7160
8239
|
] }),
|
|
7161
8240
|
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-order-items": true, className: classNames?.items, children: order.items.map(
|
|
7162
|
-
(item) => renderLineItem ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8241
|
+
(item) => renderLineItem ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderLineItem(item) }, item.id) : /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-line-item": true, className: classNames?.lineItem, children: [
|
|
7163
8242
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-order-line-info": true, children: [
|
|
7164
8243
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-order-line-qty": true, children: [
|
|
7165
8244
|
item.quantity,
|
|
@@ -7594,9 +8673,9 @@ function DateSlotPicker({
|
|
|
7594
8673
|
className,
|
|
7595
8674
|
classNames
|
|
7596
8675
|
}) {
|
|
7597
|
-
const [offset, setOffset] =
|
|
7598
|
-
const [selectedDate, setSelectedDate] =
|
|
7599
|
-
const dateRange =
|
|
8676
|
+
const [offset, setOffset] = React10.useState(0);
|
|
8677
|
+
const [selectedDate, setSelectedDate] = React10.useState(toDateString(/* @__PURE__ */ new Date()));
|
|
8678
|
+
const dateRange = React10.useMemo(() => {
|
|
7600
8679
|
const today = /* @__PURE__ */ new Date();
|
|
7601
8680
|
const start = addDays(today, offset);
|
|
7602
8681
|
const dates = [];
|
|
@@ -7619,25 +8698,25 @@ function DateSlotPicker({
|
|
|
7619
8698
|
}
|
|
7620
8699
|
);
|
|
7621
8700
|
const days = availabilityProp ?? fetchedDays;
|
|
7622
|
-
const availabilityMap =
|
|
8701
|
+
const availabilityMap = React10.useMemo(() => {
|
|
7623
8702
|
const map = /* @__PURE__ */ new Map();
|
|
7624
8703
|
for (const day of days) {
|
|
7625
8704
|
map.set(day.date, day);
|
|
7626
8705
|
}
|
|
7627
8706
|
return map;
|
|
7628
8707
|
}, [days]);
|
|
7629
|
-
const handlePrev =
|
|
8708
|
+
const handlePrev = React10.useCallback(() => {
|
|
7630
8709
|
setOffset((prev) => Math.max(0, prev - daysToShow));
|
|
7631
8710
|
}, [daysToShow]);
|
|
7632
|
-
const handleNext =
|
|
8711
|
+
const handleNext = React10.useCallback(() => {
|
|
7633
8712
|
setOffset((prev) => prev + daysToShow);
|
|
7634
8713
|
}, [daysToShow]);
|
|
7635
|
-
const handleDateChange =
|
|
8714
|
+
const handleDateChange = React10.useCallback((value) => {
|
|
7636
8715
|
if (typeof value === "string") {
|
|
7637
8716
|
setSelectedDate(value);
|
|
7638
8717
|
}
|
|
7639
8718
|
}, []);
|
|
7640
|
-
const handleSlotSelect =
|
|
8719
|
+
const handleSlotSelect = React10.useCallback(
|
|
7641
8720
|
(slot) => {
|
|
7642
8721
|
onSlotSelect?.(slot, selectedDate);
|
|
7643
8722
|
},
|
|
@@ -8140,7 +9219,7 @@ function DefaultCatalogueLayout({
|
|
|
8140
9219
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-medium", children: "No products found" }),
|
|
8141
9220
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try adjusting your filters" })
|
|
8142
9221
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: products.map(
|
|
8143
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9222
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8144
9223
|
ProductCard,
|
|
8145
9224
|
{
|
|
8146
9225
|
product,
|
|
@@ -8247,7 +9326,7 @@ function CompactCatalogueLayout({
|
|
|
8247
9326
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-medium", children: "No items found" }),
|
|
8248
9327
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different category or search" })
|
|
8249
9328
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: products.map(
|
|
8250
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9329
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8251
9330
|
ProductCard,
|
|
8252
9331
|
{
|
|
8253
9332
|
product,
|
|
@@ -8270,8 +9349,8 @@ var BUILT_IN_LAYOUTS = {
|
|
|
8270
9349
|
["compact" /* Compact */]: CompactCatalogueLayout
|
|
8271
9350
|
};
|
|
8272
9351
|
function useDebounce(value, delay) {
|
|
8273
|
-
const [debounced, setDebounced] =
|
|
8274
|
-
|
|
9352
|
+
const [debounced, setDebounced] = React10__default.default.useState(value);
|
|
9353
|
+
React10__default.default.useEffect(() => {
|
|
8275
9354
|
const timer = setTimeout(() => setDebounced(value), delay);
|
|
8276
9355
|
return () => clearTimeout(timer);
|
|
8277
9356
|
}, [value, delay]);
|
|
@@ -8295,15 +9374,15 @@ function CataloguePage({
|
|
|
8295
9374
|
className,
|
|
8296
9375
|
classNames
|
|
8297
9376
|
}) {
|
|
8298
|
-
const [selectedCategory, setSelectedCategory] =
|
|
8299
|
-
const [searchQuery, setSearchQuery] =
|
|
8300
|
-
const [sortBy, setSortBy] =
|
|
8301
|
-
const [sortOrder, setSortOrder] =
|
|
8302
|
-
const [inStockOnly, setInStockOnly] =
|
|
8303
|
-
const [selectedTags, setSelectedTags] =
|
|
8304
|
-
const [minPrice, setMinPrice] =
|
|
8305
|
-
const [maxPrice, setMaxPrice] =
|
|
8306
|
-
const [page, setPage] =
|
|
9377
|
+
const [selectedCategory, setSelectedCategory] = React10.useState(null);
|
|
9378
|
+
const [searchQuery, setSearchQuery] = React10.useState("");
|
|
9379
|
+
const [sortBy, setSortBy] = React10.useState(defaultSort?.by ?? "created_at");
|
|
9380
|
+
const [sortOrder, setSortOrder] = React10.useState(defaultSort?.order ?? "desc");
|
|
9381
|
+
const [inStockOnly, setInStockOnly] = React10.useState(false);
|
|
9382
|
+
const [selectedTags, setSelectedTags] = React10.useState([]);
|
|
9383
|
+
const [minPrice, setMinPrice] = React10.useState("");
|
|
9384
|
+
const [maxPrice, setMaxPrice] = React10.useState("");
|
|
9385
|
+
const [page, setPage] = React10.useState(1);
|
|
8307
9386
|
const debouncedSearch = useDebounce(searchQuery, 300);
|
|
8308
9387
|
const { products: fetchedProducts, isLoading, pagination } = useProducts({
|
|
8309
9388
|
enabled: productsProp === void 0,
|
|
@@ -8324,22 +9403,22 @@ function CataloguePage({
|
|
|
8324
9403
|
const products = productsProp ?? fetchedProducts;
|
|
8325
9404
|
const categories = categoriesProp ?? fetchedCategories;
|
|
8326
9405
|
const totalPages = pagination?.total_pages ?? 1;
|
|
8327
|
-
const handleCategoryChange =
|
|
9406
|
+
const handleCategoryChange = React10.useCallback((id) => {
|
|
8328
9407
|
setSelectedCategory(id);
|
|
8329
9408
|
setPage(1);
|
|
8330
9409
|
}, []);
|
|
8331
|
-
const handleSortChange =
|
|
9410
|
+
const handleSortChange = React10.useCallback((by, order) => {
|
|
8332
9411
|
setSortBy(by);
|
|
8333
9412
|
setSortOrder(order);
|
|
8334
9413
|
setPage(1);
|
|
8335
9414
|
}, []);
|
|
8336
|
-
const handleTagToggle =
|
|
9415
|
+
const handleTagToggle = React10.useCallback((tag) => {
|
|
8337
9416
|
setSelectedTags(
|
|
8338
9417
|
(prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
|
|
8339
9418
|
);
|
|
8340
9419
|
setPage(1);
|
|
8341
9420
|
}, []);
|
|
8342
|
-
const handlePriceRangeChange =
|
|
9421
|
+
const handlePriceRangeChange = React10.useCallback((min, max) => {
|
|
8343
9422
|
setMinPrice(min);
|
|
8344
9423
|
setMaxPrice(max);
|
|
8345
9424
|
setPage(1);
|
|
@@ -8999,12 +10078,161 @@ function DigitalProductLayout({
|
|
|
8999
10078
|
)
|
|
9000
10079
|
] });
|
|
9001
10080
|
}
|
|
10081
|
+
function BundleProductLayout({
|
|
10082
|
+
product,
|
|
10083
|
+
onAddToCart,
|
|
10084
|
+
renderBreadcrumb,
|
|
10085
|
+
relatedProducts,
|
|
10086
|
+
showRelated = true,
|
|
10087
|
+
className
|
|
10088
|
+
}) {
|
|
10089
|
+
const images = product.images || (product.image_url ? [product.image_url] : []);
|
|
10090
|
+
const components = product.components || [];
|
|
10091
|
+
const onSale = chunkPEDLCL72_js.isOnSale(product);
|
|
10092
|
+
const discount = chunkPEDLCL72_js.getDiscountPercentage(product);
|
|
10093
|
+
const baseTotal = components.reduce(
|
|
10094
|
+
(sum, c) => sum + chunkPEDLCL72_js.parsePrice(c.effective_price ?? 0) * (c.quantity ?? 1),
|
|
10095
|
+
0
|
|
10096
|
+
);
|
|
10097
|
+
const bundlePrice = chunkPEDLCL72_js.parsePrice(product.default_price);
|
|
10098
|
+
const savings = baseTotal > bundlePrice ? baseTotal - bundlePrice : 0;
|
|
10099
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "bundle", className: cn("space-y-8", className), children: [
|
|
10100
|
+
renderBreadcrumb?.(product),
|
|
10101
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10102
|
+
TwoColumnGrid,
|
|
10103
|
+
{
|
|
10104
|
+
left: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10105
|
+
ProductImageGallery,
|
|
10106
|
+
{
|
|
10107
|
+
images,
|
|
10108
|
+
productName: product.name
|
|
10109
|
+
}
|
|
10110
|
+
),
|
|
10111
|
+
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
10112
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
10113
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-indigo-700 bg-indigo-50 border border-indigo-200/60 px-2.5 py-1 rounded-md", children: "Bundle" }),
|
|
10114
|
+
savings > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-emerald-700 bg-emerald-50 border border-emerald-200/60 px-2.5 py-1 rounded-md", children: [
|
|
10115
|
+
"Save ",
|
|
10116
|
+
discount,
|
|
10117
|
+
"%"
|
|
10118
|
+
] }),
|
|
10119
|
+
/* @__PURE__ */ jsxRuntime.jsx(TagPills, { tags: product.tags || [] })
|
|
10120
|
+
] }),
|
|
10121
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10122
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { "data-cimplify-product-layout-name": true, className: "text-3xl lg:text-4xl font-bold tracking-tight", children: product.name }),
|
|
10123
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-3 mt-2", children: [
|
|
10124
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "text-2xl font-bold" }),
|
|
10125
|
+
onSale && baseTotal > 0 && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: baseTotal, className: "text-lg text-muted-foreground line-through" })
|
|
10126
|
+
] })
|
|
10127
|
+
] }),
|
|
10128
|
+
product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-product-layout-description": true, className: "text-muted-foreground leading-relaxed", children: product.description }),
|
|
10129
|
+
components.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-bundle-components": true, className: "space-y-3", children: [
|
|
10130
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: "Included in this bundle" }),
|
|
10131
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border border border-border rounded-lg overflow-hidden", children: components.map((component) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-3", children: [
|
|
10132
|
+
component.product_image_url && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-lg overflow-hidden bg-muted shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: component.product_image_url, alt: component.product_name, className: "w-full h-full object-cover" }) }),
|
|
10133
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
10134
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: component.product_name }),
|
|
10135
|
+
component.quantity > 1 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
10136
|
+
"Qty: ",
|
|
10137
|
+
component.quantity
|
|
10138
|
+
] }),
|
|
10139
|
+
component.allow_variant_choice && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-violet-600 font-medium", children: "Choose variant" })
|
|
10140
|
+
] }),
|
|
10141
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: component.effective_price ?? 0, className: "text-sm text-muted-foreground shrink-0" })
|
|
10142
|
+
] }, component.id)) })
|
|
10143
|
+
] }),
|
|
10144
|
+
savings > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-bundle-savings": true, className: "flex items-center gap-2 p-3 bg-emerald-50 border border-emerald-200/60 text-sm text-emerald-800", children: [
|
|
10145
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }),
|
|
10146
|
+
"You save ",
|
|
10147
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: savings, className: "font-semibold" }),
|
|
10148
|
+
" with this bundle"
|
|
10149
|
+
] }),
|
|
10150
|
+
/* @__PURE__ */ jsxRuntime.jsx(CustomAttributesTable, { attributes: product.custom_attributes || [] }),
|
|
10151
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10152
|
+
ProductCustomizer,
|
|
10153
|
+
{
|
|
10154
|
+
product,
|
|
10155
|
+
onAddToCart
|
|
10156
|
+
}
|
|
10157
|
+
)
|
|
10158
|
+
] })
|
|
10159
|
+
}
|
|
10160
|
+
),
|
|
10161
|
+
showRelated && relatedProducts && relatedProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(RelatedProductsSection, { products: relatedProducts })
|
|
10162
|
+
] });
|
|
10163
|
+
}
|
|
10164
|
+
function CompositeProductLayout({
|
|
10165
|
+
product,
|
|
10166
|
+
onAddToCart,
|
|
10167
|
+
renderBreadcrumb,
|
|
10168
|
+
relatedProducts,
|
|
10169
|
+
showRelated = true,
|
|
10170
|
+
className
|
|
10171
|
+
}) {
|
|
10172
|
+
const images = product.images || (product.image_url ? [product.image_url] : []);
|
|
10173
|
+
const groups = product.groups || [];
|
|
10174
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-product-layout": "composite", className: cn("space-y-8", className), children: [
|
|
10175
|
+
renderBreadcrumb?.(product),
|
|
10176
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10177
|
+
TwoColumnGrid,
|
|
10178
|
+
{
|
|
10179
|
+
left: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10180
|
+
ProductImageGallery,
|
|
10181
|
+
{
|
|
10182
|
+
images,
|
|
10183
|
+
productName: product.name
|
|
10184
|
+
}
|
|
10185
|
+
),
|
|
10186
|
+
right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
10187
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
10188
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-violet-700 bg-violet-50 border border-violet-200/60 px-2.5 py-1 rounded-md", children: "Build Your Own" }),
|
|
10189
|
+
groups.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-muted-foreground bg-muted px-2.5 py-1 rounded-md", children: [
|
|
10190
|
+
groups.length,
|
|
10191
|
+
" choice",
|
|
10192
|
+
groups.length !== 1 ? "s" : ""
|
|
10193
|
+
] }),
|
|
10194
|
+
/* @__PURE__ */ jsxRuntime.jsx(TagPills, { tags: product.tags || [] })
|
|
10195
|
+
] }),
|
|
10196
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
10197
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { "data-cimplify-product-layout-name": true, className: "text-3xl lg:text-4xl font-bold tracking-tight", children: product.name }),
|
|
10198
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground mt-2", children: [
|
|
10199
|
+
"From ",
|
|
10200
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, className: "font-semibold text-foreground" })
|
|
10201
|
+
] })
|
|
10202
|
+
] }),
|
|
10203
|
+
product.description && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-product-layout-description": true, className: "text-muted-foreground leading-relaxed", children: product.description }),
|
|
10204
|
+
groups.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-composite-overview": true, className: "flex flex-wrap gap-2", children: groups.map((group) => {
|
|
10205
|
+
const availableCount = group.components.filter((c) => c.is_available && !c.is_archived).length;
|
|
10206
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-muted rounded-lg text-sm", children: [
|
|
10207
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: group.name }),
|
|
10208
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
|
|
10209
|
+
group.min_selections > 0 ? `Pick ${group.min_selections}` : "Optional",
|
|
10210
|
+
` \xB7 ${availableCount} option${availableCount !== 1 ? "s" : ""}`
|
|
10211
|
+
] })
|
|
10212
|
+
] }, group.id);
|
|
10213
|
+
}) }),
|
|
10214
|
+
/* @__PURE__ */ jsxRuntime.jsx(CustomAttributesTable, { attributes: product.custom_attributes || [] }),
|
|
10215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10216
|
+
ProductCustomizer,
|
|
10217
|
+
{
|
|
10218
|
+
product,
|
|
10219
|
+
onAddToCart
|
|
10220
|
+
}
|
|
10221
|
+
)
|
|
10222
|
+
] })
|
|
10223
|
+
}
|
|
10224
|
+
),
|
|
10225
|
+
showRelated && relatedProducts && relatedProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(RelatedProductsSection, { products: relatedProducts })
|
|
10226
|
+
] });
|
|
10227
|
+
}
|
|
9002
10228
|
var ProductTemplate = /* @__PURE__ */ ((ProductTemplate2) => {
|
|
9003
10229
|
ProductTemplate2["Default"] = "default";
|
|
9004
10230
|
ProductTemplate2["Food"] = "food";
|
|
9005
10231
|
ProductTemplate2["Wholesale"] = "wholesale";
|
|
9006
10232
|
ProductTemplate2["Service"] = "service";
|
|
9007
10233
|
ProductTemplate2["Digital"] = "digital";
|
|
10234
|
+
ProductTemplate2["Bundle"] = "bundle";
|
|
10235
|
+
ProductTemplate2["Composite"] = "composite";
|
|
9008
10236
|
ProductTemplate2["Physical"] = "physical";
|
|
9009
10237
|
return ProductTemplate2;
|
|
9010
10238
|
})(ProductTemplate || {});
|
|
@@ -9013,6 +10241,8 @@ var BUILT_IN_LAYOUTS2 = {
|
|
|
9013
10241
|
["wholesale" /* Wholesale */]: WholesaleProductLayout,
|
|
9014
10242
|
["service" /* Service */]: ServiceProductLayout,
|
|
9015
10243
|
["digital" /* Digital */]: DigitalProductLayout,
|
|
10244
|
+
["bundle" /* Bundle */]: BundleProductLayout,
|
|
10245
|
+
["composite" /* Composite */]: CompositeProductLayout,
|
|
9016
10246
|
["default" /* Default */]: DefaultProductLayout
|
|
9017
10247
|
};
|
|
9018
10248
|
function resolveTemplateKey(product) {
|
|
@@ -9020,19 +10250,25 @@ function resolveTemplateKey(product) {
|
|
|
9020
10250
|
if (typeof metaTemplate === "string" && metaTemplate.trim()) {
|
|
9021
10251
|
return metaTemplate.trim();
|
|
9022
10252
|
}
|
|
10253
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Bundle) {
|
|
10254
|
+
return "bundle" /* Bundle */;
|
|
10255
|
+
}
|
|
10256
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Composite) {
|
|
10257
|
+
return "composite" /* Composite */;
|
|
10258
|
+
}
|
|
9023
10259
|
if (product.quantity_pricing && product.quantity_pricing.length > 1) {
|
|
9024
10260
|
return "wholesale" /* Wholesale */;
|
|
9025
10261
|
}
|
|
9026
|
-
if (product.type ===
|
|
10262
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Service) {
|
|
9027
10263
|
return "service" /* Service */;
|
|
9028
10264
|
}
|
|
9029
|
-
if (product.type ===
|
|
10265
|
+
if (product.type === chunkR4AKAGZQ_js.PRODUCT_TYPE.Digital) {
|
|
9030
10266
|
return "digital" /* Digital */;
|
|
9031
10267
|
}
|
|
9032
|
-
if (product.render_hint ===
|
|
10268
|
+
if (product.render_hint === chunkR4AKAGZQ_js.RENDER_HINT.Food) {
|
|
9033
10269
|
return "food" /* Food */;
|
|
9034
10270
|
}
|
|
9035
|
-
if (product.render_hint ===
|
|
10271
|
+
if (product.render_hint === chunkR4AKAGZQ_js.RENDER_HINT.Physical) {
|
|
9036
10272
|
return "physical" /* Physical */;
|
|
9037
10273
|
}
|
|
9038
10274
|
return "default" /* Default */;
|
|
@@ -9298,9 +10534,9 @@ function DefaultCollectionLayout({
|
|
|
9298
10534
|
onQuickAdd,
|
|
9299
10535
|
className
|
|
9300
10536
|
}) {
|
|
9301
|
-
const [searchQuery, setSearchQuery] =
|
|
9302
|
-
const [activeTag, setActiveTag] =
|
|
9303
|
-
const collectionTags =
|
|
10537
|
+
const [searchQuery, setSearchQuery] = React10.useState("");
|
|
10538
|
+
const [activeTag, setActiveTag] = React10.useState(null);
|
|
10539
|
+
const collectionTags = React10.useMemo(() => {
|
|
9304
10540
|
const tagSet = /* @__PURE__ */ new Set();
|
|
9305
10541
|
for (const p of products) {
|
|
9306
10542
|
if (p.tags) {
|
|
@@ -9309,7 +10545,7 @@ function DefaultCollectionLayout({
|
|
|
9309
10545
|
}
|
|
9310
10546
|
return Array.from(tagSet).slice(0, 6);
|
|
9311
10547
|
}, [products]);
|
|
9312
|
-
const filtered =
|
|
10548
|
+
const filtered = React10.useMemo(() => {
|
|
9313
10549
|
let result = products;
|
|
9314
10550
|
if (searchQuery.trim().length >= 2) {
|
|
9315
10551
|
const q = searchQuery.toLowerCase();
|
|
@@ -9384,7 +10620,7 @@ function DefaultCollectionLayout({
|
|
|
9384
10620
|
] })
|
|
9385
10621
|
] }),
|
|
9386
10622
|
filtered.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
|
|
9387
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
10623
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9388
10624
|
ProductCard,
|
|
9389
10625
|
{
|
|
9390
10626
|
product,
|
|
@@ -9437,7 +10673,7 @@ function FeaturedCollectionLayout({
|
|
|
9437
10673
|
] })
|
|
9438
10674
|
] }),
|
|
9439
10675
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: products.map(
|
|
9440
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
10676
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9441
10677
|
ProductCard,
|
|
9442
10678
|
{
|
|
9443
10679
|
product,
|
|
@@ -9459,10 +10695,10 @@ function CatalogueCollectionLayout({
|
|
|
9459
10695
|
onQuickAdd,
|
|
9460
10696
|
className
|
|
9461
10697
|
}) {
|
|
9462
|
-
const [searchQuery, setSearchQuery] =
|
|
9463
|
-
const [activeCategory, setActiveCategory] =
|
|
9464
|
-
const [sortBy, setSortBy] =
|
|
9465
|
-
const categories =
|
|
10698
|
+
const [searchQuery, setSearchQuery] = React10.useState("");
|
|
10699
|
+
const [activeCategory, setActiveCategory] = React10.useState(null);
|
|
10700
|
+
const [sortBy, setSortBy] = React10.useState("default");
|
|
10701
|
+
const categories = React10.useMemo(() => {
|
|
9466
10702
|
const cats = /* @__PURE__ */ new Map();
|
|
9467
10703
|
for (const p of products) {
|
|
9468
10704
|
if (p.category_id && p.tags) {
|
|
@@ -9473,7 +10709,7 @@ function CatalogueCollectionLayout({
|
|
|
9473
10709
|
}
|
|
9474
10710
|
return Array.from(cats.values()).slice(0, 8);
|
|
9475
10711
|
}, [products]);
|
|
9476
|
-
const filtered =
|
|
10712
|
+
const filtered = React10.useMemo(() => {
|
|
9477
10713
|
let result = products;
|
|
9478
10714
|
if (searchQuery.trim().length >= 2) {
|
|
9479
10715
|
const q = searchQuery.toLowerCase();
|
|
@@ -9561,7 +10797,7 @@ function CatalogueCollectionLayout({
|
|
|
9561
10797
|
] })
|
|
9562
10798
|
] }),
|
|
9563
10799
|
filtered.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
|
|
9564
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
10800
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9565
10801
|
ProductCard,
|
|
9566
10802
|
{
|
|
9567
10803
|
product,
|
|
@@ -9740,13 +10976,13 @@ function OrderHistoryPage({
|
|
|
9740
10976
|
className,
|
|
9741
10977
|
classNames
|
|
9742
10978
|
}) {
|
|
9743
|
-
const [statusFilter, setStatusFilter] =
|
|
9744
|
-
const [selectedOrder, setSelectedOrder] =
|
|
9745
|
-
const handleTabChange =
|
|
10979
|
+
const [statusFilter, setStatusFilter] = React10.useState(void 0);
|
|
10980
|
+
const [selectedOrder, setSelectedOrder] = React10.useState(null);
|
|
10981
|
+
const handleTabChange = React10.useCallback((value) => {
|
|
9746
10982
|
const filter = STATUS_FILTERS.find((f) => f.tabValue === value);
|
|
9747
10983
|
setStatusFilter(filter?.value);
|
|
9748
10984
|
}, []);
|
|
9749
|
-
const handleOrderClick =
|
|
10985
|
+
const handleOrderClick = React10.useCallback(
|
|
9750
10986
|
(order) => {
|
|
9751
10987
|
if (onOrderNavigate) {
|
|
9752
10988
|
onOrderNavigate(order);
|
|
@@ -9756,7 +10992,7 @@ function OrderHistoryPage({
|
|
|
9756
10992
|
},
|
|
9757
10993
|
[onOrderNavigate]
|
|
9758
10994
|
);
|
|
9759
|
-
const handleBack =
|
|
10995
|
+
const handleBack = React10.useCallback(() => {
|
|
9760
10996
|
setSelectedOrder(null);
|
|
9761
10997
|
}, []);
|
|
9762
10998
|
const activeTabValue = STATUS_FILTERS.find((f) => f.value === statusFilter)?.tabValue ?? "all";
|
|
@@ -9941,7 +11177,7 @@ function DefaultSearchLayout({
|
|
|
9941
11177
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
|
|
9942
11178
|
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
|
|
9943
11179
|
] }) : results.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: results.map(
|
|
9944
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11180
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9945
11181
|
ProductCard,
|
|
9946
11182
|
{
|
|
9947
11183
|
product,
|
|
@@ -10043,7 +11279,7 @@ function CompactSearchLayout({
|
|
|
10043
11279
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
|
|
10044
11280
|
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
|
|
10045
11281
|
] }) : results.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: results.map(
|
|
10046
|
-
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
11282
|
+
(product) => renderCard ? /* @__PURE__ */ jsxRuntime.jsx(React10__default.default.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
10047
11283
|
ProductCard,
|
|
10048
11284
|
{
|
|
10049
11285
|
product,
|
|
@@ -10374,11 +11610,11 @@ function DeliveryEstimate({
|
|
|
10374
11610
|
}) {
|
|
10375
11611
|
const context = useOptionalCimplifyClient();
|
|
10376
11612
|
const client = context?.client ?? null;
|
|
10377
|
-
const [result, setResult] =
|
|
10378
|
-
const [isLoading, setIsLoading] =
|
|
10379
|
-
const [error, setError] =
|
|
10380
|
-
const requestIdRef =
|
|
10381
|
-
|
|
11613
|
+
const [result, setResult] = React10.useState(null);
|
|
11614
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
11615
|
+
const [error, setError] = React10.useState(null);
|
|
11616
|
+
const requestIdRef = React10.useRef(0);
|
|
11617
|
+
React10.useEffect(() => {
|
|
10382
11618
|
if (!client) return;
|
|
10383
11619
|
const nextRequestId = ++requestIdRef.current;
|
|
10384
11620
|
setIsLoading(true);
|
|
@@ -10459,10 +11695,10 @@ function CurrencySelector({
|
|
|
10459
11695
|
}) {
|
|
10460
11696
|
const context = useOptionalCimplifyClient();
|
|
10461
11697
|
const client = context?.client ?? null;
|
|
10462
|
-
const [rates, setRates] =
|
|
10463
|
-
const [isLoadingRates, setIsLoadingRates] =
|
|
10464
|
-
const requestIdRef =
|
|
10465
|
-
|
|
11698
|
+
const [rates, setRates] = React10.useState({});
|
|
11699
|
+
const [isLoadingRates, setIsLoadingRates] = React10.useState(false);
|
|
11700
|
+
const requestIdRef = React10.useRef(0);
|
|
11701
|
+
React10.useEffect(() => {
|
|
10466
11702
|
if (!showRate || !baseCurrency || !client) return;
|
|
10467
11703
|
const targets = currencies.filter((c) => c !== baseCurrency);
|
|
10468
11704
|
if (targets.length === 0) return;
|
|
@@ -10610,7 +11846,7 @@ function ResourcePicker({
|
|
|
10610
11846
|
|
|
10611
11847
|
Object.defineProperty(exports, "getVariantDisplayName", {
|
|
10612
11848
|
enumerable: true,
|
|
10613
|
-
get: function () { return
|
|
11849
|
+
get: function () { return chunkR4AKAGZQ_js.getVariantDisplayName; }
|
|
10614
11850
|
});
|
|
10615
11851
|
exports.AccommodationCard = AccommodationCard;
|
|
10616
11852
|
exports.Ad = Ad;
|
|
@@ -10622,6 +11858,8 @@ exports.AvailabilityBadge = AvailabilityBadge;
|
|
|
10622
11858
|
exports.BillingPlanSelector = BillingPlanSelector;
|
|
10623
11859
|
exports.BookingCard = BookingCard;
|
|
10624
11860
|
exports.BookingList = BookingList;
|
|
11861
|
+
exports.BundleProductCard = BundleProductCard;
|
|
11862
|
+
exports.BundleProductLayout = BundleProductLayout;
|
|
10625
11863
|
exports.BundleSelector = BundleSelector;
|
|
10626
11864
|
exports.CardImage = CardImage;
|
|
10627
11865
|
exports.CardShell = CardShell;
|
|
@@ -10644,9 +11882,12 @@ exports.CompactCartLayout = CompactCartLayout;
|
|
|
10644
11882
|
exports.CompactCatalogueLayout = CompactCatalogueLayout;
|
|
10645
11883
|
exports.CompactSearchLayout = CompactSearchLayout;
|
|
10646
11884
|
exports.CompactServiceCard = CompactServiceCard;
|
|
11885
|
+
exports.CompositeProductCard = CompositeProductCard;
|
|
11886
|
+
exports.CompositeProductLayout = CompositeProductLayout;
|
|
10647
11887
|
exports.CompositeSelector = CompositeSelector;
|
|
10648
11888
|
exports.CurrencySelector = CurrencySelector;
|
|
10649
11889
|
exports.CustomAttributesTable = CustomAttributesTable;
|
|
11890
|
+
exports.CustomerInputFields = CustomerInputFields;
|
|
10650
11891
|
exports.DateSlotPicker = DateSlotPicker;
|
|
10651
11892
|
exports.DealBanner = DealBanner;
|
|
10652
11893
|
exports.DealsPage = DealsPage;
|
|
@@ -10749,6 +11990,8 @@ exports.useRecommendations = useRecommendations;
|
|
|
10749
11990
|
exports.useSearch = useSearch;
|
|
10750
11991
|
exports.useServiceAvailability = useServiceAvailability;
|
|
10751
11992
|
exports.useServices = useServices;
|
|
11993
|
+
exports.useSubscription = useSubscription;
|
|
11994
|
+
exports.useSubscriptions = useSubscriptions;
|
|
10752
11995
|
exports.useTaxonomies = useTaxonomies;
|
|
10753
11996
|
exports.useTaxonomy = useTaxonomy;
|
|
10754
11997
|
exports.useTaxonomyPath = useTaxonomyPath;
|