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

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,11 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 2.0.0-beta.2
4
+
5
+ ### Minor Changes
6
+
7
+ - dd69cc6: ZERO-3079: Modularize pre-order middleware
8
+
3
9
  ## 2.0.0-beta.1
4
10
 
5
11
  ### 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
 
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.2",
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.2",
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
+ }
@@ -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
+ };