@akinon/next 1.61.0 → 1.62.0-rc.24

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 (59) hide show
  1. package/CHANGELOG.md +661 -0
  2. package/api/client.ts +23 -2
  3. package/assets/styles/index.css +49 -0
  4. package/assets/styles/index.css.map +1 -0
  5. package/assets/styles/index.scss +50 -26
  6. package/bin/pz-install-plugins.js +0 -0
  7. package/bin/pz-install-theme.js +0 -0
  8. package/bin/pz-postbuild.js +0 -0
  9. package/bin/pz-postdev.js +0 -0
  10. package/bin/pz-postinstall.js +0 -0
  11. package/bin/pz-poststart.js +0 -0
  12. package/bin/pz-prebuild.js +0 -0
  13. package/bin/pz-predev.js +0 -0
  14. package/bin/pz-prestart.js +0 -0
  15. package/components/file-input.tsx +8 -0
  16. package/components/index.ts +1 -0
  17. package/components/input.tsx +21 -7
  18. package/components/link.tsx +17 -13
  19. package/components/plugin-module.tsx +8 -3
  20. package/components/price.tsx +11 -4
  21. package/components/selected-payment-option-view.tsx +2 -1
  22. package/data/client/account.ts +3 -2
  23. package/data/client/api.ts +1 -1
  24. package/data/client/b2b.ts +35 -2
  25. package/data/client/basket.ts +6 -5
  26. package/data/client/checkout.ts +55 -10
  27. package/data/client/user.ts +3 -2
  28. package/data/server/category.ts +0 -4
  29. package/data/server/list.ts +0 -4
  30. package/data/server/product.ts +1 -4
  31. package/data/server/special-page.ts +0 -4
  32. package/data/urls.ts +17 -4
  33. package/hooks/index.ts +2 -1
  34. package/hooks/use-message-listener.ts +24 -0
  35. package/hooks/use-pagination.ts +2 -2
  36. package/hooks/use-payment-options.ts +2 -1
  37. package/middlewares/complete-gpay.ts +1 -1
  38. package/middlewares/complete-masterpass.ts +1 -1
  39. package/middlewares/currency.ts +1 -0
  40. package/middlewares/default.ts +226 -167
  41. package/middlewares/index.ts +3 -1
  42. package/middlewares/oauth-login.ts +6 -1
  43. package/middlewares/saved-card-redirection.ts +179 -0
  44. package/middlewares/three-d-redirection.ts +1 -1
  45. package/middlewares/url-redirection.ts +14 -2
  46. package/package.json +2 -2
  47. package/plugins.d.ts +6 -0
  48. package/plugins.js +2 -1
  49. package/redux/middlewares/checkout.ts +77 -13
  50. package/redux/reducers/checkout.ts +23 -3
  51. package/redux/reducers/index.ts +3 -1
  52. package/routes/pretty-url.tsx +7 -9
  53. package/types/commerce/address.ts +1 -1
  54. package/types/commerce/b2b.ts +12 -2
  55. package/types/commerce/checkout.ts +31 -0
  56. package/types/commerce/order.ts +1 -0
  57. package/types/index.ts +10 -1
  58. package/utils/index.ts +27 -6
  59. package/utils/redirection-iframe.ts +85 -0
package/api/client.ts CHANGED
@@ -4,6 +4,7 @@ import settings from 'settings';
4
4
  import logger from '../utils/log';
5
5
  import formatCookieString from '../utils/format-cookie-string';
6
6
  import cookieParser from 'set-cookie-parser';
7
+ import { cookies } from 'next/headers';
7
8
 
8
9
  interface RouteParams {
9
10
  params: {
@@ -80,11 +81,27 @@ async function proxyRequest(...args) {
80
81
  }
81
82
  } as RequestInit;
82
83
 
84
+ const nextCookies = cookies();
85
+ const segment = nextCookies.get('pz-segment')?.value;
86
+ const currency = nextCookies.get('pz-external-currency')?.value;
87
+
88
+ if (segment) {
89
+ fetchOptions.headers['X-Segment-Id'] = segment;
90
+ }
91
+
92
+ if (currency) {
93
+ fetchOptions.headers = Object.assign({}, fetchOptions.headers, {
94
+ 'x-currency': currency
95
+ });
96
+ }
97
+
83
98
  if (options.contentType) {
84
99
  fetchOptions.headers['Content-Type'] = options.contentType;
85
100
  }
86
101
 
87
- const isMultipartFormData = req.headers.get('content-type')?.includes('multipart/form-data;');
102
+ const isMultipartFormData = req.headers
103
+ .get('content-type')
104
+ ?.includes('multipart/form-data;');
88
105
 
89
106
  if (req.method !== 'GET') {
90
107
  let body: Record<string, any> | FormData = {};
@@ -108,7 +125,11 @@ async function proxyRequest(...args) {
108
125
 
109
126
  Object.keys(body ?? {}).forEach((key) => {
110
127
  if (body[key]) {
111
- formData.append(key, body[key]);
128
+ if (typeof body[key] === 'object' && body[key] !== null) {
129
+ formData.append(key, JSON.stringify(body[key]));
130
+ } else {
131
+ formData.append(key, body[key]);
132
+ }
112
133
  }
113
134
  });
114
135
 
@@ -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"}
@@ -1,29 +1,53 @@
1
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;
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
- iframe {
12
- width: 100%;
13
- height: 100%;
14
- border: none;
15
- background-color: white;
16
- }
11
+ iframe {
12
+ width: 100%;
13
+ height: 100%;
14
+ border: none;
15
+ background-color: white;
16
+ }
17
17
 
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
- }
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
+ }
File without changes
File without changes
File without changes
package/bin/pz-postdev.js CHANGED
File without changes
File without changes
File without changes
File without changes
package/bin/pz-predev.js CHANGED
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ import { forwardRef } from 'react';
2
+ import { FileInputProps } from '../types/index';
3
+
4
+ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
5
+ function fileInput(props, ref) {
6
+ return <input type="file" {...props} ref={ref} />;
7
+ }
8
+ );
@@ -19,3 +19,4 @@ export * from './trans';
19
19
  export * from './link';
20
20
  export * from './pagination';
21
21
  export * from './live-commerce';
22
+ export * from './file-input';
@@ -1,17 +1,30 @@
1
1
  import clsx from 'clsx';
2
- import { forwardRef, FocusEvent, useState } from 'react';
2
+ import { forwardRef, FocusEvent, useState, Ref } from 'react';
3
3
  import { Controller } from 'react-hook-form';
4
- import NumberFormat, { NumberFormatProps } from 'react-number-format';
4
+
5
+ // @ts-ignore
6
+ import { PatternFormat, PatternFormatProps } from 'react-number-format';
5
7
  import { InputProps } from '../types';
6
8
  import { twMerge } from 'tailwind-merge';
7
9
 
10
+ const PatternFormatWithRef = forwardRef(
11
+ (props: PatternFormatProps, ref: Ref<HTMLInputElement>) => {
12
+ return <PatternFormat {...props} getInputRef={ref} />;
13
+ }
14
+ );
15
+ PatternFormatWithRef.displayName = 'PatternFormatWithRef';
16
+
8
17
  export const Input = forwardRef<
9
18
  HTMLInputElement,
10
19
  InputProps &
11
20
  Pick<
12
- NumberFormatProps,
13
- 'format' | 'mask' | 'allowEmptyFormatting' | 'onValueChange'
14
- >
21
+ PatternFormatProps,
22
+ 'mask' | 'allowEmptyFormatting' | 'onValueChange'
23
+ > & {
24
+ format?: string;
25
+ defaultValue?: string;
26
+ type?: string;
27
+ }
15
28
  >((props, ref) => {
16
29
  const [focused, setFocused] = useState(false);
17
30
  const [hasValue, setHasValue] = useState(false);
@@ -36,6 +49,7 @@ export const Input = forwardRef<
36
49
  ),
37
50
  props.className
38
51
  );
52
+
39
53
  const inputProps: any = {
40
54
  id,
41
55
  ref,
@@ -78,14 +92,14 @@ export const Input = forwardRef<
78
92
  <Controller
79
93
  name={props.name ?? ''}
80
94
  control={props.control}
81
- defaultValue={false}
82
95
  render={({ field }) => (
83
- <NumberFormat
96
+ <PatternFormatWithRef
84
97
  format={format}
85
98
  mask={mask ?? ''}
86
99
  {...rest}
87
100
  {...field}
88
101
  {...inputProps}
102
+ type={props.type as 'text' | 'password' | 'tel'}
89
103
  />
90
104
  )}
91
105
  />
@@ -10,28 +10,32 @@ type LinkProps = Omit<
10
10
  React.AnchorHTMLAttributes<HTMLAnchorElement>,
11
11
  keyof NextLinkProps
12
12
  > &
13
- NextLinkProps;
13
+ NextLinkProps & {
14
+ href: string;
15
+ };
14
16
 
15
17
  export const Link = ({ children, href, ...rest }: LinkProps) => {
16
18
  const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
17
19
  const formattedHref = useMemo(() => {
18
- if (typeof href !== 'string' || href.startsWith('http')) {
19
- return href;
20
+ if (!href) {
21
+ return '#';
20
22
  }
21
23
 
22
- const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
23
- const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
24
+ if (typeof href === 'string' && !href.startsWith('http')) {
25
+ const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
26
+ const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
24
27
 
25
- if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
26
- return hrefWithLocale;
27
- } else if (
28
- localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
29
- locale !== defaultLocaleValue
30
- ) {
31
- return hrefWithLocale;
28
+ if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
29
+ return hrefWithLocale;
30
+ } else if (
31
+ localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
32
+ locale !== defaultLocaleValue
33
+ ) {
34
+ return hrefWithLocale;
35
+ }
32
36
  }
33
37
 
34
- return href || '#';
38
+ return href;
35
39
  }, [href, defaultLocaleValue, locale, localeUrlStrategy]);
36
40
 
37
41
  return (
@@ -19,7 +19,8 @@ enum Plugin {
19
19
  Masterpass = 'pz-masterpass',
20
20
  B2B = 'pz-b2b',
21
21
  Akifast = 'pz-akifast',
22
- MultiBasket = 'pz-multi-basket'
22
+ MultiBasket = 'pz-multi-basket',
23
+ SavedCard = 'pz-saved-card'
23
24
  }
24
25
 
25
26
  export enum Component {
@@ -43,7 +44,8 @@ export enum Component {
43
44
  BasketB2B = 'BasketB2b',
44
45
  AkifastQuickLoginButton = 'QuickLoginButton',
45
46
  AkifastCheckoutButton = 'CheckoutButton',
46
- MultiBasket = 'MultiBasket'
47
+ MultiBasket = 'MultiBasket',
48
+ SavedCard = 'SavedCardOption'
47
49
  }
48
50
 
49
51
  const PluginComponents = new Map([
@@ -75,7 +77,8 @@ const PluginComponents = new Map([
75
77
  Plugin.Akifast,
76
78
  [Component.AkifastQuickLoginButton, Component.AkifastCheckoutButton]
77
79
  ],
78
- [Plugin.MultiBasket, [Component.MultiBasket]]
80
+ [Plugin.MultiBasket, [Component.MultiBasket]],
81
+ [Plugin.SavedCard, [Component.SavedCard]]
79
82
  ]);
80
83
 
81
84
  const getPlugin = (component: Component) => {
@@ -138,6 +141,8 @@ export default function PluginModule({
138
141
  promise = import(`${'@akinon/pz-akifast'}`);
139
142
  } else if (plugin === Plugin.MultiBasket) {
140
143
  promise = import(`${'@akinon/pz-multi-basket'}`);
144
+ } else if (plugin === Plugin.SavedCard) {
145
+ promise = import(`${'@akinon/pz-saved-card'}`);
141
146
  }
142
147
  } catch (error) {
143
148
  logger.error(error);
@@ -1,11 +1,14 @@
1
1
  import { useMemo } from 'react';
2
- import NumberFormat, { NumberFormatProps } from 'react-number-format';
2
+
3
+ // @ts-ignore
4
+ import { NumericFormat, NumericFormatProps } from 'react-number-format';
3
5
  import { getCurrency } from '@akinon/next/utils';
4
6
 
5
7
  import { useLocalization } from '@akinon/next/hooks';
6
8
  import { PriceProps } from '../types';
9
+ import Settings from 'settings';
7
10
 
8
- export const Price = (props: NumberFormatProps & PriceProps) => {
11
+ export const Price = (props: NumericFormatProps & PriceProps) => {
9
12
  const {
10
13
  value,
11
14
  currencyCode,
@@ -27,6 +30,10 @@ export const Price = (props: NumberFormatProps & PriceProps) => {
27
30
  // TODO: This is very bad practice. It broke decimalScale.
28
31
  const _value = value?.toString().replace('.', ',');
29
32
 
33
+ const currentCurrencyDecimalScale = Settings.localization.currencies.find(
34
+ (currency) => currency.code === currencyCode_
35
+ ).decimalScale;
36
+
30
37
  const currency = useMemo(
31
38
  () =>
32
39
  getCurrency({
@@ -39,14 +46,14 @@ export const Price = (props: NumberFormatProps & PriceProps) => {
39
46
  );
40
47
 
41
48
  return (
42
- <NumberFormat
49
+ <NumericFormat
43
50
  value={useNegative ? `-${useNegativeSpace}${_value}` : _value}
44
51
  {...{
45
52
  [useCurrencyAfterPrice ? 'suffix' : 'prefix']: currency
46
53
  }}
47
54
  displayType={displayType}
48
55
  thousandSeparator={thousandSeparator}
49
- decimalScale={decimalScale}
56
+ decimalScale={currentCurrencyDecimalScale ?? decimalScale}
50
57
  decimalSeparator={decimalSeparator}
51
58
  fixedDecimalScale={fixedDecimalScale}
52
59
  {...rest}
@@ -17,7 +17,8 @@ const paymentTypeToView = {
17
17
  loyalty_money: 'loyalty',
18
18
  masterpass: 'credit-card',
19
19
  pay_on_delivery: 'pay-on-delivery',
20
- redirection: 'redirection'
20
+ redirection: 'redirection',
21
+ saved_card: 'saved-card'
21
22
  // Add other mappings as needed
22
23
  };
23
24
 
@@ -21,6 +21,7 @@ interface GetOrdersParams {
21
21
  page?: number;
22
22
  createdDate?: string;
23
23
  endDate?: string;
24
+ shipping_option_slug?: string;
24
25
  }
25
26
 
26
27
  export interface GetQuotationsResponse {
@@ -114,9 +115,9 @@ const accountApi = api.injectEndpoints({
114
115
  query: (id) => buildClientRequestUrl(account.orderId(id))
115
116
  }),
116
117
  getOrders: builder.query<GetOrdersResponse, GetOrdersParams>({
117
- query: ({ page, limit, createdDate, endDate } = {}) =>
118
+ query: ({ page, limit, createdDate, endDate, shipping_option_slug } = {}) =>
118
119
  buildClientRequestUrl(
119
- account.getOrders({ page, limit, createdDate, endDate })
120
+ account.getOrders({ page, limit, createdDate, endDate, shipping_option_slug })
120
121
  )
121
122
  }),
122
123
  getQuotations: builder.query<GetQuotationsResponse, GetQuotationsParams>({
@@ -67,7 +67,7 @@ export const api = createApi({
67
67
  baseQuery: customBaseQuery,
68
68
  tagTypes: [
69
69
  'Basket',
70
- 'AllBaskets',
70
+ 'MultiBasket',
71
71
  'BasketB2b',
72
72
  'DraftsB2b',
73
73
  'Product',
@@ -12,7 +12,9 @@ import {
12
12
  SaveBasketParams,
13
13
  UpdateProductParams,
14
14
  DeleteProductParams,
15
- CreateQuotationParams
15
+ CreateQuotationParams,
16
+ BasketStatusResponse,
17
+ ExportBasketResponse
16
18
  } from '../../types';
17
19
 
18
20
  const b2bApi = api.injectEndpoints({
@@ -89,6 +91,34 @@ const b2bApi = api.injectEndpoints({
89
91
  }),
90
92
  invalidatesTags: ['BasketB2b', 'DraftsB2b']
91
93
  }),
94
+ exportBasket: build.mutation<ExportBasketResponse, string>({
95
+ query: (queryString) => {
96
+ return {
97
+ url: buildClientRequestUrl(b2b.basketExport(queryString)),
98
+ method: 'GET'
99
+ };
100
+ }
101
+ }),
102
+ getBasketStatus: build.mutation<BasketStatusResponse, string>({
103
+ query: (cacheKey) => {
104
+ return {
105
+ url: buildClientRequestUrl(b2b.statusBasket(cacheKey)),
106
+ method: 'GET'
107
+ };
108
+ }
109
+ }),
110
+ uploadFile: build.mutation<void, FormData>({
111
+ query: (body) => {
112
+ return {
113
+ url: buildClientRequestUrl(b2b.basketImport, {
114
+ useFormData: true
115
+ }),
116
+ method: 'POST',
117
+ body
118
+ };
119
+ },
120
+ invalidatesTags: ['BasketB2b']
121
+ })
92
122
  }),
93
123
  overrideExisting: true
94
124
  });
@@ -102,5 +132,8 @@ export const {
102
132
  useLoadBasketMutation,
103
133
  useUpdateProductMutation,
104
134
  useDeleteProductMutation,
105
- useCreateQuotationMutation
135
+ useCreateQuotationMutation,
136
+ useGetBasketStatusMutation,
137
+ useExportBasketMutation,
138
+ useUploadFileMutation
106
139
  } = b2bApi;
@@ -28,7 +28,7 @@ export const basketApi = api.injectEndpoints({
28
28
  query: ({ namespace }) =>
29
29
  buildClientRequestUrl(basket.getBasketDetail(namespace)),
30
30
  transformResponse: (response: { basket: Basket }) => response.basket,
31
- providesTags: ['AllBaskets']
31
+ providesTags: ['MultiBasket']
32
32
  }),
33
33
  getAllBaskets: build.query<Basket[], void>({
34
34
  query: () =>
@@ -36,7 +36,7 @@ export const basketApi = api.injectEndpoints({
36
36
  contentType: 'application/json'
37
37
  }),
38
38
  transformResponse: (response: { baskets: Basket[] }) => response.baskets,
39
- providesTags: ['AllBaskets']
39
+ providesTags: ['MultiBasket']
40
40
  }),
41
41
  removeBasket: build.mutation<Basket, { pk: number }>({
42
42
  query: ({ pk }) => ({
@@ -46,7 +46,7 @@ export const basketApi = api.injectEndpoints({
46
46
  method: 'DELETE',
47
47
  body: { pk }
48
48
  }),
49
- invalidatesTags: ['AllBaskets', 'Basket']
49
+ invalidatesTags: ['MultiBasket', 'Basket']
50
50
  }),
51
51
  selectMainBasket: build.mutation<Basket, { pk: number }>({
52
52
  query: ({ pk }) => ({
@@ -57,7 +57,7 @@ export const basketApi = api.injectEndpoints({
57
57
  body: { pk }
58
58
  }),
59
59
  transformResponse: (response: { baskets: Basket }) => response.baskets,
60
- invalidatesTags: ['AllBaskets', 'Basket']
60
+ invalidatesTags: ['MultiBasket', 'Basket']
61
61
  }),
62
62
  updateQuantity: build.mutation<
63
63
  UpdateQuantityResponse,
@@ -69,7 +69,8 @@ export const basketApi = api.injectEndpoints({
69
69
  }),
70
70
  method: 'PUT',
71
71
  body
72
- })
72
+ }),
73
+ invalidatesTags: ['MultiBasket', 'Basket']
73
74
  }),
74
75
  clearBasket: build.mutation<Basket, void>({
75
76
  query: (body) => ({
@@ -57,6 +57,7 @@ export interface CompleteCreditCardParams {
57
57
  card_month: string;
58
58
  card_year: string;
59
59
  use_three_d?: boolean;
60
+ save?: boolean;
60
61
  }
61
62
 
62
63
  interface GetContractResponse {
@@ -228,7 +229,8 @@ export const checkoutApi = api.injectEndpoints({
228
229
  card_number,
229
230
  card_month,
230
231
  card_year,
231
- use_three_d = true
232
+ use_three_d = true,
233
+ save = undefined
232
234
  }) => {
233
235
  const paymentOption =
234
236
  store.getState().checkout?.preOrder?.payment_option;
@@ -242,20 +244,26 @@ export const checkoutApi = api.injectEndpoints({
242
244
  };
243
245
  }
244
246
 
247
+ const body: Record<string, string> = {
248
+ agreement: '1',
249
+ use_three_d: use_three_d ? '1' : '0',
250
+ card_cvv,
251
+ card_holder,
252
+ card_month,
253
+ card_number,
254
+ card_year
255
+ };
256
+
257
+ if (save !== undefined) {
258
+ body.save = save ? '1' : '0';
259
+ }
260
+
245
261
  return {
246
262
  url: buildClientRequestUrl(checkout.completeCreditCardPayment, {
247
263
  useFormData: true
248
264
  }),
249
265
  method: 'POST',
250
- body: {
251
- agreement: '1',
252
- use_three_d: use_three_d ? '1' : '0',
253
- card_cvv,
254
- card_holder,
255
- card_month,
256
- card_number,
257
- card_year
258
- }
266
+ body
259
267
  };
260
268
  },
261
269
  async onQueryStarted(args, { dispatch, queryFulfilled }) {
@@ -380,6 +388,22 @@ export const checkoutApi = api.injectEndpoints({
380
388
  dispatch(setShippingStepBusy(false));
381
389
  }
382
390
  }),
391
+ setDataSourceShippingOptions: build.mutation<CheckoutResponse, number[]>({
392
+ query: (pks) => ({
393
+ url: buildClientRequestUrl(checkout.setDataSourceShippingOption, {
394
+ useFormData: true
395
+ }),
396
+ method: 'POST',
397
+ body: {
398
+ data_source_shipping_options: JSON.stringify(pks)
399
+ }
400
+ }),
401
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
402
+ dispatch(setShippingStepBusy(true));
403
+ await queryFulfilled;
404
+ dispatch(setShippingStepBusy(false));
405
+ }
406
+ }),
383
407
  setRetailStore: build.mutation<CheckoutResponse, SetRetailStoreParams>({
384
408
  query: ({ retailStorePk, billingAddressPk }) => ({
385
409
  url: buildClientRequestUrl(
@@ -681,6 +705,25 @@ export const checkoutApi = api.injectEndpoints({
681
705
  };
682
706
  }
683
707
  }),
708
+ setAttributeBasedShippingOptions: build.mutation<
709
+ CheckoutResponse,
710
+ Record<string, number>
711
+ >({
712
+ query: (options) => ({
713
+ url: buildClientRequestUrl(checkout.setAttributeBasedShippingOption, {
714
+ useFormData: true
715
+ }),
716
+ method: 'POST',
717
+ body: {
718
+ attribute_based_shipping_options: JSON.stringify(options)
719
+ }
720
+ }),
721
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
722
+ dispatch(setShippingStepBusy(true));
723
+ await queryFulfilled;
724
+ dispatch(setShippingStepBusy(false));
725
+ }
726
+ }),
684
727
  setOrderSelectionPage: build.mutation<
685
728
  CheckoutResponse,
686
729
  { extra_field: ExtraField }
@@ -712,6 +755,7 @@ export const {
712
755
  useSetDeliveryOptionMutation,
713
756
  useSetAddressesMutation,
714
757
  useSetShippingOptionMutation,
758
+ useSetDataSourceShippingOptionsMutation,
715
759
  useSetPaymentOptionMutation,
716
760
  useSetBinNumberMutation,
717
761
  useSetInstallmentOptionMutation,
@@ -730,5 +774,6 @@ export const {
730
774
  usePayWithLoyaltyBalanceMutation,
731
775
  useSetOrderNoteMutation,
732
776
  useSetDeliveryBagsMutation,
777
+ useSetAttributeBasedShippingOptionsMutation,
733
778
  useSetOrderSelectionPageMutation
734
779
  } = checkoutApi;