@propeller-commerce/propeller-v2-react-ui 0.23.0 → 0.24.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 CHANGED
@@ -8,6 +8,46 @@ once it reaches 1.0. Until then (the `0.x` line) the public API may change
8
8
  between minor versions; breaking changes are called out below and in
9
9
  [MIGRATION.md](./MIGRATION.md).
10
10
 
11
+ ## [0.24.0] - 2026-09-25
12
+
13
+ ### Added
14
+
15
+ - `QuickOrderProps.includeTax` and the `colPriceInclVat` label key.
16
+
17
+ ### Fixed
18
+
19
+ - **QuickOrder showed tax-inclusive prices under an "excl. VAT" header, and
20
+ ignored the shop's price toggle.** The rows read `price.net`, which the API
21
+ defines as the price *including* tax, while the column said excl. VAT — so a
22
+ line read 21 % high against the same product on the PDP or in the cart. The
23
+ component now takes `includeTax` (resolved from `<PropellerProvider>` like
24
+ every other price-bearing component), picks `price.gross` or `price.net` to
25
+ match, and labels the column accordingly. (PWP-1027)
26
+
27
+ - **The authorization-request detail mixed tax bases in one row.** The unit
28
+ price came from `totalSum` (excl. VAT) and the line total from `totalSumNet`
29
+ (incl. VAT), so 1 × € 478,55 showed a € 579,05 total and the lines did not sum
30
+ to the "Total excl. VAT" figure printed directly below them. Both cells are
31
+ now excl. VAT, matching that totals block, and the column headers say so.
32
+ (PWP-1029)
33
+
34
+ ## [0.23.1] - 2026-09-24
35
+
36
+ ### Fixed
37
+
38
+ - **The language fallback never ran, so a machine listed in one language still
39
+ opened empty.** 0.23.0 added the fallback but only advanced it on a *thrown*
40
+ error. The API answers a wrong-language slug with a **partial** response —
41
+ `machine: null` alongside `SPARE_PARTS_MACHINE_NOT_FOUND_ERROR` — and the
42
+ SDK's `runOperation` returns that data rather than throwing unless the client
43
+ opts into `throwOnPartialErrors`, which no boilerplate does. So `getMachine`
44
+ resolved to `null`, the first candidate language was accepted as a hit, the
45
+ remaining languages were never tried and `notFound` was never set: one
46
+ request in the tree language per page, and the same empty listing as before.
47
+ A `null` machine now counts as "not found in this language" and the loop
48
+ continues, so the fallback reaches the language the slug was authored in and
49
+ a slug that resolves nowhere sets `notFound`. (PWP-993)
50
+
11
51
  ## [0.23.0] - 2026-09-24
12
52
 
13
53
  ### Fixed
package/dist/index.cjs CHANGED
@@ -2807,7 +2807,8 @@ function machineLanguageCandidates(machineLanguage, language, extra) {
2807
2807
  async function resolveMachineAcrossLanguages(candidates, fetchOne) {
2808
2808
  for (const language of candidates) {
2809
2809
  try {
2810
- return { machine: await fetchOne(language), language };
2810
+ const machine = await fetchOne(language);
2811
+ if (machine !== null && machine !== void 0) return { machine, language };
2811
2812
  } catch (error) {
2812
2813
  if (!isMachineNotFound(error)) throw error;
2813
2814
  }
@@ -14396,6 +14397,7 @@ function blankRow() {
14396
14397
  productId: null,
14397
14398
  name: "",
14398
14399
  netPrice: 0,
14400
+ grossPrice: 0,
14399
14401
  quantity: 1,
14400
14402
  minQuantity: 1,
14401
14403
  matches: [],
@@ -14426,6 +14428,7 @@ function QuickOrderInner(props) {
14426
14428
  const graphqlClient = props.graphqlClient;
14427
14429
  const displayPrice = (n) => props.formatPrice ? props.formatPrice(n) : propellerV2CoreUi.formatPrice(n, { symbol: currency, locale: propellerV2CoreUi.localeForLanguage(props.language) });
14428
14430
  const L = (key, fallback) => propellerV2CoreUi.getLabel(labels, key, fallback);
14431
+ const rowPrice = (r) => props.includeTax ? r.netPrice : r.grossPrice;
14429
14432
  const { submitting, searchProducts, submit } = useQuickOrder({
14430
14433
  graphqlClient,
14431
14434
  user,
@@ -14452,7 +14455,7 @@ function QuickOrderInner(props) {
14452
14455
  }, []);
14453
14456
  const onCodeInput = React6.useCallback(
14454
14457
  (key, value) => {
14455
- patchRow(key, { code: value, productId: null, name: "", netPrice: 0, searched: false });
14458
+ patchRow(key, { code: value, productId: null, name: "", netPrice: 0, grossPrice: 0, searched: false });
14456
14459
  setNotice(null);
14457
14460
  const timers = searchTimers.current;
14458
14461
  if (timers[key]) clearTimeout(timers[key]);
@@ -14473,7 +14476,7 @@ function QuickOrderInner(props) {
14473
14476
  const dup = rows.some((r) => r.key !== key && r.productId && r.code === match.sku);
14474
14477
  if (dup) {
14475
14478
  setNotice(L("alreadyInList", "Product is already in the list"));
14476
- patchRow(key, { code: "", matches: [], productId: null, name: "", netPrice: 0, searched: false });
14479
+ patchRow(key, { code: "", matches: [], productId: null, name: "", netPrice: 0, grossPrice: 0, searched: false });
14477
14480
  return;
14478
14481
  }
14479
14482
  patchRow(key, {
@@ -14482,6 +14485,7 @@ function QuickOrderInner(props) {
14482
14485
  clusterId: match.clusterId,
14483
14486
  name: match.name,
14484
14487
  netPrice: match.netPrice,
14488
+ grossPrice: match.grossPrice,
14485
14489
  quantity: match.minQuantity,
14486
14490
  minQuantity: match.minQuantity,
14487
14491
  matches: [],
@@ -14543,6 +14547,7 @@ function QuickOrderInner(props) {
14543
14547
  clusterId: exact.clusterId,
14544
14548
  name: exact.name,
14545
14549
  netPrice: exact.netPrice,
14550
+ grossPrice: exact.grossPrice,
14546
14551
  quantity: Math.max(exact.minQuantity, line.quantity),
14547
14552
  minQuantity: exact.minQuantity
14548
14553
  });
@@ -14612,7 +14617,7 @@ function QuickOrderInner(props) {
14612
14617
  /* @__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: [
14613
14618
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3", children: L("colCode", "Article no. / SKU") }),
14614
14619
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3", children: L("colName", "Product name") }),
14615
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2", children: L("colPrice", "excl. VAT") }),
14620
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2", children: props.includeTax ? L("colPriceInclVat", "incl. VAT") : L("colPrice", "excl. VAT") }),
14616
14621
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1", children: L("colQuantity", "Qty") }),
14617
14622
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-2 text-right", children: L("colTotal", "Total") }),
14618
14623
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-1" })
@@ -14665,7 +14670,7 @@ function QuickOrderInner(props) {
14665
14670
  "input",
14666
14671
  {
14667
14672
  type: "text",
14668
- value: r.productId ? displayPrice(r.netPrice) : "",
14673
+ value: r.productId ? displayPrice(rowPrice(r)) : "",
14669
14674
  disabled: true,
14670
14675
  className: "w-full rounded border border-input bg-muted/40 px-2 py-1.5 text-sm text-muted-foreground"
14671
14676
  }
@@ -14685,7 +14690,7 @@ function QuickOrderInner(props) {
14685
14690
  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"
14686
14691
  }
14687
14692
  ) }),
14688
- /* @__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) : "" }),
14693
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-9 md:col-span-2 text-right text-sm text-foreground whitespace-nowrap", children: r.productId ? displayPrice(rowPrice(r) * r.quantity) : "" }),
14689
14694
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3 md:col-span-1 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
14690
14695
  "button",
14691
14696
  {
@@ -17725,8 +17730,8 @@ function PurchaseAuthorizationRequests(rawProps) {
17725
17730
  /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-muted/50 border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
17726
17731
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-left px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemProduct", "Product") }),
17727
17732
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-right px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemQty", "Qty") }),
17728
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-right px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemUnitPrice", "Unit price") }),
17729
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-right px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemTotal", "Total") })
17733
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-right px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemUnitPrice", "Unit price excl. VAT") }),
17734
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "text-right px-3 py-2 font-medium text-muted-foreground", children: propellerV2CoreUi.getLabel(props.labels, "itemTotal", "Total excl. VAT") })
17730
17735
  ] }) }),
17731
17736
  /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: getModalItems().map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
17732
17737
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2", children: getProductName5(item) }),
@@ -17734,7 +17739,7 @@ function PurchaseAuthorizationRequests(rawProps) {
17734
17739
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-right", children: formatPrice17(
17735
17740
  (item.quantity ?? 0) > 0 ? (item.totalSum ?? 0) / (item.quantity ?? 1) : 0
17736
17741
  ) }),
17737
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-right font-medium", children: formatPrice17(item.totalSumNet ?? 0) })
17742
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-right font-medium", children: formatPrice17(item.totalSum ?? 0) })
17738
17743
  ] }, idx)) })
17739
17744
  ] }) })
17740
17745
  ] }),