@zenky/storefront-vue 0.10.18 → 0.11.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
@@ -206,6 +206,43 @@ All notable changes to this project are documented in this file. The format foll
206
206
  `register()` returning `true` left the user believing they were signed in when they
207
207
  weren't. This path now performs a real `login()` with the same password instead.
208
208
 
209
+ ## 0.11.0 - 2026-10-07
210
+
211
+ Needs `@zenky/storefront-api` `^1.7.0` (peer dependency).
212
+
213
+ ### Added
214
+
215
+ - Order packaging: `ORDER_WITH` now includes `packages`, and `useCartStore` gets
216
+ `setOrderPackages(packages, packagingPrice)`. Add/remove responses don't carry
217
+ `packages`, so `useCartOperations` reloads them after the total is recalculated, but
218
+ only when the checkout total reports `packaging_price > 0`; at zero a leftover list is
219
+ cleared locally without a request. Late or out-of-order responses (an older sync, or a
220
+ previous order) are dropped, and a failed reload is logged without breaking the
221
+ add/remove. Needs `@zenky/storefront-api` with `Order.packages`,
222
+ `Order.packaging_price` and `OrderCheckoutTotal.packaging_price`.
223
+ - Merchant product badges (`/products`): `toProductBadgeViews` validates the backend
224
+ `Product.badges` list — drops badges with nothing to show, repeated ids and unusable
225
+ icons, accepts only hex colors (alpha is ignored) and http(s) image urls, and returns
226
+ `colors: null` when either color is missing or invalid so the consumer can fall back to
227
+ its theme. `getProductBadgeLayout` tells a text badge from an image without a label (drawn
228
+ as a square with no background), `filterProductBadges` hides either kind, and
229
+ `getProductBadgeAccent` derives a palette from the badge's own text/background pair
230
+ (accent, readable `on` color, hue-shifted gradient end, readable text, translucent glass
231
+ fill) with plain JS math, no CSS color functions. Styles, sizes and placement stay with
232
+ the consumer. Needs `@zenky/storefront-api` with `Product.badges` (`^1.6.0`).
233
+
234
+ ### Changed
235
+
236
+ - `useCartStore.setOrder` keeps the previous `packages` (and `packaging_price`, unless the
237
+ new order brings its own) when the new order has the same id and no `packages`;
238
+ responses such as `setOrderPayments` omit them, and replacing the order wholesale made
239
+ the packaging block disappear while the total still included it.
240
+ - `addToCart` now forwards `promotionId` / `promotionRewardId` to the API as
241
+ `promotion_id` / `promotion_reward_id`, so promotion gifts are added through the regular
242
+ pipeline (total recalculation, packaging sync, promotion re-check) instead of a direct
243
+ SDK call. Gift adds do not emit add-to-cart analytics events (`productAddedToCart`,
244
+ `productQuantityIncreased`, `trackAddedToCart`); removal events are unchanged.
245
+
209
246
  ## 0.10.7 - 2026-08-02
210
247
 
211
248
  ### Added
@@ -1,13 +1,13 @@
1
- export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from '../chunk-6BXHWR5E.js';
2
- export { useCartCredentials } from '../chunk-2DUKIVKC.js';
1
+ export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from '../chunk-5KCBZJV3.js';
3
2
  import '../chunk-5QCUH3FF.js';
4
3
  export { getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getValidationErrors, logCartError } from '../chunk-TE42OCFK.js';
5
- import '../chunk-544USTPB.js';
6
4
  import '../chunk-4JCJHAL3.js';
7
- import '../chunk-T52G6JN7.js';
8
5
  import '../chunk-TIQ7AJLY.js';
9
- import '../chunk-IOYYCA75.js';
10
6
  import '../chunk-FS2UNPTY.js';
11
7
  import '../chunk-2Y6QTHXI.js';
8
+ export { useCartCredentials } from '../chunk-QFKA2R6D.js';
9
+ import '../chunk-544USTPB.js';
10
+ import '../chunk-TXR76IDL.js';
11
+ import '../chunk-IOYYCA75.js';
12
12
  //# sourceMappingURL=index.js.map
13
13
  //# sourceMappingURL=index.js.map
@@ -1,13 +1,13 @@
1
- import { useCartCredentials, usePromotionsChecker } from './chunk-2DUKIVKC.js';
2
1
  import { createRuntimeState } from './chunk-5QCUH3FF.js';
3
2
  import { logCartError, getCartErrorHttpCode, getCartErrorCode, getCartErrorMessage } from './chunk-TE42OCFK.js';
4
- import { usePromotionsStore } from './chunk-544USTPB.js';
5
3
  import { useCatalogStore } from './chunk-4JCJHAL3.js';
6
- import { useRuntime, useCartStore, useAuthStore, useOrderSettingsStore } from './chunk-T52G6JN7.js';
7
4
  import { toRequestedMethod } from './chunk-TIQ7AJLY.js';
8
- import { useStoreProfileStore } from './chunk-IOYYCA75.js';
9
5
  import { getRemoteCatalog } from './chunk-FS2UNPTY.js';
10
6
  import { minorToMajor, majorToMinor } from './chunk-2Y6QTHXI.js';
7
+ import { useCartCredentials, usePromotionsChecker } from './chunk-QFKA2R6D.js';
8
+ import { usePromotionsStore } from './chunk-544USTPB.js';
9
+ import { useRuntime, useCartStore, useAuthStore, useOrderSettingsStore } from './chunk-TXR76IDL.js';
10
+ import { useStoreProfileStore } from './chunk-IOYYCA75.js';
11
11
  import { PaymentMethod, OrderAuthenticationMethod, DeliveryMethod, OrderCartCheckerResultAction, RecaptchaAction } from '@zenky/storefront-api';
12
12
  import { ref, computed, watch, watchEffect, getCurrentScope, onScopeDispose, toValue } from 'vue';
13
13
  import { storeToRefs } from 'pinia';
@@ -340,6 +340,7 @@ var ORDER_INCLUDES = [
340
340
  "payments",
341
341
  "progress",
342
342
  "promocode",
343
+ "packages",
343
344
  "variants.variant.options",
344
345
  "variants.product.images",
345
346
  "variants.product.categories",
@@ -1339,17 +1340,43 @@ var BATCH_DELAY = 250;
1339
1340
  var CART_LINE_KIND_PREFIX = "cart-line-";
1340
1341
  var getOperationsState = createRuntimeState(() => ({
1341
1342
  batches: /* @__PURE__ */ new Map(),
1342
- inflight: /* @__PURE__ */ new Set()
1343
+ inflight: /* @__PURE__ */ new Set(),
1344
+ packagesSeq: 0
1343
1345
  }));
1344
1346
  function useCartOperations(credentials, initialization, sdk, deps) {
1345
1347
  const { notifier, activity } = deps;
1346
1348
  const runtime = useRuntime();
1347
1349
  const { events, rum, commerceEvents, messages } = runtime;
1348
- const { batches, inflight } = getOperationsState(runtime);
1350
+ const state = getOperationsState(runtime);
1351
+ const { batches, inflight } = state;
1349
1352
  const cartStore = useCartStore();
1350
1353
  const profileStore = useStoreProfileStore();
1351
1354
  const { run: runMutation, bumpKindsWithPrefix } = useCartMutation();
1352
1355
  const { recalculateAfterOrderChange } = useCartRecalculation({ notifier, activity });
1356
+ async function syncPackages(isStale) {
1357
+ const mySeq = ++state.packagesSeq;
1358
+ const packagingPrice = cartStore.checkoutTotal?.packaging_price ?? 0;
1359
+ const hasPackages = (cartStore.order?.packages?.length ?? 0) > 0;
1360
+ if (packagingPrice <= 0) {
1361
+ if (hasPackages && !isStale()) cartStore.setOrderPackages([], 0);
1362
+ return;
1363
+ }
1364
+ try {
1365
+ const fresh = await sdk.orders.getOrder(
1366
+ credentials.getStoreId(),
1367
+ credentials.getCredentials(),
1368
+ { with: "packages" }
1369
+ );
1370
+ if (isStale() || mySeq !== state.packagesSeq) return;
1371
+ if (fresh.id !== cartStore.order?.id) return;
1372
+ cartStore.setOrderPackages(fresh.packages ?? [], fresh.packaging_price ?? null);
1373
+ } catch (e) {
1374
+ logCartError(
1375
+ { scope: "cart-packages", context: { orderId: cartStore.credentials?.id } },
1376
+ e
1377
+ );
1378
+ }
1379
+ }
1353
1380
  function flushBatch(lineKey) {
1354
1381
  if (inflight.has(lineKey)) return;
1355
1382
  const batch = batches.get(lineKey);
@@ -1362,6 +1389,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1362
1389
  inflight.add(lineKey);
1363
1390
  const sentDelta = batch.delta;
1364
1391
  const isAdd = sentDelta > 0;
1392
+ const isPromotionLine = Boolean(batch.promotionId);
1365
1393
  const qty = Math.abs(sentDelta);
1366
1394
  const { variantId, productId, productName, variantLabel } = batch;
1367
1395
  const execute = async () => {
@@ -1382,6 +1410,10 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1382
1410
  product_variant_id: variantId,
1383
1411
  quantity: qty,
1384
1412
  modifiers: batch.modifiers,
1413
+ ...batch.promotionId ? {
1414
+ promotion_id: batch.promotionId,
1415
+ promotion_reward_id: batch.promotionRewardId
1416
+ } : {},
1385
1417
  ...batch.recommendationsBlock ? { recommendations_block: batch.recommendationsBlock } : {}
1386
1418
  }
1387
1419
  );
@@ -1414,7 +1446,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1414
1446
  optimisticCorrected = true;
1415
1447
  const integrations = events?.get() ?? null;
1416
1448
  const orderVariant = cartStore.order?.variants?.find((v) => variantLineKey(v) === lineKey) ?? null;
1417
- if (isAdd) {
1449
+ if (isAdd && !isPromotionLine) {
1418
1450
  if (!wasInCartBefore) {
1419
1451
  integrations?.productAddedToCart({
1420
1452
  order: cartStore.order,
@@ -1426,7 +1458,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1426
1458
  orderVariant
1427
1459
  });
1428
1460
  }
1429
- } else {
1461
+ } else if (!isAdd) {
1430
1462
  const isNowInCart = cartStore.order?.variants?.some((v) => variantLineKey(v) === lineKey) ?? false;
1431
1463
  if (!isNowInCart) {
1432
1464
  const product = variantBeforeChange?.product ?? null;
@@ -1443,7 +1475,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1443
1475
  }
1444
1476
  const commerceOrderId = cartStore.credentials?.id;
1445
1477
  if (commerceOrderId && commerceEvents) {
1446
- if (isAdd) {
1478
+ if (isAdd && !isPromotionLine) {
1447
1479
  const currency = profileStore.currency;
1448
1480
  const cartTotal = cartStore.order?.total_price;
1449
1481
  commerceEvents.trackAddedToCart(commerceOrderId, {
@@ -1454,7 +1486,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1454
1486
  totalPrice: cartTotal != null ? minorToMajor(cartTotal, currency) : void 0,
1455
1487
  recommendationsBlock: batch.recommendationsBlock
1456
1488
  });
1457
- } else {
1489
+ } else if (!isAdd) {
1458
1490
  commerceEvents.trackRemovedFromCart(commerceOrderId, {
1459
1491
  productId,
1460
1492
  productVariantId: variantId,
@@ -1463,6 +1495,7 @@ function useCartOperations(credentials, initialization, sdk, deps) {
1463
1495
  }
1464
1496
  }
1465
1497
  await recalculateAfterOrderChange();
1498
+ await syncPackages(isStale);
1466
1499
  if (isAdd && productName) {
1467
1500
  const parts = [productName, variantLabel].filter(Boolean);
1468
1501
  notifier.message(messages.format("cart.added.title"), {
@@ -1950,5 +1983,5 @@ function useVisibleCartVariants() {
1950
1983
  }
1951
1984
 
1952
1985
  export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCashDenominationsMinor, getDefaultRoundStepsMinor, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey };
1953
- //# sourceMappingURL=chunk-6BXHWR5E.js.map
1954
- //# sourceMappingURL=chunk-6BXHWR5E.js.map
1986
+ //# sourceMappingURL=chunk-5KCBZJV3.js.map
1987
+ //# sourceMappingURL=chunk-5KCBZJV3.js.map