@propeller-commerce/propeller-v2-react-ui 0.6.0 → 0.7.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/CHANGELOG.md +37 -0
- package/dist/index.cjs +512 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +202 -20
- package/dist/index.d.ts +202 -20
- package/dist/index.js +511 -23
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -248,6 +248,7 @@ function useAddress(options) {
|
|
|
248
248
|
);
|
|
249
249
|
return { loading, error, createAddress, updateAddress, deleteAddress, setDefaultAddress };
|
|
250
250
|
}
|
|
251
|
+
var isViewerSearchInput = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
251
252
|
function useAuth(options) {
|
|
252
253
|
const { graphqlClient, language = "NL", onAuthHeaderUpdate, configuration } = options;
|
|
253
254
|
const [loading, setLoading] = React6.useState(false);
|
|
@@ -284,8 +285,14 @@ function useAuth(options) {
|
|
|
284
285
|
...configuration?.companyTrackAttributes?.length && {
|
|
285
286
|
companyAttributesInput: { attributeDescription: { names: configuration.companyTrackAttributes } }
|
|
286
287
|
},
|
|
287
|
-
|
|
288
|
+
// Contact-scoped pagination inputs — only when the host supplies a real
|
|
289
|
+
// input object (an empty array `[]` is truthy but 400s the viewer). See
|
|
290
|
+
// isViewerSearchInput.
|
|
291
|
+
...isViewerSearchInput(configuration?.contactPAConfigInput) && {
|
|
288
292
|
contactPAConfigInput: configuration.contactPAConfigInput
|
|
293
|
+
},
|
|
294
|
+
...isViewerSearchInput(configuration?.contactCompaniesSearchInput) && {
|
|
295
|
+
contactCompaniesSearchInput: configuration.contactCompaniesSearchInput
|
|
289
296
|
}
|
|
290
297
|
};
|
|
291
298
|
const viewer = await userService.getViewer(viewerInput);
|
|
@@ -2491,6 +2498,140 @@ function useProductSearch(options) {
|
|
|
2491
2498
|
goToPage: pagination.goToPage
|
|
2492
2499
|
};
|
|
2493
2500
|
}
|
|
2501
|
+
function toMatch(item, language) {
|
|
2502
|
+
const isCluster = "clusterId" in item;
|
|
2503
|
+
const displayItem = isCluster ? item.defaultProduct : item;
|
|
2504
|
+
const productId = displayItem?.productId ?? item.productId;
|
|
2505
|
+
const clusterId = isCluster ? item.clusterId : void 0;
|
|
2506
|
+
const name = language && item.names?.find((n) => n.language === language)?.value || item.names?.[0]?.value || "Product";
|
|
2507
|
+
const netPrice = displayItem?.price?.net ?? 0;
|
|
2508
|
+
const grossPrice = displayItem?.price?.gross ?? 0;
|
|
2509
|
+
const minQuantity = Math.max(1, displayItem?.minimumQuantity ?? 1);
|
|
2510
|
+
const imageUrl = isCluster ? propellerV2CoreUi.getClusterImageUrl(item) : propellerV2CoreUi.getProductImageUrl(item);
|
|
2511
|
+
return {
|
|
2512
|
+
productId,
|
|
2513
|
+
clusterId,
|
|
2514
|
+
name,
|
|
2515
|
+
sku: item.sku || displayItem?.sku || "",
|
|
2516
|
+
netPrice,
|
|
2517
|
+
grossPrice,
|
|
2518
|
+
minQuantity,
|
|
2519
|
+
imageUrl
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
function useQuickOrder(options) {
|
|
2523
|
+
const {
|
|
2524
|
+
graphqlClient,
|
|
2525
|
+
user,
|
|
2526
|
+
companyId,
|
|
2527
|
+
configuration = {},
|
|
2528
|
+
onCartCreated,
|
|
2529
|
+
afterAddToCart
|
|
2530
|
+
} = options;
|
|
2531
|
+
const language = options.language || "NL";
|
|
2532
|
+
const searchLimit = options.searchLimit ?? 8;
|
|
2533
|
+
const [submitting, setSubmitting] = React6.useState(false);
|
|
2534
|
+
const [error, setError] = React6.useState(null);
|
|
2535
|
+
const searchProducts = React6.useCallback(
|
|
2536
|
+
async (term) => {
|
|
2537
|
+
const trimmed = term.trim();
|
|
2538
|
+
if (!trimmed || !graphqlClient) return [];
|
|
2539
|
+
try {
|
|
2540
|
+
const service = propellerV2CoreUi.createServices(graphqlClient).product;
|
|
2541
|
+
const input = {
|
|
2542
|
+
term: trimmed,
|
|
2543
|
+
language,
|
|
2544
|
+
page: 1,
|
|
2545
|
+
offset: searchLimit,
|
|
2546
|
+
statuses: [propellerSdkV2.ProductStatus.A, propellerSdkV2.ProductStatus.P, propellerSdkV2.ProductStatus.T, propellerSdkV2.ProductStatus.S],
|
|
2547
|
+
sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
|
|
2548
|
+
searchFields: [
|
|
2549
|
+
{
|
|
2550
|
+
fieldNames: [
|
|
2551
|
+
propellerSdkV2.ProductSearchableField.SKU,
|
|
2552
|
+
propellerSdkV2.ProductSearchableField.NAME,
|
|
2553
|
+
propellerSdkV2.ProductSearchableField.KEYWORDS,
|
|
2554
|
+
propellerSdkV2.ProductSearchableField.CUSTOM_KEYWORDS
|
|
2555
|
+
],
|
|
2556
|
+
boost: 5
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
fieldNames: [
|
|
2560
|
+
propellerSdkV2.ProductSearchableField.MANUFACTURER_CODE,
|
|
2561
|
+
propellerSdkV2.ProductSearchableField.EAN_CODE,
|
|
2562
|
+
propellerSdkV2.ProductSearchableField.BAR_CODE,
|
|
2563
|
+
propellerSdkV2.ProductSearchableField.SUPPLIER_CODE,
|
|
2564
|
+
propellerSdkV2.ProductSearchableField.PRODUCT_ID
|
|
2565
|
+
],
|
|
2566
|
+
boost: 1
|
|
2567
|
+
}
|
|
2568
|
+
]
|
|
2569
|
+
};
|
|
2570
|
+
const variables = {
|
|
2571
|
+
input,
|
|
2572
|
+
language,
|
|
2573
|
+
imageVariantFilters: configuration.imageVariantFiltersSmall
|
|
2574
|
+
};
|
|
2575
|
+
const result = await service.getProducts(variables);
|
|
2576
|
+
const items = result?.items ?? [];
|
|
2577
|
+
return items.map((it) => toMatch(it, language));
|
|
2578
|
+
} catch {
|
|
2579
|
+
return [];
|
|
2580
|
+
}
|
|
2581
|
+
},
|
|
2582
|
+
[graphqlClient, language, searchLimit, configuration]
|
|
2583
|
+
);
|
|
2584
|
+
const submit = React6.useCallback(
|
|
2585
|
+
async (lines) => {
|
|
2586
|
+
const valid = lines.filter((l) => l.productId && (l.quantity ?? 0) > 0);
|
|
2587
|
+
if (!valid.length) return { success: false, error: "No items to add" };
|
|
2588
|
+
if (!graphqlClient) return { success: false, error: "No GraphQL client" };
|
|
2589
|
+
setSubmitting(true);
|
|
2590
|
+
setError(null);
|
|
2591
|
+
try {
|
|
2592
|
+
const services = propellerV2CoreUi.createServices(graphqlClient);
|
|
2593
|
+
const cart = await initCart({
|
|
2594
|
+
services,
|
|
2595
|
+
user: user ?? null,
|
|
2596
|
+
companyId,
|
|
2597
|
+
language,
|
|
2598
|
+
imageSearchFilters: configuration.imageSearchFiltersGrid,
|
|
2599
|
+
imageVariantFilters: configuration.imageVariantFiltersSmall,
|
|
2600
|
+
onCartCreated
|
|
2601
|
+
});
|
|
2602
|
+
const items = valid.map((l) => ({
|
|
2603
|
+
productId: l.productId,
|
|
2604
|
+
quantity: l.quantity,
|
|
2605
|
+
...l.clusterId ? { clusterId: l.clusterId } : {}
|
|
2606
|
+
}));
|
|
2607
|
+
const bulk = await services.cart.bulkUpdateCartItems({
|
|
2608
|
+
input: { cartId: cart.cartId, items }
|
|
2609
|
+
});
|
|
2610
|
+
const updated = await services.cart.getCart({
|
|
2611
|
+
cartId: cart.cartId,
|
|
2612
|
+
language,
|
|
2613
|
+
imageSearchFilters: configuration.imageSearchFiltersGrid,
|
|
2614
|
+
imageVariantFilters: configuration.imageVariantFiltersSmall
|
|
2615
|
+
});
|
|
2616
|
+
const finalCart = updated ?? cart;
|
|
2617
|
+
afterAddToCart?.(finalCart);
|
|
2618
|
+
return {
|
|
2619
|
+
success: true,
|
|
2620
|
+
cart: finalCart,
|
|
2621
|
+
added: (bulk?.created ?? 0) + (bulk?.updated ?? 0)
|
|
2622
|
+
};
|
|
2623
|
+
} catch (e) {
|
|
2624
|
+
const msg = e instanceof Error ? e.message : "Failed to add items to cart";
|
|
2625
|
+
setError(msg);
|
|
2626
|
+
return { success: false, error: msg };
|
|
2627
|
+
} finally {
|
|
2628
|
+
setSubmitting(false);
|
|
2629
|
+
}
|
|
2630
|
+
},
|
|
2631
|
+
[graphqlClient, user, companyId, language, configuration, onCartCreated, afterAddToCart]
|
|
2632
|
+
);
|
|
2633
|
+
return { submitting, error, searchProducts, submit };
|
|
2634
|
+
}
|
|
2494
2635
|
var inflightFetches3 = /* @__PURE__ */ new Set();
|
|
2495
2636
|
var STOREFRONT_STATUSES = [
|
|
2496
2637
|
propellerSdkV2.ProductStatus.A,
|
|
@@ -3466,7 +3607,13 @@ function LoginForm(rawProps) {
|
|
|
3466
3607
|
const [email, setEmail] = React6.useState("");
|
|
3467
3608
|
const [password, setPassword] = React6.useState("");
|
|
3468
3609
|
const { loading, error: authError, login } = useAuth({
|
|
3469
|
-
graphqlClient: props.graphqlClient
|
|
3610
|
+
graphqlClient: props.graphqlClient,
|
|
3611
|
+
// Resolved from <PropellerDepsProvider> by useInfraProps (the app's full
|
|
3612
|
+
// `config`), so the login viewer requests the configured track attributes +
|
|
3613
|
+
// pagination inputs (companyTrackAttributes → MY_INSTALLATIONS,
|
|
3614
|
+
// contactCompaniesSearchInput, contactPAConfigInput). Without this the header
|
|
3615
|
+
// login returns a viewer with no companies/attributes until a later refresh.
|
|
3616
|
+
configuration: props.configuration
|
|
3470
3617
|
});
|
|
3471
3618
|
propellerV2CoreUi.getLabel(props.labels, "email", "Email");
|
|
3472
3619
|
propellerV2CoreUi.getLabel(props.labels, "password", "Password");
|
|
@@ -6372,7 +6519,7 @@ function CartItem(rawProps) {
|
|
|
6372
6519
|
}
|
|
6373
6520
|
return "#";
|
|
6374
6521
|
}
|
|
6375
|
-
function
|
|
6522
|
+
function getProductImageUrl6() {
|
|
6376
6523
|
return props.cartItem.product?.media?.images?.items?.[0]?.imageVariants?.[0]?.url || "";
|
|
6377
6524
|
}
|
|
6378
6525
|
function getProductSku3() {
|
|
@@ -6556,7 +6703,7 @@ function CartItem(rawProps) {
|
|
|
6556
6703
|
derived: {
|
|
6557
6704
|
name: getProductName5(),
|
|
6558
6705
|
sku: getProductSku3(),
|
|
6559
|
-
imageUrl:
|
|
6706
|
+
imageUrl: getProductImageUrl6(),
|
|
6560
6707
|
productUrl: getProductUrl2(),
|
|
6561
6708
|
isBundle: isBundleItem(),
|
|
6562
6709
|
bundleName: getBundleName(),
|
|
@@ -9530,7 +9677,7 @@ function GridToolbar(rawProps) {
|
|
|
9530
9677
|
const [currentSortOrder, setCurrentSortOrder] = React6.useState(propellerSdkV2.SortOrder.DESC);
|
|
9531
9678
|
const [currentOffset, setCurrentOffset] = React6.useState(12);
|
|
9532
9679
|
const [currentViewMode, setCurrentViewMode] = React6.useState("grid");
|
|
9533
|
-
function
|
|
9680
|
+
function getLabel55(key) {
|
|
9534
9681
|
const labels = props.labels || {};
|
|
9535
9682
|
return labels[key] !== void 0 ? labels[key] : DEFAULT_LABELS[key] || key;
|
|
9536
9683
|
}
|
|
@@ -9609,7 +9756,7 @@ function GridToolbar(rawProps) {
|
|
|
9609
9756
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-grid-toolbar__count text-sm text-muted-foreground font-medium", children: props.itemsFound > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9610
9757
|
props.itemsFound,
|
|
9611
9758
|
"\xA0",
|
|
9612
|
-
props.itemsFound === 1 ?
|
|
9759
|
+
props.itemsFound === 1 ? getLabel55("productSingular") : getLabel55("productPlural")
|
|
9613
9760
|
] }) : null }),
|
|
9614
9761
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-grid-toolbar__controls flex flex-wrap items-center gap-3", children: [
|
|
9615
9762
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9620,7 +9767,7 @@ function GridToolbar(rawProps) {
|
|
|
9620
9767
|
onChange: (e) => handleOffsetChange(parseInt(e.target.value)),
|
|
9621
9768
|
children: getOffsetOptions()?.map((n) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: n, children: [
|
|
9622
9769
|
n,
|
|
9623
|
-
|
|
9770
|
+
getLabel55("perPage")
|
|
9624
9771
|
] }, n))
|
|
9625
9772
|
}
|
|
9626
9773
|
),
|
|
@@ -9636,7 +9783,7 @@ function GridToolbar(rawProps) {
|
|
|
9636
9783
|
{
|
|
9637
9784
|
value: field,
|
|
9638
9785
|
disabled: field === "PRICE" && isPriceSortDisabled(),
|
|
9639
|
-
children:
|
|
9786
|
+
children: getLabel55(field)
|
|
9640
9787
|
},
|
|
9641
9788
|
field
|
|
9642
9789
|
))
|
|
@@ -9649,8 +9796,8 @@ function GridToolbar(rawProps) {
|
|
|
9649
9796
|
value: currentSortOrder,
|
|
9650
9797
|
onChange: (e) => handleSortOrderChange(e.target.value),
|
|
9651
9798
|
children: [
|
|
9652
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: propellerSdkV2.SortOrder.ASC, children:
|
|
9653
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: propellerSdkV2.SortOrder.DESC, children:
|
|
9799
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: propellerSdkV2.SortOrder.ASC, children: getLabel55("ASC") }),
|
|
9800
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: propellerSdkV2.SortOrder.DESC, children: getLabel55("DESC") })
|
|
9654
9801
|
]
|
|
9655
9802
|
}
|
|
9656
9803
|
),
|
|
@@ -9660,7 +9807,7 @@ function GridToolbar(rawProps) {
|
|
|
9660
9807
|
type: "button",
|
|
9661
9808
|
className: "propeller-grid-toolbar__view-toggle h-9 w-9 flex items-center justify-center rounded-control border border-input bg-transparent hover:bg-accent hover:text-accent-foreground transition-colors",
|
|
9662
9809
|
onClick: (event) => handleViewChange(),
|
|
9663
|
-
title: currentViewMode === "grid" ?
|
|
9810
|
+
title: currentViewMode === "grid" ? getLabel55("switchToList") : getLabel55("switchToGrid"),
|
|
9664
9811
|
children: [
|
|
9665
9812
|
currentViewMode === "grid" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9666
9813
|
"svg",
|
|
@@ -9718,7 +9865,7 @@ function GridToolbar(rawProps) {
|
|
|
9718
9865
|
onClick: (event) => {
|
|
9719
9866
|
if (props.onClearFilters) props.onClearFilters();
|
|
9720
9867
|
},
|
|
9721
|
-
children:
|
|
9868
|
+
children: getLabel55("clearAll")
|
|
9722
9869
|
}
|
|
9723
9870
|
),
|
|
9724
9871
|
props.priceFilterMin !== void 0 || props.priceFilterMax !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -9729,7 +9876,7 @@ function GridToolbar(rawProps) {
|
|
|
9729
9876
|
if (props.onPriceFilterRemove) props.onPriceFilterRemove();
|
|
9730
9877
|
},
|
|
9731
9878
|
children: [
|
|
9732
|
-
|
|
9879
|
+
getLabel55("price"),
|
|
9733
9880
|
": \u20AC",
|
|
9734
9881
|
props.priceFilterMin ?? 0,
|
|
9735
9882
|
" \u2013 \u20AC",
|
|
@@ -9766,7 +9913,7 @@ var DEFAULT_LABELS2 = {
|
|
|
9766
9913
|
of: "of"
|
|
9767
9914
|
};
|
|
9768
9915
|
function GridPagination(props) {
|
|
9769
|
-
function
|
|
9916
|
+
function getLabel55(key) {
|
|
9770
9917
|
const labels = props.labels || {};
|
|
9771
9918
|
return labels[key] !== void 0 ? labels[key] : DEFAULT_LABELS2[key] || key;
|
|
9772
9919
|
}
|
|
@@ -9839,15 +9986,15 @@ function GridPagination(props) {
|
|
|
9839
9986
|
className: "propeller-grid-pagination__btn propeller-grid-pagination__btn--prev inline-flex items-center rounded-control border border-input bg-card px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed",
|
|
9840
9987
|
disabled: currentPage === 1,
|
|
9841
9988
|
onClick: () => handlePageChange(currentPage - 1),
|
|
9842
|
-
children:
|
|
9989
|
+
children: getLabel55("previous")
|
|
9843
9990
|
}
|
|
9844
9991
|
),
|
|
9845
9992
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "propeller-grid-pagination__info px-2 text-sm font-medium text-muted-foreground", children: [
|
|
9846
|
-
|
|
9993
|
+
getLabel55("page"),
|
|
9847
9994
|
"\xA0",
|
|
9848
9995
|
currentPage,
|
|
9849
9996
|
"\xA0",
|
|
9850
|
-
|
|
9997
|
+
getLabel55("of"),
|
|
9851
9998
|
"\xA0",
|
|
9852
9999
|
totalPages
|
|
9853
10000
|
] }),
|
|
@@ -9858,7 +10005,7 @@ function GridPagination(props) {
|
|
|
9858
10005
|
className: "propeller-grid-pagination__btn propeller-grid-pagination__btn--next inline-flex items-center rounded-control border border-input bg-card px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed",
|
|
9859
10006
|
disabled: currentPage === totalPages,
|
|
9860
10007
|
onClick: () => handlePageChange(currentPage + 1),
|
|
9861
|
-
children:
|
|
10008
|
+
children: getLabel55("next")
|
|
9862
10009
|
}
|
|
9863
10010
|
)
|
|
9864
10011
|
] }) : null,
|
|
@@ -9870,7 +10017,7 @@ function GridPagination(props) {
|
|
|
9870
10017
|
className: "propeller-grid-pagination__btn propeller-grid-pagination__btn--prev inline-flex items-center rounded-control border border-input bg-card px-3 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed",
|
|
9871
10018
|
disabled: currentPage === 1,
|
|
9872
10019
|
onClick: () => handlePageChange(currentPage - 1),
|
|
9873
|
-
children:
|
|
10020
|
+
children: getLabel55("previous")
|
|
9874
10021
|
}
|
|
9875
10022
|
),
|
|
9876
10023
|
getFullPages().map((item, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9897,7 +10044,7 @@ function GridPagination(props) {
|
|
|
9897
10044
|
className: "propeller-grid-pagination__btn propeller-grid-pagination__btn--next inline-flex items-center rounded-control border border-input bg-card px-3 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed",
|
|
9898
10045
|
disabled: currentPage === totalPages,
|
|
9899
10046
|
onClick: () => handlePageChange(currentPage + 1),
|
|
9900
|
-
children:
|
|
10047
|
+
children: getLabel55("next")
|
|
9901
10048
|
}
|
|
9902
10049
|
)
|
|
9903
10050
|
] }) : null
|
|
@@ -10376,7 +10523,7 @@ function formatPrice9(price, currency) {
|
|
|
10376
10523
|
function getProductName2(product) {
|
|
10377
10524
|
return product.names?.[0]?.value || `Product ${product.productId}`;
|
|
10378
10525
|
}
|
|
10379
|
-
function
|
|
10526
|
+
function getProductImageUrl4(product) {
|
|
10380
10527
|
const media = product.media;
|
|
10381
10528
|
if (media?.images?.items && Array.isArray(media.images.items) && media.images.items.length > 0) {
|
|
10382
10529
|
const firstImage = media.images.items[0];
|
|
@@ -10405,7 +10552,7 @@ function ClusterOptions(props) {
|
|
|
10405
10552
|
(p) => p.productId.toString() === selectedProductId
|
|
10406
10553
|
);
|
|
10407
10554
|
if (selectedProduct) {
|
|
10408
|
-
previewImageUrl =
|
|
10555
|
+
previewImageUrl = getProductImageUrl4(selectedProduct);
|
|
10409
10556
|
previewName = getProductName2(selectedProduct);
|
|
10410
10557
|
previewPrice = formatPrice9(selectedProduct.price?.gross || 0, props.currency ?? "\u20AC");
|
|
10411
10558
|
}
|
|
@@ -13782,6 +13929,347 @@ function OrderList(rawProps) {
|
|
|
13782
13929
|
] });
|
|
13783
13930
|
}
|
|
13784
13931
|
var OrderList_default = OrderList;
|
|
13932
|
+
var ROW_SEQ = 0;
|
|
13933
|
+
function blankRow() {
|
|
13934
|
+
ROW_SEQ += 1;
|
|
13935
|
+
return {
|
|
13936
|
+
key: `qo-${ROW_SEQ}`,
|
|
13937
|
+
code: "",
|
|
13938
|
+
productId: null,
|
|
13939
|
+
name: "",
|
|
13940
|
+
netPrice: 0,
|
|
13941
|
+
quantity: 1,
|
|
13942
|
+
minQuantity: 1,
|
|
13943
|
+
matches: [],
|
|
13944
|
+
searching: false,
|
|
13945
|
+
searched: false
|
|
13946
|
+
};
|
|
13947
|
+
}
|
|
13948
|
+
function QuickOrderInner(props) {
|
|
13949
|
+
const {
|
|
13950
|
+
companyId,
|
|
13951
|
+
language = "NL",
|
|
13952
|
+
currency = "\u20AC",
|
|
13953
|
+
configuration,
|
|
13954
|
+
initialRows = 5,
|
|
13955
|
+
searchThreshold = 3,
|
|
13956
|
+
debounceMs = 300,
|
|
13957
|
+
parseSpreadsheet,
|
|
13958
|
+
templateUrl,
|
|
13959
|
+
maxUploadBytes = 2 * 1024 * 1024,
|
|
13960
|
+
maxUploadRows = 500,
|
|
13961
|
+
onCartCreated,
|
|
13962
|
+
afterAddToCart,
|
|
13963
|
+
onMissingCodes,
|
|
13964
|
+
className,
|
|
13965
|
+
labels
|
|
13966
|
+
} = props;
|
|
13967
|
+
const user = props.user ?? null;
|
|
13968
|
+
const graphqlClient = props.graphqlClient;
|
|
13969
|
+
const displayPrice = (n) => props.formatPrice ? props.formatPrice(n) : propellerV2CoreUi.formatPrice(n, { symbol: currency });
|
|
13970
|
+
const L = (key, fallback) => propellerV2CoreUi.getLabel(labels, key, fallback);
|
|
13971
|
+
const { submitting, searchProducts, submit } = useQuickOrder({
|
|
13972
|
+
graphqlClient,
|
|
13973
|
+
user,
|
|
13974
|
+
companyId,
|
|
13975
|
+
language,
|
|
13976
|
+
configuration,
|
|
13977
|
+
onCartCreated,
|
|
13978
|
+
afterAddToCart
|
|
13979
|
+
});
|
|
13980
|
+
const [rows, setRows] = React6.useState(
|
|
13981
|
+
() => Array.from({ length: Math.max(1, initialRows) }, blankRow)
|
|
13982
|
+
);
|
|
13983
|
+
const [missing, setMissing] = React6.useState([]);
|
|
13984
|
+
const [uploadError, setUploadError] = React6.useState(null);
|
|
13985
|
+
const [uploading, setUploading] = React6.useState(false);
|
|
13986
|
+
const [notice, setNotice] = React6.useState(null);
|
|
13987
|
+
const fileInputRef = React6.useRef(null);
|
|
13988
|
+
const searchTimers = React6.useRef({});
|
|
13989
|
+
const patchRow = React6.useCallback((key, patch) => {
|
|
13990
|
+
setRows((prev) => prev.map((r) => r.key === key ? { ...r, ...patch } : r));
|
|
13991
|
+
}, []);
|
|
13992
|
+
const onCodeInput = React6.useCallback(
|
|
13993
|
+
(key, value) => {
|
|
13994
|
+
patchRow(key, { code: value, productId: null, name: "", netPrice: 0, searched: false });
|
|
13995
|
+
setNotice(null);
|
|
13996
|
+
const timers = searchTimers.current;
|
|
13997
|
+
if (timers[key]) clearTimeout(timers[key]);
|
|
13998
|
+
if (value.trim().length < searchThreshold) {
|
|
13999
|
+
patchRow(key, { matches: [], searching: false, searched: false });
|
|
14000
|
+
return;
|
|
14001
|
+
}
|
|
14002
|
+
patchRow(key, { searching: true });
|
|
14003
|
+
timers[key] = setTimeout(async () => {
|
|
14004
|
+
const results = await searchProducts(value);
|
|
14005
|
+
patchRow(key, { matches: results, searching: false, searched: true });
|
|
14006
|
+
}, debounceMs);
|
|
14007
|
+
},
|
|
14008
|
+
[patchRow, searchProducts, searchThreshold, debounceMs]
|
|
14009
|
+
);
|
|
14010
|
+
const selectMatch = React6.useCallback(
|
|
14011
|
+
(key, match) => {
|
|
14012
|
+
const dup = rows.some((r) => r.key !== key && r.productId && r.code === match.sku);
|
|
14013
|
+
if (dup) {
|
|
14014
|
+
setNotice(L("alreadyInList", "Product is already in the list"));
|
|
14015
|
+
patchRow(key, { code: "", matches: [], productId: null, name: "", netPrice: 0, searched: false });
|
|
14016
|
+
return;
|
|
14017
|
+
}
|
|
14018
|
+
patchRow(key, {
|
|
14019
|
+
code: match.sku,
|
|
14020
|
+
productId: match.productId,
|
|
14021
|
+
clusterId: match.clusterId,
|
|
14022
|
+
name: match.name,
|
|
14023
|
+
netPrice: match.netPrice,
|
|
14024
|
+
quantity: match.minQuantity,
|
|
14025
|
+
minQuantity: match.minQuantity,
|
|
14026
|
+
matches: [],
|
|
14027
|
+
searching: false,
|
|
14028
|
+
searched: false
|
|
14029
|
+
});
|
|
14030
|
+
},
|
|
14031
|
+
[rows, patchRow, L]
|
|
14032
|
+
);
|
|
14033
|
+
const setQuantity = React6.useCallback(
|
|
14034
|
+
(key, raw) => {
|
|
14035
|
+
const n = parseInt(raw, 10);
|
|
14036
|
+
setRows(
|
|
14037
|
+
(prev) => prev.map(
|
|
14038
|
+
(r) => r.key === key ? { ...r, quantity: Number.isFinite(n) && n > 0 ? Math.max(r.minQuantity, n) : r.minQuantity } : r
|
|
14039
|
+
)
|
|
14040
|
+
);
|
|
14041
|
+
},
|
|
14042
|
+
[]
|
|
14043
|
+
);
|
|
14044
|
+
const addRow = React6.useCallback(() => setRows((prev) => [...prev, blankRow()]), []);
|
|
14045
|
+
const removeRow = React6.useCallback(
|
|
14046
|
+
(key) => setRows((prev) => prev.length > 1 ? prev.filter((r) => r.key !== key) : prev),
|
|
14047
|
+
[]
|
|
14048
|
+
);
|
|
14049
|
+
const resolvedCount = React6.useMemo(() => rows.filter((r) => r.productId).length, [rows]);
|
|
14050
|
+
const onFileChosen = React6.useCallback(
|
|
14051
|
+
async (file) => {
|
|
14052
|
+
if (!file || !parseSpreadsheet) return;
|
|
14053
|
+
setUploadError(null);
|
|
14054
|
+
setMissing([]);
|
|
14055
|
+
if (file.size > maxUploadBytes) {
|
|
14056
|
+
setUploadError(`File too large (max ${Math.round(maxUploadBytes / 1024 / 1024)} MB)`);
|
|
14057
|
+
return;
|
|
14058
|
+
}
|
|
14059
|
+
setUploading(true);
|
|
14060
|
+
try {
|
|
14061
|
+
let lines = await parseSpreadsheet(file);
|
|
14062
|
+
lines = lines.slice(0, maxUploadRows).map((l) => ({ code: String(l.code ?? "").trim(), quantity: Math.max(1, parseInt(String(l.quantity), 10) || 1) })).filter((l) => l.code.length > 0);
|
|
14063
|
+
if (!lines.length) {
|
|
14064
|
+
setUploadError("No valid rows found in the file");
|
|
14065
|
+
return;
|
|
14066
|
+
}
|
|
14067
|
+
const resolved = [];
|
|
14068
|
+
const notFound = [];
|
|
14069
|
+
for (const line of lines) {
|
|
14070
|
+
const matches = await searchProducts(line.code);
|
|
14071
|
+
const exact = matches.find((m) => m.sku.toLowerCase() === line.code.toLowerCase()) || matches[0];
|
|
14072
|
+
if (!exact) {
|
|
14073
|
+
notFound.push(line.code);
|
|
14074
|
+
continue;
|
|
14075
|
+
}
|
|
14076
|
+
if (resolved.some((r) => r.productId === exact.productId)) continue;
|
|
14077
|
+
const row = blankRow();
|
|
14078
|
+
resolved.push({
|
|
14079
|
+
...row,
|
|
14080
|
+
code: exact.sku,
|
|
14081
|
+
productId: exact.productId,
|
|
14082
|
+
clusterId: exact.clusterId,
|
|
14083
|
+
name: exact.name,
|
|
14084
|
+
netPrice: exact.netPrice,
|
|
14085
|
+
quantity: Math.max(exact.minQuantity, line.quantity),
|
|
14086
|
+
minQuantity: exact.minQuantity
|
|
14087
|
+
});
|
|
14088
|
+
}
|
|
14089
|
+
if (resolved.length) {
|
|
14090
|
+
setRows([...resolved, blankRow()]);
|
|
14091
|
+
}
|
|
14092
|
+
if (notFound.length) {
|
|
14093
|
+
setMissing(notFound);
|
|
14094
|
+
onMissingCodes?.(notFound);
|
|
14095
|
+
}
|
|
14096
|
+
} catch {
|
|
14097
|
+
setUploadError("Could not read the file");
|
|
14098
|
+
} finally {
|
|
14099
|
+
setUploading(false);
|
|
14100
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
14101
|
+
}
|
|
14102
|
+
},
|
|
14103
|
+
[parseSpreadsheet, maxUploadBytes, maxUploadRows, searchProducts, onMissingCodes]
|
|
14104
|
+
);
|
|
14105
|
+
const handleSubmit = React6.useCallback(async () => {
|
|
14106
|
+
const lines = rows.filter((r) => r.productId).map((r) => ({ productId: r.productId, quantity: r.quantity, clusterId: r.clusterId, code: r.code }));
|
|
14107
|
+
if (!lines.length) {
|
|
14108
|
+
setNotice(L("noItems", "Add at least one product before submitting"));
|
|
14109
|
+
return;
|
|
14110
|
+
}
|
|
14111
|
+
const res = await submit(lines);
|
|
14112
|
+
if (res.success) {
|
|
14113
|
+
setRows(Array.from({ length: Math.max(1, initialRows) }, blankRow));
|
|
14114
|
+
setMissing([]);
|
|
14115
|
+
setNotice(null);
|
|
14116
|
+
} else {
|
|
14117
|
+
setNotice(res.error ?? "Failed to add items to cart");
|
|
14118
|
+
}
|
|
14119
|
+
}, [rows, submit, initialRows, L]);
|
|
14120
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className ?? "propeller-quick-order", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col lg:flex-row gap-8", children: [
|
|
14121
|
+
parseSpreadsheet ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full lg:w-1/3", children: [
|
|
14122
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-3 text-foreground", children: L("uploadTitle", "Upload Excel file") }),
|
|
14123
|
+
templateUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14124
|
+
"a",
|
|
14125
|
+
{
|
|
14126
|
+
href: templateUrl,
|
|
14127
|
+
target: "_blank",
|
|
14128
|
+
rel: "noopener nofollow",
|
|
14129
|
+
className: "text-primary hover:underline text-sm inline-block mb-4",
|
|
14130
|
+
children: L("downloadTemplate", "Download XLSX template")
|
|
14131
|
+
}
|
|
14132
|
+
) : null,
|
|
14133
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-3", children: L("uploadHint", "Column A: article no. / SKU \u2014 Column B: quantity. First two rows are ignored.") }),
|
|
14134
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14135
|
+
"input",
|
|
14136
|
+
{
|
|
14137
|
+
ref: fileInputRef,
|
|
14138
|
+
type: "file",
|
|
14139
|
+
accept: ".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel",
|
|
14140
|
+
className: "block w-full text-sm text-muted-foreground file:mr-3 file:py-2 file:px-4 file:rounded file:border-0 file:bg-primary file:text-primary-foreground hover:file:bg-primary/90",
|
|
14141
|
+
onChange: (e) => onFileChosen(e.target.files?.[0]),
|
|
14142
|
+
disabled: uploading
|
|
14143
|
+
}
|
|
14144
|
+
),
|
|
14145
|
+
uploading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mt-2", children: L("upload", "Uploading\u2026") }) : null,
|
|
14146
|
+
uploadError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive mt-2", children: uploadError }) : null
|
|
14147
|
+
] }) : null,
|
|
14148
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
14149
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-3 text-foreground", children: L("title", "Add your products manually") }),
|
|
14150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden md:grid grid-cols-12 gap-2 px-2 pb-2 text-xs font-medium text-muted-foreground border-b border-border", children: [
|
|
14151
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3", children: L("colCode", "Article no. / SKU") }),
|
|
14152
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3", children: L("colName", "Product name") }),
|
|
14153
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2", children: L("colPrice", "excl. VAT") }),
|
|
14154
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1", children: L("colQuantity", "Qty") }),
|
|
14155
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 text-right", children: L("colTotal", "Total") }),
|
|
14156
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1" })
|
|
14157
|
+
] }),
|
|
14158
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 gap-2 items-center py-2 relative", children: [
|
|
14159
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-3 relative", children: [
|
|
14160
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14161
|
+
"input",
|
|
14162
|
+
{
|
|
14163
|
+
type: "text",
|
|
14164
|
+
value: r.code,
|
|
14165
|
+
onChange: (e) => onCodeInput(r.key, e.target.value),
|
|
14166
|
+
readOnly: !!r.productId,
|
|
14167
|
+
placeholder: L("colCode", "Article no. / SKU"),
|
|
14168
|
+
className: "w-full rounded border border-input bg-background px-2 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
|
14169
|
+
}
|
|
14170
|
+
),
|
|
14171
|
+
(r.searching || r.matches.length > 0 || r.searched) && !r.productId ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "absolute z-20 mt-1 w-[320px] max-w-[90vw] bg-card border border-border rounded shadow-lg max-h-72 overflow-auto", children: r.searching ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "px-3 py-2 text-sm text-muted-foreground", children: "\u2026" }) : r.matches.length ? r.matches.map((m) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14172
|
+
"button",
|
|
14173
|
+
{
|
|
14174
|
+
type: "button",
|
|
14175
|
+
onClick: () => selectMatch(r.key, m),
|
|
14176
|
+
className: "flex items-center gap-2 w-full text-left px-3 py-2 hover:bg-muted text-sm",
|
|
14177
|
+
children: [
|
|
14178
|
+
m.imageUrl ? (
|
|
14179
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
14180
|
+
/* @__PURE__ */ jsxRuntime.jsx("img", { src: m.imageUrl, alt: "", width: 32, height: 32, className: "rounded object-cover" })
|
|
14181
|
+
) : null,
|
|
14182
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1", children: [
|
|
14183
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-foreground", children: m.name }),
|
|
14184
|
+
m.sku ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block text-xs text-muted-foreground", children: [
|
|
14185
|
+
"SKU: ",
|
|
14186
|
+
m.sku
|
|
14187
|
+
] }) : null
|
|
14188
|
+
] })
|
|
14189
|
+
]
|
|
14190
|
+
}
|
|
14191
|
+
) }, `${r.key}-${m.productId}`)) : /* @__PURE__ */ jsxRuntime.jsx("li", { className: "px-3 py-2 text-sm text-muted-foreground", children: L("noResults", "No results found") }) }) : null
|
|
14192
|
+
] }),
|
|
14193
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-6 md:col-span-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14194
|
+
"input",
|
|
14195
|
+
{
|
|
14196
|
+
type: "text",
|
|
14197
|
+
value: r.name,
|
|
14198
|
+
disabled: true,
|
|
14199
|
+
className: "w-full rounded border border-input bg-muted/40 px-2 py-1.5 text-sm text-muted-foreground"
|
|
14200
|
+
}
|
|
14201
|
+
) }),
|
|
14202
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3 md:col-span-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14203
|
+
"input",
|
|
14204
|
+
{
|
|
14205
|
+
type: "text",
|
|
14206
|
+
value: r.productId ? displayPrice(r.netPrice) : "",
|
|
14207
|
+
disabled: true,
|
|
14208
|
+
className: "w-full rounded border border-input bg-muted/40 px-2 py-1.5 text-sm text-muted-foreground"
|
|
14209
|
+
}
|
|
14210
|
+
) }),
|
|
14211
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3 md:col-span-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14212
|
+
"input",
|
|
14213
|
+
{
|
|
14214
|
+
type: "number",
|
|
14215
|
+
min: r.minQuantity,
|
|
14216
|
+
step: 1,
|
|
14217
|
+
value: r.productId ? r.quantity : "",
|
|
14218
|
+
disabled: !r.productId,
|
|
14219
|
+
onChange: (e) => setQuantity(r.key, e.target.value),
|
|
14220
|
+
onKeyDown: (e) => {
|
|
14221
|
+
if (["e", "E", "+", "-", "."].includes(e.key)) e.preventDefault();
|
|
14222
|
+
},
|
|
14223
|
+
className: "w-full rounded border border-input bg-background px-2 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:bg-muted/40"
|
|
14224
|
+
}
|
|
14225
|
+
) }),
|
|
14226
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-9 md:col-span-2 text-right text-sm text-foreground whitespace-nowrap", children: r.productId ? displayPrice(r.netPrice * r.quantity) : "" }),
|
|
14227
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3 md:col-span-1 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14228
|
+
"button",
|
|
14229
|
+
{
|
|
14230
|
+
type: "button",
|
|
14231
|
+
onClick: () => removeRow(r.key),
|
|
14232
|
+
"aria-label": L("remove", "Remove"),
|
|
14233
|
+
className: "text-muted-foreground hover:text-destructive p-1",
|
|
14234
|
+
children: "\u2715"
|
|
14235
|
+
}
|
|
14236
|
+
) })
|
|
14237
|
+
] }, r.key)) }),
|
|
14238
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14239
|
+
"button",
|
|
14240
|
+
{
|
|
14241
|
+
type: "button",
|
|
14242
|
+
onClick: addRow,
|
|
14243
|
+
className: "mt-3 text-primary hover:underline text-sm font-medium",
|
|
14244
|
+
children: [
|
|
14245
|
+
"+ ",
|
|
14246
|
+
L("addRow", "Add more rows")
|
|
14247
|
+
]
|
|
14248
|
+
}
|
|
14249
|
+
),
|
|
14250
|
+
missing.length ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-destructive mt-4", children: [
|
|
14251
|
+
L("missingCodes", "The following products were not added:"),
|
|
14252
|
+
" ",
|
|
14253
|
+
missing.join(", ")
|
|
14254
|
+
] }) : null,
|
|
14255
|
+
notice ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive mt-2", children: notice }) : null,
|
|
14256
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end mt-6 pt-4 border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14257
|
+
"button",
|
|
14258
|
+
{
|
|
14259
|
+
type: "button",
|
|
14260
|
+
onClick: handleSubmit,
|
|
14261
|
+
disabled: submitting || resolvedCount === 0,
|
|
14262
|
+
className: "bg-primary text-primary-foreground px-6 py-2.5 rounded font-medium hover:bg-primary/90 transition disabled:opacity-50 disabled:cursor-not-allowed",
|
|
14263
|
+
children: submitting ? L("adding", "Adding\u2026") : L("addToCart", "Add to cart")
|
|
14264
|
+
}
|
|
14265
|
+
) })
|
|
14266
|
+
] })
|
|
14267
|
+
] }) });
|
|
14268
|
+
}
|
|
14269
|
+
function QuickOrder(rawProps) {
|
|
14270
|
+
const props = useInfraProps(rawProps);
|
|
14271
|
+
return /* @__PURE__ */ jsxRuntime.jsx(QuickOrderInner, { ...props });
|
|
14272
|
+
}
|
|
13785
14273
|
function OrderShipments(props) {
|
|
13786
14274
|
const [activeShipment, setActiveShipment] = React6.useState(null);
|
|
13787
14275
|
const shipments = props.order?.shipments || [];
|
|
@@ -18258,6 +18746,7 @@ exports.PropellerDepsProvider = PropellerDepsProvider;
|
|
|
18258
18746
|
exports.PropellerProvider = PropellerProvider;
|
|
18259
18747
|
exports.PurchaseAuthorizationConfigurator = PurchaseAuthorizationConfigurator_default;
|
|
18260
18748
|
exports.PurchaseAuthorizationRequests = PurchaseAuthorizationRequests_default;
|
|
18749
|
+
exports.QuickOrder = QuickOrder;
|
|
18261
18750
|
exports.QuoteActions = QuoteActions_default;
|
|
18262
18751
|
exports.RegisterForm = RegisterForm_default;
|
|
18263
18752
|
exports.SearchBar = SearchBar_default;
|
|
@@ -18288,6 +18777,7 @@ exports.usePropellerDeps = usePropellerDeps;
|
|
|
18288
18777
|
exports.usePropellerScope = usePropellerScope;
|
|
18289
18778
|
exports.usePurchaseAuthorizationConfigurator = usePurchaseAuthorizationConfigurator;
|
|
18290
18779
|
exports.usePurchaseAuthorizationRequests = usePurchaseAuthorizationRequests;
|
|
18780
|
+
exports.useQuickOrder = useQuickOrder;
|
|
18291
18781
|
exports.useRequiredPropellerDeps = useRequiredPropellerDeps;
|
|
18292
18782
|
exports.useResolvedProps = useResolvedProps;
|
|
18293
18783
|
exports.useServices = useServices;
|