@akinon/next 1.89.0-rc.2 → 1.89.0-rc.21

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,169 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 1.89.0-rc.21
4
+
5
+ ### Minor Changes
6
+
7
+ - e974d8e: ZERO-3406: Fix rc build
8
+
9
+ ## 1.89.0-rc.20
10
+
11
+ ### Minor Changes
12
+
13
+ - e68e120: ZERO-3398: Add redirectUrlMiddleware to handle redirection based on checkout results
14
+
15
+ ## 1.89.0-rc.19
16
+
17
+ ### Minor Changes
18
+
19
+ - 823d82f: ZERO-3393: Enhance error handling in checkout middleware to ensure errors are checked for existence before processing
20
+
21
+ ## 1.89.0-rc.18
22
+
23
+ ## 1.89.0-rc.17
24
+
25
+ ### Minor Changes
26
+
27
+ - 9b7d0de: ZERO-3393: Improve error handling in checkout middleware to support both object and array error formats
28
+
29
+ ## 1.89.0-rc.16
30
+
31
+ ### Minor Changes
32
+
33
+ - 68bbcb2: ZERO-3393: Fix error handling in checkout middleware to check for errors array length
34
+
35
+ ## 1.89.0-rc.15
36
+
37
+ ## 1.89.0-rc.14
38
+
39
+ ## 1.89.0-rc.13
40
+
41
+ ## 1.89.0-rc.12
42
+
43
+ ## 1.89.0-rc.11
44
+
45
+ ## 1.89.0-rc.10
46
+
47
+ ### Minor Changes
48
+
49
+ - 5dfeea04: ZERO-2801: Revert ZERO-2801
50
+ - 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
51
+ - 2d9b2b2c: ZERO-2816: Add segment to headers
52
+ - 5e1feca6: Revert "ZERO-3286: Add notFound handling for chunk URLs starting with \_next"
53
+ - d8fad39: ZERO-3370: include plugins test to build stage
54
+ - 40a46853: ZERO-3182: Optimize basket update mutation with optimistic update
55
+ - f49bb74f: ZERO-3097: Add setCookie to logging in payment redirection middlewares
56
+ - e9541a13: ZERO-2816: Add headers to url
57
+ - 72fd4d67: ZERO-3084: Fix URL search parameters encoding in default middleware
58
+ - c53ef7b9: 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.
59
+ - 64699d3f: ZERO-2761: Fix invalid import for plugin module
60
+ - bf354de: ZERO-3321: add babel compiler for akinon/next test
61
+ - 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
62
+ - d552629f: ZERO-3182: Refactor basketApi to use invalidatesTags and comment out onQueryStarted logic
63
+ - 448adef: ZERO-3321: move csp test to akinon-next
64
+ - 17f87524: ZERO-2816: Make the incoming currency lowercase
65
+ - 65d3b862: ZERO-3054: Update headers in appFetch
66
+ - bbe18b9f: ZERO-2575: Fix build error
67
+ - 17bfadc4: ZERO-3275: Disable OpenTelemetry monitoring in production environment
68
+ - 4920742c: Disable getCachedTranslations
69
+ - b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
70
+ - 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
71
+ - 7e56d6b6: ZERO-2841: Update api tagTypes
72
+ - dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
73
+ - 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
74
+ - 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
75
+ - 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
76
+ - eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
77
+ - 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
78
+ - 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
79
+ - f2c92d5c: ZERO-2816: Update cookie name
80
+ - 7bd3d992: ZERO-2801: Refactor locale middleware to handle single locale configuration
81
+ - fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
82
+ - acf0320: ZERO-3321: remove babel config
83
+ - 387356b: ZERO-3323: Refactor locale filtering logic in URL matcher regex
84
+ - 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
85
+ - 3f9b8d7e: ZERO-2761: Update plugins.js for akinon-next
86
+ - b2ee69b: ZERO-3321: delete unnecessary files
87
+ - 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
88
+
89
+ ## 1.89.0-rc.9
90
+
91
+ ### Minor Changes
92
+
93
+ - 5dfeea04: ZERO-2801: Revert ZERO-2801
94
+ - 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
95
+ - 2d9b2b2c: ZERO-2816: Add segment to headers
96
+ - 5e1feca6: Revert "ZERO-3286: Add notFound handling for chunk URLs starting with \_next"
97
+ - d8fad39: ZERO-3370: include plugins test to build stage
98
+ - 40a46853: ZERO-3182: Optimize basket update mutation with optimistic update
99
+ - f49bb74f: ZERO-3097: Add setCookie to logging in payment redirection middlewares
100
+ - e9541a13: ZERO-2816: Add headers to url
101
+ - 72fd4d67: ZERO-3084: Fix URL search parameters encoding in default middleware
102
+ - c53ef7b9: 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.
103
+ - 64699d3f: ZERO-2761: Fix invalid import for plugin module
104
+ - bf354de: ZERO-3321: add babel compiler for akinon/next test
105
+ - 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
106
+ - d552629f: ZERO-3182: Refactor basketApi to use invalidatesTags and comment out onQueryStarted logic
107
+ - 448adef: ZERO-3321: move csp test to akinon-next
108
+ - 17f87524: ZERO-2816: Make the incoming currency lowercase
109
+ - 65d3b862: ZERO-3054: Update headers in appFetch
110
+ - bbe18b9f: ZERO-2575: Fix build error
111
+ - 17bfadc4: ZERO-3275: Disable OpenTelemetry monitoring in production environment
112
+ - 4920742c: Disable getCachedTranslations
113
+ - b6e5b624: ZERO-3257: Enhance locale middleware to redirect using existing or default locale and support 303 status for POST requests
114
+ - 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
115
+ - 7e56d6b6: ZERO-2841: Update api tagTypes
116
+ - dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
117
+ - 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
118
+ - 43c182ee: ZERO-3054: Update Redis variable checks to conditionally include CACHE_SECRET
119
+ - 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
120
+ - eeb20bea: Revert "ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing"
121
+ - 3bf63c8a: ZERO-3286: Add notFound handling for chunk URLs starting with \_next
122
+ - 9be2c081: ZERO-3243: Improve basket update query handling with optimistic updates
123
+ - f2c92d5c: ZERO-2816: Update cookie name
124
+ - 7bd3d992: ZERO-2801: Refactor locale middleware to handle single locale configuration
125
+ - fdd255ee: ZERO-3054: Refactor cache handler to use custom Redis handler and implement key hashing
126
+ - acf0320: ZERO-3321: remove babel config
127
+ - 387356b: ZERO-3323: Refactor locale filtering logic in URL matcher regex
128
+ - 49eeebfa: ZERO-2909: Add deleteCollectionItem query to wishlistApi
129
+ - 3f9b8d7e: ZERO-2761: Update plugins.js for akinon-next
130
+ - b2ee69b: ZERO-3321: delete unnecessary files
131
+ - 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
132
+
133
+ ## 1.89.0-rc.8
134
+
135
+ ### Minor Changes
136
+
137
+ - d8fad39: ZERO-3370: include plugins test to build stage
138
+ - 943a239: ZERO-3370: add allowJs in akinon-next test tsconfig
139
+ - 0cabbda: ZERO-3370: replace inline monorepo check with reusable utility
140
+
141
+ ## 1.89.0-rc.7
142
+
143
+ ### Minor Changes
144
+
145
+ - dfaceff: ZERO-3356: Add useLoyaltyAvailability hook and update checkout state management
146
+
147
+ ## 1.89.0-rc.6
148
+
149
+ ## 1.89.0-rc.5
150
+
151
+ ## 1.89.0-rc.4
152
+
153
+ ### Minor Changes
154
+
155
+ - bf354de: ZERO-3321: add babel compiler for akinon/next test
156
+ - 448adef: ZERO-3321: move csp test to akinon-next
157
+ - 6c3629c: ZERO-3321: fix jest tests in akinon-next for standalone projects
158
+ - acf0320: ZERO-3321: remove babel config
159
+ - b2ee69b: ZERO-3321: delete unnecessary files
160
+
161
+ ## 1.89.0-rc.3
162
+
163
+ ### Minor Changes
164
+
165
+ - 63774a6: ZERO-3351: Add commerce redirection ignore list functionality and related utility
166
+
3
167
  ## 1.89.0-rc.2
4
168
 
5
169
  ## 1.89.0-rc.1
@@ -0,0 +1,83 @@
1
+ import { resolve } from 'path';
2
+ import type { NextConfig } from 'next';
3
+
4
+ function findBaseDir() {
5
+ const insideNodeModules = __dirname.includes('node_modules');
6
+
7
+ if (insideNodeModules) {
8
+ return resolve(__dirname, '../../../../');
9
+ } else {
10
+ return resolve(__dirname, '../../../apps/projectzeronext');
11
+ }
12
+ }
13
+
14
+ const baseDir = findBaseDir();
15
+
16
+ jest.mock('next-pwa', () => {
17
+ return () => (config: NextConfig) => config;
18
+ });
19
+
20
+ jest.mock('@sentry/nextjs', () => ({
21
+ withSentryConfig: (config: NextConfig) => config
22
+ }));
23
+
24
+ jest.mock('../with-pz-config.js', () => {
25
+ return (config: NextConfig) => {
26
+ const originalHeaders = config.headers;
27
+
28
+ config.headers = async () => {
29
+ const originalHeadersResult = (await originalHeaders?.()) ?? [];
30
+
31
+ return [
32
+ {
33
+ source: '/(.*)',
34
+ headers: [
35
+ {
36
+ key: 'Content-Security-Policy',
37
+ value: 'https://*.akifast.com akifast.com'
38
+ }
39
+ ]
40
+ },
41
+ ...originalHeadersResult
42
+ ];
43
+ };
44
+ return config;
45
+ };
46
+ });
47
+
48
+ interface Header {
49
+ key: string;
50
+ value: string;
51
+ }
52
+
53
+ interface HeaderGroup {
54
+ source: string;
55
+ headers: Header[];
56
+ }
57
+
58
+ const nextConfigPath = resolve(baseDir, 'next.config.mjs');
59
+ let nextConfig: any;
60
+
61
+ beforeAll(async () => {
62
+ nextConfig = await import(nextConfigPath);
63
+ });
64
+
65
+ describe('Next.js Configuration', () => {
66
+ it('should contain Content-Security-Policy header with akifast domain values', async () => {
67
+ const headers = nextConfig.default.headers;
68
+ expect(headers).toBeDefined();
69
+
70
+ const headersResult = await headers();
71
+
72
+ const cspHeaders = headersResult
73
+ .flatMap((headerGroup: HeaderGroup) => headerGroup.headers)
74
+ .filter((header: Header) => header.key === 'Content-Security-Policy');
75
+
76
+ expect(cspHeaders.length).toBeGreaterThan(0);
77
+
78
+ const lastCspHeader = cspHeaders[cspHeaders.length - 1];
79
+
80
+ expect(lastCspHeader.value).toContain('akifast.com');
81
+ expect(lastCspHeader.value).toContain('https://*.akifast.com');
82
+ });
83
+ });
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "display": "Default",
4
+ "compilerOptions": {
5
+ "composite": false,
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "inlineSources": false,
11
+ "isolatedModules": true,
12
+ "moduleResolution": "node",
13
+ "noUnusedLocals": false,
14
+ "noUnusedParameters": false,
15
+ "preserveWatchOutput": true,
16
+ "skipLibCheck": true,
17
+ "strict": true,
18
+ "jsx": "react-jsx",
19
+ "allowJs": true
20
+ },
21
+ "exclude": ["node_modules"],
22
+ "include": [".", "../."]
23
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ presets: [
3
+ ['@babel/preset-env', { targets: { node: 'current' } }],
4
+ '@babel/preset-typescript'
5
+ ]
6
+ };
@@ -2,6 +2,7 @@
2
2
 
3
3
  const runScript = require('./run-script');
4
4
 
5
+ runScript('pz-run-tests.js');
5
6
  runScript('pz-install-theme.js');
6
7
  runScript('pz-pre-check-dist.js');
7
8
  runScript('pz-generate-translations.js');
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require('child_process');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+ const glob = require('glob');
7
+ const findBaseDir = require('../utils/find-base-dir');
8
+ const checkMonorepo = require('../utils/check-monorepo');
9
+
10
+ const IS_MONOREPO = checkMonorepo() !== null;
11
+ const BASE_DIR = findBaseDir();
12
+ const PLUGINS = require(path.join(BASE_DIR, 'src', 'plugins.js'));
13
+
14
+ function findPluginTestFiles(akinonNextPackagePath) {
15
+ const pluginsRootPath = path.join(
16
+ akinonNextPackagePath,
17
+ '..',
18
+ '..',
19
+ IS_MONOREPO ? 'packages' : '@akinon'
20
+ );
21
+
22
+ if (!fs.existsSync(pluginsRootPath)) {
23
+ console.log('Plugins directory not found:', pluginsRootPath);
24
+ return [];
25
+ }
26
+
27
+ return PLUGINS.reduce((testFiles, pluginName) => {
28
+ const pluginDirectoryPath = path.join(pluginsRootPath, pluginName);
29
+ if (fs.existsSync(pluginDirectoryPath)) {
30
+ const pluginTestFiles = glob.sync('**/*.test.ts', {
31
+ cwd: pluginDirectoryPath,
32
+ absolute: true
33
+ });
34
+
35
+ return testFiles.concat(pluginTestFiles);
36
+ } else {
37
+ console.log(`Plugin directory not found: ${pluginName}`);
38
+ }
39
+ return testFiles;
40
+ }, []);
41
+ }
42
+
43
+ function isJestInstalled() {
44
+ try {
45
+ const jestExecutablePath = path.join(
46
+ BASE_DIR,
47
+ 'node_modules',
48
+ '.bin',
49
+ 'jest'
50
+ );
51
+ return fs.existsSync(jestExecutablePath);
52
+ } catch (error) {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ function getAkinonNextPackagePath() {
58
+ if (!IS_MONOREPO) {
59
+ return path.resolve(__dirname, '..');
60
+ }
61
+
62
+ return path.resolve(__dirname, '../../../packages/akinon-next');
63
+ }
64
+
65
+ if (!isJestInstalled()) {
66
+ console.error('\x1b[31mError: Jest is not installed in the project!\x1b[0m');
67
+ console.error(
68
+ 'Please install all dependencies by running one of the following commands:'
69
+ );
70
+ console.error(' npm install');
71
+ console.error(' yarn install');
72
+ process.exit(1);
73
+ }
74
+
75
+ const jestExecutablePath = path.join(BASE_DIR, 'node_modules', '.bin', 'jest');
76
+ const akinonNextPackagePath = getAkinonNextPackagePath();
77
+
78
+ const testFiles = [
79
+ ...glob.sync('__tests__/**/*.test.ts', {
80
+ cwd: akinonNextPackagePath,
81
+ absolute: true
82
+ }),
83
+ ...findPluginTestFiles(akinonNextPackagePath)
84
+ ];
85
+
86
+ console.log(`Found ${testFiles.length} test files to run`);
87
+
88
+ const jestArguments = [
89
+ ...testFiles,
90
+ `--config ${path.join(akinonNextPackagePath, 'jest.config.js')}`,
91
+ '--runTestsByPath',
92
+ '--passWithNoTests'
93
+ ];
94
+
95
+ spawn(jestExecutablePath, jestArguments, {
96
+ cwd: akinonNextPackagePath,
97
+ stdio: 'inherit',
98
+ shell: true
99
+ });
@@ -55,8 +55,8 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
55
55
  : formattedValue;
56
56
 
57
57
  const currentCurrencyDecimalScale = Settings.localization.currencies.find(
58
- (currency) => currency.code === currencyCode_
59
- ).decimalScale;
58
+ (currency) => currency?.code === currencyCode_
59
+ )?.decimalScale;
60
60
 
61
61
  return (
62
62
  <NumericFormat
@@ -0,0 +1,21 @@
1
+ import { useAppSelector } from '../redux/hooks';
2
+
3
+ export const useLoyaltyAvailability = () => {
4
+ const { paymentOptions, unavailablePaymentOptions } = useAppSelector(
5
+ (state) => state.checkout
6
+ );
7
+
8
+ const hasLoyaltyInAvailable = paymentOptions.some(
9
+ (option) =>
10
+ option.payment_type === 'loyalty_money' ||
11
+ option.payment_type === 'loyalty'
12
+ );
13
+
14
+ const hasLoyaltyInUnavailable = unavailablePaymentOptions.some(
15
+ (option) =>
16
+ option.payment_type === 'loyalty_money' ||
17
+ option.payment_type === 'loyalty'
18
+ );
19
+
20
+ return hasLoyaltyInAvailable || hasLoyaltyInUnavailable;
21
+ };
package/jest.config.js ADDED
@@ -0,0 +1,19 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ preset: 'ts-jest',
5
+ testEnvironment: 'node',
6
+ rootDir: path.resolve(__dirname),
7
+ roots: [],
8
+ testMatch: ['**/*.test.ts'],
9
+ testPathIgnorePatterns: [],
10
+ transformIgnorePatterns: [],
11
+ transform: {
12
+ '^.+\\.(tsx?|jsx?|mjs?)$': [
13
+ 'ts-jest',
14
+ {
15
+ tsconfig: path.resolve(__dirname, '__tests__/tsconfig.json')
16
+ }
17
+ ]
18
+ }
19
+ };
@@ -4,6 +4,7 @@ import { PzNextRequest } from '.';
4
4
  import logger from '../utils/log';
5
5
  import { urlLocaleMatcherRegex } from '../utils';
6
6
  import { getUrlPathWithLocale } from '../utils/localization';
7
+ import { shouldIgnoreRedirect } from '../utils/redirect-ignore';
7
8
  import { ROUTES } from 'routes';
8
9
 
9
10
  // This middleware is used to handle url redirections set in Omnitron
@@ -60,20 +61,13 @@ const withUrlRedirection =
60
61
 
61
62
  const setCookies = request.headers.getSetCookie();
62
63
 
63
- if (settings.commerceRedirectionIgnoreList) {
64
- const shouldIgnoreRedirect =
65
- settings.commerceRedirectionIgnoreList.some((ignorePath) =>
66
- redirectUrl.pathname.startsWith(
67
- getUrlPathWithLocale(
68
- ignorePath,
69
- req.middlewareParams.rewrites.locale
70
- )
71
- )
72
- );
73
-
74
- if (shouldIgnoreRedirect) {
75
- return middleware(req, event);
76
- }
64
+ if (
65
+ shouldIgnoreRedirect(
66
+ url.pathname,
67
+ req.middlewareParams.rewrites.locale
68
+ )
69
+ ) {
70
+ return middleware(req, event);
77
71
  }
78
72
 
79
73
  const response = NextResponse.redirect(redirectUrl.toString(), {
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.89.0-rc.2",
4
+ "version": "1.89.0-rc.21",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -13,6 +13,9 @@
13
13
  "pz-predev": "bin/pz-predev.js",
14
14
  "pz-postdev": "bin/pz-postdev.js"
15
15
  },
16
+ "scripts": {
17
+ "test": "jest"
18
+ },
16
19
  "dependencies": {
17
20
  "@opentelemetry/exporter-trace-otlp-http": "0.46.0",
18
21
  "@opentelemetry/resources": "1.19.0",
@@ -31,13 +34,21 @@
31
34
  "set-cookie-parser": "2.6.0"
32
35
  },
33
36
  "devDependencies": {
34
- "@akinon/eslint-plugin-projectzero": "1.89.0-rc.2",
37
+ "@akinon/eslint-plugin-projectzero": "1.89.0-rc.21",
38
+ "@babel/core": "7.26.10",
39
+ "@babel/preset-env": "7.26.9",
40
+ "@babel/preset-typescript": "7.27.0",
41
+ "@types/jest": "29.5.14",
35
42
  "@types/react-redux": "7.1.30",
36
43
  "@types/set-cookie-parser": "2.4.7",
37
44
  "@typescript-eslint/eslint-plugin": "6.7.4",
38
45
  "@typescript-eslint/parser": "6.7.4",
46
+ "babel-jest": "29.7.0",
39
47
  "eslint": "8.56.0",
40
48
  "eslint-config-next": "14.2.3",
41
- "eslint-config-prettier": "8.5.0"
49
+ "eslint-config-prettier": "8.5.0",
50
+ "jest": "29.7.0",
51
+ "ts-jest": "29.3.2",
52
+ "typescript": "5.2.2"
42
53
  }
43
54
  }
@@ -20,7 +20,8 @@ import {
20
20
  setShippingOptions,
21
21
  setHepsipayAvailability,
22
22
  setWalletPaymentData,
23
- setPayOnDeliveryOtpModalActive
23
+ setPayOnDeliveryOtpModalActive,
24
+ setUnavailablePaymentOptions
24
25
  } from '../../redux/reducers/checkout';
25
26
  import { RootState, TypedDispatch } from 'redux/store';
26
27
  import { checkoutApi } from '../../data/client/checkout';
@@ -36,6 +37,7 @@ interface CheckoutResult {
36
37
  errors?: Record<string, string[]>;
37
38
  pre_order?: PreOrder;
38
39
  context_list?: CheckoutContext[];
40
+ redirect_url?: string;
39
41
  };
40
42
  }
41
43
 
@@ -49,7 +51,11 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
49
51
  const result: CheckoutResult = next(action);
50
52
  const errors = result?.payload?.errors;
51
53
 
52
- if (errors) {
54
+ if (
55
+ !!errors &&
56
+ ((typeof errors === 'object' && Object.keys(errors).length > 0) ||
57
+ (Array.isArray(errors) && errors.length > 0))
58
+ ) {
53
59
  dispatch(setErrors(errors));
54
60
  }
55
61
 
@@ -57,6 +63,33 @@ export const errorMiddleware: Middleware = ({ dispatch }: MiddlewareParams) => {
57
63
  };
58
64
  };
59
65
 
66
+ export const redirectUrlMiddleware: Middleware = () => {
67
+ return (next) => (action) => {
68
+ const result: CheckoutResult = next(action);
69
+ const redirectUrl = result?.payload?.redirect_url;
70
+
71
+ if (redirectUrl) {
72
+ const currentLocale = getCookie('pz-locale');
73
+
74
+ let url = redirectUrl;
75
+
76
+ if (currentLocale && !redirectUrl.includes('/orders/redirection')) {
77
+ const { defaultLocaleValue, localeUrlStrategy } = settings.localization;
78
+
79
+ url =
80
+ currentLocale === defaultLocaleValue &&
81
+ localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales
82
+ ? redirectUrl
83
+ : `/${currentLocale}${redirectUrl}`;
84
+ }
85
+
86
+ window.location.href = url;
87
+ }
88
+
89
+ return result;
90
+ };
91
+ };
92
+
60
93
  export const contextListMiddleware: Middleware = ({
61
94
  dispatch,
62
95
  getState
@@ -148,6 +181,14 @@ export const contextListMiddleware: Middleware = ({
148
181
  dispatch(setPaymentOptions(context.page_context.payment_options));
149
182
  }
150
183
 
184
+ if (context.page_context.unavailable_options) {
185
+ dispatch(
186
+ setUnavailablePaymentOptions(
187
+ context.page_context.unavailable_options
188
+ )
189
+ );
190
+ }
191
+
151
192
  if (context.page_context.credit_payment_options) {
152
193
  dispatch(
153
194
  setCreditPaymentOptions(context.page_context.credit_payment_options)
@@ -5,6 +5,7 @@ import { ROUTES } from 'routes';
5
5
  import type { Middleware } from '@reduxjs/toolkit';
6
6
  import {
7
7
  errorMiddleware,
8
+ redirectUrlMiddleware,
8
9
  contextListMiddleware,
9
10
  hepsiPayMiddleware,
10
11
  walletPaymentMiddleware
@@ -50,6 +51,7 @@ const middlewares = [
50
51
  rtkQueryResponseHandler,
51
52
  rtkQueryErrorHandler,
52
53
  errorMiddleware,
54
+ redirectUrlMiddleware,
53
55
  ...preOrderMiddlewares,
54
56
  contextListMiddleware,
55
57
  hepsiPayMiddleware,
@@ -40,6 +40,7 @@ export interface CheckoutState {
40
40
  shippingOptions: ShippingOption[];
41
41
  dataSourceShippingOptions: DataSource[];
42
42
  paymentOptions: PaymentOption[];
43
+ unavailablePaymentOptions: PaymentOption[];
43
44
  creditPaymentOptions: CheckoutCreditPaymentOption[];
44
45
  selectedCreditPaymentPk: number;
45
46
  paymentChoices: PaymentChoice[];
@@ -94,6 +95,7 @@ const initialState: CheckoutState = {
94
95
  shippingOptions: [],
95
96
  dataSourceShippingOptions: [],
96
97
  paymentOptions: [],
98
+ unavailablePaymentOptions: [],
97
99
  creditPaymentOptions: [],
98
100
  selectedCreditPaymentPk: null,
99
101
  paymentChoices: [],
@@ -157,6 +159,9 @@ const checkoutSlice = createSlice({
157
159
  setPaymentOptions(state, { payload }) {
158
160
  state.paymentOptions = payload;
159
161
  },
162
+ setUnavailablePaymentOptions(state, { payload }) {
163
+ state.unavailablePaymentOptions = payload;
164
+ },
160
165
  setPaymentChoices(state, { payload }) {
161
166
  state.paymentChoices = payload;
162
167
  },
@@ -218,9 +223,10 @@ export const {
218
223
  setShippingOptions,
219
224
  setDataSourceShippingOptions,
220
225
  setPaymentOptions,
226
+ setUnavailablePaymentOptions,
227
+ setPaymentChoices,
221
228
  setCreditPaymentOptions,
222
229
  setSelectedCreditPaymentPk,
223
- setPaymentChoices,
224
230
  setCardType,
225
231
  setInstallmentOptions,
226
232
  setBankAccounts,
@@ -0,0 +1,35 @@
1
+ import settings from 'settings';
2
+ import { getUrlPathWithLocale } from './localization';
3
+
4
+ type IgnorePath = string | RegExp;
5
+
6
+ const defaultIgnoreList: string[] = [];
7
+
8
+ const extraIgnores: IgnorePath[] = Array.isArray(
9
+ settings.commerceRedirectionIgnoreList
10
+ )
11
+ ? settings.commerceRedirectionIgnoreList.map((path) => {
12
+ if (path === '/users/reset') {
13
+ return /^\/users\/reset\/[^/]+\/[^/]+\/$/;
14
+ }
15
+ return path;
16
+ })
17
+ : [];
18
+
19
+ export function shouldIgnoreRedirect(
20
+ pathname: string,
21
+ locale: string
22
+ ): boolean {
23
+ if (!pathname) return false;
24
+
25
+ const rawIgnoreList: IgnorePath[] = [...defaultIgnoreList, ...extraIgnores];
26
+
27
+ return rawIgnoreList.some((ignorePath) => {
28
+ if (ignorePath instanceof RegExp) {
29
+ return ignorePath.test(pathname);
30
+ }
31
+
32
+ const localized = getUrlPathWithLocale(ignorePath, locale);
33
+ return localized === pathname;
34
+ });
35
+ }