@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.
- package/package.json +13 -13
- package/src/analytics/analytics.ts +2 -1
- package/src/analytics/googleUniversal.ts +12 -2
- package/src/analytics/head/index.tsx +1 -2
- package/src/analytics/ikas.ts +24 -6
- package/src/components/checkout/components/address-form/index.tsx +1 -1
- package/src/components/checkout/components/cart-summary/cart-item/index.tsx +11 -9
- package/src/components/checkout/components/cart-summary/cart-item/style.module.scss +7 -10
- package/src/components/checkout/components/cart-summary/index.tsx +41 -17
- package/src/components/checkout/components/customer-addresses/index.tsx +6 -2
- package/src/components/checkout/components/form-item/index.tsx +9 -11
- package/src/components/checkout/components/master-pass/credit-card-form/index.tsx +2 -0
- package/src/components/checkout/components/offer-product/index.tsx +16 -19
- package/src/components/checkout/components/offer-product/style.module.scss +1 -3
- package/src/components/checkout/components/phone-number-input/get-countries.ts +37 -5
- package/src/components/checkout/components/phone-number-input/index.tsx +15 -10
- package/src/components/checkout/index.tsx +14 -12
- package/src/components/checkout/model.ts +95 -61
- package/src/components/checkout/modelMasterPass.ts +2 -2
- package/src/components/checkout/steps/step-payment/index.tsx +6 -1
- package/src/components/checkout/steps/step-payment/payment-gateways/index.tsx +12 -3
- package/src/components/checkout/steps/step-payment/payment-gateways/installments/index.tsx +5 -3
- package/src/components/checkout/steps/step-payment/style.module.scss +5 -0
- package/src/components/checkout/steps/step-shipping/index.tsx +9 -4
- package/src/components/checkout/steps/step-success/index.tsx +4 -3
- package/src/components/page/head.tsx +12 -0
- package/src/components/page/index.tsx +10 -9
- package/src/components/page-editor/ThemeComponentEditor.tsx +15 -8
- package/src/components/page-editor/model.ts +44 -107
- package/src/models/data/cart/campaign-offer/index.ts +13 -2
- package/src/models/data/cart/index.ts +1 -1
- package/src/models/data/category/path-item/index.ts +4 -0
- package/src/models/data/checkout/index.ts +11 -3
- package/src/models/data/checkout-settings/price/index.ts +2 -0
- package/src/models/data/index.ts +3 -0
- package/src/models/data/merchant-settings/index.ts +9 -0
- package/src/models/data/order/index.ts +51 -32
- package/src/models/data/order/line-item/index.ts +34 -13
- package/src/models/data/order/line-item/variant/value/index.ts +1 -1
- package/src/models/data/order/transaction/index.ts +2 -5
- package/src/models/data/product/filter/index.ts +4 -13
- package/src/models/data/product/index.ts +21 -3
- package/src/models/data/product/option-set/index.ts +4 -0
- package/src/models/data/product/option-set/option/index.ts +33 -10
- package/src/models/data/product/variant/index.ts +23 -1
- package/src/models/data/product/variant/price/index.ts +23 -9
- package/src/models/data/product/variant-type/index.ts +2 -0
- package/src/models/data/raffle/index.ts +9 -7
- package/src/models/data/state/index.ts +6 -2
- package/src/models/data/storefront/index.ts +2 -0
- package/src/models/ui/product-list/index.ts +26 -17
- package/src/models/ui/raffle-list/index.ts +1 -1
- package/src/models/ui/validator/form/raffle-form.ts +16 -3
- package/src/models/ui/validator/rules/index.ts +14 -13
- package/src/page-data-init/index.ts +159 -404
- package/src/pages/checkout.tsx +2 -1
- package/src/pages/editor.tsx +5 -2
- package/src/store/cart/index.ts +2 -2
- package/src/store/customer/index.ts +7 -17
- package/src/store/raffle/index.ts +7 -10
- package/src/utils/constants.ts +1 -1
- package/src/utils/currency.ts +9 -183
- 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.
|
|
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.
|
|
28
|
-
"@ikas/storefront-config": "^4.0.0-alpha.
|
|
29
|
-
"@ikas/storefront-model-functions": "^4.0.0-alpha.
|
|
30
|
-
"@ikas/storefront-models": "^4.0.0-alpha.
|
|
31
|
-
"@ikas/storefront-providers": "^4.0.0-alpha.
|
|
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": "
|
|
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.
|
|
56
|
-
"@ikas/storefront-config": "^4.0.0-alpha.
|
|
57
|
-
"@ikas/storefront-model-functions": "^4.0.0-alpha.
|
|
58
|
-
"@ikas/storefront-models": "^4.0.0-alpha.
|
|
59
|
-
"@ikas/storefront-providers": "^4.0.0-alpha.
|
|
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": "
|
|
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,
|
|
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
|
package/src/analytics/ikas.ts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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-
|
|
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 {
|
|
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
|
-
?
|
|
163
|
-
:
|
|
164
|
-
cartItem.overridenPriceWithQuantity,
|
|
165
|
-
currencyCode
|
|
166
|
-
)}
|
|
166
|
+
? cartItem.formattedFinalPriceWithQuantity
|
|
167
|
+
: cartItem.formattedOverridenPriceWithQuantity}
|
|
167
168
|
</span>
|
|
168
169
|
)}
|
|
169
170
|
{!!adjustmentTotal
|
|
170
|
-
?
|
|
171
|
+
? formatCurrency(
|
|
171
172
|
cartItem.finalPriceWithQuantity - adjustmentTotal,
|
|
172
|
-
currencyCode
|
|
173
|
+
currencyCode,
|
|
174
|
+
cartItem.currencySymbol
|
|
173
175
|
)
|
|
174
|
-
:
|
|
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
|
-
|
|
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 {
|
|
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
|
-
{`${
|
|
99
|
-
|
|
100
|
-
|
|
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={
|
|
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
|
-
?
|
|
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={
|
|
155
|
+
value={checkout.formattedTotalTax}
|
|
155
156
|
/>
|
|
156
157
|
)}
|
|
157
158
|
{!!vm.installmentExtraPrice && (
|
|
158
159
|
<InfoRow
|
|
159
160
|
label={t("checkout-page:cartInterest")}
|
|
160
|
-
value={
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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>
|
|
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
|
-
{
|
|
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 &&
|
|
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
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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 {
|
|
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
|
|
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.
|
|
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
|
-
{
|
|
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.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
type CountryType = {
|
|
5
|
+
export type CountryType = {
|
|
7
6
|
value: CountryCode;
|
|
8
7
|
label: string | undefined;
|
|
9
8
|
};
|
|
10
9
|
|
|
11
|
-
const
|
|
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:
|
|
47
|
+
label: lang[country],
|
|
16
48
|
}))
|
|
17
49
|
.sort((a, b) => compareStrings(a.label, b.label));
|
|
18
50
|
};
|