@ikas/storefront 4.0.0-alpha.5 → 4.0.0-alpha.50

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.
Files changed (85) hide show
  1. package/package.json +13 -13
  2. package/src/analytics/analytics.ts +2 -1
  3. package/src/analytics/googleUniversal.ts +12 -2
  4. package/src/analytics/head/index.tsx +1 -2
  5. package/src/analytics/ikas.ts +25 -7
  6. package/src/components/checkout/components/address-form/index.tsx +1 -1
  7. package/src/components/checkout/components/address-form/model.ts +1 -0
  8. package/src/components/checkout/components/button/style.module.scss +2 -2
  9. package/src/components/checkout/components/cart-summary/cart-item/index.tsx +16 -29
  10. package/src/components/checkout/components/cart-summary/cart-item/style.module.scss +60 -23
  11. package/src/components/checkout/components/cart-summary/index.tsx +58 -27
  12. package/src/components/checkout/components/cart-summary/style.module.scss +48 -3
  13. package/src/components/checkout/components/customer-addresses/index.tsx +7 -2
  14. package/src/components/checkout/components/customer-addresses/model.ts +16 -8
  15. package/src/components/checkout/components/error/index.tsx +1 -1
  16. package/src/components/checkout/components/error/unknown-error/index.tsx +4 -2
  17. package/src/components/checkout/components/form-item/index.tsx +9 -11
  18. package/src/components/checkout/components/master-pass/credit-card-form/index.tsx +2 -0
  19. package/src/components/checkout/components/offer-product/index.tsx +16 -19
  20. package/src/components/checkout/components/offer-product/style.module.scss +1 -3
  21. package/src/components/checkout/components/phone-number-input/get-countries.ts +37 -5
  22. package/src/components/checkout/components/phone-number-input/index.tsx +15 -10
  23. package/src/components/checkout/index.tsx +28 -19
  24. package/src/components/checkout/model.ts +214 -91
  25. package/src/components/checkout/modelMasterPass.ts +2 -2
  26. package/src/components/checkout/steps/step-info/index.tsx +9 -3
  27. package/src/components/checkout/steps/step-payment/billing-address/index.tsx +1 -1
  28. package/src/components/checkout/steps/step-payment/index.tsx +11 -2
  29. package/src/components/checkout/steps/step-payment/payment-gateways/index.tsx +12 -3
  30. package/src/components/checkout/steps/step-payment/payment-gateways/installments/index.tsx +5 -3
  31. package/src/components/checkout/steps/step-payment/style.module.scss +5 -0
  32. package/src/components/checkout/steps/step-shipping/index.tsx +9 -4
  33. package/src/components/checkout/steps/step-success/index.tsx +15 -7
  34. package/src/components/page/head.tsx +12 -0
  35. package/src/components/page/index.tsx +10 -9
  36. package/src/components/page-editor/ThemeComponentEditor.tsx +19 -8
  37. package/src/components/page-editor/model.ts +44 -107
  38. package/src/models/data/cart/campaign-offer/index.ts +13 -2
  39. package/src/models/data/cart/index.ts +1 -1
  40. package/src/models/data/category/path-item/index.ts +4 -0
  41. package/src/models/data/checkout/index.ts +36 -4
  42. package/src/models/data/checkout-settings/price/index.ts +2 -0
  43. package/src/models/data/country/index.ts +4 -0
  44. package/src/models/data/country/location-translations/index.ts +15 -0
  45. package/src/models/data/index.ts +3 -0
  46. package/src/models/data/merchant-settings/index.ts +9 -0
  47. package/src/models/data/order/index.ts +51 -32
  48. package/src/models/data/order/line-item/base-unit/index.ts +22 -0
  49. package/src/models/data/order/line-item/base-unit/unit-type/index.ts +14 -0
  50. package/src/models/data/order/line-item/index.ts +76 -18
  51. package/src/models/data/order/line-item/variant/index.ts +8 -0
  52. package/src/models/data/order/line-item/variant/price/index.ts +2 -0
  53. package/src/models/data/order/line-item/variant/unit/index.ts +17 -0
  54. package/src/models/data/order/line-item/variant/value/index.ts +1 -1
  55. package/src/models/data/order/transaction/index.ts +2 -5
  56. package/src/models/data/product/attribute-value/index.ts +40 -0
  57. package/src/models/data/product/base-unit/index.ts +32 -0
  58. package/src/models/data/product/filter/index.ts +4 -13
  59. package/src/models/data/product/index.ts +45 -7
  60. package/src/models/data/product/option-set/index.ts +8 -3
  61. package/src/models/data/product/option-set/option/index.ts +36 -13
  62. package/src/models/data/product/variant/index.ts +26 -1
  63. package/src/models/data/product/variant/price/index.ts +25 -9
  64. package/src/models/data/product/variant/unit/index.ts +17 -0
  65. package/src/models/data/product/variant-type/index.ts +2 -0
  66. package/src/models/data/raffle/index.ts +9 -7
  67. package/src/models/data/state/index.ts +6 -2
  68. package/src/models/data/storefront/index.ts +2 -0
  69. package/src/models/data/storefront/routing/index.tsx +4 -0
  70. package/src/models/ui/product-list/index.ts +26 -17
  71. package/src/models/ui/raffle-list/index.ts +1 -1
  72. package/src/models/ui/validator/form/raffle-form.ts +16 -3
  73. package/src/models/ui/validator/rules/index.ts +14 -13
  74. package/src/page-data-init/index.ts +159 -404
  75. package/src/pages/checkout.tsx +2 -1
  76. package/src/pages/editor.tsx +5 -2
  77. package/src/store/base.ts +2 -2
  78. package/src/store/cart/index.ts +2 -2
  79. package/src/store/customer/index.ts +7 -17
  80. package/src/store/index.ts +2 -0
  81. package/src/store/raffle/index.ts +7 -10
  82. package/src/utils/constants.ts +1 -1
  83. package/src/utils/currency.ts +9 -183
  84. package/src/components/checkout/components/phone-number-input/locale/en.ts +0 -257
  85. package/src/models/data/category/init.ts +0 -33
@@ -12,6 +12,7 @@ import {
12
12
  IkasOrderCustomer,
13
13
  IkasCartCampaignOfferStatus,
14
14
  IkasProduct,
15
+ IkasProductVariant,
15
16
  IkasCartCampaignOffer,
16
17
  IkasCheckout,
17
18
  IkasStockLocation,
@@ -19,6 +20,7 @@ import {
19
20
  IkasTransactionStatus,
20
21
  IkasCampaignOfferTargetPageType,
21
22
  IkasCampaignOfferProduct,
23
+ IkasOrderShippingMethod,
22
24
  } from "../../models";
23
25
  import { IkasOrderAddress } from "../../models/data/order/address";
24
26
  import {
@@ -91,8 +93,8 @@ export default class CheckoutViewModel {
91
93
 
92
94
  stripeResponse: CreateStripePaymentIntentResponse | null = null;
93
95
 
94
- checkoutCampaignOffer: CampaignOfferType | undefined;
95
- postCheckoutCampaignOffer: CampaignOfferType | undefined;
96
+ checkoutCampaignOffer?: CampaignOfferType;
97
+ postCheckoutCampaignOffer?: CampaignOfferType;
96
98
 
97
99
  returnPolicy: string;
98
100
  privacyPolicy: string;
@@ -173,6 +175,11 @@ export default class CheckoutViewModel {
173
175
  } else {
174
176
  return this.changeStep(CheckoutStep.INFO);
175
177
  }
178
+ } else if (
179
+ this.step === CheckoutStep.SUCCESS &&
180
+ !this.canProceedToPayment
181
+ ) {
182
+ return this.changeStep(CheckoutStep.INFO);
176
183
  } else if (
177
184
  ![
178
185
  CheckoutStep.INFO,
@@ -249,12 +256,6 @@ export default class CheckoutViewModel {
249
256
  }
250
257
  }
251
258
 
252
- if (this.step === CheckoutStep.PAYMENT) {
253
- if (this.isInStoreDelivery) {
254
- this.checkout.billingAddress = new IkasOrderAddress();
255
- }
256
- }
257
-
258
259
  if (this.step !== CheckoutStep.SUCCESS) {
259
260
  if (this.checkout.isComplete) {
260
261
  return this.changeStep(CheckoutStep.SUCCESS);
@@ -365,7 +366,9 @@ export default class CheckoutViewModel {
365
366
 
366
367
  get canProceedToShipping() {
367
368
  return (
368
- this.checkout.shippingAddress?.isValid &&
369
+ (this.isDigitalOnly
370
+ ? this.checkout.billingAddress?.isValid
371
+ : this.checkout.shippingAddress?.isValid) &&
369
372
  this.checkout.hasValidCustomerEmail &&
370
373
  this.error?.type !== ErrorType.NO_SHIPPING_ERROR
371
374
  );
@@ -431,6 +434,12 @@ export default class CheckoutViewModel {
431
434
  );
432
435
  }
433
436
 
437
+ get isDigitalOnly() {
438
+ return (
439
+ this.checkout.shippingMethod === IkasOrderShippingMethod.DIGITAL_DELIVERY
440
+ );
441
+ }
442
+
434
443
  // VALIDATIONS END
435
444
 
436
445
  saveCart = async () => {
@@ -440,10 +449,18 @@ export default class CheckoutViewModel {
440
449
  input = await this.inStockDeliveryInputData(input);
441
450
  }
442
451
 
443
- if (this.step === CheckoutStep.INFO) {
452
+ if (
453
+ (this.step === CheckoutStep.INFO ||
454
+ this.step === CheckoutStep.SHIPPING) &&
455
+ !this.isDigitalOnly
456
+ ) {
444
457
  input.billingAddress = null;
445
458
  }
446
459
 
460
+ if (this.isDigitalOnly) {
461
+ input.shippingAddress = null;
462
+ }
463
+
447
464
  const response = await CartStoreAPI.saveCart({ input });
448
465
 
449
466
  if (response?.graphQLErrors && response.graphQLErrors.length) {
@@ -456,6 +473,7 @@ export default class CheckoutViewModel {
456
473
  } else {
457
474
  throw {
458
475
  type: ErrorType.API_ERROR,
476
+ data: response.firstErrorMessage,
459
477
  };
460
478
  }
461
479
  }
@@ -510,6 +528,7 @@ export default class CheckoutViewModel {
510
528
  if (!checkStocksResponse.isSuccess) {
511
529
  throw {
512
530
  type: ErrorType.API_ERROR,
531
+ data: checkStocksResponse.firstErrorMessage,
513
532
  };
514
533
  }
515
534
 
@@ -555,6 +574,7 @@ export default class CheckoutViewModel {
555
574
  if (!response.isSuccess || !response.data?.length) {
556
575
  this.error = {
557
576
  type: ErrorType.API_ERROR,
577
+ data: response.firstErrorMessage,
558
578
  };
559
579
  return;
560
580
  }
@@ -608,7 +628,7 @@ export default class CheckoutViewModel {
608
628
  try {
609
629
  await this.checkStocks();
610
630
  } catch (err) {
611
- if (err.type) {
631
+ if (typeof err.type !== undefined) {
612
632
  this.error = err;
613
633
  } else {
614
634
  console.log(err);
@@ -632,6 +652,7 @@ export default class CheckoutViewModel {
632
652
  ) {
633
653
  this.error = {
634
654
  type: ErrorType.API_ERROR,
655
+ data: paymentGatewaysResponse.firstErrorMessage,
635
656
  };
636
657
  return;
637
658
  }
@@ -704,18 +725,29 @@ export default class CheckoutViewModel {
704
725
  this.checkout.customer = new IkasOrderCustomer(
705
726
  this.store.customerStore.customer as any
706
727
  );
707
- } else if (!this.checkout.customer)
708
- this.checkout.customer = new IkasOrderCustomer({});
728
+ } else {
729
+ this.checkout.customer = new IkasOrderCustomer(
730
+ this.checkout.customer || {}
731
+ );
732
+ }
709
733
  };
710
734
 
711
735
  createShippingAddress = () => {
736
+ if (this.isDigitalOnly) return;
737
+
712
738
  if (!this.checkout.shippingAddress) {
713
- const customerAddresses = this.store.customerStore.customer?.addresses;
714
- this.onSelectedShippingAddressIdChange(
715
- customerAddresses?.length ? customerAddresses[0].id! : "-1"
716
- );
739
+ if (!!this.store.customerStore.customer) {
740
+ const customerAddresses = this.store.customerStore.customer.addresses;
741
+ this.onSelectedShippingAddressIdChange(
742
+ customerAddresses?.length ? customerAddresses[0].id! : "-1"
743
+ );
744
+ } else {
745
+ this.onSelectedShippingAddressIdChange("-1");
746
+ }
717
747
  } else {
718
- this.selectedShippingAddressId = this.checkout.shippingAddress.id || "-1";
748
+ this.checkout.shippingAddress = new IkasOrderAddress(
749
+ _cloneDeep(this.checkout.shippingAddress) || {}
750
+ );
719
751
  this.checkout.shippingAddress.checkoutSettings = this.checkoutSettings;
720
752
  }
721
753
  };
@@ -726,25 +758,21 @@ export default class CheckoutViewModel {
726
758
  USE_DIFFERENT_ADDRESS_KEY
727
759
  );
728
760
 
729
- if (this.useDifferentAddress) {
730
- if (this.checkout.billingAddress) {
731
- this.selectedBillingAddressId =
732
- this.checkout.billingAddress.id || "-1";
733
- }
734
- this.checkout.billingAddress =
735
- this.checkout.billingAddress || new IkasOrderAddress();
736
- } else {
737
- if (this.isInStoreDelivery) {
738
- this.checkout.billingAddress = new IkasOrderAddress(
739
- _cloneDeep(this.checkout.billingAddress) || {}
761
+ if (!this.checkout.billingAddress) {
762
+ if (!!this.store.customerStore.customer) {
763
+ const customerAddresses = this.store.customerStore.customer.addresses;
764
+ this.onSelectedBillingAddressIdChange(
765
+ customerAddresses?.length ? customerAddresses[0].id! : "-1"
740
766
  );
741
767
  } else {
742
- this.checkout.billingAddress = new IkasOrderAddress(
743
- _cloneDeep(this.checkout.shippingAddress) || {}
744
- );
768
+ this.onSelectedBillingAddressIdChange("-1");
745
769
  }
770
+ } else {
771
+ this.checkout.billingAddress = new IkasOrderAddress(
772
+ _cloneDeep(this.checkout.billingAddress) || {}
773
+ );
774
+ this.checkout.billingAddress.checkoutSettings = this.checkoutSettings;
746
775
  }
747
- this.checkout.billingAddress.checkoutSettings = this.checkoutSettings;
748
776
  }
749
777
  };
750
778
 
@@ -759,6 +787,8 @@ export default class CheckoutViewModel {
759
787
  const newCart = await this.saveCart();
760
788
 
761
789
  if (newCart) this.checkout = new IkasCheckout(newCart);
790
+ if (this.checkout.shippingAddress)
791
+ this.checkout.shippingAddress.checkoutSettings = this.checkoutSettings;
762
792
  this.isChangingShippingMethod = false;
763
793
  };
764
794
 
@@ -983,6 +1013,9 @@ export default class CheckoutViewModel {
983
1013
  customer.addresses.push(newAddress);
984
1014
 
985
1015
  await this.store.customerStore.saveCustomer(customer);
1016
+ this.store.customerStore.customer.addresses?.forEach(
1017
+ (address) => (address.checkoutSettings = this.checkoutSettings)
1018
+ );
986
1019
 
987
1020
  if (type === "shipping") {
988
1021
  this.checkout.shippingAddress!.id = newAddress.id;
@@ -1035,6 +1068,34 @@ export default class CheckoutViewModel {
1035
1068
  } else {
1036
1069
  this.changeStep(CheckoutStep.PAYMENT);
1037
1070
  }
1071
+ } catch (err) {
1072
+ if (typeof err.type !== undefined) {
1073
+ this.error = err;
1074
+ } else {
1075
+ console.log(err);
1076
+ this.error = {
1077
+ type: ErrorType.UNKNOWN,
1078
+ };
1079
+ }
1080
+ this.isStepLoading = false;
1081
+ }
1082
+ };
1083
+
1084
+ onProceedToDigitalOnlyPaymentClick = async () => {
1085
+ if (!this.canProceedToPayment) {
1086
+ this.isErrorsVisible = true;
1087
+ return;
1088
+ }
1089
+
1090
+ this.isErrorsVisible = false;
1091
+
1092
+ try {
1093
+ this.isStepLoading = true;
1094
+
1095
+ await this.checkStocks();
1096
+ await this.saveCart();
1097
+
1098
+ this.changeStep(CheckoutStep.PAYMENT);
1038
1099
  } catch (err) {
1039
1100
  if (err.type) {
1040
1101
  this.error = err;
@@ -1063,7 +1124,7 @@ export default class CheckoutViewModel {
1063
1124
  this.error = undefined;
1064
1125
  this.changeStep(CheckoutStep.PAYMENT);
1065
1126
  } catch (err) {
1066
- if (err.type) {
1127
+ if (typeof err.type !== undefined) {
1067
1128
  this.error = err;
1068
1129
  } else {
1069
1130
  console.log(err);
@@ -1105,6 +1166,46 @@ export default class CheckoutViewModel {
1105
1166
  return;
1106
1167
  }
1107
1168
 
1169
+ await this.createSaleTransaction();
1170
+ } catch (err) {
1171
+ if (typeof err.type !== undefined) {
1172
+ this.error = err;
1173
+ } else {
1174
+ this.error = {
1175
+ type: ErrorType.UNKNOWN,
1176
+ };
1177
+ }
1178
+ this.isStepLoading = false;
1179
+ }
1180
+ };
1181
+
1182
+ onCompleteDigitalOnlyPaymentClick = async () => {
1183
+ if (
1184
+ !this.canProceedToPayment ||
1185
+ (this.checkoutSettings.showTermsAndConditionsCheckbox &&
1186
+ !this.isTermsAndConditionsChecked)
1187
+ ) {
1188
+ this.isErrorsVisible = true;
1189
+ return;
1190
+ }
1191
+
1192
+ try {
1193
+ this.isErrorsVisible = false;
1194
+ this.isStepLoading = true;
1195
+
1196
+ await this.checkStocks();
1197
+ await this.saveCart();
1198
+
1199
+ if (this.isCustomFlowStripe) {
1200
+ const stripeFromBtn = document.querySelector("#stripe-form-btn");
1201
+ if (stripeFromBtn) {
1202
+ //@ts-ignore
1203
+ stripeFromBtn.click();
1204
+ }
1205
+
1206
+ return;
1207
+ }
1208
+
1108
1209
  await this.createSaleTransaction();
1109
1210
  } catch (err) {
1110
1211
  if (err.type) {
@@ -1194,6 +1295,7 @@ export default class CheckoutViewModel {
1194
1295
  process.env.NEXT_PUBLIC_BASE_URL + response.data.returnSlug;
1195
1296
  } else {
1196
1297
  throw {
1298
+ data: response.firstErrorMessage,
1197
1299
  type: ErrorType.UNKNOWN,
1198
1300
  };
1199
1301
  }
@@ -1316,32 +1418,25 @@ export default class CheckoutViewModel {
1316
1418
  this.isContactModalVisible = value;
1317
1419
  };
1318
1420
 
1319
- getWaitingForActionCampaignOffer = (
1421
+ getWaitingForActionCampaignOffers = (
1320
1422
  targetPage: IkasCampaignOfferTargetPageType
1321
1423
  ) => {
1322
- if (this.checkout.campaignOffers && this.checkout.campaignOffers.length) {
1323
- const filteredCampaignOffer = this.checkout.campaignOffers.filter(
1324
- (co) =>
1325
- co.status === IkasCartCampaignOfferStatus.WAITING_FOR_ACTION &&
1326
- co.campaignOffer?.targetPageTypes.some((tpt) => tpt === targetPage)
1327
- );
1328
-
1329
- if (filteredCampaignOffer.length) {
1330
- return filteredCampaignOffer[0];
1331
- }
1332
- }
1424
+ if (!this.checkout.campaignOffers || !this.checkout.campaignOffers.length)
1425
+ return;
1333
1426
 
1334
- return null;
1427
+ const filteredCampaignOffers = this.checkout.campaignOffers.filter(
1428
+ (co) =>
1429
+ co.status === IkasCartCampaignOfferStatus.WAITING_FOR_ACTION &&
1430
+ co.campaignOffer?.targetPageTypes.some((tpt) => tpt === targetPage)
1431
+ );
1432
+ return filteredCampaignOffers;
1335
1433
  };
1336
1434
 
1337
1435
  getOffer = (waitingForActionCampaignOffer: IkasCartCampaignOffer) => {
1338
- if (waitingForActionCampaignOffer.campaignOffer) {
1339
- return waitingForActionCampaignOffer.campaignOffer.offers.find(
1340
- (o) => o.id === waitingForActionCampaignOffer.campaignOfferProductId
1341
- );
1342
- }
1343
-
1344
- return null;
1436
+ if (!waitingForActionCampaignOffer.campaignOffer) return null;
1437
+ return waitingForActionCampaignOffer.campaignOffer.offers.find(
1438
+ (o) => o.id === waitingForActionCampaignOffer.campaignOfferProductId
1439
+ );
1345
1440
  };
1346
1441
 
1347
1442
  getProduct = async (productId: string) => {
@@ -1351,61 +1446,88 @@ export default class CheckoutViewModel {
1351
1446
  },
1352
1447
  });
1353
1448
 
1354
- if (
1355
- productsResponse.isSuccess &&
1356
- productsResponse.data &&
1357
- productsResponse.data.data &&
1358
- productsResponse.data.data.length
1359
- ) {
1360
- const product = productsResponse.data.data[0];
1361
- const selectedVariant = product.variants.find((v) => v.isActive);
1362
- const productDetail = new IkasProduct({
1363
- ...product,
1364
- selectedVariantValues: (selectedVariant || product.variants[0])
1365
- .variantValues,
1366
- });
1449
+ if (!productsResponse.isSuccess || !productsResponse?.data?.data?.length)
1450
+ return null;
1451
+
1452
+ const product = productsResponse.data.data[0];
1453
+ const selectedVariant = product.variants.find((v) => v.isActive);
1454
+ const productDetail = new IkasProduct({
1455
+ ...product,
1456
+ selectedVariantValues: (selectedVariant || product.variants[0])
1457
+ .variantValues,
1458
+ });
1459
+
1460
+ return productDetail;
1461
+ };
1462
+
1463
+ getOfferProductVariants = ({
1464
+ offer,
1465
+ product,
1466
+ }: {
1467
+ offer: IkasCampaignOfferProduct;
1468
+ product: IkasProduct;
1469
+ }) => {
1470
+ const variants: IkasProductVariant[] = [];
1471
+
1472
+ if (offer.excludedVariantIdList?.length) {
1473
+ product.variants.forEach((v) => {
1474
+ const isVariantExcluded = offer!.excludedVariantIdList?.some(
1475
+ (ev) => ev === v.id
1476
+ );
1477
+ if (!v.hasStock || isVariantExcluded) return;
1367
1478
 
1368
- return productDetail;
1479
+ variants.push(v);
1480
+ });
1481
+ } else {
1482
+ variants.push(...product.variants.filter((v) => v.hasStock));
1369
1483
  }
1370
1484
 
1371
- return null;
1485
+ return variants;
1372
1486
  };
1373
1487
 
1374
1488
  getCampaignOfferProducts = async (
1375
1489
  targetPage: IkasCampaignOfferTargetPageType
1376
- ) => {
1377
- const waitingForActionCampaignOffer =
1378
- this.getWaitingForActionCampaignOffer(targetPage);
1490
+ ): Promise<CampaignOfferType | undefined> => {
1491
+ const waitingForActionCampaignOffers =
1492
+ this.getWaitingForActionCampaignOffers(targetPage);
1379
1493
 
1380
1494
  if (
1381
- waitingForActionCampaignOffer &&
1382
- waitingForActionCampaignOffer.campaignOffer
1383
- ) {
1495
+ !waitingForActionCampaignOffers ||
1496
+ !waitingForActionCampaignOffers.length
1497
+ )
1498
+ return;
1499
+
1500
+ for (let i = 0; i < waitingForActionCampaignOffers.length; i++) {
1501
+ const waitingForActionCampaignOffer = waitingForActionCampaignOffers[i];
1502
+
1384
1503
  const offer = this.getOffer(waitingForActionCampaignOffer);
1504
+ if (!offer) continue;
1385
1505
 
1386
- if (offer) {
1387
- const productDetail = await this.getProduct(offer.productId);
1506
+ const product = await this.getProduct(offer.productId);
1507
+ if (!product) continue;
1388
1508
 
1389
- if (productDetail) {
1390
- return {
1391
- productDetail,
1392
- campaignOffer: waitingForActionCampaignOffer,
1393
- offer,
1394
- };
1395
- }
1396
- }
1397
- }
1509
+ const variants: IkasProductVariant[] = this.getOfferProductVariants({
1510
+ offer,
1511
+ product,
1512
+ });
1513
+ if (!variants.length) continue;
1398
1514
 
1399
- return undefined;
1515
+ return {
1516
+ product,
1517
+ variants,
1518
+ campaignOffer: waitingForActionCampaignOffer,
1519
+ offer,
1520
+ };
1521
+ }
1400
1522
  };
1401
1523
 
1402
1524
  getCampaignOffer = async () => {
1403
- this.checkoutCampaignOffer = (await this.getCampaignOfferProducts(
1525
+ this.checkoutCampaignOffer = await this.getCampaignOfferProducts(
1404
1526
  IkasCampaignOfferTargetPageType.CHECKOUT
1405
- )) as any;
1406
- this.postCheckoutCampaignOffer = (await this.getCampaignOfferProducts(
1527
+ );
1528
+ this.postCheckoutCampaignOffer = await this.getCampaignOfferProducts(
1407
1529
  IkasCampaignOfferTargetPageType.POST_CHECKOUT
1408
- )) as any;
1530
+ );
1409
1531
  };
1410
1532
 
1411
1533
  updateCartCampaignOffer = async (props: UpdateCartCampaignOfferInput) => {
@@ -1461,6 +1583,7 @@ export type StockErrorData = {
1461
1583
 
1462
1584
  export type CampaignOfferType = {
1463
1585
  product: IkasProduct;
1586
+ variants: IkasProductVariant[];
1464
1587
  campaignOffer: IkasCartCampaignOffer;
1465
1588
  offer: IkasCampaignOfferProduct;
1466
1589
  };
@@ -6,7 +6,7 @@ import { useTranslation } from "../../utils/i18n";
6
6
  import { IkasBaseStore } from "../../store";
7
7
  import { IkasCheckout, IkasPaymentGateway } from "../../models";
8
8
  import { MasterPassOperationTypeEnum } from "@ikas/storefront-api";
9
- import { getMasterpassRequestToken } from "@ikas/storefront-api";
9
+ import { getMasterPassRequestToken } from "@ikas/storefront-api";
10
10
  import { IkasStorefrontConfig } from "@ikas/storefront-config";
11
11
 
12
12
  const isServer = typeof localStorage === "undefined";
@@ -437,7 +437,7 @@ export default class MasterPassModel {
437
437
  operationType: MasterPassOperationTypeEnum;
438
438
  phoneNumber: string;
439
439
  }) => {
440
- const response = await getMasterpassRequestToken({
440
+ const response = await getMasterPassRequestToken({
441
441
  cartId,
442
442
  paymentGatewayId,
443
443
  operationType,
@@ -31,7 +31,9 @@ const CheckoutStepInfo: React.FC<Props> = ({ vm }) => {
31
31
  );
32
32
 
33
33
  const customerAddressesViewModel = React.useMemo(() => {
34
- return new CustomerAddressesViewModel(vm, "shipping");
34
+ return vm.isDigitalOnly
35
+ ? new CustomerAddressesViewModel(vm, "billing")
36
+ : new CustomerAddressesViewModel(vm, "shipping");
35
37
  }, [vm]);
36
38
 
37
39
  return (
@@ -70,12 +72,16 @@ const CheckoutStepInfo: React.FC<Props> = ({ vm }) => {
70
72
  marginTop: vm.store.customerStore.customer ? "0px" : "32px",
71
73
  }}
72
74
  text={
73
- vm.deliveryMethod === "address"
75
+ vm.deliveryMethod === "address" && !vm.isDigitalOnly
74
76
  ? t("checkout-page:actions.continueWithShipping")
75
77
  : t("checkout-page:actions.continueWithPayment")
76
78
  }
77
79
  isLoading={vm.isStepLoading}
78
- onClick={vm.onProceedToShippingClick}
80
+ onClick={
81
+ vm.isDigitalOnly
82
+ ? vm.onProceedToDigitalOnlyPaymentClick
83
+ : vm.onProceedToShippingClick
84
+ }
79
85
  />
80
86
  )}
81
87
  </div>
@@ -31,7 +31,7 @@ export const BillingAddress: React.FC<Props> = observer(({ vm }) => {
31
31
  marginBottom: vm.useDifferentAddress ? "24px" : "0px",
32
32
  }}
33
33
  >
34
- {vm.deliveryMethod === "address" && (
34
+ {vm.deliveryMethod === "address" && !vm.isDigitalOnly && (
35
35
  <Checkbox
36
36
  value={!vm.useDifferentAddress}
37
37
  hasError={vm.isErrorsVisible && !vm.isTermsAndConditionsChecked}
@@ -48,7 +48,12 @@ export const CheckoutStepPayment: React.FC<Props> = observer(({ vm }) => {
48
48
  const policyLabel = policyInputData.map((p) =>
49
49
  p.isVariable ? (
50
50
  <span
51
- className={styles.TermsLabelSpan}
51
+ className={[
52
+ styles.TermsLabelSpan,
53
+ vm.isErrorsVisible && !vm.isTermsAndConditionsChecked
54
+ ? styles.Error
55
+ : "",
56
+ ].join(" ")}
52
57
  onClick={
53
58
  p.value === "{{ ackPrivacyPolicy }}"
54
59
  ? onShowPrivacyPolicyClick
@@ -88,7 +93,11 @@ export const CheckoutStepPayment: React.FC<Props> = observer(({ vm }) => {
88
93
  }}
89
94
  text={t("checkout-page:actions.completeOrder")}
90
95
  isLoading={vm.isStepLoading}
91
- onClick={vm.onCompletePaymentClick}
96
+ onClick={
97
+ vm.isDigitalOnly
98
+ ? vm.onCompleteDigitalOnlyPaymentClick
99
+ : vm.onCompletePaymentClick
100
+ }
92
101
  />
93
102
 
94
103
  {!!t("checkout-page:securePaymentTooltip") && (
@@ -12,15 +12,20 @@ import { CreditCardForm } from "../../../components/credit-card-form";
12
12
  import { Installments } from "./installments";
13
13
  import SelectBox from "../../../components/select-box";
14
14
  import styles from "./style.module.scss";
15
- import { formatMoney, useTranslation } from "../../../../../utils";
15
+ import { formatCurrency, useTranslation } from "../../../../../utils";
16
16
  import SVGExternal from "../../../components/svg/external";
17
17
  import SVGMasterCard from "../../../components/master-pass/payment-gateway/svg/master-card";
18
18
  import { IkasPaymentGatewayAdditionalPrice } from "../../../../../models/data/payment-gateway/additional-price";
19
- import { StripeForm } from "../../../components/stripe";
19
+ import dynamic from "next/dynamic";
20
20
  import { Card as MasterPassCard } from "../../../modelMasterPass";
21
21
  import CreditCardData from "../../../components/credit-card-form/model";
22
22
  import CreditCardFormMasterPass from "../../../components/master-pass/credit-card-form";
23
23
 
24
+ //@ts-ignore
25
+ const StripeForm = dynamic(() =>
26
+ import("../../../components/stripe").then((mod) => mod.StripeForm)
27
+ );
28
+
24
29
  type Props = {
25
30
  vm: CheckoutViewModel;
26
31
  };
@@ -50,7 +55,11 @@ export const PaymentGateways: React.FC<Props> = observer(({ vm }) => {
50
55
 
51
56
  return `${
52
57
  ap.amountType === IkasPaymentGatewayTransactionFeeType.AMOUNT
53
- ? formatMoney(ap.amount, vm.checkout.currencyCode)
58
+ ? formatCurrency(
59
+ ap.amount,
60
+ vm.checkout.currencyCode,
61
+ vm.checkout.currencySymbol
62
+ )
54
63
  : " %" + ap.amount
55
64
  }${
56
65
  ap.type === IkasPaymentGatewayAdditionalPriceType.DECREMENT
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { observer } from "mobx-react-lite";
3
3
  import CheckoutViewModel from "../../../../model";
4
4
 
5
- import { formatMoney, useTranslation } from "../../../../../../utils";
5
+ import { formatCurrency, useTranslation } from "../../../../../../utils";
6
6
  import styles from "./style.module.scss";
7
7
  import { Toggle } from "../../../../../../components/checkout/components/toggle";
8
8
 
@@ -33,17 +33,19 @@ export const Installments: React.FC<Props> = observer(({ vm }) => {
33
33
  </div>
34
34
  {ip.installmentCount !== 1 && (
35
35
  <div className={styles.InstallmentPrice}>
36
- {formatMoney(
36
+ {formatCurrency(
37
37
  ip.installmentPrice!,
38
38
  vm.checkout!.currencyCode,
39
+ vm.checkout!.currencySymbol
39
40
  )}
40
41
  </div>
41
42
  )}
42
43
  </div>
43
44
  <div className={styles.Price}>
44
- {formatMoney(
45
+ {formatCurrency(
45
46
  ip.totalPrice!,
46
47
  vm.checkout!.currencyCode,
48
+ vm.checkout!.currencySymbol
47
49
  )}
48
50
  </div>
49
51
  </div>
@@ -5,12 +5,17 @@
5
5
 
6
6
  .TermsLabelSpan {
7
7
  color: $primaryTextColor;
8
+ font-weight: 500;
8
9
 
9
10
  &:hover {
10
11
  text-decoration: underline;
11
12
  }
12
13
  }
13
14
 
15
+ .Error {
16
+ color: $errorColor;
17
+ }
18
+
14
19
  .SecurePaymentContainer {
15
20
  width: 100%;
16
21
  display: flex;