@akinon/next 2.0.0-beta.1 → 2.0.0-beta.3

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 2.0.0-beta.3
4
+
5
+ ### Minor Changes
6
+
7
+ - 5536b80: ZERO-3104: Add optional headers parameter
8
+
9
+ ## 2.0.0-beta.2
10
+
11
+ ### Minor Changes
12
+
13
+ - a006015: ZERO-3116: Add not-found page and update default middleware.
14
+ - 999168d: ZERO-3104: Remove local cache handler from CacheHandler initialization
15
+ - 1eeb3d8: ZERO-3116: Add not found page
16
+ - 86a5a62: ZERO-3104: Add optional headers parameter to data fetching functions
17
+ - dd69cc6: ZERO-3079: Modularize pre-order middleware
18
+
3
19
  ## 2.0.0-beta.1
4
20
 
5
21
  ### Minor Changes
@@ -4,7 +4,7 @@ import { RootState } from 'redux/store';
4
4
  import { useAppSelector } from '../redux/hooks';
5
5
  import dynamic, { DynamicOptionsLoadingProps } from 'next/dynamic';
6
6
  import { PaymentOptionViews } from 'views/checkout/steps/payment';
7
- import { useMemo } from 'react';
7
+ import { JSX, useMemo } from 'react';
8
8
 
9
9
  const fallbackView = () => <></>;
10
10
 
@@ -7,7 +7,8 @@ import { ServerVariables } from '../../utils/server-variables';
7
7
  const getFlatPageDataHandler = (
8
8
  pk: number,
9
9
  locale: string,
10
- currency: string
10
+ currency: string,
11
+ headers?: Record<string, string>
11
12
  ) => {
12
13
  return async function () {
13
14
  const data = await appFetch<FlatPage>({
@@ -17,7 +18,8 @@ const getFlatPageDataHandler = (
17
18
  init: {
18
19
  headers: {
19
20
  Accept: 'application/json',
20
- 'Content-Type': 'application/json'
21
+ 'Content-Type': 'application/json',
22
+ ...(headers ?? {})
21
23
  }
22
24
  }
23
25
  });
@@ -29,15 +31,17 @@ const getFlatPageDataHandler = (
29
31
  export const getFlatPageData = ({
30
32
  pk,
31
33
  locale = ServerVariables.locale,
32
- currency = ServerVariables.currency
34
+ currency = ServerVariables.currency,
35
+ headers
33
36
  }: {
34
37
  pk: number;
35
38
  locale?: string;
36
39
  currency?: string;
40
+ headers?: Record<string, string>;
37
41
  }) => {
38
42
  return Cache.wrap(
39
43
  CacheKey.FlatPage(pk),
40
44
  locale,
41
- getFlatPageDataHandler(pk, locale, currency)
45
+ getFlatPageDataHandler(pk, locale, currency, headers)
42
46
  );
43
47
  };
@@ -5,7 +5,12 @@ import appFetch from '../../utils/app-fetch';
5
5
  import { ServerVariables } from '../../utils/server-variables';
6
6
  import { form } from '../urls';
7
7
 
8
- const getFormDataHandler = (pk: number, locale: string, currency: string) => {
8
+ const getFormDataHandler = (
9
+ pk: number,
10
+ locale: string,
11
+ currency: string,
12
+ headers?: Record<string, string>
13
+ ) => {
9
14
  return async function () {
10
15
  const data = await appFetch<FormType>({
11
16
  url: form.getForm(pk),
@@ -14,7 +19,8 @@ const getFormDataHandler = (pk: number, locale: string, currency: string) => {
14
19
  init: {
15
20
  headers: {
16
21
  Accept: 'application/json',
17
- 'Content-Type': 'application/json'
22
+ 'Content-Type': 'application/json',
23
+ ...(headers ?? {})
18
24
  }
19
25
  }
20
26
  });
@@ -26,15 +32,17 @@ const getFormDataHandler = (pk: number, locale: string, currency: string) => {
26
32
  export const getFormData = ({
27
33
  pk,
28
34
  locale = ServerVariables.locale,
29
- currency = ServerVariables.currency
35
+ currency = ServerVariables.currency,
36
+ headers
30
37
  }: {
31
38
  pk: number;
32
39
  locale?: string;
33
40
  currency?: string;
41
+ headers?: Record<string, string>;
34
42
  }) => {
35
43
  return Cache.wrap(
36
44
  CacheKey.Form(pk),
37
45
  locale,
38
- getFormDataHandler(pk, locale, currency)
46
+ getFormDataHandler(pk, locale, currency, headers)
39
47
  );
40
48
  };
@@ -7,7 +7,8 @@ import { ServerVariables } from '../../utils/server-variables';
7
7
  const getLandingPageHandler = (
8
8
  pk: number,
9
9
  locale: string,
10
- currency: string
10
+ currency: string,
11
+ headers?: Record<string, string>
11
12
  ) => {
12
13
  return async function () {
13
14
  const data = await appFetch<LandingPage>({
@@ -17,7 +18,8 @@ const getLandingPageHandler = (
17
18
  init: {
18
19
  headers: {
19
20
  Accept: 'application/json',
20
- 'Content-Type': 'application/json'
21
+ 'Content-Type': 'application/json',
22
+ ...(headers ?? {})
21
23
  }
22
24
  }
23
25
  });
@@ -29,15 +31,17 @@ const getLandingPageHandler = (
29
31
  export const getLandingPageData = ({
30
32
  pk,
31
33
  locale = ServerVariables.locale,
32
- currency = ServerVariables.currency
34
+ currency = ServerVariables.currency,
35
+ headers
33
36
  }: {
34
37
  pk: number;
35
38
  locale?: string;
36
39
  currency?: string;
40
+ headers?: Record<string, string>;
37
41
  }) => {
38
42
  return Cache.wrap(
39
43
  CacheKey.LandingPage(pk),
40
44
  locale,
41
- getLandingPageHandler(pk, locale, currency)
45
+ getLandingPageHandler(pk, locale, currency, headers)
42
46
  );
43
47
  };
@@ -13,6 +13,7 @@ interface MenuHandlerParams {
13
13
  currency?: string;
14
14
  depth?: number;
15
15
  parent?: string;
16
+ headers?: Record<string, string>;
16
17
  }
17
18
 
18
19
  const DEFAULT_DEPTH = 3;
@@ -22,13 +23,17 @@ const getMenuHandler =
22
23
  locale = ServerVariables.locale,
23
24
  currency = ServerVariables.currency,
24
25
  depth,
25
- parent
26
+ parent,
27
+ headers
26
28
  }: MenuHandlerParams = {}) =>
27
29
  async () => {
28
30
  const response = await appFetch<MenuResponse>({
29
31
  url: misc.menus(depth ?? DEFAULT_DEPTH, parent),
30
32
  locale,
31
- currency
33
+ currency,
34
+ init: {
35
+ headers
36
+ }
32
37
  });
33
38
 
34
39
  return response?.menu;
@@ -11,6 +11,7 @@ type GetProduct = {
11
11
  currency?: string;
12
12
  searchParams?: URLSearchParams;
13
13
  groupProduct?: boolean;
14
+ headers?: Record<string, string>;
14
15
  };
15
16
 
16
17
  const getProductDataHandler = ({
@@ -18,7 +19,8 @@ const getProductDataHandler = ({
18
19
  locale,
19
20
  currency,
20
21
  searchParams,
21
- groupProduct
22
+ groupProduct,
23
+ headers
22
24
  }: GetProduct) => {
23
25
  return async function () {
24
26
  let url = groupProduct
@@ -40,7 +42,8 @@ const getProductDataHandler = ({
40
42
  init: {
41
43
  headers: {
42
44
  Accept: 'application/json',
43
- 'Content-Type': 'application/json'
45
+ 'Content-Type': 'application/json',
46
+ ...(headers ?? {})
44
47
  }
45
48
  }
46
49
  });
@@ -95,7 +98,8 @@ export const getProductData = async ({
95
98
  locale = ServerVariables.locale,
96
99
  currency = ServerVariables.currency,
97
100
  searchParams,
98
- groupProduct
101
+ groupProduct,
102
+ headers
99
103
  }: GetProduct) => {
100
104
  return Cache.wrap(
101
105
  CacheKey[groupProduct ? 'GroupProduct' : 'Product'](
@@ -103,7 +107,14 @@ export const getProductData = async ({
103
107
  searchParams ?? new URLSearchParams()
104
108
  ),
105
109
  locale,
106
- getProductDataHandler({ pk, locale, currency, searchParams, groupProduct }),
110
+ getProductDataHandler({
111
+ pk,
112
+ locale,
113
+ currency,
114
+ searchParams,
115
+ groupProduct,
116
+ headers
117
+ }),
107
118
  {
108
119
  expire: 300
109
120
  }
@@ -7,9 +7,10 @@ interface SeoDataParams {
7
7
  url: string;
8
8
  locale?: string;
9
9
  currency?: string;
10
+ headers?: Record<string, string>;
10
11
  }
11
12
 
12
- function getSeoDataHandler({ url, locale, currency }: SeoDataParams) {
13
+ function getSeoDataHandler({ url, locale, currency, headers }: SeoDataParams) {
13
14
  return async function () {
14
15
  let data = {} as {
15
16
  title: string;
@@ -19,7 +20,12 @@ function getSeoDataHandler({ url, locale, currency }: SeoDataParams) {
19
20
  };
20
21
 
21
22
  try {
22
- data = await appFetch({ url: misc.cmsSeo(url), locale, currency });
23
+ data = await appFetch({
24
+ url: misc.cmsSeo(url),
25
+ locale,
26
+ currency,
27
+ init: { headers }
28
+ });
23
29
  } catch (error) {
24
30
  // logger.error('Error while fetching seo data', { url, error });
25
31
  }
@@ -31,11 +37,12 @@ function getSeoDataHandler({ url, locale, currency }: SeoDataParams) {
31
37
  export const getSeoData = async (
32
38
  url,
33
39
  locale = ServerVariables.locale,
34
- currency = ServerVariables.currency
40
+ currency = ServerVariables.currency,
41
+ headers?: Record<string, string>
35
42
  ) => {
36
43
  return Cache.wrap(
37
44
  CacheKey.Seo(url),
38
45
  locale,
39
- getSeoDataHandler({ url, locale, currency })
46
+ getSeoDataHandler({ url, locale, currency, headers })
40
47
  );
41
48
  };
@@ -6,29 +6,44 @@ import { widgets } from '../urls';
6
6
  import { ServerVariables } from '../../utils/server-variables';
7
7
 
8
8
  const getWidgetDataHandler =
9
- (slug: string, locale: string, currency: string) => async () => {
9
+ (
10
+ slug: string,
11
+ locale: string,
12
+ currency: string,
13
+ headers?: Record<string, string>
14
+ ) =>
15
+ async () => {
10
16
  if (!slug) {
11
17
  return null;
12
18
  }
13
19
 
14
- return await appFetch({ url: widgets.getWidget(slug), locale, currency });
20
+ return await appFetch({
21
+ url: widgets.getWidget(slug),
22
+ locale,
23
+ currency,
24
+ init: {
25
+ headers
26
+ }
27
+ });
15
28
  };
16
29
 
17
30
  export const getWidgetData = async <T>({
18
31
  slug,
19
32
  locale = ServerVariables.locale,
20
33
  currency = ServerVariables.currency,
21
- cacheOptions
34
+ cacheOptions,
35
+ headers
22
36
  }: {
23
37
  slug: string;
24
38
  locale?: string;
25
39
  currency?: string;
26
40
  cacheOptions?: CacheOptions;
41
+ headers?: Record<string, string>;
27
42
  }): Promise<WidgetResultType<T>> => {
28
43
  return Cache.wrap(
29
44
  CacheKey.Widget(slug),
30
45
  locale,
31
- getWidgetDataHandler(slug, locale, currency),
46
+ getWidgetDataHandler(slug, locale, currency, headers),
32
47
  cacheOptions
33
48
  );
34
49
  };
@@ -23,10 +23,10 @@ CacheHandler.onCreation(async () => {
23
23
  timeoutMs: 5000
24
24
  });
25
25
 
26
- const localHandler = createLruHandler();
26
+ // const localHandler = createLruHandler();
27
27
 
28
28
  return {
29
- handlers: [redisHandler, localHandler]
29
+ handlers: [redisHandler]
30
30
  };
31
31
  });
32
32
 
@@ -288,19 +288,6 @@ const withPzDefault =
288
288
  `searchparams|${url.searchParams.toString()}`;
289
289
  }
290
290
 
291
- if (
292
- !req.middlewareParams.found &&
293
- Settings.customNotFoundEnabled
294
- ) {
295
- let pathname = url.pathname
296
- .replace(/\/+$/, '')
297
- .split('/');
298
- url.pathname = url.pathname.replace(
299
- pathname.pop(),
300
- 'pz-not-found'
301
- );
302
- }
303
-
304
291
  Settings.rewrites.forEach((rewrite) => {
305
292
  url.pathname = url.pathname.replace(
306
293
  rewrite.source,
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": "2.0.0-beta.1",
4
+ "version": "2.0.0-beta.3",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "set-cookie-parser": "2.6.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@akinon/eslint-plugin-projectzero": "2.0.0-beta.1",
33
+ "@akinon/eslint-plugin-projectzero": "2.0.0-beta.3",
34
34
  "@types/react-redux": "7.1.30",
35
35
  "@types/set-cookie-parser": "2.4.7",
36
36
  "@typescript-eslint/eslint-plugin": "8.18.2",
@@ -6,10 +6,12 @@ import type { Middleware } from '@reduxjs/toolkit';
6
6
  import {
7
7
  errorMiddleware,
8
8
  contextListMiddleware,
9
- preOrderMiddleware,
10
9
  hepsiPayMiddleware,
11
10
  walletPaymentMiddleware
12
11
  } from './checkout';
12
+
13
+ import { preOrderMiddlewares } from './pre-order';
14
+
13
15
  import { api } from '../../data/client/api';
14
16
  import logger from '@akinon/next/utils/log';
15
17
 
@@ -48,7 +50,7 @@ const middlewares = [
48
50
  rtkQueryResponseHandler,
49
51
  rtkQueryErrorHandler,
50
52
  errorMiddleware,
51
- preOrderMiddleware,
53
+ ...preOrderMiddlewares,
52
54
  contextListMiddleware,
53
55
  hepsiPayMiddleware,
54
56
  walletPaymentMiddleware,
@@ -0,0 +1,45 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+ import { setPreOrder } from '../../../redux/reducers/checkout';
5
+
6
+ export const setAddressMiddleware: Middleware = ({
7
+ getState,
8
+ dispatch
9
+ }: MiddlewareParams) => {
10
+ return (next) => (action) => {
11
+ const result: CheckoutResult = next(action);
12
+ const preOrder = result?.payload?.pre_order;
13
+
14
+ if (!preOrder) {
15
+ return result;
16
+ }
17
+
18
+ const { addressList: addresses } = getState().checkout;
19
+ const { endpoints: apiEndpoints } = checkoutApi;
20
+
21
+ const hasNoAddresses =
22
+ !preOrder?.shipping_address || !preOrder?.billing_address;
23
+ const isCustomerDelivery =
24
+ !preOrder?.delivery_option ||
25
+ preOrder.delivery_option.delivery_option_type === 'customer';
26
+
27
+ const firstAddressPk = addresses?.[0]?.pk;
28
+
29
+ if (
30
+ hasNoAddresses &&
31
+ addresses?.length > 0 &&
32
+ isCustomerDelivery &&
33
+ firstAddressPk
34
+ ) {
35
+ dispatch(
36
+ apiEndpoints.setAddresses.initiate({
37
+ shippingAddressPk: firstAddressPk,
38
+ billingAddressPk: firstAddressPk
39
+ })
40
+ );
41
+ }
42
+
43
+ return result;
44
+ };
45
+ };
@@ -0,0 +1,40 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const attributeBasedShippingOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { attributeBasedShippingOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ if (
21
+ Object.keys(attributeBasedShippingOptions).length > 0 &&
22
+ !preOrder.attribute_based_shipping_options
23
+ ) {
24
+ const initialSelectedOptions: Record<string, number> = Object.fromEntries(
25
+ Object.entries(attributeBasedShippingOptions).map(([key, options]) => [
26
+ key,
27
+ options.attribute_based_shipping_options[0].pk
28
+ ])
29
+ );
30
+
31
+ dispatch(
32
+ apiEndpoints.setAttributeBasedShippingOptions.initiate(
33
+ initialSelectedOptions
34
+ )
35
+ );
36
+ }
37
+
38
+ return result;
39
+ };
40
+ };
@@ -0,0 +1,37 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const dataSourceShippingOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { dataSourceShippingOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ if (
21
+ dataSourceShippingOptions?.length > 0 &&
22
+ !preOrder?.data_source_shipping_options
23
+ ) {
24
+ const selectedPks = dataSourceShippingOptions
25
+ .map((opt) => opt.data_source_shipping_options?.[0]?.pk)
26
+ .filter((pk) => pk);
27
+
28
+ if (selectedPks.length > 0) {
29
+ dispatch(
30
+ apiEndpoints.setDataSourceShippingOptions.initiate(selectedPks)
31
+ );
32
+ }
33
+ }
34
+
35
+ return result;
36
+ };
37
+ };
@@ -0,0 +1,34 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const deliveryOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { deliveryOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ if (!preOrder?.delivery_option && deliveryOptions?.length > 0) {
21
+ const customerDeliveryOption = deliveryOptions.find(
22
+ (opt) => opt.delivery_option_type === 'customer'
23
+ )?.pk;
24
+
25
+ if (customerDeliveryOption) {
26
+ dispatch(
27
+ apiEndpoints.setDeliveryOption.initiate(customerDeliveryOption)
28
+ );
29
+ }
30
+ }
31
+
32
+ return result;
33
+ };
34
+ };
@@ -0,0 +1,25 @@
1
+ import { preOrderValidationMiddleware } from './pre-order-validation';
2
+ import { redirectionMiddleware } from './redirection';
3
+ import { setPreOrderMiddleware } from './set-pre-order';
4
+ import { deliveryOptionMiddleware } from './delivery-option';
5
+ import { setAddressMiddleware } from './address';
6
+ import { shippingOptionMiddleware } from './shipping-option';
7
+ import { dataSourceShippingOptionMiddleware } from './data-source-shipping-option';
8
+ import { attributeBasedShippingOptionMiddleware } from './attribute-based-shipping-option';
9
+ import { paymentOptionMiddleware } from './payment-option';
10
+ import { installmentOptionMiddleware } from './installment-option';
11
+ import { shippingStepMiddleware } from './shipping-step';
12
+
13
+ export const preOrderMiddlewares = [
14
+ preOrderValidationMiddleware,
15
+ redirectionMiddleware,
16
+ setPreOrderMiddleware,
17
+ deliveryOptionMiddleware,
18
+ setAddressMiddleware,
19
+ shippingOptionMiddleware,
20
+ dataSourceShippingOptionMiddleware,
21
+ attributeBasedShippingOptionMiddleware,
22
+ paymentOptionMiddleware,
23
+ installmentOptionMiddleware,
24
+ shippingStepMiddleware
25
+ ];
@@ -0,0 +1,36 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const installmentOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { installmentOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ if (
21
+ !preOrder?.installment &&
22
+ preOrder?.payment_option?.payment_type !== 'saved_card' &&
23
+ installmentOptions.length > 0
24
+ ) {
25
+ const firstInstallmentOptionPk = installmentOptions[0]?.pk;
26
+
27
+ if (firstInstallmentOptionPk) {
28
+ dispatch(
29
+ apiEndpoints.setInstallmentOption.initiate(firstInstallmentOptionPk)
30
+ );
31
+ }
32
+ }
33
+
34
+ return result;
35
+ };
36
+ };
@@ -0,0 +1,28 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const paymentOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { paymentOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ if (!preOrder?.payment_option && paymentOptions.length > 0) {
21
+ const firstPaymentOptionPk = paymentOptions[0]?.pk;
22
+
23
+ dispatch(apiEndpoints.setPaymentOption.initiate(firstPaymentOptionPk));
24
+ }
25
+
26
+ return result;
27
+ };
28
+ };
@@ -0,0 +1,20 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult } from '../../../types';
3
+
4
+ export const preOrderValidationMiddleware: Middleware = () => {
5
+ return (next) => (action) => {
6
+ const result: CheckoutResult = next(action);
7
+ const preOrder = result?.payload?.pre_order;
8
+
9
+ if (
10
+ !preOrder ||
11
+ ['guestLogin', 'getCheckoutLoyaltyBalance'].includes(
12
+ action?.meta?.arg?.endpointName
13
+ )
14
+ ) {
15
+ return result;
16
+ }
17
+
18
+ return result;
19
+ };
20
+ };
@@ -0,0 +1,34 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const redirectionMiddleware: Middleware = ({
6
+ dispatch
7
+ }: MiddlewareParams) => {
8
+ return (next) => (action) => {
9
+ const result = next(action);
10
+ const preOrder = result?.payload?.pre_order;
11
+
12
+ if (!preOrder) {
13
+ return result;
14
+ }
15
+
16
+ if (preOrder?.is_redirected) {
17
+ const contextList = result?.payload?.context_list;
18
+
19
+ if (
20
+ contextList?.find(
21
+ (ctx) => ctx.page_name === 'RedirectionPaymentSelectedPage'
22
+ )
23
+ ) {
24
+ dispatch(
25
+ checkoutApi.endpoints.setPaymentOption.initiate(
26
+ preOrder.payment_option?.pk
27
+ )
28
+ );
29
+ }
30
+ }
31
+
32
+ return result;
33
+ };
34
+ };
@@ -0,0 +1,18 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { MiddlewareParams } from '../../../types';
3
+ import { setPreOrder } from '../../../redux/reducers/checkout';
4
+
5
+ export const setPreOrderMiddleware: Middleware = ({
6
+ dispatch
7
+ }: MiddlewareParams) => {
8
+ return (next) => (action) => {
9
+ const result = next(action);
10
+ const preOrder = result?.payload?.pre_order;
11
+
12
+ if (preOrder) {
13
+ dispatch(setPreOrder(preOrder));
14
+ }
15
+
16
+ return result;
17
+ };
18
+ };
@@ -0,0 +1,38 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { checkoutApi } from '../../../data/client/checkout';
4
+
5
+ export const shippingOptionMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { shippingOptions } = getState().checkout;
18
+ const { endpoints: apiEndpoints } = checkoutApi;
19
+
20
+ const hasShippingOptions = shippingOptions?.length > 0;
21
+
22
+ const isShippingOptionValid = preOrder?.shipping_option
23
+ ? shippingOptions.some((opt) => opt.pk === preOrder.shipping_option.pk)
24
+ : false;
25
+
26
+ if (hasShippingOptions && !isShippingOptionValid) {
27
+ const defaultShippingOption = shippingOptions[0]?.pk;
28
+
29
+ if (defaultShippingOption) {
30
+ dispatch(
31
+ apiEndpoints.setShippingOption.initiate(defaultShippingOption)
32
+ );
33
+ }
34
+ }
35
+
36
+ return result;
37
+ };
38
+ };
@@ -0,0 +1,34 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+ import { CheckoutResult, MiddlewareParams } from '../../../types';
3
+ import { setShippingStepCompleted } from '../../reducers/checkout';
4
+
5
+ export const shippingStepMiddleware: Middleware = ({
6
+ getState,
7
+ dispatch
8
+ }: MiddlewareParams) => {
9
+ return (next) => (action) => {
10
+ const result: CheckoutResult = next(action);
11
+ const preOrder = result?.payload?.pre_order;
12
+
13
+ if (!preOrder) {
14
+ return result;
15
+ }
16
+
17
+ const { addressList: addresses } = getState().checkout;
18
+
19
+ if (preOrder) {
20
+ const stepCompleted = [
21
+ preOrder.delivery_option?.delivery_option_type === 'retail_store'
22
+ ? true
23
+ : preOrder.shipping_address?.pk,
24
+ preOrder.billing_address?.pk,
25
+ preOrder.shipping_option?.pk,
26
+ addresses.length > 0
27
+ ].every(Boolean);
28
+
29
+ dispatch(setShippingStepCompleted(stepCompleted));
30
+ }
31
+
32
+ return result;
33
+ };
34
+ };
@@ -4,6 +4,7 @@ import { RetailStore } from './misc';
4
4
  import { PaymentOption } from './order';
5
5
  import { Product } from './product';
6
6
  import { JSX } from 'react';
7
+ import { RootState, TypedDispatch } from 'redux/store';
7
8
 
8
9
  export enum CheckoutStep {
9
10
  Shipping = 'shipping',
@@ -186,3 +187,16 @@ export interface AttributeBasedShippingOption {
186
187
  attribute_key: string;
187
188
  [key: string]: any;
188
189
  }
190
+
191
+ export interface CheckoutResult {
192
+ payload: {
193
+ errors?: Record<string, string[]>;
194
+ pre_order?: PreOrder;
195
+ context_list?: CheckoutContext[];
196
+ };
197
+ }
198
+
199
+ export interface MiddlewareParams {
200
+ getState: () => RootState;
201
+ dispatch: TypedDispatch;
202
+ }
package/types/index.ts CHANGED
@@ -199,7 +199,6 @@ export interface Settings {
199
199
  extraPaymentTypes?: string[];
200
200
  masterpassJsUrl?: string;
201
201
  };
202
- customNotFoundEnabled: boolean;
203
202
  useOptimizedTranslations?: boolean;
204
203
  plugins?: Record<string, Record<string, any>>;
205
204
  includedProxyHeaders?: string[];
@@ -0,0 +1,31 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+
3
+ export enum MiddlewareNames {
4
+ PreOrderValidationMiddleware = 'preOrderValidationMiddleware',
5
+ RedirectionMiddleware = 'redirectionMiddleware',
6
+ SetPreOrderMiddleware = 'setPreOrderMiddleware',
7
+ DeliveryOptionMiddleware = 'deliveryOptionMiddleware',
8
+ SetAddressMiddleware = 'setAddressMiddleware',
9
+ ShippingOptionMiddleware = 'shippingOptionMiddleware',
10
+ DataSourceShippingOptionMiddleware = 'dataSourceShippingOptionMiddleware',
11
+ AttributeBasedShippingOptionMiddleware = 'attributeBasedShippingOptionMiddleware',
12
+ PaymentOptionMiddleware = 'paymentOptionMiddleware',
13
+ InstallmentOptionMiddleware = 'installmentOptionMiddleware',
14
+ ShippingStepMiddleware = 'shippingStepMiddleware'
15
+ }
16
+
17
+ export const overrideMiddleware = (
18
+ middlewares: Middleware[],
19
+ updates: { name: MiddlewareNames; middleware: Middleware }[]
20
+ ): void => {
21
+ const updatesMap = new Map(
22
+ updates.map(({ name, middleware }) => [name, middleware])
23
+ );
24
+
25
+ middlewares.forEach((mw, index) => {
26
+ const updatedMiddleware = updatesMap.get(mw.name as MiddlewareNames);
27
+ if (updatedMiddleware) {
28
+ middlewares[index] = updatedMiddleware;
29
+ }
30
+ });
31
+ };