@akinon/next 1.44.0 → 1.45.0-rc.1
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 +248 -0
- package/api/client.ts +33 -9
- package/assets/styles/index.css +49 -0
- package/assets/styles/index.css.map +1 -0
- package/assets/styles/index.scss +50 -26
- package/components/input.tsx +21 -7
- package/components/link.tsx +17 -13
- package/components/pagination.tsx +1 -2
- package/components/price.tsx +11 -4
- package/components/selected-payment-option-view.tsx +26 -38
- package/data/client/account.ts +10 -9
- package/data/client/address.ts +32 -8
- package/data/client/api.ts +2 -2
- package/data/client/basket.ts +11 -13
- package/data/client/checkout.ts +47 -4
- package/data/server/category.ts +2 -2
- package/data/server/list.ts +2 -2
- package/data/server/product.ts +15 -13
- package/data/server/special-page.ts +2 -2
- package/data/urls.ts +5 -1
- package/hooks/index.ts +2 -1
- package/hooks/use-message-listener.ts +24 -0
- package/hooks/use-payment-options.ts +2 -1
- package/lib/cache-handler.mjs +33 -0
- package/lib/cache.ts +18 -6
- package/middlewares/default.ts +50 -2
- package/middlewares/locale.ts +32 -30
- package/middlewares/pretty-url.ts +4 -0
- package/middlewares/url-redirection.ts +4 -0
- package/package.json +5 -4
- package/plugins.d.ts +1 -0
- package/redux/middlewares/checkout.ts +70 -11
- package/redux/reducers/checkout.ts +24 -5
- package/redux/reducers/config.ts +2 -0
- package/routes/pretty-url.tsx +194 -0
- package/types/commerce/account.ts +1 -0
- package/types/commerce/address.ts +1 -1
- package/types/commerce/checkout.ts +30 -0
- package/types/commerce/misc.ts +2 -0
- package/types/commerce/order.ts +12 -0
- package/types/index.ts +28 -2
- package/utils/app-fetch.ts +1 -1
- package/utils/generate-commerce-search-params.ts +6 -2
- package/utils/index.ts +27 -6
- package/utils/menu-generator.ts +2 -2
- package/utils/redirection-iframe.ts +85 -0
- package/utils/server-translation.ts +5 -1
- package/with-pz-config.js +11 -1
|
@@ -33,6 +33,23 @@ export interface ShippingOption {
|
|
|
33
33
|
slug: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export interface DataSource {
|
|
37
|
+
pk: number;
|
|
38
|
+
name: string;
|
|
39
|
+
data_source_shipping_options: DataSourceShippingOption[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface DataSourceShippingOption {
|
|
43
|
+
pk: number;
|
|
44
|
+
shipping_amount: string;
|
|
45
|
+
shipping_option_name: string;
|
|
46
|
+
shipping_option_logo: string | null;
|
|
47
|
+
data_source: {
|
|
48
|
+
pk: number;
|
|
49
|
+
title: string | null;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
36
53
|
export interface CheckoutAddressType {
|
|
37
54
|
label: string;
|
|
38
55
|
text: string;
|
|
@@ -78,6 +95,8 @@ export interface PreOrder {
|
|
|
78
95
|
retail_store?: RetailStore;
|
|
79
96
|
gift_box?: GiftBox;
|
|
80
97
|
credit_payment_option?: CheckoutCreditPaymentOption;
|
|
98
|
+
data_source_shipping_options: any;
|
|
99
|
+
attribute_based_shipping_options?: AttributeBasedShippingOption[];
|
|
81
100
|
}
|
|
82
101
|
|
|
83
102
|
export interface GuestLoginFormParams {
|
|
@@ -117,6 +136,7 @@ export interface CheckoutContext {
|
|
|
117
136
|
redirect_url?: string;
|
|
118
137
|
context_data?: any;
|
|
119
138
|
balance?: string;
|
|
139
|
+
attribute_based_shipping_options?: AttributeBasedShippingOption[];
|
|
120
140
|
[key: string]: any;
|
|
121
141
|
};
|
|
122
142
|
}
|
|
@@ -142,3 +162,13 @@ export interface BankAccount {
|
|
|
142
162
|
pk: number;
|
|
143
163
|
sort_order: number;
|
|
144
164
|
}
|
|
165
|
+
|
|
166
|
+
export interface AttributeBasedShippingOption {
|
|
167
|
+
pk: number;
|
|
168
|
+
shipping_amount: string | null;
|
|
169
|
+
shipping_option_name: string | null;
|
|
170
|
+
shipping_option_logo: string | null;
|
|
171
|
+
attribute_value: string | null;
|
|
172
|
+
attribute_key: string;
|
|
173
|
+
[key: string]: any;
|
|
174
|
+
}
|
package/types/commerce/misc.ts
CHANGED
package/types/commerce/order.ts
CHANGED
|
@@ -52,6 +52,10 @@ export interface OrderItem {
|
|
|
52
52
|
quantity: string;
|
|
53
53
|
unit_price: string;
|
|
54
54
|
total_amount: string;
|
|
55
|
+
attributes: {
|
|
56
|
+
gift_note: string;
|
|
57
|
+
[key: string]: any;
|
|
58
|
+
};
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
export interface Order {
|
|
@@ -105,6 +109,14 @@ export interface Order {
|
|
|
105
109
|
shipping_option: number;
|
|
106
110
|
tracking_number: string;
|
|
107
111
|
tracking_url: string;
|
|
112
|
+
[key: string]: any;
|
|
113
|
+
bank: {
|
|
114
|
+
pk: number;
|
|
115
|
+
name: string;
|
|
116
|
+
slug: string;
|
|
117
|
+
logo: string;
|
|
118
|
+
[key: string]: any;
|
|
119
|
+
};
|
|
108
120
|
}
|
|
109
121
|
|
|
110
122
|
export interface Quotations {
|
package/types/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { LocaleUrlStrategy } from '../localization';
|
|
|
2
2
|
import { PzNextRequest } from '../middlewares';
|
|
3
3
|
import { Control, FieldError } from 'react-hook-form';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
|
-
|
|
5
|
+
import { UsePaginationType } from '../hooks/use-pagination';
|
|
6
6
|
declare global {
|
|
7
7
|
interface Window {
|
|
8
8
|
// we did it like this because declare types needs to be identical, if not it will fail
|
|
@@ -68,9 +68,17 @@ export interface Currency {
|
|
|
68
68
|
* @see https://en.wikipedia.org/wiki/ISO_4217
|
|
69
69
|
*/
|
|
70
70
|
code: string;
|
|
71
|
+
/**
|
|
72
|
+
* Number of decimal places to display.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* decimalScale: 3
|
|
76
|
+
*/
|
|
77
|
+
decimalScale?: number;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
export interface Settings {
|
|
81
|
+
usePrettyUrlRoute?: boolean;
|
|
74
82
|
commerceUrl: string;
|
|
75
83
|
redis: {
|
|
76
84
|
defaultExpirationTime: number;
|
|
@@ -216,7 +224,7 @@ export type Translations = { [key: string]: object };
|
|
|
216
224
|
|
|
217
225
|
export interface PageProps<T = any> {
|
|
218
226
|
params: T;
|
|
219
|
-
searchParams:
|
|
227
|
+
searchParams: { [key: string]: string | string[] | undefined };
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
export interface LayoutProps<T = any> extends PageProps<T> {
|
|
@@ -283,3 +291,21 @@ export interface AccordionProps {
|
|
|
283
291
|
export interface PluginModuleComponentProps {
|
|
284
292
|
settings?: Record<string, any>;
|
|
285
293
|
}
|
|
294
|
+
|
|
295
|
+
export interface PaginationProps {
|
|
296
|
+
total: number | undefined;
|
|
297
|
+
limit?: number | undefined;
|
|
298
|
+
currentPage: number | undefined;
|
|
299
|
+
numberOfPages?: number | undefined;
|
|
300
|
+
containerClassName?: string;
|
|
301
|
+
moreButtonClassName?: string;
|
|
302
|
+
prevClassName?: string;
|
|
303
|
+
nextClassName?: string;
|
|
304
|
+
pageClassName?: string;
|
|
305
|
+
threshold?: number | undefined;
|
|
306
|
+
delta?: number | undefined;
|
|
307
|
+
render?: (pagination: UsePaginationType) => ReactNode;
|
|
308
|
+
type?: 'infinite' | 'list' | 'more';
|
|
309
|
+
onPageChange?: (page: number) => void;
|
|
310
|
+
direction?: 'next' | 'prev';
|
|
311
|
+
}
|
package/utils/app-fetch.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import logger from './log';
|
|
2
2
|
|
|
3
|
-
export const generateCommerceSearchParams = (searchParams?:
|
|
3
|
+
export const generateCommerceSearchParams = (searchParams?: {
|
|
4
|
+
[key: string]: string | string[] | undefined;
|
|
5
|
+
}) => {
|
|
4
6
|
if (!searchParams) {
|
|
5
7
|
return null;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
const urlSerchParams = new URLSearchParams(
|
|
10
|
+
const urlSerchParams = new URLSearchParams(
|
|
11
|
+
searchParams as Record<string, string>
|
|
12
|
+
);
|
|
9
13
|
|
|
10
14
|
Object.entries(searchParams).forEach(([key, value]) => {
|
|
11
15
|
if (typeof value === 'object') {
|
package/utils/index.ts
CHANGED
|
@@ -63,18 +63,33 @@ export function getTranslateFn(path: string, translations: any) {
|
|
|
63
63
|
|
|
64
64
|
export function buildClientRequestUrl(
|
|
65
65
|
path: string,
|
|
66
|
-
options?: ClientRequestOptions
|
|
66
|
+
options?: ClientRequestOptions & { cache?: boolean }
|
|
67
67
|
) {
|
|
68
68
|
let url = `/api/client${path}`;
|
|
69
69
|
|
|
70
|
+
let hasQuery = url.includes('?');
|
|
71
|
+
|
|
70
72
|
if (options) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const { cache, ...otherOptions } = options;
|
|
74
|
+
|
|
75
|
+
if (Object.keys(otherOptions).length > 0) {
|
|
76
|
+
if (hasQuery) {
|
|
77
|
+
url += '&';
|
|
78
|
+
} else {
|
|
79
|
+
url += '?';
|
|
80
|
+
hasQuery = true;
|
|
81
|
+
}
|
|
82
|
+
url += `options=${encodeURIComponent(JSON.stringify(otherOptions))}`;
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
|
|
85
|
+
if (cache === false) {
|
|
86
|
+
if (hasQuery) {
|
|
87
|
+
url += '&';
|
|
88
|
+
} else {
|
|
89
|
+
url += '?';
|
|
90
|
+
}
|
|
91
|
+
url += `t=${Date.now()}`;
|
|
92
|
+
}
|
|
78
93
|
}
|
|
79
94
|
|
|
80
95
|
return url;
|
|
@@ -102,6 +117,12 @@ export function buildCDNUrl(url: string, config?: CDNOptions) {
|
|
|
102
117
|
''
|
|
103
118
|
);
|
|
104
119
|
|
|
120
|
+
const noOptionFileExtension = url?.split('.').pop()?.toLowerCase() ?? '';
|
|
121
|
+
|
|
122
|
+
if (noOptionFileExtension === 'svg' || noOptionFileExtension === 'gif') {
|
|
123
|
+
return url;
|
|
124
|
+
}
|
|
125
|
+
|
|
105
126
|
let options = '';
|
|
106
127
|
|
|
107
128
|
if (config) {
|
package/utils/menu-generator.ts
CHANGED
|
@@ -13,8 +13,8 @@ export const menuGenerator = (arr: MenuItemType[]) => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
Object.values(data).forEach((item) => {
|
|
16
|
-
if (item.
|
|
17
|
-
data[item.
|
|
16
|
+
if (item.parent_pk) {
|
|
17
|
+
data[item.parent_pk].children.push(item);
|
|
18
18
|
} else {
|
|
19
19
|
tree.push(item);
|
|
20
20
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const iframeURLChange = (iframe, callback) => {
|
|
2
|
+
iframe.addEventListener('load', () => {
|
|
3
|
+
setTimeout(() => {
|
|
4
|
+
if (iframe?.contentWindow?.location) {
|
|
5
|
+
callback(iframe.contentWindow.location);
|
|
6
|
+
}
|
|
7
|
+
}, 0);
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const removeIframe = async () => {
|
|
12
|
+
const iframeSelector = document.querySelector(
|
|
13
|
+
'.checkout-payment-redirection-iframe-wrapper'
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const redirectionPaymentWrapper = document.querySelector(
|
|
17
|
+
'.checkout-redirection-payment-wrapper'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const form = redirectionPaymentWrapper.querySelector('form') as HTMLElement;
|
|
21
|
+
|
|
22
|
+
if (!iframeSelector) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
iframeSelector.remove();
|
|
27
|
+
|
|
28
|
+
if (form) {
|
|
29
|
+
form.style.display = 'block';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
location.reload();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const showRedirectionIframe = (redirectUrl: string) => {
|
|
36
|
+
const iframeWrapper = document.createElement('div');
|
|
37
|
+
const iframe = document.createElement('iframe');
|
|
38
|
+
const closeButton = document.createElement('div');
|
|
39
|
+
const redirectionPaymentWrapper = document.querySelector(
|
|
40
|
+
'.checkout-redirection-payment-wrapper'
|
|
41
|
+
);
|
|
42
|
+
const form = redirectionPaymentWrapper.querySelector('form') as HTMLElement;
|
|
43
|
+
|
|
44
|
+
iframeWrapper.className = 'checkout-payment-redirection-iframe-wrapper';
|
|
45
|
+
closeButton.className = 'close-button';
|
|
46
|
+
|
|
47
|
+
iframe.setAttribute('src', redirectUrl);
|
|
48
|
+
closeButton.innerHTML = '✕';
|
|
49
|
+
closeButton.addEventListener('click', removeIframe);
|
|
50
|
+
|
|
51
|
+
iframeWrapper.append(iframe, closeButton);
|
|
52
|
+
|
|
53
|
+
if (form) {
|
|
54
|
+
form.style.display = 'none';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
redirectionPaymentWrapper.appendChild(iframeWrapper);
|
|
58
|
+
|
|
59
|
+
iframeURLChange(iframe, (location) => {
|
|
60
|
+
if (location.origin !== window.location.origin) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const searchParams = new URLSearchParams(location.search);
|
|
65
|
+
const isOrderCompleted = location.href.includes('/orders/completed');
|
|
66
|
+
|
|
67
|
+
if (isOrderCompleted) {
|
|
68
|
+
(window.parent as any)?.postMessage?.(
|
|
69
|
+
JSON.stringify({
|
|
70
|
+
url: location.pathname
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
searchParams.has('success') ||
|
|
77
|
+
isOrderCompleted ||
|
|
78
|
+
location.href.includes('/orders/checkout')
|
|
79
|
+
) {
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
removeIframe();
|
|
82
|
+
}, 0);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|
|
@@ -5,10 +5,10 @@ import { getTranslateFn } from '../utils';
|
|
|
5
5
|
import { Translations } from '../types';
|
|
6
6
|
import settings from 'settings';
|
|
7
7
|
import logger from './log';
|
|
8
|
+
import { unstable_cache } from 'next/cache';
|
|
8
9
|
|
|
9
10
|
export const translations: Translations = {};
|
|
10
11
|
|
|
11
|
-
// TODO: Read translations from cache
|
|
12
12
|
export async function getTranslations(locale_: string) {
|
|
13
13
|
try {
|
|
14
14
|
const locale = settings.localization.locales.find(
|
|
@@ -52,6 +52,10 @@ export async function getTranslations(locale_: string) {
|
|
|
52
52
|
return translations;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export const getCachedTranslations = unstable_cache(async (locale: string) =>
|
|
56
|
+
getTranslations(locale)
|
|
57
|
+
);
|
|
58
|
+
|
|
55
59
|
export function t(path: string) {
|
|
56
60
|
return getTranslateFn(path, translations);
|
|
57
61
|
}
|
package/with-pz-config.js
CHANGED
|
@@ -8,6 +8,7 @@ const defaultConfig = {
|
|
|
8
8
|
transpilePackages: ['@akinon/next', ...pzPlugins.map((p) => `@akinon/${p}`)],
|
|
9
9
|
skipTrailingSlashRedirect: true,
|
|
10
10
|
poweredByHeader: false,
|
|
11
|
+
cacheMaxMemorySize: 0,
|
|
11
12
|
env: {
|
|
12
13
|
NEXT_PUBLIC_SENTRY_DSN: process.env.SENTRY_DSN
|
|
13
14
|
},
|
|
@@ -65,7 +66,12 @@ const defaultConfig = {
|
|
|
65
66
|
}
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
const withPzConfig = (
|
|
69
|
+
const withPzConfig = (
|
|
70
|
+
myNextConfig = {},
|
|
71
|
+
options = {
|
|
72
|
+
useCacheHandler: false
|
|
73
|
+
}
|
|
74
|
+
) => {
|
|
69
75
|
let extendedConfig = deepMerge({}, defaultConfig, myNextConfig);
|
|
70
76
|
|
|
71
77
|
const originalPzHeadersFunction = defaultConfig.headers;
|
|
@@ -91,6 +97,10 @@ const withPzConfig = (myNextConfig = {}) => {
|
|
|
91
97
|
return [...pzRewrites, ...myRewrites];
|
|
92
98
|
};
|
|
93
99
|
|
|
100
|
+
if (options.useCacheHandler && process.env.CACHE_HOST) {
|
|
101
|
+
extendedConfig.cacheHandler = require.resolve('./lib/cache-handler.mjs');
|
|
102
|
+
}
|
|
103
|
+
|
|
94
104
|
return extendedConfig;
|
|
95
105
|
};
|
|
96
106
|
|