@ikas/storefront 4.0.0-alpha.4 → 4.0.0-alpha.41

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 (63) 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 +24 -6
  6. package/src/components/checkout/components/address-form/index.tsx +1 -1
  7. package/src/components/checkout/components/cart-summary/cart-item/index.tsx +11 -9
  8. package/src/components/checkout/components/cart-summary/cart-item/style.module.scss +7 -10
  9. package/src/components/checkout/components/cart-summary/index.tsx +41 -17
  10. package/src/components/checkout/components/customer-addresses/index.tsx +6 -2
  11. package/src/components/checkout/components/form-item/index.tsx +9 -11
  12. package/src/components/checkout/components/master-pass/credit-card-form/index.tsx +2 -0
  13. package/src/components/checkout/components/offer-product/index.tsx +16 -19
  14. package/src/components/checkout/components/offer-product/style.module.scss +1 -3
  15. package/src/components/checkout/components/phone-number-input/get-countries.ts +37 -5
  16. package/src/components/checkout/components/phone-number-input/index.tsx +15 -10
  17. package/src/components/checkout/index.tsx +14 -12
  18. package/src/components/checkout/model.ts +95 -61
  19. package/src/components/checkout/modelMasterPass.ts +2 -2
  20. package/src/components/checkout/steps/step-payment/index.tsx +6 -1
  21. package/src/components/checkout/steps/step-payment/payment-gateways/index.tsx +12 -3
  22. package/src/components/checkout/steps/step-payment/payment-gateways/installments/index.tsx +5 -3
  23. package/src/components/checkout/steps/step-payment/style.module.scss +5 -0
  24. package/src/components/checkout/steps/step-shipping/index.tsx +9 -4
  25. package/src/components/checkout/steps/step-success/index.tsx +4 -3
  26. package/src/components/page/head.tsx +12 -0
  27. package/src/components/page/index.tsx +10 -9
  28. package/src/components/page-editor/ThemeComponentEditor.tsx +15 -8
  29. package/src/components/page-editor/model.ts +44 -107
  30. package/src/models/data/cart/campaign-offer/index.ts +13 -2
  31. package/src/models/data/cart/index.ts +1 -1
  32. package/src/models/data/category/path-item/index.ts +4 -0
  33. package/src/models/data/checkout/index.ts +11 -3
  34. package/src/models/data/checkout-settings/price/index.ts +2 -0
  35. package/src/models/data/index.ts +3 -0
  36. package/src/models/data/merchant-settings/index.ts +9 -0
  37. package/src/models/data/order/index.ts +51 -32
  38. package/src/models/data/order/line-item/index.ts +34 -13
  39. package/src/models/data/order/line-item/variant/value/index.ts +1 -1
  40. package/src/models/data/order/transaction/index.ts +2 -5
  41. package/src/models/data/product/filter/index.ts +4 -13
  42. package/src/models/data/product/index.ts +21 -3
  43. package/src/models/data/product/option-set/index.ts +4 -0
  44. package/src/models/data/product/option-set/option/index.ts +33 -10
  45. package/src/models/data/product/variant/index.ts +23 -1
  46. package/src/models/data/product/variant/price/index.ts +23 -9
  47. package/src/models/data/product/variant-type/index.ts +2 -0
  48. package/src/models/data/raffle/index.ts +9 -7
  49. package/src/models/data/state/index.ts +6 -2
  50. package/src/models/data/storefront/index.ts +2 -0
  51. package/src/models/ui/product-list/index.ts +26 -17
  52. package/src/models/ui/raffle-list/index.ts +1 -1
  53. package/src/models/ui/validator/form/raffle-form.ts +16 -3
  54. package/src/models/ui/validator/rules/index.ts +14 -13
  55. package/src/page-data-init/index.ts +159 -404
  56. package/src/pages/checkout.tsx +2 -1
  57. package/src/pages/editor.tsx +5 -2
  58. package/src/store/cart/index.ts +2 -2
  59. package/src/store/customer/index.ts +7 -17
  60. package/src/store/raffle/index.ts +7 -10
  61. package/src/utils/constants.ts +1 -1
  62. package/src/utils/currency.ts +9 -183
  63. package/src/components/checkout/components/phone-number-input/locale/en.ts +0 -257
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikas/storefront",
3
- "version": "4.0.0-alpha.4",
3
+ "version": "4.0.0-alpha.41",
4
4
  "description": "Storefront functionality for ikas storefront themes.",
5
5
  "author": "Umut Ozan Yıldırım",
6
6
  "license": "ISC",
@@ -24,18 +24,18 @@
24
24
  "libphonenumber-js": "^1.10.6"
25
25
  },
26
26
  "devDependencies": {
27
- "@ikas/storefront-api": "^4.0.0-alpha.4",
28
- "@ikas/storefront-config": "^4.0.0-alpha.4",
29
- "@ikas/storefront-model-functions": "^4.0.0-alpha.4",
30
- "@ikas/storefront-models": "^4.0.0-alpha.4",
31
- "@ikas/storefront-providers": "^4.0.0-alpha.4",
27
+ "@ikas/storefront-api": "^4.0.0-alpha.41",
28
+ "@ikas/storefront-config": "^4.0.0-alpha.41",
29
+ "@ikas/storefront-model-functions": "^4.0.0-alpha.41",
30
+ "@ikas/storefront-models": "^4.0.0-alpha.41",
31
+ "@ikas/storefront-providers": "^4.0.0-alpha.41",
32
32
  "@rollup/plugin-commonjs": "^22.0.0",
33
33
  "@rollup/plugin-json": "^4.1.0",
34
34
  "@rollup/plugin-node-resolve": "^13.3.0",
35
35
  "@types/react-phone-number-input": "^3.0.10",
36
36
  "mobx": "^6.1.3",
37
37
  "mobx-react-lite": "^3.1.5",
38
- "next": "canary",
38
+ "next": "12.2.0",
39
39
  "prettier": "^2.2.1",
40
40
  "react": "17.0.2",
41
41
  "react-dom": "17.0.2",
@@ -52,14 +52,14 @@
52
52
  "html-react-parser": "^1.4.0"
53
53
  },
54
54
  "peerDependencies": {
55
- "@ikas/storefront-api": "^4.0.0-alpha.4",
56
- "@ikas/storefront-config": "^4.0.0-alpha.4",
57
- "@ikas/storefront-model-functions": "^4.0.0-alpha.4",
58
- "@ikas/storefront-models": "^4.0.0-alpha.4",
59
- "@ikas/storefront-providers": "^4.0.0-alpha.4",
55
+ "@ikas/storefront-api": "^4.0.0-alpha.41",
56
+ "@ikas/storefront-config": "^4.0.0-alpha.41",
57
+ "@ikas/storefront-model-functions": "^4.0.0-alpha.41",
58
+ "@ikas/storefront-models": "^4.0.0-alpha.41",
59
+ "@ikas/storefront-providers": "^4.0.0-alpha.41",
60
60
  "mobx": "^6.1.3",
61
61
  "mobx-react-lite": "^3.1.5",
62
- "next": "canary",
62
+ "next": "12.2.0",
63
63
  "react": "17.0.2",
64
64
  "react-dom": "17.0.2",
65
65
  "lodash": "^4.17.20",
@@ -54,6 +54,7 @@ export class Analytics {
54
54
  const customerInfo = await Analytics.getCustomerInfo();
55
55
 
56
56
  GoogleTagManager.pageView(url);
57
+ GoogleUniversal.pageView(window.location.pathname);
57
58
  IkasAnalytics.pageView(pageType);
58
59
 
59
60
  tryForEach(Analytics.subscribers, (s) => {
@@ -194,7 +195,7 @@ export class Analytics {
194
195
  try {
195
196
  localStorage.removeItem(LS_BEGIN_CHECKOUT_KEY);
196
197
 
197
- FacebookPixel.purchase(checkout, checkout.orderNumber || "");
198
+ FacebookPixel.purchase(checkout, transaction.id || "");
198
199
  GoogleTagManager.purchase(checkout, checkout.orderNumber || "");
199
200
  IkasAnalytics.orderSuccess(checkout);
200
201
  GoogleAnalytics.purchase(checkout, checkout.orderNumber || "");
@@ -8,12 +8,23 @@ export class GoogleUniversal {
8
8
  makeAutoObservable(this);
9
9
  }
10
10
 
11
+ static pageView(url: string) {
12
+ try {
13
+ if (!isServer && (window as any).ga) {
14
+ (window as any).ga("set", "page", url);
15
+ (window as any).ga("send", "pageview");
16
+ }
17
+ return;
18
+ } catch (err) {
19
+ console.error(err);
20
+ }
21
+ }
22
+
11
23
  static productView(productDetail: IkasProduct) {
12
24
  try {
13
25
  if (!isServer && (window as any).ga) {
14
26
  (window as any).ga("ec:addProduct", productToGUItem(productDetail));
15
27
  (window as any).ga("ec:setAction", "detail");
16
- (window as any).ga("send", "pageview");
17
28
  }
18
29
  return;
19
30
  } catch (err) {
@@ -79,7 +90,6 @@ export class GoogleUniversal {
79
90
  shipping: "" + checkout.shippingTotal,
80
91
  coupon: checkout.couponCode,
81
92
  });
82
- (window as any).ga("send", "pageview");
83
93
  }
84
94
  return;
85
95
  } catch (err) {
@@ -79,8 +79,7 @@ export const AnalyticsHead: React.FC<HeadProps> = observer(({ blockHTML }) => {
79
79
  dangerouslySetInnerHTML={{
80
80
  __html: `window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
81
81
  ga('create', '${universalAnalyticsId}', 'auto');
82
- ga('require', 'ec');
83
- ga('send', 'pageview');`,
82
+ ga('require', 'ec');`,
84
83
  }}
85
84
  />
86
85
  <script
@@ -144,10 +144,18 @@ export default class IkasAnalytics {
144
144
  static sessionId?: string | null;
145
145
  static visitorId?: string | null;
146
146
 
147
+ static async createUUID() {
148
+ const response = await fetch(
149
+ `${process.env.NEXT_PUBLIC_BASE_URL}/generate-id/1`
150
+ );
151
+ const responseJson = await response.json();
152
+ return responseJson.data[0] as string;
153
+ }
154
+
147
155
  static async createSessionId() {
148
156
  try {
149
157
  const idWithExpiry: IdWithExpiry = {
150
- id: Date.now() + "",
158
+ id: await this.createUUID(),
151
159
  expiry: Date.now() + this.EXPIRY_LENGTH,
152
160
  };
153
161
 
@@ -167,7 +175,8 @@ export default class IkasAnalytics {
167
175
  if (existingSessionIdData) {
168
176
  const idWithExpiry = JSON.parse(existingSessionIdData) as IdWithExpiry;
169
177
 
170
- if (idWithExpiry.expiry < Date.now()) {
178
+ // Remove old ids so that they can be replaced with UUIDs (length 13 check)
179
+ if (idWithExpiry.expiry < Date.now() || idWithExpiry.id.length <= 13) {
171
180
  await this.createSessionId();
172
181
  } else {
173
182
  // Extend the duration of the sessionId
@@ -181,21 +190,30 @@ export default class IkasAnalytics {
181
190
  } else {
182
191
  await this.createSessionId();
183
192
  }
193
+
194
+ IkasStorefrontConfig.init({
195
+ sessionId: this.sessionId || "",
196
+ });
184
197
  } catch (err) {
185
198
  console.error(err);
186
199
  }
187
200
  }
188
201
 
189
- static checkVisitorId() {
202
+ static async checkVisitorId() {
190
203
  try {
191
204
  const existingVisitorId = localStorage.getItem(this.VISITOR_ID_KEY);
192
205
 
193
- if (existingVisitorId) {
206
+ // Remove old ids so that they can be replaced with UUIDs (length 13 check)
207
+ if (existingVisitorId && existingVisitorId.length > 13) {
194
208
  this.visitorId = existingVisitorId;
195
209
  } else {
196
- this.visitorId = Date.now() + "";
210
+ this.visitorId = await this.createUUID();
197
211
  localStorage.setItem(this.VISITOR_ID_KEY, this.visitorId);
198
212
  }
213
+
214
+ IkasStorefrontConfig.init({
215
+ visitorId: this.visitorId,
216
+ });
199
217
  } catch (err) {
200
218
  console.error(err);
201
219
  }
@@ -299,7 +317,7 @@ export default class IkasAnalytics {
299
317
  static async sendEvents(events: Event[]) {
300
318
  try {
301
319
  await this.checkSessionId();
302
- this.checkVisitorId();
320
+ await this.checkVisitorId();
303
321
 
304
322
  const store = IkasBaseStore.getInstance();
305
323
  const cloudFrontEvent: CloudFrontEvent = {
@@ -315,7 +315,7 @@ const CityInput: React.FC<FormItemProps> = observer(({ vm }) => {
315
315
  return (
316
316
  <FormItem
317
317
  type={FormItemType.TEXT}
318
- autocomplete="address-level3"
318
+ autocomplete="address-level2"
319
319
  label={t("checkout-page:city")}
320
320
  value={vm.city?.name || ""}
321
321
  onChange={vm.onCityInputChange}
@@ -4,7 +4,11 @@ import {
4
4
  IkasOrderLineItem,
5
5
  IkasProductOptionType,
6
6
  } from "../../../../../models";
7
- import { formatDate, formatMoney, useTranslation } from "../../../../../utils";
7
+ import {
8
+ formatDate,
9
+ formatCurrency,
10
+ useTranslation,
11
+ } from "../../../../../utils";
8
12
  import CheckoutViewModel from "../../../../../components/checkout/model";
9
13
  import { Modal } from "../../modal";
10
14
 
@@ -159,19 +163,17 @@ export const CartItem: React.FC<Props> = observer(
159
163
  {!!cartItem.overridenPriceWithQuantity && (
160
164
  <span className={styles.GrayPrice}>
161
165
  {!!adjustmentTotal
162
- ? formatMoney(cartItem.finalPriceWithQuantity, currencyCode)
163
- : formatMoney(
164
- cartItem.overridenPriceWithQuantity,
165
- currencyCode
166
- )}
166
+ ? cartItem.formattedFinalPriceWithQuantity
167
+ : cartItem.formattedOverridenPriceWithQuantity}
167
168
  </span>
168
169
  )}
169
170
  {!!adjustmentTotal
170
- ? formatMoney(
171
+ ? formatCurrency(
171
172
  cartItem.finalPriceWithQuantity - adjustmentTotal,
172
- currencyCode
173
+ currencyCode,
174
+ cartItem.currencySymbol
173
175
  )
174
- : formatMoney(cartItem.finalPriceWithQuantity, currencyCode)}
176
+ : cartItem.formattedFinalPriceWithQuantity}
175
177
  </div>
176
178
  </div>
177
179
  </div>
@@ -8,14 +8,12 @@
8
8
  .ImageContainer {
9
9
  flex: 0 0 auto;
10
10
  width: 114px;
11
- height: 114px;
12
11
  position: relative;
13
12
  margin-right: 16px;
14
13
 
15
14
  .Image {
16
15
  width: 100%;
17
- height: 100%;
18
- object-fit: cover;
16
+ object-fit: contain;
19
17
  border-radius: 8px;
20
18
  }
21
19
  }
@@ -55,7 +53,6 @@
55
53
  cursor: pointer;
56
54
  text-decoration: underline;
57
55
  }
58
-
59
56
  }
60
57
  }
61
58
 
@@ -64,7 +61,7 @@
64
61
  display: flex;
65
62
  align-items: center;
66
63
  color: $primaryTextColor;
67
-
64
+
68
65
  .GrayPrice {
69
66
  font-size: 14px;
70
67
  color: $secondaryTextColor;
@@ -78,25 +75,25 @@
78
75
  flex-direction: column;
79
76
  margin-bottom: 24px;
80
77
  max-width: 400px;
81
-
78
+
82
79
  .OptionName {
83
80
  font-size: 14px;
84
81
  color: $primaryTextColor;
85
82
  margin-right: 8px;
86
83
  font-weight: 500;
87
84
  }
88
-
85
+
89
86
  .OptionValue {
90
87
  font-size: 14px;
91
88
  color: $secondaryTextColor;
92
89
  }
93
-
90
+
94
91
  .OptionsHorContainer {
95
92
  display: flex;
96
93
  align-items: center;
97
94
  flex-wrap: wrap;
98
95
  }
99
-
96
+
100
97
  .OptionColorValue {
101
98
  width: 24px;
102
99
  height: 24px;
@@ -104,4 +101,4 @@
104
101
  margin-right: 4px;
105
102
  }
106
103
  }
107
- }
104
+ }
@@ -5,7 +5,7 @@ import _sortBy from "lodash/sortBy";
5
5
  import InputWithButton from "../input-with-button";
6
6
  import NotificationBox from "../notification-box";
7
7
  import CheckoutViewModel, { CheckoutStep } from "../../model";
8
- import { formatMoney, useTranslation } from "../../../../utils";
8
+ import { formatCurrency, useTranslation } from "../../../../utils";
9
9
  import { CartItem } from "./cart-item";
10
10
  import { FormItem } from "../form-item";
11
11
  import { FormItemType } from "../form-item/model";
@@ -95,9 +95,13 @@ export const CartSummary: React.FC<Props> = observer(({ vm, allowExpand }) => {
95
95
  <div className={styles.Left}>{t("checkout-page:summary")}</div>
96
96
  <div className={styles.Price}>
97
97
  <span className={styles.PriceText}>
98
- {`${formatMoney(vm.finalPrice || 0, checkout.currencyCode)} (${
99
- checkout.items.length
100
- } ${t("checkout-page:cartItemProduct")})`}
98
+ {`${formatCurrency(
99
+ vm.finalPrice || 0,
100
+ checkout.currencyCode,
101
+ checkout.currencySymbol
102
+ )} (${checkout.items.length} ${t(
103
+ "checkout-page:cartItemProduct"
104
+ )})`}
101
105
  </span>
102
106
  <span className={arrowDownClasses}>
103
107
  <SVGArrowDown />
@@ -132,7 +136,7 @@ export const CartSummary: React.FC<Props> = observer(({ vm, allowExpand }) => {
132
136
  )}
133
137
  <InfoRow
134
138
  label={t("checkout-page:subtotal")}
135
- value={formatMoney(checkout.totalPrice, checkout.currencyCode)}
139
+ value={checkout.formattedTotalPrice}
136
140
  tooltipText={t("checkout-page:subtotalTooltip")}
137
141
  />
138
142
  {!!checkout.shippingLines?.length && (
@@ -140,10 +144,7 @@ export const CartSummary: React.FC<Props> = observer(({ vm, allowExpand }) => {
140
144
  label={t("checkout-page:cartShippingTitle")}
141
145
  value={
142
146
  checkout.shippingTotal
143
- ? formatMoney(
144
- checkout.shippingTotal,
145
- checkout.currencyCode
146
- )
147
+ ? checkout.formattedShippingTotal
147
148
  : t("checkout-page:free")
148
149
  }
149
150
  />
@@ -151,15 +152,16 @@ export const CartSummary: React.FC<Props> = observer(({ vm, allowExpand }) => {
151
152
  {!!checkout.totalTax && !!vm.customizationProps?.showTax && (
152
153
  <InfoRow
153
154
  label={t("checkout-page:cartTaxTitle")}
154
- value={formatMoney(checkout.totalTax, checkout.currencyCode)}
155
+ value={checkout.formattedTotalTax}
155
156
  />
156
157
  )}
157
158
  {!!vm.installmentExtraPrice && (
158
159
  <InfoRow
159
160
  label={t("checkout-page:cartInterest")}
160
- value={formatMoney(
161
+ value={formatCurrency(
161
162
  vm.installmentExtraPrice,
162
- checkout.currencyCode
163
+ checkout.currencyCode,
164
+ checkout.currencySymbol
163
165
  )}
164
166
  />
165
167
  )}
@@ -193,7 +195,11 @@ export const CartSummary: React.FC<Props> = observer(({ vm, allowExpand }) => {
193
195
  <div className={styles.Title}>{t("checkout-page:total")}</div>
194
196
  </div>
195
197
  <div className={styles.TotalPrice}>
196
- {formatMoney(vm.finalPrice || 0, checkout.currencyCode)}
198
+ {formatCurrency(
199
+ vm.finalPrice || 0,
200
+ checkout.currencyCode,
201
+ checkout.currencySymbol
202
+ )}
197
203
  </div>
198
204
  </div>
199
205
 
@@ -273,7 +279,11 @@ const Adjustments: React.FC<CommonProps> = observer(({ vm }) => {
273
279
  <div className={styles.Value}>
274
280
  <span>{adjustment.type === "DECREMENT" ? "- " : ""}</span>{" "}
275
281
  <span>
276
- {formatMoney(adjustment.amount, vm.checkout.currencyCode)}
282
+ {formatCurrency(
283
+ adjustment.amount,
284
+ vm.checkout.currencyCode,
285
+ vm.checkout.currencySymbol
286
+ )}
277
287
  </span>
278
288
  </div>
279
289
  </div>
@@ -304,7 +314,11 @@ const CalculatedAdditionalPrices: React.FC<CommonProps> = observer(({ vm }) => {
304
314
  <div className={styles.Value}>
305
315
  <span>{adjustment.type === "DECREMENT" ? "- " : ""}</span>{" "}
306
316
  <span>
307
- {formatMoney(adjustment.amount, vm.checkout!.currencyCode)}
317
+ {formatCurrency(
318
+ adjustment.amount,
319
+ vm.checkout!.currencyCode,
320
+ vm.checkout!.currencySymbol
321
+ )}
308
322
  </span>
309
323
  </div>
310
324
  </div>
@@ -318,7 +332,13 @@ const CalculatedAdditionalPrices: React.FC<CommonProps> = observer(({ vm }) => {
318
332
  </div>
319
333
  </div>
320
334
  <div className={styles.Value}>
321
- <span>{formatMoney(gpl.price, vm.checkout.currencyCode)}</span>
335
+ <span>
336
+ {formatCurrency(
337
+ gpl.price,
338
+ vm.checkout.currencyCode,
339
+ vm.checkout!.currencySymbol
340
+ )}
341
+ </span>
322
342
  </div>
323
343
  </div>
324
344
  ))}
@@ -410,7 +430,11 @@ const Coupon: React.FC<CouponProps> = observer(
410
430
  <div className={styles.Value}>
411
431
  <span>{adjustment?.type === "DECREMENT" ? "- " : ""}</span>{" "}
412
432
  <span>
413
- {formatMoney(adjustment?.amount || 0, vm.checkout.currencyCode)}
433
+ {formatCurrency(
434
+ adjustment?.amount || 0,
435
+ vm.checkout.currencyCode,
436
+ vm.checkout.currencySymbol
437
+ )}
414
438
  </span>
415
439
  </div>
416
440
  )}
@@ -143,7 +143,9 @@ const CustomerAddresses: React.FC<Props> = ({ vm }) => {
143
143
 
144
144
  {!!vm.vm.store.customerStore.customer &&
145
145
  !vm.editingCustomerAddress &&
146
- vm.vm.deliveryMethod === "address" && (
146
+ (vm.vm.deliveryMethod === "address" ||
147
+ (vm.vm.step === CheckoutStep.PAYMENT &&
148
+ vm.vm.deliveryMethod === "in-store")) && (
147
149
  <div className={checkoutStyles.RowPB}>
148
150
  {vm.vm.store.customerStore.customer.addresses?.map((address) => (
149
151
  <SelectBox
@@ -183,7 +185,9 @@ const CustomerAddresses: React.FC<Props> = ({ vm }) => {
183
185
  vm.vm.step === CheckoutStep.INFO &&
184
186
  vm.vm.deliveryMethod === "address"
185
187
  ? addressForm
186
- : vm.vm.step === CheckoutStep.PAYMENT && addressForm}
188
+ : vm.vm.step === CheckoutStep.PAYMENT &&
189
+ !vm.vm.store.customerStore.customer &&
190
+ addressForm}
187
191
 
188
192
  {vm.vm.deliveryMethod === "in-store" && (
189
193
  <div className={checkoutStyles.RowPB}>
@@ -7,6 +7,7 @@ import styles from "./style.module.scss";
7
7
 
8
8
  import { useTranslation } from "../../../../utils";
9
9
  import ReactTooltip from "react-tooltip";
10
+ import { PhoneNumberInput } from "../phone-number-input";
10
11
 
11
12
  export const FormItem: React.FC<Props> = observer((props) => {
12
13
  const { t } = useTranslation();
@@ -108,17 +109,14 @@ export const FormItem: React.FC<Props> = observer((props) => {
108
109
  />
109
110
  )}
110
111
  {vm.type === FormItemType.TEL && (
111
- <div></div>
112
- // <PhoneInput
113
- // key={props.currentCountryCode || "1"}
114
- // disabled={vm.disabled}
115
- // defaultCountry={props.currentCountryCode}
116
- // placeholder={t("checkout-page:enterPhoneNumber")}
117
- // value={vm.value ? vm.value : ""}
118
- // onChange={vm.onPhoneChange}
119
- // international={true}
120
- // addInternationalOption={false}
121
- // />
112
+ <PhoneNumberInput
113
+ key={props.currentCountryCode || "1"}
114
+ disabled={vm.disabled}
115
+ defaultCountry={props.currentCountryCode}
116
+ placeholder={t("checkout-page:enterPhoneNumber")}
117
+ value={vm.value ? vm.value : ""}
118
+ onChange={vm.onPhoneChange}
119
+ />
122
120
  )}
123
121
  {vm.type === FormItemType.TEXT_AREA && <TextArea vm={vm} />}
124
122
  {vm.type === FormItemType.SELECT && (
@@ -132,7 +132,9 @@ const CreditCardFormMasterPass = observer(({ vm }: Props) => {
132
132
  <div className={checkoutStyles.RowPB}>
133
133
  <FormItem
134
134
  name="masterPassPhoneNumber"
135
+ autocomplete="tel"
135
136
  type={FormItemType.TEL}
137
+ currentCountryCode={vm.store.currentCountryCode}
136
138
  disabled={
137
139
  vm.mpVM.isSaveCardToMasterPassPhoneNumberInputDisabled
138
140
  }
@@ -8,7 +8,7 @@ import SVGCross from "../svg/cross";
8
8
  import styles from "./style.module.scss";
9
9
  import { useTranslation } from "../../../../utils/i18n";
10
10
  import { IkasProductVariant } from "../../../../models";
11
- import { formatMoney } from "../../../../utils/currency";
11
+ import { formatCurrency } from "../../../../utils/currency";
12
12
 
13
13
  type Props = {
14
14
  vm: CheckoutViewModel;
@@ -18,7 +18,7 @@ type Props = {
18
18
  const OfferProduct: React.FC<Props> = ({ vm, campaignOffer }) => {
19
19
  const { t } = useTranslation();
20
20
  const [selectedVariant, setSelectedVariant] =
21
- React.useState<IkasProductVariant>(campaignOffer!.product.selectedVariant);
21
+ React.useState<IkasProductVariant>(campaignOffer.variants[0]);
22
22
 
23
23
  const acceptOffer = () => {
24
24
  vm.updateCartCampaignOffer({
@@ -43,7 +43,7 @@ const OfferProduct: React.FC<Props> = ({ vm, campaignOffer }) => {
43
43
  };
44
44
 
45
45
  const onVariantChange = (value: string) => {
46
- const variant = campaignOffer.product.variants.find((v) => v.id === value);
46
+ const variant = campaignOffer.variants.find((v) => v.id === value);
47
47
 
48
48
  if (variant) {
49
49
  setSelectedVariant(variant);
@@ -95,35 +95,32 @@ const OfferProduct: React.FC<Props> = ({ vm, campaignOffer }) => {
95
95
  <span className={styles.Discount}>
96
96
  {selectedVariant.price.formattedFinalPrice}
97
97
  </span>{" "}
98
- {formatMoney(
98
+ {formatCurrency(
99
99
  selectedVariant.price.finalPrice -
100
100
  (selectedVariant.price.finalPrice *
101
101
  (campaignOffer.offer.discountAmount || 100)) /
102
102
  100,
103
- vm.checkout!.currencyCode
103
+ vm.checkout!.currencyCode,
104
+ vm.checkout!.currencySymbol
104
105
  )}
105
106
  </div>
106
107
  <div className={styles.Actions}>
107
- {campaignOffer.product.hasVariant &&
108
- campaignOffer.product.hasStock && (
109
- <Select
110
- value={selectedVariant.id}
111
- onSelectChange={onVariantChange}
112
- options={campaignOffer.product.variants
113
- .filter((v) => v.hasStock)
114
- .map((v) => ({
115
- label: v.variantValues.map((vv) => vv.name).join(", "),
116
- value: v.id,
117
- }))}
118
- />
119
- )}
108
+ {campaignOffer.variants.length > 1 && (
109
+ <Select
110
+ value={selectedVariant.id}
111
+ onSelectChange={onVariantChange}
112
+ options={campaignOffer.variants.map((v) => ({
113
+ label: v.variantValues.map((vv) => vv.name).join(", "),
114
+ value: v.id,
115
+ }))}
116
+ />
117
+ )}
120
118
  <Button
121
119
  style={{
122
120
  width: "100%",
123
121
  height: 44,
124
122
  fontSize: 14,
125
123
  }}
126
- isDisabled={!campaignOffer.product.hasStock}
127
124
  text={t("checkout-page:actions.addToCart")}
128
125
  onClick={acceptOffer}
129
126
  />
@@ -62,7 +62,6 @@
62
62
  }
63
63
 
64
64
  .ImageContainer {
65
- height: 136px;
66
65
  width: 136px;
67
66
  position: relative;
68
67
  background-color: #fff;
@@ -73,8 +72,7 @@
73
72
 
74
73
  .Image {
75
74
  width: 100%;
76
- height: 100%;
77
- object-fit: cover;
75
+ object-fit: contain;
78
76
  border-radius: 8px;
79
77
  }
80
78
 
@@ -1,18 +1,50 @@
1
+ import { IkasStorefrontConfig } from "@ikas/storefront-config";
1
2
  import { CountryCode, getCountries as categories } from "libphonenumber-js";
2
3
  import compareStrings from "./compare-strings";
3
4
 
4
- import en from "./locale/en";
5
-
6
- type CountryType = {
5
+ export type CountryType = {
7
6
  value: CountryCode;
8
7
  label: string | undefined;
9
8
  };
10
9
 
11
- const getCountries = (): CountryType[] => {
10
+ const getUrl = () => {
11
+ const languages = [
12
+ "de",
13
+ "el",
14
+ "en",
15
+ "es",
16
+ "fi",
17
+ "fr",
18
+ "it",
19
+ "nb",
20
+ "pl",
21
+ "pt-BR",
22
+ "pt",
23
+ "ru",
24
+ "sv",
25
+ "tr",
26
+ "ua",
27
+ "vi",
28
+ ];
29
+
30
+ let locale = IkasStorefrontConfig.getCurrentLocale();
31
+
32
+ if (!languages.some((language) => language === locale)) {
33
+ locale = "en";
34
+ }
35
+
36
+ return `https://cdn.myikas.com/sf/static/locale/country/${locale}.json`;
37
+ };
38
+
39
+ const getCountries = async (): Promise<CountryType[]> => {
40
+ const url = getUrl();
41
+ const response = await fetch(url);
42
+ const lang = await response.json();
43
+
12
44
  return categories()
13
45
  .map((country) => ({
14
46
  value: country,
15
- label: en[country],
47
+ label: lang[country],
16
48
  }))
17
49
  .sort((a, b) => compareStrings(a.label, b.label));
18
50
  };