@propeller-commerce/propeller-v2-react-ui 0.15.6 → 0.15.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1535,10 +1535,18 @@ interface UseQuickOrderOptions {
1535
1535
  language?: string;
1536
1536
  /** Max typeahead results per row. Defaults to 8. */
1537
1537
  searchLimit?: number;
1538
- /** Image filters forwarded to search + cart queries. */
1538
+ /** Tax zone for price calculation. Defaults to `'NL'`. */
1539
+ taxZone?: string;
1540
+ /** Orderlist (contract) ids to scope the catalogue by. */
1541
+ orderlistIds?: number[];
1542
+ /** Set `false` to ignore `orderlistIds`. Defaults to true when ids are given. */
1543
+ applyOrderlists?: boolean;
1544
+ /** Image filters + the base category the search is scoped to. */
1539
1545
  configuration?: {
1540
1546
  imageSearchFiltersGrid?: MediaImageProductSearchInput;
1541
1547
  imageVariantFiltersSmall?: TransformationsInput;
1548
+ /** Catalog root. Without it the search returns nothing — see `searchProducts`. */
1549
+ baseCategoryId?: number;
1542
1550
  };
1543
1551
  /** Fires when `submit` creates a fresh cart — persist the cart id. */
1544
1552
  onCartCreated?: (cart: Cart) => void;
@@ -1576,10 +1584,16 @@ interface UseQuickOrderReturn {
1576
1584
  *
1577
1585
  * @remarks
1578
1586
  * GraphQL integration: services are built per-call via `createServices(graphqlClient)`.
1579
- * `searchProducts` calls `services.product.getProducts()` (`ProductService`, the
1580
- * `ProductSearch` operation). `submit` resolves a cart with the shared `initCart`
1581
- * flow, then calls `services.cart.bulkUpdateCartItems()` once with every line
1582
- * (`CartItemBulk`). All calls require an authenticated session.
1587
+ * `searchProducts` calls `services.category.getCategory()` over
1588
+ * `configuration.baseCategoryId` — the same path ProductGrid and the SearchBar
1589
+ * preview use. The flat `products` resolver ignores orderlist scoping
1590
+ * server-side, so searching through it returns products outside the user's
1591
+ * catalogue. Without a `baseCategoryId` the search returns nothing rather than
1592
+ * falling back to that resolver.
1593
+ *
1594
+ * `submit` resolves a cart with the shared `initCart` flow, then calls
1595
+ * `services.cart.bulkUpdateCartItems()` once with every line (`CartItemBulk`).
1596
+ * All calls require an authenticated session.
1583
1597
  */
1584
1598
  declare function useQuickOrder(options: UseQuickOrderOptions): UseQuickOrderReturn;
1585
1599
 
@@ -5219,11 +5233,12 @@ interface OrderBonusItemsProps {
5219
5233
  * Renders an order's bonus items — free items added through incentives — as a
5220
5234
  * read-only "Bonus items" section (heading + table of OrderItemCard rows).
5221
5235
  *
5222
- * Bonus items are order items of `class === 'product'` (the free goods) with
5223
- * `isBonus === 'Y'` — whether standalone or grouped by the backend under an
5224
- * `incentive` item via `parentOrderItemId`. Any backend-side grouping is
5225
- * purely presentational; in the flat SDK item list every bonus good is
5226
- * already `product`/`isBonus === Y`, so filtering on that yields the same set.
5236
+ * Bonus items are order items of `class === 'product'` with `isBonus === 'Y'`.
5237
+ * The API models the discount as a separate sibling `incentive` item that
5238
+ * carries the negative delta and points back via `parentOrderItemId`, so the
5239
+ * product line alone still shows the undiscounted price. Each bonus line is
5240
+ * therefore netted against its incentive siblings before display — a fully
5241
+ * discounted item reaches 0, a partially discounted one keeps the remainder.
5227
5242
  *
5228
5243
  * Renders nothing when there are no bonus items, so it's safe to drop into any
5229
5244
  * order surface (thank-you, order details, quote details) unconditionally.
@@ -5379,7 +5394,20 @@ interface QuickOrderProps {
5379
5394
  configuration?: {
5380
5395
  imageSearchFiltersGrid?: MediaImageProductSearchInput;
5381
5396
  imageVariantFiltersSmall?: TransformationsInput;
5397
+ /**
5398
+ * Catalog root the code search is scoped to. Required: without it the
5399
+ * typeahead and the upload resolve nothing, since searching outside a
5400
+ * category ignores orderlist scoping and would surface products the user
5401
+ * has no access to.
5402
+ */
5403
+ baseCategoryId?: number;
5382
5404
  };
5405
+ /** Tax zone for price calculation. Defaults to `'NL'`. */
5406
+ taxZone?: string;
5407
+ /** Orderlist (contract) ids to scope the catalogue by. */
5408
+ orderlistIds?: number[];
5409
+ /** Set `false` to ignore `orderlistIds`. Defaults to true when ids are given. */
5410
+ applyOrderlists?: boolean;
5383
5411
  /** Number of blank rows to start with. Defaults to 5. */
5384
5412
  initialRows?: number;
5385
5413
  /** Minimum characters before the typeahead fires. Defaults to 3. */
package/dist/index.d.ts CHANGED
@@ -1535,10 +1535,18 @@ interface UseQuickOrderOptions {
1535
1535
  language?: string;
1536
1536
  /** Max typeahead results per row. Defaults to 8. */
1537
1537
  searchLimit?: number;
1538
- /** Image filters forwarded to search + cart queries. */
1538
+ /** Tax zone for price calculation. Defaults to `'NL'`. */
1539
+ taxZone?: string;
1540
+ /** Orderlist (contract) ids to scope the catalogue by. */
1541
+ orderlistIds?: number[];
1542
+ /** Set `false` to ignore `orderlistIds`. Defaults to true when ids are given. */
1543
+ applyOrderlists?: boolean;
1544
+ /** Image filters + the base category the search is scoped to. */
1539
1545
  configuration?: {
1540
1546
  imageSearchFiltersGrid?: MediaImageProductSearchInput;
1541
1547
  imageVariantFiltersSmall?: TransformationsInput;
1548
+ /** Catalog root. Without it the search returns nothing — see `searchProducts`. */
1549
+ baseCategoryId?: number;
1542
1550
  };
1543
1551
  /** Fires when `submit` creates a fresh cart — persist the cart id. */
1544
1552
  onCartCreated?: (cart: Cart) => void;
@@ -1576,10 +1584,16 @@ interface UseQuickOrderReturn {
1576
1584
  *
1577
1585
  * @remarks
1578
1586
  * GraphQL integration: services are built per-call via `createServices(graphqlClient)`.
1579
- * `searchProducts` calls `services.product.getProducts()` (`ProductService`, the
1580
- * `ProductSearch` operation). `submit` resolves a cart with the shared `initCart`
1581
- * flow, then calls `services.cart.bulkUpdateCartItems()` once with every line
1582
- * (`CartItemBulk`). All calls require an authenticated session.
1587
+ * `searchProducts` calls `services.category.getCategory()` over
1588
+ * `configuration.baseCategoryId` — the same path ProductGrid and the SearchBar
1589
+ * preview use. The flat `products` resolver ignores orderlist scoping
1590
+ * server-side, so searching through it returns products outside the user's
1591
+ * catalogue. Without a `baseCategoryId` the search returns nothing rather than
1592
+ * falling back to that resolver.
1593
+ *
1594
+ * `submit` resolves a cart with the shared `initCart` flow, then calls
1595
+ * `services.cart.bulkUpdateCartItems()` once with every line (`CartItemBulk`).
1596
+ * All calls require an authenticated session.
1583
1597
  */
1584
1598
  declare function useQuickOrder(options: UseQuickOrderOptions): UseQuickOrderReturn;
1585
1599
 
@@ -5219,11 +5233,12 @@ interface OrderBonusItemsProps {
5219
5233
  * Renders an order's bonus items — free items added through incentives — as a
5220
5234
  * read-only "Bonus items" section (heading + table of OrderItemCard rows).
5221
5235
  *
5222
- * Bonus items are order items of `class === 'product'` (the free goods) with
5223
- * `isBonus === 'Y'` — whether standalone or grouped by the backend under an
5224
- * `incentive` item via `parentOrderItemId`. Any backend-side grouping is
5225
- * purely presentational; in the flat SDK item list every bonus good is
5226
- * already `product`/`isBonus === Y`, so filtering on that yields the same set.
5236
+ * Bonus items are order items of `class === 'product'` with `isBonus === 'Y'`.
5237
+ * The API models the discount as a separate sibling `incentive` item that
5238
+ * carries the negative delta and points back via `parentOrderItemId`, so the
5239
+ * product line alone still shows the undiscounted price. Each bonus line is
5240
+ * therefore netted against its incentive siblings before display — a fully
5241
+ * discounted item reaches 0, a partially discounted one keeps the remainder.
5227
5242
  *
5228
5243
  * Renders nothing when there are no bonus items, so it's safe to drop into any
5229
5244
  * order surface (thank-you, order details, quote details) unconditionally.
@@ -5379,7 +5394,20 @@ interface QuickOrderProps {
5379
5394
  configuration?: {
5380
5395
  imageSearchFiltersGrid?: MediaImageProductSearchInput;
5381
5396
  imageVariantFiltersSmall?: TransformationsInput;
5397
+ /**
5398
+ * Catalog root the code search is scoped to. Required: without it the
5399
+ * typeahead and the upload resolve nothing, since searching outside a
5400
+ * category ignores orderlist scoping and would surface products the user
5401
+ * has no access to.
5402
+ */
5403
+ baseCategoryId?: number;
5382
5404
  };
5405
+ /** Tax zone for price calculation. Defaults to `'NL'`. */
5406
+ taxZone?: string;
5407
+ /** Orderlist (contract) ids to scope the catalogue by. */
5408
+ orderlistIds?: number[];
5409
+ /** Set `false` to ignore `orderlistIds`. Defaults to true when ids are given. */
5410
+ applyOrderlists?: boolean;
5383
5411
  /** Number of blank rows to start with. Defaults to 5. */
5384
5412
  initialRows?: number;
5385
5413
  /** Minimum characters before the typeahead fires. Defaults to 3. */
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { getLabel, getLocalizedValue, formatPrice, getClusterSku, getClusterImageUrl, isContentHidden, getProductSku, getProductImageUrl, createServices, err, ok, formatSurcharge, deriveUserMode, isContact, isCustomer, getAddresses, attributeNameMatches, getAttributeDisplayName, filterProductsBySelections, extractAttributeValues, buildInventoryFilter, MIN_STOCK_THRESHOLD, getLanguageString, collectAttributeValues, getCountryName } from '@propeller-commerce/propeller-v2-core-ui';
2
+ import { getLabel, getLocalizedValue, formatPrice, getClusterSku, getClusterImageUrl, isContentHidden, getProductSku, getProductImageUrl, createServices, err, ok, formatSurcharge, deriveUserMode, isContact, isCustomer, getAddresses, attributeNameMatches, getAttributeDisplayName, filterProductsBySelections, extractAttributeValues, buildInventoryFilter, MIN_STOCK_THRESHOLD, getNettedBonusItems, getLanguageString, collectAttributeValues, getCountryName } from '@propeller-commerce/propeller-v2-core-ui';
3
3
  export * from '@propeller-commerce/propeller-v2-core-ui';
4
4
  import * as React6 from 'react';
5
5
  import { createContext, useState, useRef, useMemo, useCallback, useContext, useEffect } from 'react';
@@ -2576,21 +2576,33 @@ function useQuickOrder(options) {
2576
2576
  } = options;
2577
2577
  const language = options.language || "NL";
2578
2578
  const searchLimit = options.searchLimit ?? 8;
2579
+ const taxZone = options.taxZone || "NL";
2580
+ const { orderlistIds, applyOrderlists } = options;
2579
2581
  const [submitting, setSubmitting] = useState(false);
2580
2582
  const [error, setError] = useState(null);
2581
2583
  const searchProducts = useCallback(
2582
2584
  async (term) => {
2583
2585
  const trimmed = term.trim();
2584
2586
  if (!trimmed || !graphqlClient) return [];
2587
+ const catId = configuration.baseCategoryId ?? 0;
2588
+ if (!catId) return [];
2585
2589
  try {
2586
- const service = createServices(graphqlClient).product;
2590
+ const service = createServices(graphqlClient).category;
2591
+ const orderlistScope = orderlistIds && orderlistIds.length > 0 ? { applyOrderlists: applyOrderlists !== false, orderlistIds } : { applyOrderlists: false };
2592
+ const userId = user && "contactId" in user ? user.contactId : user && "customerId" in user ? user.customerId : void 0;
2593
+ const contactId = user && "contactId" in user ? user.contactId : void 0;
2594
+ const customerId = user && "customerId" in user ? user.customerId : void 0;
2587
2595
  const input = {
2588
2596
  term: trimmed,
2589
2597
  language,
2590
2598
  page: 1,
2591
2599
  offset: searchLimit,
2592
2600
  statuses: [ProductStatus.A, ProductStatus.P, ProductStatus.T, ProductStatus.S],
2601
+ hidden: false,
2593
2602
  sortInputs: [{ field: ProductSortField.RELEVANCE, order: SortOrder.DESC }],
2603
+ ...companyId && { companyId },
2604
+ ...userId !== void 0 && { userId },
2605
+ ...orderlistScope,
2594
2606
  searchFields: [
2595
2607
  {
2596
2608
  fieldNames: [
@@ -2614,18 +2626,36 @@ function useQuickOrder(options) {
2614
2626
  ]
2615
2627
  };
2616
2628
  const variables = {
2617
- input,
2629
+ categoryId: catId,
2618
2630
  language,
2631
+ categoryProductSearchInput: input,
2632
+ priceCalculateProductInput: {
2633
+ taxZone,
2634
+ ...companyId && { companyId },
2635
+ ...contactId !== void 0 && { contactId },
2636
+ ...customerId !== void 0 && { customerId }
2637
+ },
2638
+ imageSearchFilters: configuration.imageSearchFiltersGrid,
2619
2639
  imageVariantFilters: configuration.imageVariantFiltersSmall
2620
2640
  };
2621
- const result = await service.getProducts(variables);
2622
- const items = result?.items ?? [];
2641
+ const response = await service.getCategory(variables);
2642
+ const items = response?.products?.items ?? [];
2623
2643
  return items.map((it) => toMatch(it, language));
2624
2644
  } catch {
2625
2645
  return [];
2626
2646
  }
2627
2647
  },
2628
- [graphqlClient, language, searchLimit, configuration]
2648
+ [
2649
+ graphqlClient,
2650
+ language,
2651
+ searchLimit,
2652
+ configuration,
2653
+ user,
2654
+ companyId,
2655
+ taxZone,
2656
+ orderlistIds,
2657
+ applyOrderlists
2658
+ ]
2629
2659
  );
2630
2660
  const submit = useCallback(
2631
2661
  async (lines) => {
@@ -13614,9 +13644,7 @@ var OrderItemCard_default = OrderItemCard;
13614
13644
  function OrderBonusItems(rawProps) {
13615
13645
  const props = useInfraProps(rawProps);
13616
13646
  const allItems = props.items ?? props.order?.items ?? [];
13617
- const bonusItems = allItems.filter(
13618
- (item) => item.class === OrderItemClass.product && item.isBonus === YesNo.Y
13619
- );
13647
+ const bonusItems = getNettedBonusItems(allItems);
13620
13648
  if (bonusItems.length === 0) return null;
13621
13649
  const OrderItemCardImpl = props.orderItemCardComponent ?? OrderItemCard_default;
13622
13650
  return /* @__PURE__ */ jsxs("div", { className: `propeller-order-bonus-items ${props.className || "mb-8"}`, children: [
@@ -14142,6 +14170,9 @@ function QuickOrderInner(props) {
14142
14170
  companyId,
14143
14171
  language,
14144
14172
  configuration,
14173
+ taxZone: props.taxZone,
14174
+ orderlistIds: props.orderlistIds,
14175
+ applyOrderlists: props.applyOrderlists,
14145
14176
  onCartCreated,
14146
14177
  afterAddToCart
14147
14178
  });