@akinon/next 1.41.0-rc.1 → 1.42.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -7
- package/assets/styles/index.css +49 -0
- package/assets/styles/index.css.map +1 -0
- package/assets/styles/index.scss +50 -26
- package/components/plugin-module.tsx +26 -4
- package/components/price.tsx +6 -1
- package/components/selected-payment-option-view.tsx +26 -38
- package/data/client/checkout.ts +26 -3
- package/data/urls.ts +2 -0
- package/hooks/index.ts +2 -1
- package/hooks/use-message-listener.ts +24 -0
- package/hooks/use-payment-options.ts +2 -1
- package/package.json +3 -3
- package/plugins.d.ts +1 -0
- package/plugins.js +2 -1
- package/redux/middlewares/checkout.ts +39 -8
- package/redux/reducers/checkout.ts +8 -1
- package/types/commerce/checkout.ts +18 -0
- package/types/commerce/order.ts +7 -0
- package/types/index.ts +13 -0
- package/utils/redirection-iframe.ts +85 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
4
|
-
|
|
5
|
-
### Minor Changes
|
|
6
|
-
|
|
7
|
-
- 98bb8dc: ZERO-2706: Cache getTranlations method
|
|
8
|
-
|
|
9
|
-
## 1.41.0-rc.0
|
|
3
|
+
## 1.42.0-rc.0
|
|
10
4
|
|
|
11
5
|
### Minor Changes
|
|
12
6
|
|
|
7
|
+
- 90282b5: ZERO-2729: Audit packages for yarn and npm and also update app-template
|
|
8
|
+
- 572d2e8: ZERO-2667: Add iframe support for redirection payment methods
|
|
13
9
|
- a4c8d6a: ZERO-2663: Fix the image url for gif and svgs and return them without options
|
|
14
10
|
- c53ea3e: ZERO-2609: Reset additional form fields when selectedFormType is not company
|
|
15
11
|
- c53ef7b: ZERO-2668: The Link component has been updated to improve the logic for handling href values. Previously, if the href was not a string or started with 'http', it would return the href as is. Now, if the href is not provided, it will default to '#' to prevent any potential errors. Additionally, if the href is a string and does not start with 'http', it will be formatted with the locale and pathname, based on the localeUrlStrategy and defaultLocaleValue. This ensures that the correct href is generated based on the localization settings.
|
|
12
|
+
- 0d3a913: ZERO-2725: Update decimal scale in Price component
|
|
16
13
|
- 1448a96: ZERO-2612: add errors type in CheckoutState
|
|
14
|
+
- d3474c6: ZERO-2655: Add data source shipping option
|
|
17
15
|
- 75080fd: ZERO-2630: Add max limit to postcode area
|
|
18
16
|
- 91265bb: ZERO-2551: Improve pretty url and caching performance
|
|
19
17
|
- bbe18b9: ZERO-2575: Fix build error
|
|
18
|
+
- 98bb8dc: ZERO-2706: Cache getTranlations method
|
|
19
|
+
- dcc8a15: ZERO-2694: added build step to RC branch pipeline
|
|
20
|
+
- fad2768: ZERO-2739: add gpay to payment plugin map
|
|
20
21
|
- dff0d59: ZERO-2659: add formData support to proxy api requests
|
|
21
22
|
- beb499e: ZERO-2551: Add new tsconfig paths
|
|
23
|
+
- c47be30: ZERO-2744: Update Order and OrderItem types
|
|
24
|
+
- e9a46ac: ZERO-2738: add CVC input to registered cards in Masterpass
|
|
22
25
|
- f046f8e: ZERO-2575: update version for react-number-format
|
|
26
|
+
- 86d2531: ZERO-2693: resolve dependency collision warning for eslint-config-next
|
|
27
|
+
|
|
28
|
+
## 1.41.0
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- 8f09473: ZERO-2686: create akifast plugin
|
|
23
33
|
|
|
24
34
|
## 1.40.0
|
|
25
35
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
.checkout-payment-iframe-wrapper {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
border: none;
|
|
8
|
+
z-index: 1000;
|
|
9
|
+
background-color: white;
|
|
10
|
+
}
|
|
11
|
+
.checkout-payment-iframe-wrapper iframe {
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
border: none;
|
|
15
|
+
background-color: white;
|
|
16
|
+
}
|
|
17
|
+
.checkout-payment-iframe-wrapper .close-button {
|
|
18
|
+
position: fixed;
|
|
19
|
+
top: 16px;
|
|
20
|
+
right: 16px;
|
|
21
|
+
width: 32px;
|
|
22
|
+
height: 32px;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
z-index: 1001;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.checkout-payment-redirection-iframe-wrapper {
|
|
30
|
+
width: 100%;
|
|
31
|
+
position: relative;
|
|
32
|
+
}
|
|
33
|
+
.checkout-payment-redirection-iframe-wrapper iframe {
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
border: none;
|
|
37
|
+
background-color: white;
|
|
38
|
+
}
|
|
39
|
+
.checkout-payment-redirection-iframe-wrapper .close-button {
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: 16px;
|
|
42
|
+
right: 16px;
|
|
43
|
+
width: 32px;
|
|
44
|
+
height: 32px;
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
z-index: 1001;
|
|
49
|
+
}/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["index.scss","index.css"],"names":[],"mappings":"AAAA;EACE,eAAA;EACA,MAAA;EACA,OAAA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;ACCF;ADCE;EACE,WAAA;EACA,YAAA;EACA,YAAA;EACA,uBAAA;ACCJ;ADEE;EACE,eAAA;EACA,SAAA;EACA,WAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,aAAA;ACAJ;;ADIA;EACE,WAAA;EACA,kBAAA;ACDF;ADGE;EACE,WAAA;EACA,YAAA;EACA,YAAA;EACA,uBAAA;ACDJ;ADIE;EACE,kBAAA;EACA,SAAA;EACA,WAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,aAAA;ACFJ","file":"index.css"}
|
package/assets/styles/index.scss
CHANGED
|
@@ -1,29 +1,53 @@
|
|
|
1
1
|
.checkout-payment-iframe-wrapper {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
border: none;
|
|
8
|
+
z-index: 1000;
|
|
9
|
+
background-color: white;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
iframe {
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
border: none;
|
|
15
|
+
background-color: white;
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
18
|
+
.close-button {
|
|
19
|
+
position: fixed;
|
|
20
|
+
top: 16px;
|
|
21
|
+
right: 16px;
|
|
22
|
+
width: 32px;
|
|
23
|
+
height: 32px;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
z-index: 1001;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.checkout-payment-redirection-iframe-wrapper {
|
|
32
|
+
width: 100%;
|
|
33
|
+
position: relative;
|
|
34
|
+
|
|
35
|
+
iframe {
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 100%;
|
|
38
|
+
border: none;
|
|
39
|
+
background-color: white;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.close-button {
|
|
43
|
+
position: absolute;
|
|
44
|
+
top: 16px;
|
|
45
|
+
right: 16px;
|
|
46
|
+
width: 32px;
|
|
47
|
+
height: 32px;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
z-index: 1001;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -4,6 +4,7 @@ import dynamic from 'next/dynamic';
|
|
|
4
4
|
import plugins from 'plugins';
|
|
5
5
|
import logger from '../utils/log';
|
|
6
6
|
import { useMemo } from 'react';
|
|
7
|
+
import settings from 'settings';
|
|
7
8
|
|
|
8
9
|
enum Plugin {
|
|
9
10
|
BasketGiftPack = 'pz-basket-gift-pack',
|
|
@@ -16,13 +17,15 @@ enum Plugin {
|
|
|
16
17
|
BKMExpress = 'pz-bkm',
|
|
17
18
|
CreditPayment = 'pz-credit-payment',
|
|
18
19
|
Masterpass = 'pz-masterpass',
|
|
19
|
-
B2B = 'pz-b2b'
|
|
20
|
+
B2B = 'pz-b2b',
|
|
21
|
+
Akifast = 'pz-akifast'
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export enum Component {
|
|
23
25
|
BasketGiftPack = 'BasketGiftPack',
|
|
24
26
|
ClickCollect = 'ClickCollect',
|
|
25
27
|
OneClickCheckoutButtons = 'OneClickCheckoutButtons',
|
|
28
|
+
OneClickProviderButton = 'OneClickCheckoutButton',
|
|
26
29
|
PayOnDelivery = 'PayOnDelivery',
|
|
27
30
|
CheckoutGiftPack = 'CheckoutGiftPack',
|
|
28
31
|
GPay = 'GPayOption',
|
|
@@ -36,13 +39,18 @@ export enum Component {
|
|
|
36
39
|
MasterpassOtpModal = 'MasterpassOtpModal',
|
|
37
40
|
MasterpassLinkModal = 'MasterpassLinkModal',
|
|
38
41
|
MyQuotationsB2B = 'AccountMyQuotations',
|
|
39
|
-
BasketB2B = 'BasketB2b'
|
|
42
|
+
BasketB2B = 'BasketB2b',
|
|
43
|
+
AkifastQuickLoginButton = 'QuickLoginButton',
|
|
44
|
+
AkifastCheckoutButton = 'CheckoutButton'
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
const PluginComponents = new Map([
|
|
43
48
|
[Plugin.BasketGiftPack, [Component.BasketGiftPack]],
|
|
44
49
|
[Plugin.ClickCollect, [Component.ClickCollect]],
|
|
45
|
-
[
|
|
50
|
+
[
|
|
51
|
+
Plugin.OneClickCheckout,
|
|
52
|
+
[Component.OneClickCheckoutButtons, Component.OneClickProviderButton]
|
|
53
|
+
],
|
|
46
54
|
[Plugin.PayOnDelivery, [Component.PayOnDelivery]],
|
|
47
55
|
[Plugin.CheckoutGiftPack, [Component.CheckoutGiftPack]],
|
|
48
56
|
[Plugin.GPay, [Component.GPay]],
|
|
@@ -60,7 +68,11 @@ const PluginComponents = new Map([
|
|
|
60
68
|
Component.MasterpassLinkModal
|
|
61
69
|
]
|
|
62
70
|
],
|
|
63
|
-
[Plugin.B2B, [Component.MyQuotationsB2B, Component.BasketB2B]]
|
|
71
|
+
[Plugin.B2B, [Component.MyQuotationsB2B, Component.BasketB2B]],
|
|
72
|
+
[
|
|
73
|
+
Plugin.Akifast,
|
|
74
|
+
[Component.AkifastQuickLoginButton, Component.AkifastCheckoutButton]
|
|
75
|
+
]
|
|
64
76
|
]);
|
|
65
77
|
|
|
66
78
|
const getPlugin = (component: Component) => {
|
|
@@ -81,6 +93,14 @@ export default function PluginModule({
|
|
|
81
93
|
children?: React.ReactNode;
|
|
82
94
|
}) {
|
|
83
95
|
const plugin = getPlugin(component);
|
|
96
|
+
const pluginSettings = settings.plugins?.[plugin];
|
|
97
|
+
|
|
98
|
+
if (pluginSettings) {
|
|
99
|
+
props = {
|
|
100
|
+
...props,
|
|
101
|
+
settings: pluginSettings
|
|
102
|
+
};
|
|
103
|
+
}
|
|
84
104
|
|
|
85
105
|
const Component = useMemo(
|
|
86
106
|
() =>
|
|
@@ -111,6 +131,8 @@ export default function PluginModule({
|
|
|
111
131
|
promise = import(`${'@akinon/pz-masterpass'}`);
|
|
112
132
|
} else if (plugin === Plugin.B2B) {
|
|
113
133
|
promise = import(`${'@akinon/pz-b2b'}`);
|
|
134
|
+
} else if (plugin === Plugin.Akifast) {
|
|
135
|
+
promise = import(`${'@akinon/pz-akifast'}`);
|
|
114
136
|
}
|
|
115
137
|
} catch (error) {
|
|
116
138
|
logger.error(error);
|
package/components/price.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { getCurrency } from '@akinon/next/utils';
|
|
|
5
5
|
|
|
6
6
|
import { useLocalization } from '@akinon/next/hooks';
|
|
7
7
|
import { PriceProps } from '../types';
|
|
8
|
+
import Settings from '@theme/settings';
|
|
8
9
|
|
|
9
10
|
export const Price = (props: NumericFormatProps & PriceProps) => {
|
|
10
11
|
const {
|
|
@@ -28,6 +29,10 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
|
|
|
28
29
|
// TODO: This is very bad practice. It broke decimalScale.
|
|
29
30
|
const _value = value?.toString().replace('.', ',');
|
|
30
31
|
|
|
32
|
+
const currentCurrencyDecimalScale = Settings.localization.currencies.find(
|
|
33
|
+
(currency) => currency.code === currencyCode_
|
|
34
|
+
).decimalScale;
|
|
35
|
+
|
|
31
36
|
const currency = useMemo(
|
|
32
37
|
() =>
|
|
33
38
|
getCurrency({
|
|
@@ -47,7 +52,7 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
|
|
|
47
52
|
}}
|
|
48
53
|
displayType={displayType}
|
|
49
54
|
thousandSeparator={thousandSeparator}
|
|
50
|
-
decimalScale={decimalScale}
|
|
55
|
+
decimalScale={currentCurrencyDecimalScale ?? decimalScale}
|
|
51
56
|
decimalSeparator={decimalSeparator}
|
|
52
57
|
fixedDecimalScale={fixedDecimalScale}
|
|
53
58
|
{...rest}
|
|
@@ -6,6 +6,21 @@ import dynamic from 'next/dynamic';
|
|
|
6
6
|
import { PaymentOptionViews } from 'views/checkout/steps/payment';
|
|
7
7
|
import { useMemo } from 'react';
|
|
8
8
|
|
|
9
|
+
const fallbackView = () => <div />;
|
|
10
|
+
|
|
11
|
+
const paymentTypeToView = {
|
|
12
|
+
bkm_express: 'bkm',
|
|
13
|
+
credit_card: 'credit-card',
|
|
14
|
+
credit_payment: 'credit-payment',
|
|
15
|
+
funds_transfer: 'funds-transfer',
|
|
16
|
+
gpay: 'gpay',
|
|
17
|
+
loyalty_money: 'loyalty',
|
|
18
|
+
masterpass: 'credit-card',
|
|
19
|
+
pay_on_delivery: 'pay-on-delivery',
|
|
20
|
+
redirection: 'redirection'
|
|
21
|
+
// Add other mappings as needed
|
|
22
|
+
};
|
|
23
|
+
|
|
9
24
|
export default function SelectedPaymentOptionView() {
|
|
10
25
|
const { payment_option } = useAppSelector(
|
|
11
26
|
(state: RootState) => state.checkout.preOrder
|
|
@@ -14,7 +29,7 @@ export default function SelectedPaymentOptionView() {
|
|
|
14
29
|
const Component = useMemo(
|
|
15
30
|
() =>
|
|
16
31
|
dynamic(
|
|
17
|
-
() => {
|
|
32
|
+
async () => {
|
|
18
33
|
const customOption = PaymentOptionViews.find(
|
|
19
34
|
(opt) => opt.slug === payment_option.slug
|
|
20
35
|
);
|
|
@@ -29,46 +44,19 @@ export default function SelectedPaymentOptionView() {
|
|
|
29
44
|
});
|
|
30
45
|
}
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`views/checkout/steps/payment/options/credit-card`
|
|
38
|
-
);
|
|
39
|
-
} else if (payment_option.payment_type === 'funds_transfer') {
|
|
40
|
-
promise = import(
|
|
41
|
-
`views/checkout/steps/payment/options/funds-transfer`
|
|
42
|
-
);
|
|
43
|
-
} else if (payment_option.payment_type === 'redirection') {
|
|
44
|
-
promise = import(
|
|
45
|
-
`views/checkout/steps/payment/options/redirection`
|
|
46
|
-
);
|
|
47
|
-
} else if (payment_option.payment_type === 'pay_on_delivery') {
|
|
48
|
-
promise = import(
|
|
49
|
-
`views/checkout/steps/payment/options/pay-on-delivery`
|
|
50
|
-
);
|
|
51
|
-
} else if (payment_option.payment_type === 'loyalty_money') {
|
|
52
|
-
promise = import(`views/checkout/steps/payment/options/loyalty`);
|
|
53
|
-
} else if (payment_option.payment_type === 'masterpass') {
|
|
54
|
-
promise = import(
|
|
55
|
-
`views/checkout/steps/payment/options/credit-card`
|
|
47
|
+
const view = paymentTypeToView[payment_option.payment_type];
|
|
48
|
+
if (view) {
|
|
49
|
+
try {
|
|
50
|
+
const mod = await import(
|
|
51
|
+
`views/checkout/steps/payment/options/${view}`
|
|
56
52
|
);
|
|
53
|
+
return mod.default || fallbackView;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return fallbackView;
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
// promise = import(`views/checkout/steps/payment/options/credit-payment`);
|
|
60
|
-
// }
|
|
61
|
-
// else if (payment_option.payment_type === 'gpay') {
|
|
62
|
-
// promise = import(`views/checkout/steps/payment/options/gpay`);
|
|
63
|
-
// }
|
|
64
|
-
// else if (payment_option.payment_type === 'bkm_express') {
|
|
65
|
-
// promise = import(`views/checkout/steps/payment/options/bkm`);
|
|
66
|
-
// }
|
|
67
|
-
} catch (error) {}
|
|
57
|
+
}
|
|
68
58
|
|
|
69
|
-
return
|
|
70
|
-
? promise.then((mod) => mod.default).catch(() => () => null)
|
|
71
|
-
: new Promise<any>((resolve) => resolve(() => null));
|
|
59
|
+
return fallbackView;
|
|
72
60
|
},
|
|
73
61
|
{ ssr: false }
|
|
74
62
|
),
|
package/data/client/checkout.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
setBankAccounts,
|
|
3
|
+
setCardType,
|
|
3
4
|
setInstallmentOptions,
|
|
4
5
|
setPaymentStepBusy,
|
|
5
6
|
setSelectedBankAccountPk,
|
|
6
7
|
setSelectedCreditPaymentPk,
|
|
7
|
-
setShippingStepBusy
|
|
8
|
-
setCardType
|
|
8
|
+
setShippingStepBusy
|
|
9
9
|
} from '../../redux/reducers/checkout';
|
|
10
10
|
import {
|
|
11
11
|
CheckoutContext,
|
|
@@ -20,6 +20,7 @@ import { AppDispatch, AppStore, store } from 'redux/store';
|
|
|
20
20
|
import settings from 'settings';
|
|
21
21
|
import { showMobile3dIframe } from '../../utils/mobile-3d-iframe';
|
|
22
22
|
import {
|
|
23
|
+
setCvcRequired,
|
|
23
24
|
setError,
|
|
24
25
|
setOtpModalVisible
|
|
25
26
|
} from '@akinon/pz-masterpass/src/redux/reducer';
|
|
@@ -113,7 +114,8 @@ const completeMasterpassPayment = async (
|
|
|
113
114
|
? await buildDirectPurchaseForm(commonFormValues, params)
|
|
114
115
|
: await buildPurchaseForm({
|
|
115
116
|
...commonFormValues,
|
|
116
|
-
selectedCard
|
|
117
|
+
selectedCard,
|
|
118
|
+
cardCvc: params?.card_cvv
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
window.MFS?.[
|
|
@@ -151,6 +153,10 @@ const completeMasterpassPayment = async (
|
|
|
151
153
|
return;
|
|
152
154
|
}
|
|
153
155
|
|
|
156
|
+
if (['5013', '5182'].includes(response.responseCode)) {
|
|
157
|
+
dispatch(setCvcRequired(true));
|
|
158
|
+
}
|
|
159
|
+
|
|
154
160
|
if (
|
|
155
161
|
response.token &&
|
|
156
162
|
(response.responseCode == '0000' || response.responseCode == '')
|
|
@@ -373,6 +379,22 @@ export const checkoutApi = api.injectEndpoints({
|
|
|
373
379
|
dispatch(setShippingStepBusy(false));
|
|
374
380
|
}
|
|
375
381
|
}),
|
|
382
|
+
setDataSourceShippingOptions: build.mutation<CheckoutResponse, number[]>({
|
|
383
|
+
query: (pks) => ({
|
|
384
|
+
url: buildClientRequestUrl(checkout.setDataSourceShippingOption, {
|
|
385
|
+
useFormData: true
|
|
386
|
+
}),
|
|
387
|
+
method: 'POST',
|
|
388
|
+
body: {
|
|
389
|
+
data_source_shipping_options: JSON.stringify(pks)
|
|
390
|
+
}
|
|
391
|
+
}),
|
|
392
|
+
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
|
393
|
+
dispatch(setShippingStepBusy(true));
|
|
394
|
+
await queryFulfilled;
|
|
395
|
+
dispatch(setShippingStepBusy(false));
|
|
396
|
+
}
|
|
397
|
+
}),
|
|
376
398
|
setRetailStore: build.mutation<CheckoutResponse, SetRetailStoreParams>({
|
|
377
399
|
query: ({ retailStorePk, billingAddressPk }) => ({
|
|
378
400
|
url: buildClientRequestUrl(
|
|
@@ -672,6 +694,7 @@ export const {
|
|
|
672
694
|
useSetDeliveryOptionMutation,
|
|
673
695
|
useSetAddressesMutation,
|
|
674
696
|
useSetShippingOptionMutation,
|
|
697
|
+
useSetDataSourceShippingOptionsMutation,
|
|
675
698
|
useSetPaymentOptionMutation,
|
|
676
699
|
useSetBinNumberMutation,
|
|
677
700
|
useSetInstallmentOptionMutation,
|
package/data/urls.ts
CHANGED
|
@@ -79,6 +79,8 @@ export const checkout = {
|
|
|
79
79
|
setDeliveryOption: '/orders/checkout/?page=DeliveryOptionSelectionPage',
|
|
80
80
|
setAddresses: '/orders/checkout/?page=AddressSelectionPage',
|
|
81
81
|
setShippingOption: '/orders/checkout/?page=ShippingOptionSelectionPage',
|
|
82
|
+
setDataSourceShippingOption:
|
|
83
|
+
'/orders/checkout/?page=DataSourceShippingOptionSelectionPage',
|
|
82
84
|
setPaymentOption: '/orders/checkout/?page=PaymentOptionSelectionPage',
|
|
83
85
|
setBinNumber: '/orders/checkout/?page=BinNumberPage',
|
|
84
86
|
setMasterpassBinNumber: '/orders/checkout/?page=MasterpassBinNumberPage',
|
package/hooks/index.ts
CHANGED
|
@@ -8,4 +8,5 @@ export * from './use-media-query';
|
|
|
8
8
|
export * from './use-on-click-outside';
|
|
9
9
|
export * from './use-mobile-iframe-handler';
|
|
10
10
|
export * from './use-payment-options';
|
|
11
|
-
export * from './use-pagination';
|
|
11
|
+
export * from './use-pagination';
|
|
12
|
+
export * from './use-message-listener';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useMessageListener = () => {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const handleMessage = (event: MessageEvent) => {
|
|
6
|
+
if (event.origin !== window.location.origin) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (event.data && typeof event.data === 'string') {
|
|
11
|
+
const messageData = JSON.parse(event.data);
|
|
12
|
+
if (messageData?.url) {
|
|
13
|
+
window.location.href = messageData.url;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
window.addEventListener('message', handleMessage);
|
|
19
|
+
|
|
20
|
+
return () => {
|
|
21
|
+
window.removeEventListener('message', handleMessage);
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
};
|
|
@@ -18,7 +18,8 @@ export const usePaymentOptions = () => {
|
|
|
18
18
|
pay_on_delivery: 'pz-pay-on-delivery',
|
|
19
19
|
bkm_express: 'pz-bkm',
|
|
20
20
|
credit_payment: 'pz-credit-payment',
|
|
21
|
-
masterpass: 'pz-masterpass'
|
|
21
|
+
masterpass: 'pz-masterpass',
|
|
22
|
+
gpay: 'pz-gpay'
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const isInitialTypeIncluded = (type: string) => initialTypes.has(type);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/next",
|
|
3
3
|
"description": "Core package for Project Zero Next",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.42.0-rc.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"react-redux": "8.1.3",
|
|
27
27
|
"react-string-replace": "1.1.1",
|
|
28
28
|
"redis": "4.6.13",
|
|
29
|
-
"semver": "7.
|
|
29
|
+
"semver": "7.6.2",
|
|
30
30
|
"set-cookie-parser": "2.6.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@akinon/eslint-plugin-projectzero": "1.42.0-rc.0",
|
|
33
34
|
"@types/react-redux": "7.1.30",
|
|
34
35
|
"@types/set-cookie-parser": "2.4.7",
|
|
35
36
|
"@typescript-eslint/eslint-plugin": "6.7.4",
|
|
36
37
|
"@typescript-eslint/parser": "6.7.4",
|
|
37
38
|
"eslint": "^8.14.0",
|
|
38
|
-
"@akinon/eslint-plugin-projectzero": "1.41.0-rc.1",
|
|
39
39
|
"eslint-config-prettier": "8.5.0"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/plugins.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare module '@akinon/pz-masterpass/src/utils' {
|
|
|
12
12
|
declare module '@akinon/pz-masterpass/src/redux/reducer' {
|
|
13
13
|
export const setError: any;
|
|
14
14
|
export const setOtpModalVisible: any;
|
|
15
|
+
export const setCvcRequired: any;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
declare module '@akinon/pz-otp' {
|
package/plugins.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
setPreOrder,
|
|
17
17
|
setRetailStores,
|
|
18
18
|
setShippingOptions,
|
|
19
|
+
setDataSourceShippingOptions,
|
|
19
20
|
setShippingStepCompleted,
|
|
20
21
|
setCreditPaymentOptions
|
|
21
22
|
} from '../../redux/reducers/checkout';
|
|
@@ -26,6 +27,7 @@ import { getCookie, setCookie } from '../../utils';
|
|
|
26
27
|
import settings from 'settings';
|
|
27
28
|
import { LocaleUrlStrategy } from '../../localization';
|
|
28
29
|
import { showMobile3dIframe } from '../../utils/mobile-3d-iframe';
|
|
30
|
+
import { showRedirectionIframe } from '../../utils/redirection-iframe';
|
|
29
31
|
|
|
30
32
|
interface CheckoutResult {
|
|
31
33
|
payload: {
|
|
@@ -73,6 +75,7 @@ export const preOrderMiddleware: Middleware = ({
|
|
|
73
75
|
deliveryOptions,
|
|
74
76
|
addressList: addresses,
|
|
75
77
|
shippingOptions,
|
|
78
|
+
dataSourceShippingOptions,
|
|
76
79
|
paymentOptions,
|
|
77
80
|
installmentOptions
|
|
78
81
|
} = getState().checkout;
|
|
@@ -125,6 +128,22 @@ export const preOrderMiddleware: Middleware = ({
|
|
|
125
128
|
dispatch(apiEndpoints.setShippingOption.initiate(shippingOptions[0].pk));
|
|
126
129
|
}
|
|
127
130
|
|
|
131
|
+
if (
|
|
132
|
+
dataSourceShippingOptions.length > 0 &&
|
|
133
|
+
!preOrder.data_source_shipping_options
|
|
134
|
+
) {
|
|
135
|
+
const selectedDataSourceShippingOptionsPks =
|
|
136
|
+
dataSourceShippingOptions.map(
|
|
137
|
+
(opt) => opt.data_source_shipping_options[0].pk
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
dispatch(
|
|
141
|
+
apiEndpoints.setDataSourceShippingOptions.initiate(
|
|
142
|
+
selectedDataSourceShippingOptionsPks
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
if (!preOrder.payment_option && paymentOptions.length > 0) {
|
|
129
148
|
dispatch(apiEndpoints.setPaymentOption.initiate(paymentOptions[0].pk));
|
|
130
149
|
}
|
|
@@ -163,6 +182,7 @@ export const contextListMiddleware: Middleware = ({
|
|
|
163
182
|
if (result?.payload?.context_list) {
|
|
164
183
|
result.payload.context_list.forEach((context) => {
|
|
165
184
|
const redirectUrl = context.page_context.redirect_url;
|
|
185
|
+
const isIframe = context.page_context.is_frame ?? false;
|
|
166
186
|
|
|
167
187
|
if (redirectUrl) {
|
|
168
188
|
const currentLocale = getCookie('pz-locale');
|
|
@@ -181,16 +201,19 @@ export const contextListMiddleware: Middleware = ({
|
|
|
181
201
|
}
|
|
182
202
|
|
|
183
203
|
const urlObj = new URL(url, window.location.origin);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
/iPad|iPhone|iPod|Android/i.test(navigator.userAgent)) &&
|
|
204
|
+
const isMobileDevice =
|
|
205
|
+
isMobileApp ||
|
|
206
|
+
/iPad|iPhone|iPod|Android/i.test(navigator.userAgent);
|
|
207
|
+
const isIframePaymentOptionExcluded =
|
|
189
208
|
!settings.checkout?.iframeExcludedPaymentOptions?.includes(
|
|
190
209
|
result.payload?.pre_order?.payment_option?.slug
|
|
191
|
-
)
|
|
192
|
-
)
|
|
210
|
+
);
|
|
211
|
+
urlObj.searchParams.set('t', new Date().getTime().toString());
|
|
212
|
+
|
|
213
|
+
if (isMobileDevice && !isIframePaymentOptionExcluded) {
|
|
193
214
|
showMobile3dIframe(urlObj.toString());
|
|
215
|
+
} else if (isIframe && !isIframePaymentOptionExcluded) {
|
|
216
|
+
showRedirectionIframe(urlObj.toString());
|
|
194
217
|
} else {
|
|
195
218
|
window.location.href = urlObj.toString();
|
|
196
219
|
}
|
|
@@ -220,12 +243,20 @@ export const contextListMiddleware: Middleware = ({
|
|
|
220
243
|
dispatch(setShippingOptions(context.page_context.shipping_options));
|
|
221
244
|
}
|
|
222
245
|
|
|
246
|
+
if (context.page_context.data_sources) {
|
|
247
|
+
dispatch(
|
|
248
|
+
setDataSourceShippingOptions(context.page_context.data_sources)
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
223
252
|
if (context.page_context.payment_options) {
|
|
224
253
|
dispatch(setPaymentOptions(context.page_context.payment_options));
|
|
225
254
|
}
|
|
226
255
|
|
|
227
256
|
if (context.page_context.credit_payment_options) {
|
|
228
|
-
dispatch(
|
|
257
|
+
dispatch(
|
|
258
|
+
setCreditPaymentOptions(context.page_context.credit_payment_options)
|
|
259
|
+
);
|
|
229
260
|
}
|
|
230
261
|
|
|
231
262
|
if (context.page_context.payment_choices) {
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
CheckoutCreditPaymentOption,
|
|
15
15
|
PreOrder,
|
|
16
16
|
RetailStore,
|
|
17
|
-
ShippingOption
|
|
17
|
+
ShippingOption,
|
|
18
|
+
DataSource
|
|
18
19
|
} from '../../types';
|
|
19
20
|
|
|
20
21
|
export interface CheckoutState {
|
|
@@ -36,6 +37,7 @@ export interface CheckoutState {
|
|
|
36
37
|
addressList: Address[];
|
|
37
38
|
deliveryOptions: DeliveryOption[];
|
|
38
39
|
shippingOptions: ShippingOption[];
|
|
40
|
+
dataSourceShippingOptions: DataSource[];
|
|
39
41
|
paymentOptions: PaymentOption[];
|
|
40
42
|
creditPaymentOptions: CheckoutCreditPaymentOption[];
|
|
41
43
|
selectedCreditPaymentPk: number;
|
|
@@ -67,6 +69,7 @@ const initialState: CheckoutState = {
|
|
|
67
69
|
addressList: [],
|
|
68
70
|
deliveryOptions: [],
|
|
69
71
|
shippingOptions: [],
|
|
72
|
+
dataSourceShippingOptions: [],
|
|
70
73
|
paymentOptions: [],
|
|
71
74
|
creditPaymentOptions: [],
|
|
72
75
|
selectedCreditPaymentPk: null,
|
|
@@ -121,6 +124,9 @@ const checkoutSlice = createSlice({
|
|
|
121
124
|
setShippingOptions(state, { payload }) {
|
|
122
125
|
state.shippingOptions = payload;
|
|
123
126
|
},
|
|
127
|
+
setDataSourceShippingOptions(state, { payload }) {
|
|
128
|
+
state.dataSourceShippingOptions = payload;
|
|
129
|
+
},
|
|
124
130
|
setPaymentOptions(state, { payload }) {
|
|
125
131
|
state.paymentOptions = payload;
|
|
126
132
|
},
|
|
@@ -168,6 +174,7 @@ export const {
|
|
|
168
174
|
setAddressList,
|
|
169
175
|
setDeliveryOptions,
|
|
170
176
|
setShippingOptions,
|
|
177
|
+
setDataSourceShippingOptions,
|
|
171
178
|
setPaymentOptions,
|
|
172
179
|
setCreditPaymentOptions,
|
|
173
180
|
setSelectedCreditPaymentPk,
|
|
@@ -33,6 +33,23 @@ export interface ShippingOption {
|
|
|
33
33
|
slug: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export interface DataSource {
|
|
37
|
+
pk: number;
|
|
38
|
+
name: string;
|
|
39
|
+
data_source_shipping_options: DataSourceShippingOption[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface DataSourceShippingOption {
|
|
43
|
+
pk: number;
|
|
44
|
+
shipping_amount: string;
|
|
45
|
+
shipping_option_name: string;
|
|
46
|
+
shipping_option_logo: string | null;
|
|
47
|
+
data_source: {
|
|
48
|
+
pk: number;
|
|
49
|
+
title: string | null;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
36
53
|
export interface CheckoutAddressType {
|
|
37
54
|
label: string;
|
|
38
55
|
text: string;
|
|
@@ -78,6 +95,7 @@ export interface PreOrder {
|
|
|
78
95
|
retail_store?: RetailStore;
|
|
79
96
|
gift_box?: GiftBox;
|
|
80
97
|
credit_payment_option?: CheckoutCreditPaymentOption;
|
|
98
|
+
data_source_shipping_options: any;
|
|
81
99
|
}
|
|
82
100
|
|
|
83
101
|
export interface GuestLoginFormParams {
|
package/types/commerce/order.ts
CHANGED
|
@@ -52,6 +52,10 @@ export interface OrderItem {
|
|
|
52
52
|
quantity: string;
|
|
53
53
|
unit_price: string;
|
|
54
54
|
total_amount: string;
|
|
55
|
+
attributes: {
|
|
56
|
+
gift_note: string;
|
|
57
|
+
[key: string]: any;
|
|
58
|
+
};
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
export interface Order {
|
|
@@ -105,6 +109,9 @@ export interface Order {
|
|
|
105
109
|
shipping_option: number;
|
|
106
110
|
tracking_number: string;
|
|
107
111
|
tracking_url: string;
|
|
112
|
+
bank: {
|
|
113
|
+
logo: string;
|
|
114
|
+
};
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
export interface Quotations {
|
package/types/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ declare global {
|
|
|
8
8
|
// we did it like this because declare types needs to be identical, if not it will fail
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
10
10
|
dataLayer?: Object[];
|
|
11
|
+
|
|
11
12
|
[key: string]: any;
|
|
12
13
|
}
|
|
13
14
|
}
|
|
@@ -67,6 +68,13 @@ export interface Currency {
|
|
|
67
68
|
* @see https://en.wikipedia.org/wiki/ISO_4217
|
|
68
69
|
*/
|
|
69
70
|
code: string;
|
|
71
|
+
/**
|
|
72
|
+
* Number of decimal places to display.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* decimalScale: 3
|
|
76
|
+
*/
|
|
77
|
+
decimalScale?: number;
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
export interface Settings {
|
|
@@ -183,6 +191,7 @@ export interface Settings {
|
|
|
183
191
|
masterpassJsUrl?: string;
|
|
184
192
|
};
|
|
185
193
|
customNotFoundEnabled: boolean;
|
|
194
|
+
plugins?: Record<string, Record<string, any>>;
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
export interface CacheOptions {
|
|
@@ -278,3 +287,7 @@ export interface AccordionProps {
|
|
|
278
287
|
titleClassName?: string;
|
|
279
288
|
dataTestId?: string;
|
|
280
289
|
}
|
|
290
|
+
|
|
291
|
+
export interface PluginModuleComponentProps {
|
|
292
|
+
settings?: Record<string, any>;
|
|
293
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const iframeURLChange = (iframe, callback) => {
|
|
2
|
+
iframe.addEventListener('load', () => {
|
|
3
|
+
setTimeout(() => {
|
|
4
|
+
if (iframe?.contentWindow?.location) {
|
|
5
|
+
callback(iframe.contentWindow.location);
|
|
6
|
+
}
|
|
7
|
+
}, 0);
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const removeIframe = async () => {
|
|
12
|
+
const iframeSelector = document.querySelector(
|
|
13
|
+
'.checkout-payment-redirection-iframe-wrapper'
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const redirectionPaymentWrapper = document.querySelector(
|
|
17
|
+
'.checkout-redirection-payment-wrapper'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const form = redirectionPaymentWrapper.querySelector('form') as HTMLElement;
|
|
21
|
+
|
|
22
|
+
if (!iframeSelector) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
iframeSelector.remove();
|
|
27
|
+
|
|
28
|
+
if (form) {
|
|
29
|
+
form.style.display = 'block';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
location.reload();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const showRedirectionIframe = (redirectUrl: string) => {
|
|
36
|
+
const iframeWrapper = document.createElement('div');
|
|
37
|
+
const iframe = document.createElement('iframe');
|
|
38
|
+
const closeButton = document.createElement('div');
|
|
39
|
+
const redirectionPaymentWrapper = document.querySelector(
|
|
40
|
+
'.checkout-redirection-payment-wrapper'
|
|
41
|
+
);
|
|
42
|
+
const form = redirectionPaymentWrapper.querySelector('form') as HTMLElement;
|
|
43
|
+
|
|
44
|
+
iframeWrapper.className = 'checkout-payment-redirection-iframe-wrapper';
|
|
45
|
+
closeButton.className = 'close-button';
|
|
46
|
+
|
|
47
|
+
iframe.setAttribute('src', redirectUrl);
|
|
48
|
+
closeButton.innerHTML = '✕';
|
|
49
|
+
closeButton.addEventListener('click', removeIframe);
|
|
50
|
+
|
|
51
|
+
iframeWrapper.append(iframe, closeButton);
|
|
52
|
+
|
|
53
|
+
if (form) {
|
|
54
|
+
form.style.display = 'none';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
redirectionPaymentWrapper.appendChild(iframeWrapper);
|
|
58
|
+
|
|
59
|
+
iframeURLChange(iframe, (location) => {
|
|
60
|
+
if (location.origin !== window.location.origin) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const searchParams = new URLSearchParams(location.search);
|
|
65
|
+
const isOrderCompleted = location.href.includes('/orders/completed');
|
|
66
|
+
|
|
67
|
+
if (isOrderCompleted) {
|
|
68
|
+
(window.parent as any)?.postMessage?.(
|
|
69
|
+
JSON.stringify({
|
|
70
|
+
url: location.pathname
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
searchParams.has('success') ||
|
|
77
|
+
isOrderCompleted ||
|
|
78
|
+
location.href.includes('/orders/checkout')
|
|
79
|
+
) {
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
removeIframe();
|
|
82
|
+
}, 0);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|