@akinon/next 1.96.0-snapshot-ZERO-35861-20250908151109 → 1.96.0-snapshot-ZERO-3620-20250915165755
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 +1395 -45
- package/__tests__/next-config.test.ts +1 -10
- package/__tests__/redirect.test.ts +319 -0
- package/api/cache.ts +5 -39
- package/api/image-proxy.ts +75 -0
- package/api/similar-product-list.ts +84 -0
- package/api/similar-products.ts +120 -0
- package/components/accordion.tsx +20 -5
- package/components/file-input.tsx +65 -3
- package/components/input.tsx +2 -0
- package/components/link.tsx +16 -12
- package/components/modal.tsx +32 -16
- package/components/plugin-module.tsx +30 -3
- package/data/client/checkout.ts +5 -4
- package/data/server/basket.ts +72 -0
- package/data/server/category.ts +50 -32
- package/data/server/flatpage.ts +17 -16
- package/data/server/form.ts +1 -4
- package/data/server/landingpage.ts +16 -12
- package/data/server/list.ts +24 -15
- package/data/server/menu.ts +2 -5
- package/data/server/product.ts +67 -41
- package/data/server/special-page.ts +16 -12
- package/data/server/widget.ts +1 -4
- package/data/urls.ts +5 -1
- package/hocs/server/with-segment-defaults.tsx +5 -2
- package/hooks/use-localization.ts +2 -3
- package/jest.config.js +7 -1
- package/lib/cache-handler.mjs +87 -365
- package/lib/cache.ts +25 -252
- package/middlewares/complete-gpay.ts +2 -1
- package/middlewares/complete-masterpass.ts +2 -1
- package/middlewares/default.ts +50 -13
- package/middlewares/locale.ts +9 -1
- package/middlewares/pretty-url.ts +1 -2
- package/middlewares/redirection-payment.ts +2 -1
- package/middlewares/saved-card-redirection.ts +2 -1
- package/middlewares/three-d-redirection.ts +2 -1
- package/middlewares/url-redirection.ts +8 -14
- package/package.json +3 -4
- package/plugins.d.ts +8 -0
- package/plugins.js +3 -1
- package/redux/middlewares/checkout.ts +5 -1
- package/types/commerce/order.ts +1 -0
- package/types/index.ts +34 -2
- package/utils/app-fetch.ts +7 -2
- package/utils/redirect-ignore.ts +35 -0
- package/utils/redirect.ts +31 -6
- package/with-pz-config.js +1 -5
package/components/accordion.tsx
CHANGED
|
@@ -7,15 +7,19 @@ import { AccordionProps } from '../types';
|
|
|
7
7
|
|
|
8
8
|
export const Accordion = ({
|
|
9
9
|
isCollapse = false,
|
|
10
|
+
collapseClassName,
|
|
10
11
|
title,
|
|
11
12
|
subTitle,
|
|
12
13
|
icons = ['chevron-up', 'chevron-down'],
|
|
13
14
|
iconSize = 16,
|
|
14
15
|
iconColor = 'fill-[#000000]',
|
|
15
16
|
children,
|
|
17
|
+
headerClassName,
|
|
16
18
|
className,
|
|
17
19
|
titleClassName,
|
|
18
|
-
|
|
20
|
+
subTitleClassName,
|
|
21
|
+
dataTestId,
|
|
22
|
+
contentClassName
|
|
19
23
|
}: AccordionProps) => {
|
|
20
24
|
const [collapse, setCollapse] = useState(isCollapse);
|
|
21
25
|
|
|
@@ -27,15 +31,22 @@ export const Accordion = ({
|
|
|
27
31
|
)}
|
|
28
32
|
>
|
|
29
33
|
<div
|
|
30
|
-
className=
|
|
34
|
+
className={twMerge(
|
|
35
|
+
'flex items-center justify-between cursor-pointer',
|
|
36
|
+
headerClassName
|
|
37
|
+
)}
|
|
31
38
|
onClick={() => setCollapse(!collapse)}
|
|
32
39
|
data-testid={dataTestId}
|
|
33
40
|
>
|
|
34
|
-
<div className=
|
|
41
|
+
<div className={twMerge('flex flex-col', contentClassName)}>
|
|
35
42
|
{title && (
|
|
36
43
|
<h3 className={twMerge('text-sm', titleClassName)}>{title}</h3>
|
|
37
44
|
)}
|
|
38
|
-
{subTitle &&
|
|
45
|
+
{subTitle && (
|
|
46
|
+
<h4 className={twMerge('text-xs text-gray-700', subTitleClassName)}>
|
|
47
|
+
{subTitle}
|
|
48
|
+
</h4>
|
|
49
|
+
)}
|
|
39
50
|
</div>
|
|
40
51
|
|
|
41
52
|
{icons && (
|
|
@@ -46,7 +57,11 @@ export const Accordion = ({
|
|
|
46
57
|
/>
|
|
47
58
|
)}
|
|
48
59
|
</div>
|
|
49
|
-
{collapse &&
|
|
60
|
+
{collapse && (
|
|
61
|
+
<div className={twMerge('mt-3 text-sm', collapseClassName)}>
|
|
62
|
+
{children}
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
50
65
|
</div>
|
|
51
66
|
);
|
|
52
67
|
};
|
|
@@ -1,8 +1,70 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
1
2
|
import { forwardRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { FileInputProps } from '../types';
|
|
3
6
|
|
|
4
7
|
export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
|
|
5
|
-
function
|
|
6
|
-
|
|
8
|
+
function FileInput(
|
|
9
|
+
{
|
|
10
|
+
buttonClassName,
|
|
11
|
+
onChange,
|
|
12
|
+
fileClassName,
|
|
13
|
+
fileNameWrapperClassName,
|
|
14
|
+
fileInputClassName,
|
|
15
|
+
...props
|
|
16
|
+
},
|
|
17
|
+
ref
|
|
18
|
+
) {
|
|
19
|
+
const { t } = useLocalization();
|
|
20
|
+
const [fileNames, setFileNames] = useState<string[]>([]);
|
|
21
|
+
|
|
22
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
23
|
+
const files = Array.from(event.target.files || []);
|
|
24
|
+
setFileNames(files.map((file) => file.name));
|
|
25
|
+
|
|
26
|
+
if (onChange) {
|
|
27
|
+
onChange(event);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className="relative">
|
|
33
|
+
<input
|
|
34
|
+
type="file"
|
|
35
|
+
{...props}
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={twMerge(
|
|
38
|
+
'absolute inset-0 w-full h-full opacity-0 cursor-pointer',
|
|
39
|
+
fileInputClassName
|
|
40
|
+
)}
|
|
41
|
+
onChange={handleFileChange}
|
|
42
|
+
/>
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
className={twMerge(
|
|
46
|
+
'bg-primary text-white py-2 px-4 text-sm',
|
|
47
|
+
buttonClassName
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
{t('common.file_input.select_file')}
|
|
51
|
+
</button>
|
|
52
|
+
<div
|
|
53
|
+
className={twMerge('mt-1 text-gray-500', fileNameWrapperClassName)}
|
|
54
|
+
>
|
|
55
|
+
{fileNames.length > 0 ? (
|
|
56
|
+
<ul className={twMerge('list-disc pl-4 text-xs', fileClassName)}>
|
|
57
|
+
{fileNames.map((name, index) => (
|
|
58
|
+
<li key={index}>{name}</li>
|
|
59
|
+
))}
|
|
60
|
+
</ul>
|
|
61
|
+
) : (
|
|
62
|
+
<span className={twMerge('text-xs', fileClassName)}>
|
|
63
|
+
{t('common.file_input.no_file')}
|
|
64
|
+
</span>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
7
69
|
}
|
|
8
70
|
);
|
package/components/input.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { forwardRef, FocusEvent, useState, Ref } from 'react';
|
|
3
3
|
import { Controller } from 'react-hook-form';
|
|
4
|
+
|
|
5
|
+
// @ts-ignore
|
|
4
6
|
import { PatternFormat, PatternFormatProps } from 'react-number-format';
|
|
5
7
|
import { InputProps } from '../types';
|
|
6
8
|
import { twMerge } from 'tailwind-merge';
|
package/components/link.tsx
CHANGED
|
@@ -10,7 +10,9 @@ type LinkProps = Omit<
|
|
|
10
10
|
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
11
11
|
keyof NextLinkProps
|
|
12
12
|
> &
|
|
13
|
-
NextLinkProps
|
|
13
|
+
NextLinkProps & {
|
|
14
|
+
href: string;
|
|
15
|
+
};
|
|
14
16
|
|
|
15
17
|
export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
16
18
|
const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
|
|
@@ -26,19 +28,21 @@ export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
|
26
28
|
return href;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
if (typeof href === 'string' && !href.startsWith('http')) {
|
|
32
|
+
const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
|
|
33
|
+
const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
|
|
34
|
+
|
|
35
|
+
if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
|
|
36
|
+
return hrefWithLocale;
|
|
37
|
+
} else if (
|
|
38
|
+
localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
|
|
39
|
+
locale !== defaultLocaleValue
|
|
40
|
+
) {
|
|
41
|
+
return hrefWithLocale;
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
return href
|
|
45
|
+
return href;
|
|
42
46
|
}, [href, defaultLocaleValue, locale, localeUrlStrategy]);
|
|
43
47
|
|
|
44
48
|
return (
|
package/components/modal.tsx
CHANGED
|
@@ -4,16 +4,7 @@ import { ReactPortal } from './react-portal';
|
|
|
4
4
|
import { Icon } from './icon';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
|
|
8
|
-
export interface ModalProps {
|
|
9
|
-
portalId: string;
|
|
10
|
-
children?: React.ReactNode;
|
|
11
|
-
open?: boolean;
|
|
12
|
-
setOpen?: (open: boolean) => void;
|
|
13
|
-
title?: React.ReactNode;
|
|
14
|
-
showCloseButton?: React.ReactNode;
|
|
15
|
-
className?: string;
|
|
16
|
-
}
|
|
7
|
+
import { ModalProps } from '../types';
|
|
17
8
|
|
|
18
9
|
export const Modal = (props: ModalProps) => {
|
|
19
10
|
const {
|
|
@@ -23,7 +14,14 @@ export const Modal = (props: ModalProps) => {
|
|
|
23
14
|
setOpen,
|
|
24
15
|
title = '',
|
|
25
16
|
showCloseButton = true,
|
|
26
|
-
className
|
|
17
|
+
className,
|
|
18
|
+
overlayClassName,
|
|
19
|
+
headerWrapperClassName,
|
|
20
|
+
titleClassName,
|
|
21
|
+
closeButtonClassName,
|
|
22
|
+
iconName = 'close',
|
|
23
|
+
iconSize = 16,
|
|
24
|
+
iconClassName
|
|
27
25
|
} = props;
|
|
28
26
|
|
|
29
27
|
useEffect(() => {
|
|
@@ -38,7 +36,12 @@ export const Modal = (props: ModalProps) => {
|
|
|
38
36
|
|
|
39
37
|
return (
|
|
40
38
|
<ReactPortal wrapperId={portalId}>
|
|
41
|
-
<div
|
|
39
|
+
<div
|
|
40
|
+
className={twMerge(
|
|
41
|
+
'fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50',
|
|
42
|
+
overlayClassName
|
|
43
|
+
)}
|
|
44
|
+
/>
|
|
42
45
|
<section
|
|
43
46
|
className={twMerge(
|
|
44
47
|
'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 bg-white',
|
|
@@ -46,15 +49,28 @@ export const Modal = (props: ModalProps) => {
|
|
|
46
49
|
)}
|
|
47
50
|
>
|
|
48
51
|
{(showCloseButton || title) && (
|
|
49
|
-
<div
|
|
50
|
-
|
|
52
|
+
<div
|
|
53
|
+
className={twMerge(
|
|
54
|
+
'flex px-6 py-4 border-b border-gray-400',
|
|
55
|
+
headerWrapperClassName
|
|
56
|
+
)}
|
|
57
|
+
>
|
|
58
|
+
{title && (
|
|
59
|
+
<h3 className={twMerge('text-lg font-light', titleClassName)}>
|
|
60
|
+
{title}
|
|
61
|
+
</h3>
|
|
62
|
+
)}
|
|
51
63
|
{showCloseButton && (
|
|
52
64
|
<button
|
|
53
65
|
type="button"
|
|
54
66
|
onClick={() => setOpen(false)}
|
|
55
|
-
className=
|
|
67
|
+
className={twMerge('ml-auto', closeButtonClassName)}
|
|
56
68
|
>
|
|
57
|
-
<Icon
|
|
69
|
+
<Icon
|
|
70
|
+
name={iconName}
|
|
71
|
+
size={iconSize}
|
|
72
|
+
className={iconClassName}
|
|
73
|
+
/>
|
|
58
74
|
</button>
|
|
59
75
|
)}
|
|
60
76
|
</div>
|
|
@@ -21,7 +21,9 @@ enum Plugin {
|
|
|
21
21
|
Akifast = 'pz-akifast',
|
|
22
22
|
MultiBasket = 'pz-multi-basket',
|
|
23
23
|
SavedCard = 'pz-saved-card',
|
|
24
|
-
|
|
24
|
+
Hepsipay = 'pz-hepsipay',
|
|
25
|
+
FlowPayment = 'pz-flow-payment',
|
|
26
|
+
SimilarProducts = 'pz-similar-products'
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export enum Component {
|
|
@@ -47,7 +49,15 @@ export enum Component {
|
|
|
47
49
|
AkifastCheckoutButton = 'CheckoutButton',
|
|
48
50
|
MultiBasket = 'MultiBasket',
|
|
49
51
|
SavedCard = 'SavedCardOption',
|
|
50
|
-
|
|
52
|
+
Hepsipay = 'Hepsipay',
|
|
53
|
+
FlowPayment = 'FlowPayment',
|
|
54
|
+
SimilarProductsModal = 'SimilarProductsModal',
|
|
55
|
+
SimilarProductsFilterSidebar = 'SimilarProductsFilterSidebar',
|
|
56
|
+
SimilarProductsResultsGrid = 'SimilarProductsResultsGrid',
|
|
57
|
+
SimilarProductsPlugin = 'SimilarProductsPlugin',
|
|
58
|
+
ProductImageSearchFeature = 'ProductImageSearchFeature',
|
|
59
|
+
ImageSearchButton = 'ImageSearchButton',
|
|
60
|
+
HeaderImageSearchFeature = 'HeaderImageSearchFeature'
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
const PluginComponents = new Map([
|
|
@@ -81,7 +91,20 @@ const PluginComponents = new Map([
|
|
|
81
91
|
],
|
|
82
92
|
[Plugin.MultiBasket, [Component.MultiBasket]],
|
|
83
93
|
[Plugin.SavedCard, [Component.SavedCard]],
|
|
84
|
-
[Plugin.
|
|
94
|
+
[Plugin.Hepsipay, [Component.Hepsipay]],
|
|
95
|
+
[Plugin.FlowPayment, [Component.FlowPayment]],
|
|
96
|
+
[
|
|
97
|
+
Plugin.SimilarProducts,
|
|
98
|
+
[
|
|
99
|
+
Component.SimilarProductsModal,
|
|
100
|
+
Component.SimilarProductsFilterSidebar,
|
|
101
|
+
Component.SimilarProductsResultsGrid,
|
|
102
|
+
Component.SimilarProductsPlugin,
|
|
103
|
+
Component.ProductImageSearchFeature,
|
|
104
|
+
Component.ImageSearchButton,
|
|
105
|
+
Component.HeaderImageSearchFeature
|
|
106
|
+
]
|
|
107
|
+
]
|
|
85
108
|
]);
|
|
86
109
|
|
|
87
110
|
const getPlugin = (component: Component) => {
|
|
@@ -146,8 +169,12 @@ export default function PluginModule({
|
|
|
146
169
|
promise = import(`${'@akinon/pz-multi-basket'}`);
|
|
147
170
|
} else if (plugin === Plugin.SavedCard) {
|
|
148
171
|
promise = import(`${'@akinon/pz-saved-card'}`);
|
|
172
|
+
} else if (plugin === Plugin.Hepsipay) {
|
|
173
|
+
promise = import(`${'@akinon/pz-hepsipay'}`);
|
|
149
174
|
} else if (plugin === Plugin.FlowPayment) {
|
|
150
175
|
promise = import(`${'@akinon/pz-flow-payment'}`);
|
|
176
|
+
} else if (plugin === Plugin.SimilarProducts) {
|
|
177
|
+
promise = import(`${'@akinon/pz-similar-products'}`);
|
|
151
178
|
}
|
|
152
179
|
} catch (error) {
|
|
153
180
|
logger.error(error);
|
package/data/client/checkout.ts
CHANGED
|
@@ -35,8 +35,10 @@ import {
|
|
|
35
35
|
|
|
36
36
|
interface CheckoutResponse {
|
|
37
37
|
pre_order?: PreOrder;
|
|
38
|
-
errors
|
|
39
|
-
non_field_errors
|
|
38
|
+
errors?: {
|
|
39
|
+
non_field_errors?: string;
|
|
40
|
+
sample_products?: string[];
|
|
41
|
+
[key: string]: string | string[] | undefined;
|
|
40
42
|
};
|
|
41
43
|
context_list?: CheckoutContext[];
|
|
42
44
|
template_name?: string;
|
|
@@ -884,8 +886,7 @@ export const checkoutApi = api.injectEndpoints({
|
|
|
884
886
|
method: 'POST',
|
|
885
887
|
body: formData
|
|
886
888
|
};
|
|
887
|
-
}
|
|
888
|
-
invalidatesTags: ['Checkout']
|
|
889
|
+
}
|
|
889
890
|
})
|
|
890
891
|
}),
|
|
891
892
|
overrideExisting: false
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Cache, CacheKey } from '../../lib/cache';
|
|
2
|
+
import { basket } from '../../data/urls';
|
|
3
|
+
import { Basket } from '../../types';
|
|
4
|
+
import appFetch from '../../utils/app-fetch';
|
|
5
|
+
import { ServerVariables } from '../../utils/server-variables';
|
|
6
|
+
import logger from '../../utils/log';
|
|
7
|
+
|
|
8
|
+
type GetBasketParams = {
|
|
9
|
+
locale?: string;
|
|
10
|
+
currency?: string;
|
|
11
|
+
namespace?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getBasketDataHandler = ({
|
|
15
|
+
locale,
|
|
16
|
+
currency,
|
|
17
|
+
namespace
|
|
18
|
+
}: GetBasketParams) => {
|
|
19
|
+
return async function () {
|
|
20
|
+
try {
|
|
21
|
+
const url = namespace
|
|
22
|
+
? basket.getBasketDetail(namespace)
|
|
23
|
+
: basket.getBasket;
|
|
24
|
+
|
|
25
|
+
const basketData = await appFetch<{ basket: Basket }>({
|
|
26
|
+
url,
|
|
27
|
+
locale,
|
|
28
|
+
currency,
|
|
29
|
+
init: {
|
|
30
|
+
headers: {
|
|
31
|
+
Accept: 'application/json',
|
|
32
|
+
'Content-Type': 'application/json'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!basketData?.basket) {
|
|
38
|
+
logger.warn('Basket data is undefined', {
|
|
39
|
+
handler: 'getBasketDataHandler',
|
|
40
|
+
namespace
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return basketData;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error('Error fetching basket data', {
|
|
47
|
+
handler: 'getBasketDataHandler',
|
|
48
|
+
error,
|
|
49
|
+
namespace
|
|
50
|
+
});
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const getBasketData = async ({
|
|
57
|
+
locale = ServerVariables.locale,
|
|
58
|
+
currency = ServerVariables.currency,
|
|
59
|
+
namespace
|
|
60
|
+
}: GetBasketParams = {}) => {
|
|
61
|
+
return Cache.wrap(
|
|
62
|
+
CacheKey.Basket(namespace),
|
|
63
|
+
locale,
|
|
64
|
+
getBasketDataHandler({ locale, currency, namespace }),
|
|
65
|
+
{
|
|
66
|
+
expire: 0,
|
|
67
|
+
cache: false
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
|
package/data/server/category.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { category, product } from '../urls';
|
|
|
5
5
|
import { Cache, CacheKey } from '../../lib/cache';
|
|
6
6
|
import { parse } from 'lossless-json';
|
|
7
7
|
import logger from '../../utils/log';
|
|
8
|
-
import { headers as nHeaders } from 'next/headers';
|
|
9
8
|
import { ServerVariables } from '../../utils/server-variables';
|
|
10
9
|
|
|
11
10
|
function getCategoryDataHandler(
|
|
@@ -18,19 +17,30 @@ function getCategoryDataHandler(
|
|
|
18
17
|
return async function () {
|
|
19
18
|
const params = generateCommerceSearchParams(searchParams);
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
let rawData: string;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
rawData = await appFetch<string>({
|
|
24
|
+
url: `${category.getCategoryByPk(pk)}${params ? params : ''}`,
|
|
25
|
+
locale,
|
|
26
|
+
currency,
|
|
27
|
+
init: {
|
|
28
|
+
headers: {
|
|
29
|
+
Accept: 'application/json',
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
...(headers ?? {})
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
responseType: FetchResponseType.TEXT
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error('Failed to fetch category data', {
|
|
38
|
+
handler: 'getCategoryDataHandler',
|
|
39
|
+
pk,
|
|
40
|
+
error: error.message
|
|
41
|
+
});
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
34
44
|
|
|
35
45
|
let data: GetCategoryResponse;
|
|
36
46
|
|
|
@@ -48,8 +58,8 @@ function getCategoryDataHandler(
|
|
|
48
58
|
logger.fatal('Error while parsing category data', {
|
|
49
59
|
handler: 'getCategoryDataHandler',
|
|
50
60
|
error,
|
|
51
|
-
rawData: rawData
|
|
52
|
-
? `${rawData
|
|
61
|
+
rawData: rawData?.startsWith?.('<!DOCTYPE html>')
|
|
62
|
+
? `${rawData?.substring(0, 50)}...`
|
|
53
63
|
: rawData
|
|
54
64
|
});
|
|
55
65
|
}
|
|
@@ -64,17 +74,27 @@ function getCategoryDataHandler(
|
|
|
64
74
|
return { data, breadcrumbData: undefined };
|
|
65
75
|
}
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
let breadcrumbData: { menu?: unknown } = {};
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
breadcrumbData = await appFetch<{ menu?: unknown }>({
|
|
81
|
+
url: product.breadcrumbUrl(menuItemModel),
|
|
82
|
+
locale,
|
|
83
|
+
currency,
|
|
84
|
+
init: {
|
|
85
|
+
headers: {
|
|
86
|
+
Accept: 'application/json',
|
|
87
|
+
'Content-Type': 'application/json'
|
|
88
|
+
}
|
|
75
89
|
}
|
|
76
|
-
}
|
|
77
|
-
})
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
logger.warn('Failed to fetch breadcrumb data', {
|
|
93
|
+
handler: 'getCategoryDataHandler',
|
|
94
|
+
pk,
|
|
95
|
+
error: error.message
|
|
96
|
+
});
|
|
97
|
+
}
|
|
78
98
|
|
|
79
99
|
return { data, breadcrumbData: breadcrumbData?.menu };
|
|
80
100
|
};
|
|
@@ -98,8 +118,7 @@ export const getCategoryData = ({
|
|
|
98
118
|
locale,
|
|
99
119
|
getCategoryDataHandler(pk, locale, currency, searchParams, headers),
|
|
100
120
|
{
|
|
101
|
-
expire: 300
|
|
102
|
-
compressed: true
|
|
121
|
+
expire: 300
|
|
103
122
|
}
|
|
104
123
|
);
|
|
105
124
|
};
|
|
@@ -139,8 +158,8 @@ function getCategoryBySlugDataHandler(
|
|
|
139
158
|
logger.fatal('Error while parsing category data', {
|
|
140
159
|
handler: 'getCategoryBySlugDataHandler',
|
|
141
160
|
error,
|
|
142
|
-
rawData: rawData
|
|
143
|
-
? `${rawData
|
|
161
|
+
rawData: rawData?.startsWith?.('<!DOCTYPE html>')
|
|
162
|
+
? `${rawData?.substring(0, 50)}...`
|
|
144
163
|
: rawData
|
|
145
164
|
});
|
|
146
165
|
}
|
|
@@ -159,8 +178,7 @@ export const getCategoryBySlugData = async ({
|
|
|
159
178
|
locale,
|
|
160
179
|
getCategoryBySlugDataHandler(slug, locale, currency),
|
|
161
180
|
{
|
|
162
|
-
expire: 300
|
|
163
|
-
compressed: true
|
|
181
|
+
expire: 300
|
|
164
182
|
}
|
|
165
183
|
);
|
|
166
184
|
};
|
package/data/server/flatpage.ts
CHANGED
|
@@ -11,20 +11,24 @@ const getFlatPageDataHandler = (
|
|
|
11
11
|
headers?: Record<string, string>
|
|
12
12
|
) => {
|
|
13
13
|
return async function () {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
try {
|
|
15
|
+
const data = await appFetch<FlatPage>({
|
|
16
|
+
url: flatpage.getFlatPageByPk(pk),
|
|
17
|
+
locale,
|
|
18
|
+
currency,
|
|
19
|
+
init: {
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(headers ?? {})
|
|
24
|
+
}
|
|
23
25
|
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
+
});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
return data;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
28
32
|
};
|
|
29
33
|
};
|
|
30
34
|
|
|
@@ -42,9 +46,6 @@ export const getFlatPageData = ({
|
|
|
42
46
|
return Cache.wrap(
|
|
43
47
|
CacheKey.FlatPage(pk),
|
|
44
48
|
locale,
|
|
45
|
-
getFlatPageDataHandler(pk, locale, currency, headers)
|
|
46
|
-
{
|
|
47
|
-
compressed: true
|
|
48
|
-
}
|
|
49
|
+
getFlatPageDataHandler(pk, locale, currency, headers)
|
|
49
50
|
);
|
|
50
51
|
};
|
package/data/server/form.ts
CHANGED
|
@@ -11,20 +11,24 @@ const getLandingPageHandler = (
|
|
|
11
11
|
headers?: Record<string, string>
|
|
12
12
|
) => {
|
|
13
13
|
return async function () {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
try {
|
|
15
|
+
const data = await appFetch<LandingPage>({
|
|
16
|
+
url: landingpage.getLandingPageByPk(pk),
|
|
17
|
+
locale,
|
|
18
|
+
currency,
|
|
19
|
+
init: {
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(headers ?? {})
|
|
24
|
+
}
|
|
23
25
|
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
+
});
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
return data;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
28
32
|
};
|
|
29
33
|
};
|
|
30
34
|
|