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

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 +1 -2
  3. package/src/analytics/googleUniversal.ts +2 -12
  4. package/src/analytics/head/index.tsx +2 -1
  5. package/src/analytics/ikas.ts +7 -25
  6. package/src/components/checkout/components/address-form/index.tsx +1 -1
  7. package/src/components/checkout/components/address-form/model.ts +0 -1
  8. package/src/components/checkout/components/button/style.module.scss +2 -2
  9. package/src/components/checkout/components/cart-summary/cart-item/index.tsx +29 -16
  10. package/src/components/checkout/components/cart-summary/cart-item/style.module.scss +23 -60
  11. package/src/components/checkout/components/cart-summary/index.tsx +27 -58
  12. package/src/components/checkout/components/cart-summary/style.module.scss +3 -48
  13. package/src/components/checkout/components/customer-addresses/index.tsx +2 -7
  14. package/src/components/checkout/components/customer-addresses/model.ts +8 -16
  15. package/src/components/checkout/components/error/index.tsx +1 -1
  16. package/src/components/checkout/components/error/unknown-error/index.tsx +2 -4
  17. package/src/components/checkout/components/form-item/index.tsx +11 -9
  18. package/src/components/checkout/components/master-pass/credit-card-form/index.tsx +0 -2
  19. package/src/components/checkout/components/offer-product/index.tsx +19 -16
  20. package/src/components/checkout/components/offer-product/style.module.scss +3 -1
  21. package/src/components/checkout/components/phone-number-input/get-countries.ts +5 -37
  22. package/src/components/checkout/components/phone-number-input/index.tsx +10 -15
  23. package/src/components/checkout/components/phone-number-input/locale/en.ts +257 -0
  24. package/src/components/checkout/index.tsx +19 -28
  25. package/src/components/checkout/model.ts +91 -214
  26. package/src/components/checkout/modelMasterPass.ts +2 -2
  27. package/src/components/checkout/steps/step-info/index.tsx +3 -9
  28. package/src/components/checkout/steps/step-payment/billing-address/index.tsx +1 -1
  29. package/src/components/checkout/steps/step-payment/index.tsx +2 -11
  30. package/src/components/checkout/steps/step-payment/payment-gateways/index.tsx +3 -12
  31. package/src/components/checkout/steps/step-payment/payment-gateways/installments/index.tsx +3 -5
  32. package/src/components/checkout/steps/step-payment/style.module.scss +0 -5
  33. package/src/components/checkout/steps/step-shipping/index.tsx +4 -9
  34. package/src/components/checkout/steps/step-success/index.tsx +7 -15
  35. package/src/components/page/head.tsx +0 -12
  36. package/src/components/page/index.tsx +9 -10
  37. package/src/components/page-editor/ThemeComponentEditor.tsx +8 -19
  38. package/src/components/page-editor/model.ts +107 -44
  39. package/src/models/data/cart/campaign-offer/index.ts +2 -13
  40. package/src/models/data/cart/index.ts +1 -1
  41. package/src/models/data/category/init.ts +33 -0
  42. package/src/models/data/category/path-item/index.ts +0 -4
  43. package/src/models/data/checkout/index.ts +4 -36
  44. package/src/models/data/checkout-settings/price/index.ts +0 -2
  45. package/src/models/data/country/index.ts +0 -4
  46. package/src/models/data/index.ts +0 -3
  47. package/src/models/data/merchant-settings/index.ts +0 -9
  48. package/src/models/data/order/index.ts +32 -51
  49. package/src/models/data/order/line-item/index.ts +18 -76
  50. package/src/models/data/order/line-item/variant/index.ts +0 -8
  51. package/src/models/data/order/line-item/variant/price/index.ts +0 -2
  52. package/src/models/data/order/line-item/variant/value/index.ts +1 -1
  53. package/src/models/data/order/transaction/index.ts +5 -2
  54. package/src/models/data/product/attribute-value/index.ts +0 -40
  55. package/src/models/data/product/filter/index.ts +13 -4
  56. package/src/models/data/product/index.ts +7 -45
  57. package/src/models/data/product/option-set/index.ts +3 -8
  58. package/src/models/data/product/option-set/option/index.ts +13 -36
  59. package/src/models/data/product/variant/index.ts +1 -26
  60. package/src/models/data/product/variant/price/index.ts +9 -25
  61. package/src/models/data/product/variant-type/index.ts +0 -2
  62. package/src/models/data/raffle/index.ts +7 -9
  63. package/src/models/data/state/index.ts +2 -6
  64. package/src/models/data/storefront/index.ts +0 -2
  65. package/src/models/data/storefront/routing/index.tsx +0 -4
  66. package/src/models/ui/product-list/index.ts +17 -26
  67. package/src/models/ui/raffle-list/index.ts +1 -1
  68. package/src/models/ui/validator/form/raffle-form.ts +3 -16
  69. package/src/models/ui/validator/rules/index.ts +13 -14
  70. package/src/page-data-init/index.ts +404 -159
  71. package/src/pages/checkout.tsx +1 -2
  72. package/src/pages/editor.tsx +2 -5
  73. package/src/store/base.ts +2 -2
  74. package/src/store/cart/index.ts +2 -2
  75. package/src/store/customer/index.ts +17 -7
  76. package/src/store/index.ts +0 -2
  77. package/src/store/raffle/index.ts +10 -7
  78. package/src/utils/constants.ts +1 -1
  79. package/src/utils/currency.ts +183 -9
  80. package/src/models/data/country/location-translations/index.ts +0 -15
  81. package/src/models/data/order/line-item/base-unit/index.ts +0 -22
  82. package/src/models/data/order/line-item/base-unit/unit-type/index.ts +0 -14
  83. package/src/models/data/order/line-item/variant/unit/index.ts +0 -17
  84. package/src/models/data/product/base-unit/index.ts +0 -32
  85. package/src/models/data/product/variant/unit/index.ts +0 -17
@@ -56,45 +56,12 @@
56
56
  background-color: $cardBgColor;
57
57
  }
58
58
 
59
- &.HideOnDesktop {
59
+ .HideOnDesktop {
60
60
  @media only screen and (min-width: $breakpoint) {
61
61
  display: none;
62
62
  }
63
63
  }
64
64
 
65
- .ItemsContainer {
66
- max-height: 320px;
67
- overflow-y: auto;
68
- padding-top: 10px;
69
- margin-bottom: 24px;
70
-
71
- @media only screen and (max-width: $breakpoint) {
72
- max-height: unset;
73
- }
74
-
75
- &::-webkit-scrollbar {
76
- width: 10px;
77
- }
78
-
79
- /* Track */
80
- &::-webkit-scrollbar-track {
81
- box-shadow: inset 0 0 10px 10px #E3E7EF;
82
- border: solid 3px transparent;
83
- }
84
-
85
- /* Handle */
86
- &::-webkit-scrollbar-thumb {
87
- box-shadow: inset 0 0 10px 10px #000000;
88
- border: solid 3px transparent;
89
- }
90
-
91
- // /* Handle on hover */
92
- // &::-webkit-scrollbar-thumb:hover {
93
- // box-shadow: inset 0 0 10px 10px #000000;
94
- // border: solid 3px transparent;
95
- // }
96
- }
97
-
98
65
  .DetailsContainer {
99
66
  overflow: hidden;
100
67
  width: 100%;
@@ -108,7 +75,6 @@
108
75
 
109
76
  .Details {
110
77
  overflow: hidden;
111
- padding-top: 10px;
112
78
 
113
79
  @media only screen and (max-width: $breakpoint) {
114
80
  padding-top: $mobileHorizontalPadding;
@@ -175,7 +141,7 @@
175
141
  .TotalContainer {
176
142
  display: flex;
177
143
  justify-content: space-between;
178
- // align-items: center;
144
+ align-items: center;
179
145
  margin-top: 12px;
180
146
 
181
147
  .TitleContainer {
@@ -185,25 +151,14 @@
185
151
  }
186
152
  }
187
153
 
188
- .TotalPricesContainer {
189
- display: flex;
190
- flex-direction: column;
191
- align-items: flex-end;
192
- }
193
-
194
154
  .TotalPrice {
195
155
  font-size: 20px;
196
156
  font-weight: 600;
197
157
  }
198
158
 
199
- .TotalTax {
200
- font-size: 14px;
201
- line-height: 24px;
202
- color: $secondaryTextColor;
203
- }
204
-
205
159
  @media only screen and (max-width: $breakpoint) {
206
160
  height: 64px;
161
+ margin-top: 0px;
207
162
  }
208
163
  }
209
164
 
@@ -87,7 +87,6 @@ const CustomerAddresses: React.FC<Props> = ({ vm }) => {
87
87
  return (
88
88
  <React.Fragment>
89
89
  {!!IkasStorefrontConfig.getPickupStockLocationIds() &&
90
- !vm.vm.isDigitalOnly &&
91
90
  vm.vm.availableStockLocations.length > 0 &&
92
91
  vm.vm.step !== CheckoutStep.PAYMENT && (
93
92
  <>
@@ -144,9 +143,7 @@ const CustomerAddresses: React.FC<Props> = ({ vm }) => {
144
143
 
145
144
  {!!vm.vm.store.customerStore.customer &&
146
145
  !vm.editingCustomerAddress &&
147
- (vm.vm.deliveryMethod === "address" ||
148
- (vm.vm.step === CheckoutStep.PAYMENT &&
149
- vm.vm.deliveryMethod === "in-store")) && (
146
+ vm.vm.deliveryMethod === "address" && (
150
147
  <div className={checkoutStyles.RowPB}>
151
148
  {vm.vm.store.customerStore.customer.addresses?.map((address) => (
152
149
  <SelectBox
@@ -186,9 +183,7 @@ const CustomerAddresses: React.FC<Props> = ({ vm }) => {
186
183
  vm.vm.step === CheckoutStep.INFO &&
187
184
  vm.vm.deliveryMethod === "address"
188
185
  ? addressForm
189
- : vm.vm.step === CheckoutStep.PAYMENT &&
190
- !vm.vm.store.customerStore.customer &&
191
- addressForm}
186
+ : vm.vm.step === CheckoutStep.PAYMENT && addressForm}
192
187
 
193
188
  {vm.vm.deliveryMethod === "in-store" && (
194
189
  <div className={checkoutStyles.RowPB}>
@@ -54,10 +54,9 @@ export default class CustomerAddressesViewModel {
54
54
  };
55
55
 
56
56
  onDeleteAddressClick = async () => {
57
- const addressIndex =
58
- this.vm.store.customerStore.customer?.addresses?.findIndex(
59
- (a) => a.id === this.editingCustomerAddress?.id
60
- );
57
+ const addressIndex = this.vm.store.customerStore.customer?.addresses?.findIndex(
58
+ (a) => a.id === this.editingCustomerAddress?.id
59
+ );
61
60
 
62
61
  if (addressIndex !== -1 && addressIndex !== undefined) {
63
62
  const customer = _cloneDeep(this.vm.store.customerStore.customer)!;
@@ -87,10 +86,9 @@ export default class CustomerAddressesViewModel {
87
86
  return;
88
87
  }
89
88
 
90
- const addressIndex =
91
- this.vm.store.customerStore.customer?.addresses?.findIndex(
92
- (a) => a.id === this.editingCustomerAddress?.id
93
- );
89
+ const addressIndex = this.vm.store.customerStore.customer?.addresses?.findIndex(
90
+ (a) => a.id === this.editingCustomerAddress?.id
91
+ );
94
92
 
95
93
  if (addressIndex !== -1 && addressIndex !== undefined) {
96
94
  const customer = _cloneDeep(this.vm.store.customerStore.customer)!;
@@ -115,19 +113,13 @@ export default class CustomerAddressesViewModel {
115
113
  };
116
114
 
117
115
  firstNameChangeCallback = (value: string) => {
118
- if (
119
- (!this.vm.checkout.hasCustomer && this.addressType === "shipping") ||
120
- this.vm.isDigitalOnly
121
- ) {
116
+ if (!this.vm.checkout.hasCustomer && this.addressType === "shipping") {
122
117
  this.vm.checkout.customer!.firstName = value;
123
118
  }
124
119
  };
125
120
 
126
121
  lastNameChangeCallback = (value: string) => {
127
- if (
128
- (!this.vm.checkout.hasCustomer && this.addressType === "shipping") ||
129
- this.vm.isDigitalOnly
130
- ) {
122
+ if (!this.vm.checkout.hasCustomer && this.addressType === "shipping") {
131
123
  this.vm.checkout.customer!.lastName = value;
132
124
  }
133
125
  };
@@ -31,7 +31,7 @@ const Errors: React.FC<CommonProps> = ({ vm }) => {
31
31
  break;
32
32
  case ErrorType.API_ERROR:
33
33
  case ErrorType.UNKNOWN:
34
- error = <UnknownError error={vm.error} onClose={onErrorClose} />;
34
+ error = <UnknownError onClose={onErrorClose} />;
35
35
  break;
36
36
 
37
37
  default:
@@ -2,19 +2,17 @@ import * as React from "react";
2
2
  import { observer } from "mobx-react-lite";
3
3
  import NotificationBox from "../../notification-box";
4
4
  import { useTranslation } from "../../../../../utils";
5
- import { CheckoutError } from "../../../model";
6
5
 
7
6
  type Props = {
8
- error?: CheckoutError | null;
9
7
  onClose: () => void;
10
8
  };
11
9
 
12
- export const UnknownError: React.FC<Props> = observer(({ error, onClose }) => {
10
+ export const UnknownError: React.FC<Props> = observer(({ onClose }) => {
13
11
  const { t } = useTranslation();
14
12
  return (
15
13
  <NotificationBox
16
14
  type="error"
17
- content={<div>{error?.data || t("checkout-page:errorUnknown")}</div>}
15
+ content={<div>{t("checkout-page:errorUnknown")}</div>}
18
16
  onClose={onClose}
19
17
  />
20
18
  );
@@ -7,7 +7,6 @@ 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";
11
10
 
12
11
  export const FormItem: React.FC<Props> = observer((props) => {
13
12
  const { t } = useTranslation();
@@ -109,14 +108,17 @@ export const FormItem: React.FC<Props> = observer((props) => {
109
108
  />
110
109
  )}
111
110
  {vm.type === FormItemType.TEL && (
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
- />
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
+ // />
120
122
  )}
121
123
  {vm.type === FormItemType.TEXT_AREA && <TextArea vm={vm} />}
122
124
  {vm.type === FormItemType.SELECT && (
@@ -132,9 +132,7 @@ const CreditCardFormMasterPass = observer(({ vm }: Props) => {
132
132
  <div className={checkoutStyles.RowPB}>
133
133
  <FormItem
134
134
  name="masterPassPhoneNumber"
135
- autocomplete="tel"
136
135
  type={FormItemType.TEL}
137
- currentCountryCode={vm.store.currentCountryCode}
138
136
  disabled={
139
137
  vm.mpVM.isSaveCardToMasterPassPhoneNumberInputDisabled
140
138
  }
@@ -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 { formatCurrency } from "../../../../utils/currency";
11
+ import { formatMoney } 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.variants[0]);
21
+ React.useState<IkasProductVariant>(campaignOffer!.product.selectedVariant);
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.variants.find((v) => v.id === value);
46
+ const variant = campaignOffer.product.variants.find((v) => v.id === value);
47
47
 
48
48
  if (variant) {
49
49
  setSelectedVariant(variant);
@@ -95,32 +95,35 @@ const OfferProduct: React.FC<Props> = ({ vm, campaignOffer }) => {
95
95
  <span className={styles.Discount}>
96
96
  {selectedVariant.price.formattedFinalPrice}
97
97
  </span>{" "}
98
- {formatCurrency(
98
+ {formatMoney(
99
99
  selectedVariant.price.finalPrice -
100
100
  (selectedVariant.price.finalPrice *
101
101
  (campaignOffer.offer.discountAmount || 100)) /
102
102
  100,
103
- vm.checkout!.currencyCode,
104
- vm.checkout!.currencySymbol
103
+ vm.checkout!.currencyCode
105
104
  )}
106
105
  </div>
107
106
  <div className={styles.Actions}>
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
- )}
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
+ )}
118
120
  <Button
119
121
  style={{
120
122
  width: "100%",
121
123
  height: 44,
122
124
  fontSize: 14,
123
125
  }}
126
+ isDisabled={!campaignOffer.product.hasStock}
124
127
  text={t("checkout-page:actions.addToCart")}
125
128
  onClick={acceptOffer}
126
129
  />
@@ -62,6 +62,7 @@
62
62
  }
63
63
 
64
64
  .ImageContainer {
65
+ height: 136px;
65
66
  width: 136px;
66
67
  position: relative;
67
68
  background-color: #fff;
@@ -72,7 +73,8 @@
72
73
 
73
74
  .Image {
74
75
  width: 100%;
75
- object-fit: contain;
76
+ height: 100%;
77
+ object-fit: cover;
76
78
  border-radius: 8px;
77
79
  }
78
80
 
@@ -1,50 +1,18 @@
1
- import { IkasStorefrontConfig } from "@ikas/storefront-config";
2
1
  import { CountryCode, getCountries as categories } from "libphonenumber-js";
3
2
  import compareStrings from "./compare-strings";
4
3
 
5
- export type CountryType = {
4
+ import en from "./locale/en";
5
+
6
+ type CountryType = {
6
7
  value: CountryCode;
7
8
  label: string | undefined;
8
9
  };
9
10
 
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
-
11
+ const getCountries = (): CountryType[] => {
44
12
  return categories()
45
13
  .map((country) => ({
46
14
  value: country,
47
- label: lang[country],
15
+ label: en[country],
48
16
  }))
49
17
  .sort((a, b) => compareStrings(a.label, b.label));
50
18
  };
@@ -6,7 +6,8 @@ import parsePhoneNumber, {
6
6
  getCountryCallingCode,
7
7
  parseIncompletePhoneNumber,
8
8
  } from "libphonenumber-js";
9
- import getCountries, { CountryType } from "./get-countries";
9
+
10
+ import getCountries from "./get-countries";
10
11
 
11
12
  import styles from "./style.module.scss";
12
13
 
@@ -18,20 +19,17 @@ type Props = {
18
19
  onChange: (value: string) => void;
19
20
  };
20
21
 
21
- const DEFAULT_COUNTRY = "TR";
22
+ const countries = getCountries();
22
23
 
23
24
  export const PhoneNumberInput: React.FC<Props> = observer(
24
25
  ({ defaultCountry, disabled = false, placeholder, value, onChange }) => {
25
- const [countries, setCountries] = React.useState<CountryType[]>([]);
26
26
  const [activeCountry, setActiveCountry] = React.useState(
27
- (defaultCountry as CountryCode) || DEFAULT_COUNTRY
27
+ defaultCountry as CountryCode
28
28
  );
29
29
  const [formatedValue, setFormatedValue] = React.useState("");
30
30
 
31
31
  React.useEffect(() => {
32
- fetchCountries();
33
-
34
- let countryCode = activeCountry;
32
+ let countryCode = (defaultCountry as CountryCode) || "TR";
35
33
 
36
34
  if (value) {
37
35
  const parsedPhoneNumber = parsePhoneNumber(value);
@@ -48,11 +46,6 @@ export const PhoneNumberInput: React.FC<Props> = observer(
48
46
  setActiveCountry(countryCode);
49
47
  }, []);
50
48
 
51
- const fetchCountries = async () => {
52
- const categories = await getCountries();
53
- setCountries(categories);
54
- };
55
-
56
49
  const onValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
57
50
  const phoneNumber = formatPhoneNumber(event.target.value);
58
51
  setFormatedValue(phoneNumber);
@@ -83,7 +76,9 @@ export const PhoneNumberInput: React.FC<Props> = observer(
83
76
  };
84
77
 
85
78
  const getImageSrc = () => {
86
- return `https://cdn.myikas.com/sf/assets/flags/3x2/${activeCountry}.svg`;
79
+ return `https://cdn.myikas.com/sf/assets/flags/3x2/${
80
+ activeCountry || "TR"
81
+ }.svg`;
87
82
  };
88
83
 
89
84
  return (
@@ -93,14 +88,14 @@ export const PhoneNumberInput: React.FC<Props> = observer(
93
88
  <div className={styles.Flag}>
94
89
  <img
95
90
  className={styles.FlagImage}
96
- alt={activeCountry}
91
+ alt={activeCountry || ""}
97
92
  src={getImageSrc()}
98
93
  ></img>
99
94
  <div className={styles.Arrow}></div>
100
95
  </div>
101
96
  <select
102
97
  className={styles.Select}
103
- value={activeCountry}
98
+ value={activeCountry || ""}
104
99
  onChange={onCountryChange}
105
100
  disabled={disabled}
106
101
  >