@akinon/next 1.1.1 → 1.3.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 +14 -3
- package/components/client-root.tsx +1 -40
- package/components/selected-payment-option-view.tsx +3 -0
- package/data/client/product.ts +4 -5
- package/data/urls.ts +2 -2
- package/hocs/server/with-segment-defaults.tsx +4 -1
- package/hooks/use-localization.ts +18 -3
- package/lib/cache.ts +1 -1
- package/middlewares/currency.ts +21 -1
- package/middlewares/default.ts +4 -17
- package/middlewares/pretty-url.ts +7 -1
- package/middlewares/three-d-redirection.ts +1 -20
- package/package.json +1 -1
- package/plugins.js +1 -0
- package/types/commerce/account.ts +4 -8
- package/types/commerce/product.ts +1 -2
- package/types/index.ts +14 -0
- package/utils/index.ts +3 -0
- package/utils/log.ts +0 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.3.0
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Refactor currency and locale selection
|
|
8
|
+
- Update TS types
|
|
9
|
+
- Fix 3D redirection middleware
|
|
10
|
+
- Refactor logging
|
|
11
|
+
|
|
12
|
+
## 1.2.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
6
15
|
|
|
7
|
-
- Refactor Sentry
|
|
16
|
+
- Refactor Sentry config.
|
|
17
|
+
- Add localeIncludedPrettyUrlPattern option to settings.
|
|
18
|
+
- Refactor getRetailStoreStock mutation.
|
|
8
19
|
|
|
9
20
|
## 1.1.0
|
|
10
21
|
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { usePathname } from 'next/navigation';
|
|
4
|
-
import {
|
|
5
|
-
import { api } from '../data/client/api';
|
|
6
|
-
import {
|
|
7
|
-
useClearBasketMutation,
|
|
8
|
-
useGetBasketQuery
|
|
9
|
-
} from '../data/client/basket';
|
|
10
|
-
import { useAppDispatch, useAppSelector } from '../redux/hooks';
|
|
11
|
-
import { getCookie, removeCookie } from '../utils';
|
|
12
|
-
import { useRouter } from '../hooks';
|
|
4
|
+
import { useAppSelector } from '../redux/hooks';
|
|
13
5
|
|
|
14
6
|
export default function ClientRoot({
|
|
15
7
|
children,
|
|
@@ -18,39 +10,8 @@ export default function ClientRoot({
|
|
|
18
10
|
children: React.ReactNode;
|
|
19
11
|
sessionId?: string;
|
|
20
12
|
}) {
|
|
21
|
-
const dispatch = useAppDispatch();
|
|
22
13
|
const pathname = usePathname();
|
|
23
|
-
const router = useRouter();
|
|
24
14
|
const { isMobileApp } = useAppSelector((state) => state.root);
|
|
25
|
-
const { data: basketData, isSuccess } = useGetBasketQuery();
|
|
26
|
-
const [clearBasket] = useClearBasketMutation();
|
|
27
|
-
const resetClientCache = getCookie('pz-reset-client-cache') === 'true';
|
|
28
|
-
const resetBasket = getCookie('pz-reset-basket') === 'true';
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (basketData?.basketitem_set.length && resetBasket) {
|
|
32
|
-
dispatch(
|
|
33
|
-
api.util.invalidateTags([
|
|
34
|
-
'Checkout',
|
|
35
|
-
'Product',
|
|
36
|
-
'Addresses',
|
|
37
|
-
'Favorite',
|
|
38
|
-
'Basket'
|
|
39
|
-
])
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
clearBasket();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
removeCookie('pz-reset-basket');
|
|
46
|
-
}, [resetBasket, isSuccess, basketData]);
|
|
47
|
-
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (resetClientCache) {
|
|
50
|
-
removeCookie('pz-reset-client-cache');
|
|
51
|
-
location.reload();
|
|
52
|
-
}
|
|
53
|
-
}, [resetClientCache]);
|
|
54
15
|
|
|
55
16
|
if (isMobileApp && pathname.includes('/orders/completed')) {
|
|
56
17
|
((window.parent || window) as any)?.ReactNativeWebView?.postMessage?.(
|
|
@@ -51,6 +51,9 @@ export default function SelectedPaymentOptionView() {
|
|
|
51
51
|
} else if (payment_option.payment_type === 'loyalty_money') {
|
|
52
52
|
promise = import(`views/checkout/steps/payment/options/loyalty`);
|
|
53
53
|
}
|
|
54
|
+
// else if (payment_option.payment_type === 'gpay') {
|
|
55
|
+
// promise = import(`views/checkout/steps/payment/options/gpay`);
|
|
56
|
+
// }
|
|
54
57
|
} catch (error) {}
|
|
55
58
|
|
|
56
59
|
return promise
|
package/data/client/product.ts
CHANGED
|
@@ -23,7 +23,7 @@ type GetProduct = {
|
|
|
23
23
|
pk: number;
|
|
24
24
|
searchParams?: URLSearchParams;
|
|
25
25
|
groupProduct?: boolean;
|
|
26
|
-
[key:string]: any;
|
|
26
|
+
[key: string]: any;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export const productApi = api.injectEndpoints({
|
|
@@ -34,7 +34,7 @@ export const productApi = api.injectEndpoints({
|
|
|
34
34
|
})
|
|
35
35
|
}),
|
|
36
36
|
getProductByParams: build.query<ProductResult, GetProduct>({
|
|
37
|
-
query: ({pk, searchParams, groupProduct, ...params}) => {
|
|
37
|
+
query: ({ pk, searchParams, groupProduct, ...params }) => {
|
|
38
38
|
let url = groupProduct
|
|
39
39
|
? product.getGroupProductByPk(pk)
|
|
40
40
|
: product.getProductByPk(pk);
|
|
@@ -50,11 +50,10 @@ export const productApi = api.injectEndpoints({
|
|
|
50
50
|
}),
|
|
51
51
|
getRetailStoreStock: build.mutation<StockResultType, FindInStoreFormType>({
|
|
52
52
|
query: (body) => {
|
|
53
|
-
const { productPk,
|
|
54
|
-
const hasVariant = variant ? `&integration_beden=${variant}` : '';
|
|
53
|
+
const { productPk, queryString } = body;
|
|
55
54
|
return {
|
|
56
55
|
url: buildClientRequestUrl(
|
|
57
|
-
product.getRetailStoreStock(productPk,
|
|
56
|
+
product.getRetailStoreStock(productPk, queryString),
|
|
58
57
|
{
|
|
59
58
|
contentType: 'application/json'
|
|
60
59
|
}
|
package/data/urls.ts
CHANGED
|
@@ -116,8 +116,8 @@ export const product = {
|
|
|
116
116
|
installments: (productId: number) => `/payments/cards/product/${productId}`,
|
|
117
117
|
getProductByPk: (pk: number) => `/product/${pk}`,
|
|
118
118
|
getGroupProductByPk: (pk: number) => `/group-product/${pk}`,
|
|
119
|
-
getRetailStoreStock: (productPk: string,
|
|
120
|
-
`/retail_store_stock/${productPk}
|
|
119
|
+
getRetailStoreStock: (productPk: string, queryString: string) =>
|
|
120
|
+
`/retail_store_stock/${productPk}?${queryString}`,
|
|
121
121
|
addProduct: '/baskets/basket',
|
|
122
122
|
slug: (slug: string) => `/${slug}`,
|
|
123
123
|
categoryUrl: (pk: number) => `/products/${pk}/category_nodes/?limit=1`,
|
|
@@ -74,7 +74,10 @@ const checkRedisVariables = () => {
|
|
|
74
74
|
process.env.CACHE_SECRET
|
|
75
75
|
];
|
|
76
76
|
|
|
77
|
-
if (
|
|
77
|
+
if (
|
|
78
|
+
!requiredVariableValues.every((v) => v) &&
|
|
79
|
+
process.env.NODE_ENV === 'production'
|
|
80
|
+
) {
|
|
78
81
|
logger.warn('Redis cache variables are not set', {
|
|
79
82
|
requiredVariables: ['CACHE_HOST', 'CACHE_PORT', 'CACHE_SECRET'],
|
|
80
83
|
values: requiredVariableValues
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { LocalizationContext } from '../localization/provider';
|
|
4
4
|
import { useContext } from 'react';
|
|
5
|
-
import { urlLocaleMatcherRegex } from '../utils';
|
|
5
|
+
import { setCookie, urlLocaleMatcherRegex } from '../utils';
|
|
6
6
|
import { LocaleUrlStrategy } from '../localization';
|
|
7
7
|
import { useRouter } from 'next/navigation';
|
|
8
8
|
|
|
@@ -36,7 +36,21 @@ export const useLocalization = () => {
|
|
|
36
36
|
''
|
|
37
37
|
);
|
|
38
38
|
|
|
39
|
-
router.push
|
|
39
|
+
// router.push is not used because reloading the page also clears the client side cache.
|
|
40
|
+
location.href = `${localePath}${pathnameWithoutLocale}${location.search}`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sets the currency.
|
|
45
|
+
*
|
|
46
|
+
* If the currency is linked to the locale by using `getActiveCurrencyCode` function in the settings,
|
|
47
|
+
* you need to use `setLocale` instead of this.
|
|
48
|
+
* @param currency Currency code defined in the settings.
|
|
49
|
+
*/
|
|
50
|
+
const setCurrency = (currency: string) => {
|
|
51
|
+
// It is a temp cookie to set currency in `currency` middleware.
|
|
52
|
+
setCookie('pz-set-currency', currency);
|
|
53
|
+
location.reload();
|
|
40
54
|
};
|
|
41
55
|
|
|
42
56
|
return {
|
|
@@ -52,12 +66,13 @@ export const useLocalization = () => {
|
|
|
52
66
|
*/
|
|
53
67
|
t: (path: string) => translate(path),
|
|
54
68
|
setLocale,
|
|
69
|
+
setCurrency,
|
|
55
70
|
locale,
|
|
56
71
|
currency,
|
|
57
72
|
locales,
|
|
58
73
|
currencies,
|
|
59
74
|
defaultLocaleValue,
|
|
60
75
|
defaultCurrencyCode,
|
|
61
|
-
localeUrlStrategy
|
|
76
|
+
localeUrlStrategy
|
|
62
77
|
};
|
|
63
78
|
};
|
package/lib/cache.ts
CHANGED
package/middlewares/currency.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { NextFetchEvent, NextMiddleware } from 'next/server';
|
|
2
|
-
import { ROUTES } from 'routes';
|
|
3
2
|
import settings from 'settings';
|
|
4
3
|
import { PzNextRequest } from '.';
|
|
5
4
|
import logger from '../utils/log';
|
|
5
|
+
import { basket } from '../data/urls';
|
|
6
|
+
|
|
7
|
+
const resetBasket = async (req: PzNextRequest) => {
|
|
8
|
+
await fetch(`${settings.commerceUrl}${basket.getBasket}`, {
|
|
9
|
+
method: 'DELETE',
|
|
10
|
+
headers: {
|
|
11
|
+
Cookie: req.headers.get('cookie') || '',
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
'X-CSRFToken': req.cookies.get('csrftoken')?.value ?? '',
|
|
14
|
+
Referer: settings.commerceUrl
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
};
|
|
6
18
|
|
|
7
19
|
const withCurrency =
|
|
8
20
|
(middleware: NextMiddleware) =>
|
|
@@ -34,6 +46,10 @@ const withCurrency =
|
|
|
34
46
|
defaultCurrencyCode
|
|
35
47
|
});
|
|
36
48
|
|
|
49
|
+
if (req.cookies.get('pz-set-currency')) {
|
|
50
|
+
activeCurrency = req.cookies.get('pz-set-currency')?.value;
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
if (
|
|
38
54
|
!activeCurrency ||
|
|
39
55
|
!currencies.find((c) => c.code === activeCurrency)
|
|
@@ -44,6 +60,10 @@ const withCurrency =
|
|
|
44
60
|
activeCurrency = defaultCurrencyCode;
|
|
45
61
|
}
|
|
46
62
|
|
|
63
|
+
if (req.cookies.get('pz-currency')?.value !== activeCurrency) {
|
|
64
|
+
resetBasket(req);
|
|
65
|
+
}
|
|
66
|
+
|
|
47
67
|
req.middlewareParams.rewrites.currency = activeCurrency;
|
|
48
68
|
} catch (error) {
|
|
49
69
|
logger.error('withCurrency error', error);
|
package/middlewares/default.ts
CHANGED
|
@@ -154,18 +154,6 @@ const withPzDefault =
|
|
|
154
154
|
secure: true
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
if (
|
|
158
|
-
req.cookies.get('pz-currency') &&
|
|
159
|
-
req.cookies.get('pz-currency').value !== currency
|
|
160
|
-
) {
|
|
161
|
-
logger.debug('Currency changed', {
|
|
162
|
-
currency,
|
|
163
|
-
oldCurrency: req.cookies.get('pz-currency')?.value
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
middlewareResult.cookies.set('pz-reset-basket', 'true');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
157
|
if (
|
|
170
158
|
req.cookies.get('pz-locale') &&
|
|
171
159
|
req.cookies.get('pz-locale').value !== locale
|
|
@@ -174,11 +162,6 @@ const withPzDefault =
|
|
|
174
162
|
locale,
|
|
175
163
|
oldLocale: req.cookies.get('pz-locale')?.value
|
|
176
164
|
});
|
|
177
|
-
|
|
178
|
-
middlewareResult.cookies.set(
|
|
179
|
-
'pz-reset-client-cache',
|
|
180
|
-
'true'
|
|
181
|
-
);
|
|
182
165
|
}
|
|
183
166
|
|
|
184
167
|
middlewareResult.headers.set(
|
|
@@ -186,6 +169,10 @@ const withPzDefault =
|
|
|
186
169
|
req.nextUrl.toString()
|
|
187
170
|
);
|
|
188
171
|
|
|
172
|
+
if (req.cookies.get('pz-set-currency')) {
|
|
173
|
+
middlewareResult.cookies.delete('pz-set-currency');
|
|
174
|
+
}
|
|
175
|
+
|
|
189
176
|
if (process.env.ACC_APP_VERSION) {
|
|
190
177
|
middlewareResult.headers.set(
|
|
191
178
|
'acc-app-version',
|
|
@@ -76,7 +76,13 @@ const withPrettyUrl =
|
|
|
76
76
|
return middleware(req, event);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const prettyUrlResult = await resolvePrettyUrl(
|
|
79
|
+
const prettyUrlResult = await resolvePrettyUrl(
|
|
80
|
+
Settings.localization.localeIncludedPrettyUrlPattern?.test(
|
|
81
|
+
prettyUrlPathname
|
|
82
|
+
)
|
|
83
|
+
? url.pathname
|
|
84
|
+
: prettyUrlPathname
|
|
85
|
+
);
|
|
80
86
|
|
|
81
87
|
if (prettyUrlResult.matched) {
|
|
82
88
|
req.middlewareParams.rewrites.prettyUrl = prettyUrlResult.path;
|
|
@@ -38,25 +38,6 @@ const withThreeDRedirection =
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const body = await streamToString(req.body);
|
|
41
|
-
const params = body.split('&');
|
|
42
|
-
const encodedPzParams = decodeURIComponent(
|
|
43
|
-
params.find((param) => param.startsWith('pzparams'))?.split('=')[1] ?? ''
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
logger.debug('Encoded 3D form extra params', encodedPzParams);
|
|
47
|
-
|
|
48
|
-
if (!encodedPzParams.length) {
|
|
49
|
-
logger.warn('No pzparams found in 3D form params');
|
|
50
|
-
return middleware(req, event);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const pzParams = JSON.parse(decodeURIComponent(encodedPzParams)) as {
|
|
54
|
-
session: string;
|
|
55
|
-
locale: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
logger.debug('3D form extra params', pzParams);
|
|
59
|
-
|
|
60
41
|
const requestUrl = `${Settings.commerceUrl}/orders/checkout/${url.search}`;
|
|
61
42
|
|
|
62
43
|
const request = await fetch(requestUrl, {
|
|
@@ -64,7 +45,7 @@ const withThreeDRedirection =
|
|
|
64
45
|
headers: {
|
|
65
46
|
'X-Requested-With': 'XMLHttpRequest',
|
|
66
47
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
67
|
-
Cookie: `osessionid=${
|
|
48
|
+
Cookie: `osessionid=${req.cookies.get('osessionid')?.value ?? ''}`
|
|
68
49
|
},
|
|
69
50
|
body
|
|
70
51
|
});
|
package/package.json
CHANGED
package/plugins.js
CHANGED
|
@@ -42,18 +42,14 @@ export type AccountChangePasswordFormType = {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
export type AccountProfileFormType = {
|
|
45
|
+
date_of_birth: string;
|
|
46
|
+
email_allowed: boolean;
|
|
45
47
|
first_name: string;
|
|
48
|
+
gender: string;
|
|
46
49
|
last_name: string;
|
|
47
50
|
phone: string;
|
|
48
|
-
email_allowed: boolean;
|
|
49
51
|
sms_allowed: boolean;
|
|
50
|
-
|
|
51
|
-
email: string;
|
|
52
|
-
birthdate_day: string;
|
|
53
|
-
birthdate_month: string;
|
|
54
|
-
birthdate_year: string;
|
|
55
|
-
country_code: string;
|
|
56
|
-
date_of_birth: string;
|
|
52
|
+
[key: string]: any;
|
|
57
53
|
};
|
|
58
54
|
|
|
59
55
|
export type ContactFormType = {
|
package/types/index.ts
CHANGED
|
@@ -148,6 +148,20 @@ export interface Settings {
|
|
|
148
148
|
locale: string;
|
|
149
149
|
defaultCurrencyCode: string;
|
|
150
150
|
}) => string;
|
|
151
|
+
/**
|
|
152
|
+
* By default, pretty url resolver excludes locale from url.
|
|
153
|
+
* In some cases, you may want to create flatpages and include locale in urls.
|
|
154
|
+
* This is useful if you want to manage your flatpages for different countries by using locale value.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* // URL entered in Omnitron: /en-us/pages/about-us
|
|
158
|
+
* // Locale Strategy: LocaleUrlStrategy.ShowAllLocales
|
|
159
|
+
*
|
|
160
|
+
* // If you don't use this option, pretty url resolver will remove the locale and it will be resolved as '/pages/about-us' and you will get 404. Because there is no page with this url. But if you use this option, it will be resolved as '/en-us/pages/about-us' and you will get the page.
|
|
161
|
+
* // Following pattern will include locale for all urls including '/pages/'.
|
|
162
|
+
* localeIncludedPrettyUrlPattern: new RegExp('.+/pages/.+$')
|
|
163
|
+
*/
|
|
164
|
+
localeIncludedPrettyUrlPattern?: RegExp;
|
|
151
165
|
};
|
|
152
166
|
rewrites?: Array<{
|
|
153
167
|
source: string;
|
package/utils/index.ts
CHANGED
|
@@ -35,6 +35,9 @@ export function removeCookie(name: string) {
|
|
|
35
35
|
document.cookie = name + '=' + '; expires=' + date + '; path=/';
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Use setCurrency method in useLocalization hook instead.
|
|
40
|
+
*/
|
|
38
41
|
export function setCurrency(currency: string) {
|
|
39
42
|
if (getCookie('pz-currency') !== currency) {
|
|
40
43
|
setCookie('pz-reset-basket', 'true');
|
package/utils/log.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as Sentry from '@sentry/nextjs';
|
|
2
|
-
|
|
3
1
|
enum LogLevel {
|
|
4
2
|
TRACE = 'trace',
|
|
5
3
|
DEBUG = 'debug',
|
|
@@ -94,15 +92,6 @@ const error: LoggerFn = (message, payload) => {
|
|
|
94
92
|
message,
|
|
95
93
|
payload
|
|
96
94
|
});
|
|
97
|
-
|
|
98
|
-
Sentry.withScope(function (scope) {
|
|
99
|
-
scope.setLevel('error');
|
|
100
|
-
|
|
101
|
-
Sentry.captureException({
|
|
102
|
-
message,
|
|
103
|
-
extra: payload
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
95
|
};
|
|
107
96
|
|
|
108
97
|
const warn: LoggerFn = (message, payload) => {
|
|
@@ -111,15 +100,6 @@ const warn: LoggerFn = (message, payload) => {
|
|
|
111
100
|
message,
|
|
112
101
|
payload
|
|
113
102
|
});
|
|
114
|
-
|
|
115
|
-
Sentry.withScope(function (scope) {
|
|
116
|
-
scope.setLevel('warning');
|
|
117
|
-
|
|
118
|
-
Sentry.captureEvent({
|
|
119
|
-
message,
|
|
120
|
-
extra: payload
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
103
|
};
|
|
124
104
|
|
|
125
105
|
const debug: LoggerFn = (message, payload) => {
|