@akinon/next 1.48.0 → 1.50.0-rc.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +382 -0
  2. package/api/client.ts +50 -17
  3. package/assets/styles/index.css +49 -0
  4. package/assets/styles/index.css.map +1 -0
  5. package/assets/styles/index.scss +50 -26
  6. package/bin/pz-generate-translations.js +41 -0
  7. package/bin/pz-prebuild.js +1 -0
  8. package/bin/pz-predev.js +1 -0
  9. package/components/file-input.tsx +8 -0
  10. package/components/index.ts +1 -0
  11. package/components/input.tsx +21 -7
  12. package/components/link.tsx +17 -13
  13. package/components/pagination.tsx +1 -2
  14. package/components/price.tsx +11 -4
  15. package/components/pz-root.tsx +15 -3
  16. package/components/selected-payment-option-view.tsx +26 -38
  17. package/data/client/account.ts +10 -9
  18. package/data/client/address.ts +32 -8
  19. package/data/client/api.ts +2 -2
  20. package/data/client/b2b.ts +35 -2
  21. package/data/client/basket.ts +6 -5
  22. package/data/client/checkout.ts +67 -4
  23. package/data/client/user.ts +3 -2
  24. package/data/client/wishlist.ts +8 -1
  25. package/data/server/category.ts +43 -19
  26. package/data/server/flatpage.ts +29 -7
  27. package/data/server/form.ts +29 -11
  28. package/data/server/landingpage.ts +26 -7
  29. package/data/server/list.ts +16 -6
  30. package/data/server/menu.ts +15 -2
  31. package/data/server/product.ts +46 -21
  32. package/data/server/seo.ts +17 -24
  33. package/data/server/special-page.ts +15 -5
  34. package/data/server/widget.ts +14 -7
  35. package/data/urls.ts +12 -2
  36. package/hocs/server/with-segment-defaults.tsx +4 -1
  37. package/hooks/index.ts +2 -1
  38. package/hooks/use-message-listener.ts +24 -0
  39. package/hooks/use-pagination.ts +2 -2
  40. package/hooks/use-payment-options.ts +2 -1
  41. package/lib/cache-handler.mjs +33 -0
  42. package/lib/cache.ts +8 -6
  43. package/middlewares/default.ts +91 -8
  44. package/middlewares/pretty-url.ts +11 -1
  45. package/middlewares/url-redirection.ts +4 -0
  46. package/package.json +5 -4
  47. package/plugins.d.ts +1 -0
  48. package/redux/middlewares/checkout.ts +70 -11
  49. package/redux/reducers/checkout.ts +24 -5
  50. package/redux/reducers/config.ts +2 -0
  51. package/routes/pretty-url.tsx +192 -0
  52. package/types/commerce/account.ts +1 -0
  53. package/types/commerce/address.ts +1 -1
  54. package/types/commerce/b2b.ts +12 -2
  55. package/types/commerce/checkout.ts +33 -0
  56. package/types/commerce/misc.ts +2 -0
  57. package/types/commerce/order.ts +12 -0
  58. package/types/index.ts +37 -3
  59. package/utils/app-fetch.ts +21 -10
  60. package/utils/generate-commerce-search-params.ts +3 -1
  61. package/utils/index.ts +27 -6
  62. package/utils/menu-generator.ts +2 -2
  63. package/utils/redirection-iframe.ts +85 -0
  64. package/utils/server-translation.ts +11 -1
  65. package/utils/server-variables.ts +2 -1
  66. package/with-pz-config.js +13 -2
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  setBankAccounts,
3
+ setCardType,
3
4
  setInstallmentOptions,
4
5
  setPaymentStepBusy,
5
6
  setSelectedBankAccountPk,
6
7
  setSelectedCreditPaymentPk,
7
- setShippingStepBusy,
8
- setCardType
8
+ setShippingStepBusy
9
9
  } from '../../redux/reducers/checkout';
10
10
  import {
11
11
  CheckoutContext,
@@ -20,6 +20,7 @@ import { AppDispatch, AppStore, store } from 'redux/store';
20
20
  import settings from 'settings';
21
21
  import { showMobile3dIframe } from '../../utils/mobile-3d-iframe';
22
22
  import {
23
+ setCvcRequired,
23
24
  setError,
24
25
  setOtpModalVisible
25
26
  } from '@akinon/pz-masterpass/src/redux/reducer';
@@ -113,7 +114,8 @@ const completeMasterpassPayment = async (
113
114
  ? await buildDirectPurchaseForm(commonFormValues, params)
114
115
  : await buildPurchaseForm({
115
116
  ...commonFormValues,
116
- selectedCard
117
+ selectedCard,
118
+ cardCvc: params?.card_cvv
117
119
  });
118
120
 
119
121
  window.MFS?.[
@@ -151,6 +153,10 @@ const completeMasterpassPayment = async (
151
153
  return;
152
154
  }
153
155
 
156
+ if (['5013', '5182'].includes(response.responseCode)) {
157
+ dispatch(setCvcRequired(true));
158
+ }
159
+
154
160
  if (
155
161
  response.token &&
156
162
  (response.responseCode == '0000' || response.responseCode == '')
@@ -373,6 +379,22 @@ export const checkoutApi = api.injectEndpoints({
373
379
  dispatch(setShippingStepBusy(false));
374
380
  }
375
381
  }),
382
+ setDataSourceShippingOptions: build.mutation<CheckoutResponse, number[]>({
383
+ query: (pks) => ({
384
+ url: buildClientRequestUrl(checkout.setDataSourceShippingOption, {
385
+ useFormData: true
386
+ }),
387
+ method: 'POST',
388
+ body: {
389
+ data_source_shipping_options: JSON.stringify(pks)
390
+ }
391
+ }),
392
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
393
+ dispatch(setShippingStepBusy(true));
394
+ await queryFulfilled;
395
+ dispatch(setShippingStepBusy(false));
396
+ }
397
+ }),
376
398
  setRetailStore: build.mutation<CheckoutResponse, SetRetailStoreParams>({
377
399
  query: ({ retailStorePk, billingAddressPk }) => ({
378
400
  url: buildClientRequestUrl(
@@ -654,6 +676,44 @@ export const checkoutApi = api.injectEndpoints({
654
676
  notes
655
677
  }
656
678
  })
679
+ }),
680
+ setDeliveryBags: build.mutation<
681
+ CheckoutResponse,
682
+ { sku: string; quantity?: number }
683
+ >({
684
+ query: ({ sku, quantity }) => {
685
+ const body = {
686
+ product: sku,
687
+ ...(quantity !== undefined && { quantity })
688
+ };
689
+
690
+ return {
691
+ url: buildClientRequestUrl(checkout.deliveryBagsPage, {
692
+ useFormData: true
693
+ }),
694
+ method: 'POST',
695
+ body
696
+ };
697
+ }
698
+ }),
699
+ setAttributeBasedShippingOptions: build.mutation<
700
+ CheckoutResponse,
701
+ Record<string, number>
702
+ >({
703
+ query: (options) => ({
704
+ url: buildClientRequestUrl(checkout.setAttributeBasedShippingOption, {
705
+ useFormData: true
706
+ }),
707
+ method: 'POST',
708
+ body: {
709
+ attribute_based_shipping_options: JSON.stringify(options)
710
+ }
711
+ }),
712
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
713
+ dispatch(setShippingStepBusy(true));
714
+ await queryFulfilled;
715
+ dispatch(setShippingStepBusy(false));
716
+ }
657
717
  })
658
718
  }),
659
719
  overrideExisting: false
@@ -672,6 +732,7 @@ export const {
672
732
  useSetDeliveryOptionMutation,
673
733
  useSetAddressesMutation,
674
734
  useSetShippingOptionMutation,
735
+ useSetDataSourceShippingOptionsMutation,
675
736
  useSetPaymentOptionMutation,
676
737
  useSetBinNumberMutation,
677
738
  useSetInstallmentOptionMutation,
@@ -688,5 +749,7 @@ export const {
688
749
  useCompleteLoyaltyPaymentMutation,
689
750
  useGetCheckoutLoyaltyBalanceQuery,
690
751
  usePayWithLoyaltyBalanceMutation,
691
- useSetOrderNoteMutation
752
+ useSetOrderNoteMutation,
753
+ useSetDeliveryBagsMutation,
754
+ useSetAttributeBasedShippingOptionsMutation
692
755
  } = checkoutApi;
@@ -22,11 +22,12 @@ const userApi = api.injectEndpoints({
22
22
  getCaptcha: build.query<GetCaptchaResponse, void>({
23
23
  query: () => buildClientRequestUrl(user.captcha),
24
24
  transformResponse: (response: { html: string }) => {
25
- const siteKeyMatch = response.html.match(/sitekey=["|'][^"']+/gi);
25
+ const siteKey = response.html.match(/data-sitekey="([^"]+)"/i)[1];
26
+
26
27
  const csrfTokenMatch = response.html.match(
27
28
  /name=['|"]csrfmiddlewaretoken['|"] value=['|"][^'"]+/gi
28
29
  );
29
- const siteKey = siteKeyMatch?.[0].replace(/sitekey=["|']/, '') || '';
30
+
30
31
  const csrfToken =
31
32
  csrfTokenMatch?.[0].replace(
32
33
  /name=['|"]csrfmiddlewaretoken['|"] value=['|"]/gi,
@@ -170,6 +170,12 @@ export const wishlistApi = api.injectEndpoints({
170
170
  method: 'DELETE'
171
171
  })
172
172
  }),
173
+ deleteCollectionItem: build.query<void, number>({
174
+ query: (pk: number) => ({
175
+ url: buildClientRequestUrl(wishlist.deleteCollectionItem(pk)),
176
+ method: 'DELETE'
177
+ })
178
+ }),
173
179
  editCollection: build.mutation<
174
180
  CollectionItem,
175
181
  { name: string; pk: number }
@@ -200,5 +206,6 @@ export const {
200
206
  useGetCollectionsOOSQuery,
201
207
  useLazyGetCollectionsOOSQuery,
202
208
  useLazyDeleteCollectionQuery,
203
- useEditCollectionMutation
209
+ useEditCollectionMutation,
210
+ useDeleteCollectionItemQuery
204
211
  } = wishlistApi;
@@ -5,26 +5,32 @@ 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
+ import { ServerVariables } from '../../utils/server-variables';
8
10
 
9
11
  function getCategoryDataHandler(
10
12
  pk: number,
13
+ locale: string,
14
+ currency: string,
11
15
  searchParams?: URLSearchParams,
12
16
  headers?: Record<string, string>
13
17
  ) {
14
18
  return async function () {
15
19
  const params = generateCommerceSearchParams(searchParams);
16
20
 
17
- const rawData = await appFetch<string>(
18
- `${category.getCategoryByPk(pk)}${params ? params : ''}`,
19
- {
21
+ const rawData = await appFetch<string>({
22
+ url: `${category.getCategoryByPk(pk)}${params ? params : ''}`,
23
+ locale,
24
+ currency,
25
+ init: {
20
26
  headers: {
21
27
  Accept: 'application/json',
22
28
  'Content-Type': 'application/json',
23
29
  ...(headers ?? {})
24
30
  }
25
31
  },
26
- FetchResponseType.TEXT
27
- );
32
+ responseType: FetchResponseType.TEXT
33
+ });
28
34
 
29
35
  let data: GetCategoryResponse;
30
36
 
@@ -58,15 +64,17 @@ function getCategoryDataHandler(
58
64
  return { data, breadcrumbData: undefined };
59
65
  }
60
66
 
61
- const breadcrumbData = await appFetch<any>(
62
- product.breadcrumbUrl(menuItemModel),
63
- {
67
+ const breadcrumbData = await appFetch<any>({
68
+ url: product.breadcrumbUrl(menuItemModel),
69
+ locale,
70
+ currency,
71
+ init: {
64
72
  headers: {
65
73
  Accept: 'application/json',
66
74
  'Content-Type': 'application/json'
67
75
  }
68
76
  }
69
- );
77
+ });
70
78
 
71
79
  return { data, breadcrumbData: breadcrumbData?.menu };
72
80
  };
@@ -75,33 +83,44 @@ function getCategoryDataHandler(
75
83
  export const getCategoryData = ({
76
84
  pk,
77
85
  searchParams,
78
- headers
86
+ headers,
87
+ locale = ServerVariables.locale,
88
+ currency = ServerVariables.currency
79
89
  }: {
80
90
  pk: number;
91
+ locale?: string;
92
+ currency?: string;
81
93
  searchParams?: URLSearchParams;
82
94
  headers?: Record<string, string>;
83
95
  }) => {
84
96
  return Cache.wrap(
85
97
  CacheKey.Category(pk, searchParams, headers),
86
- getCategoryDataHandler(pk, searchParams, headers),
98
+ locale,
99
+ getCategoryDataHandler(pk, locale, currency, searchParams, headers),
87
100
  {
88
101
  expire: 300
89
102
  }
90
103
  );
91
104
  };
92
105
 
93
- function getCategoryBySlugDataHandler(slug: string) {
106
+ function getCategoryBySlugDataHandler(
107
+ slug: string,
108
+ locale: string,
109
+ currency: string
110
+ ) {
94
111
  return async function () {
95
- const rawData = await appFetch<string>(
96
- category.getCategoryBySlug(slug),
97
- {
112
+ const rawData = await appFetch<string>({
113
+ url: category.getCategoryBySlug(slug),
114
+ locale,
115
+ currency,
116
+ init: {
98
117
  headers: {
99
118
  Accept: 'application/json',
100
119
  'Content-Type': 'application/json'
101
120
  }
102
121
  },
103
- FetchResponseType.TEXT
104
- );
122
+ responseType: FetchResponseType.TEXT
123
+ });
105
124
 
106
125
  let data: GetCategoryResponse;
107
126
 
@@ -129,10 +148,15 @@ function getCategoryBySlugDataHandler(slug: string) {
129
148
  };
130
149
  }
131
150
 
132
- export const getCategoryBySlugData = async ({ slug }) => {
151
+ export const getCategoryBySlugData = async ({
152
+ slug,
153
+ locale = ServerVariables.locale,
154
+ currency = ServerVariables.currency
155
+ }) => {
133
156
  return Cache.wrap(
134
157
  CacheKey.CategorySlug(slug),
135
- getCategoryBySlugDataHandler(slug),
158
+ locale,
159
+ getCategoryBySlugDataHandler(slug, locale, currency),
136
160
  {
137
161
  expire: 300
138
162
  }
@@ -2,13 +2,23 @@ import { flatpage } from '../urls';
2
2
  import { FlatPage } from '../../types';
3
3
  import appFetch from '../../utils/app-fetch';
4
4
  import { Cache, CacheKey } from '../../lib/cache';
5
+ import { ServerVariables } from '../../utils/server-variables';
5
6
 
6
- const getFlatPageDataHandler = (pk: number) => {
7
+ const getFlatPageDataHandler = (
8
+ pk: number,
9
+ locale: string,
10
+ currency: string
11
+ ) => {
7
12
  return async function () {
8
- const data = await appFetch<FlatPage>(flatpage.getFlatPageByPk(pk), {
9
- headers: {
10
- Accept: 'application/json',
11
- 'Content-Type': 'application/json'
13
+ const data = await appFetch<FlatPage>({
14
+ url: flatpage.getFlatPageByPk(pk),
15
+ locale,
16
+ currency,
17
+ init: {
18
+ headers: {
19
+ Accept: 'application/json',
20
+ 'Content-Type': 'application/json'
21
+ }
12
22
  }
13
23
  });
14
24
 
@@ -16,6 +26,18 @@ const getFlatPageDataHandler = (pk: number) => {
16
26
  };
17
27
  };
18
28
 
19
- export const getFlatPageData = ({ pk }: { pk: number }) => {
20
- return Cache.wrap(CacheKey.FlatPage(pk), getFlatPageDataHandler(pk));
29
+ export const getFlatPageData = ({
30
+ pk,
31
+ locale = ServerVariables.locale,
32
+ currency = ServerVariables.currency
33
+ }: {
34
+ pk: number;
35
+ locale?: string;
36
+ currency?: string;
37
+ }) => {
38
+ return Cache.wrap(
39
+ CacheKey.FlatPage(pk),
40
+ locale,
41
+ getFlatPageDataHandler(pk, locale, currency)
42
+ );
21
43
  };
@@ -1,15 +1,21 @@
1
- import { Cache, CacheKey } from "../../lib/cache";
2
- import { FormType } from "../../types/commerce/form";
1
+ import { Cache, CacheKey } from '../../lib/cache';
2
+ import { FormType } from '../../types/commerce/form';
3
3
 
4
- import appFetch from "../../utils/app-fetch";
5
- import { form } from "../urls";
4
+ import appFetch from '../../utils/app-fetch';
5
+ import { ServerVariables } from '../../utils/server-variables';
6
+ import { form } from '../urls';
6
7
 
7
- const getFormDataHandler = (pk: number) => {
8
+ const getFormDataHandler = (pk: number, locale: string, currency: string) => {
8
9
  return async function () {
9
- const data = await appFetch<FormType>(form.getForm(pk), {
10
- headers: {
11
- Accept: 'application/json',
12
- 'Content-Type': 'application/json'
10
+ const data = await appFetch<FormType>({
11
+ url: form.getForm(pk),
12
+ locale,
13
+ currency,
14
+ init: {
15
+ headers: {
16
+ Accept: 'application/json',
17
+ 'Content-Type': 'application/json'
18
+ }
13
19
  }
14
20
  });
15
21
 
@@ -17,6 +23,18 @@ const getFormDataHandler = (pk: number) => {
17
23
  };
18
24
  };
19
25
 
20
- export const getFormData = ({ pk }: { pk: number }) => {
21
- return Cache.wrap(CacheKey.Form(pk), getFormDataHandler(pk));
26
+ export const getFormData = ({
27
+ pk,
28
+ locale = ServerVariables.locale,
29
+ currency = ServerVariables.currency
30
+ }: {
31
+ pk: number;
32
+ locale?: string;
33
+ currency?: string;
34
+ }) => {
35
+ return Cache.wrap(
36
+ CacheKey.Form(pk),
37
+ locale,
38
+ getFormDataHandler(pk, locale, currency)
39
+ );
22
40
  };
@@ -2,23 +2,42 @@ import { landingpage } from '../urls';
2
2
  import { LandingPage } from '../../types/commerce/landingpage';
3
3
  import appFetch from '../../utils/app-fetch';
4
4
  import { Cache, CacheKey } from '../../lib/cache';
5
+ import { ServerVariables } from '../../utils/server-variables';
5
6
 
6
- const getLandingPageHandler = (pk: number) => {
7
+ const getLandingPageHandler = (
8
+ pk: number,
9
+ locale: string,
10
+ currency: string
11
+ ) => {
7
12
  return async function () {
8
- const data = await appFetch<LandingPage>(
9
- landingpage.getLandingPageByPk(pk),
10
- {
13
+ const data = await appFetch<LandingPage>({
14
+ url: landingpage.getLandingPageByPk(pk),
15
+ locale,
16
+ currency,
17
+ init: {
11
18
  headers: {
12
19
  Accept: 'application/json',
13
20
  'Content-Type': 'application/json'
14
21
  }
15
22
  }
16
- );
23
+ });
17
24
 
18
25
  return data;
19
26
  };
20
27
  };
21
28
 
22
- export const getLandingPageData = ({ pk }: { pk: number }) => {
23
- return Cache.wrap(CacheKey.LandingPage(pk), getLandingPageHandler(pk));
29
+ export const getLandingPageData = ({
30
+ pk,
31
+ locale = ServerVariables.locale,
32
+ currency = ServerVariables.currency
33
+ }: {
34
+ pk: number;
35
+ locale?: string;
36
+ currency?: string;
37
+ }) => {
38
+ return Cache.wrap(
39
+ CacheKey.LandingPage(pk),
40
+ locale,
41
+ getLandingPageHandler(pk, locale, currency)
42
+ );
24
43
  };
@@ -5,25 +5,30 @@ import { generateCommerceSearchParams } from '../../utils';
5
5
  import appFetch, { FetchResponseType } from '../../utils/app-fetch';
6
6
  import { parse } from 'lossless-json';
7
7
  import logger from '../../utils/log';
8
+ import { ServerVariables } from '../../utils/server-variables';
8
9
 
9
10
  const getListDataHandler = (
11
+ locale,
12
+ currency,
10
13
  searchParams: URLSearchParams,
11
14
  headers?: Record<string, string>
12
15
  ) => {
13
16
  return async function () {
14
17
  const params = generateCommerceSearchParams(searchParams);
15
18
 
16
- const rawData = await appFetch<string>(
17
- `${category.list}${params}`,
18
- {
19
+ const rawData = await appFetch<string>({
20
+ url: `${category.list}${params}`,
21
+ locale,
22
+ currency,
23
+ init: {
19
24
  headers: {
20
25
  Accept: 'application/json',
21
26
  'Content-Type': 'application/json',
22
27
  ...(headers ?? {})
23
28
  }
24
29
  },
25
- FetchResponseType.TEXT
26
- );
30
+ responseType: FetchResponseType.TEXT
31
+ });
27
32
 
28
33
  let data: GetCategoryResponse;
29
34
 
@@ -51,15 +56,20 @@ const getListDataHandler = (
51
56
  };
52
57
 
53
58
  export const getListData = async ({
59
+ locale = ServerVariables.locale,
60
+ currency = ServerVariables.currency,
54
61
  searchParams,
55
62
  headers
56
63
  }: {
64
+ locale?: string;
65
+ currency?: string;
57
66
  searchParams: URLSearchParams;
58
67
  headers?: Record<string, string>;
59
68
  }) => {
60
69
  return Cache.wrap(
61
70
  CacheKey.List(searchParams, headers),
62
- getListDataHandler(searchParams, headers),
71
+ locale,
72
+ getListDataHandler(locale, currency, searchParams, headers),
63
73
  {
64
74
  expire: 300
65
75
  }
@@ -1,6 +1,7 @@
1
1
  import { Cache, CacheKey } from '../../lib/cache';
2
2
  import { MenuItemType } from '../../types';
3
3
  import appFetch from '../../utils/app-fetch';
4
+ import { ServerVariables } from '../../utils/server-variables';
4
5
  import { misc } from '../urls';
5
6
 
6
7
  interface MenuResponse {
@@ -8,6 +9,8 @@ interface MenuResponse {
8
9
  }
9
10
 
10
11
  interface MenuHandlerParams {
12
+ locale?: string;
13
+ currency?: string;
11
14
  depth?: number;
12
15
  parent?: string;
13
16
  }
@@ -15,9 +18,18 @@ interface MenuHandlerParams {
15
18
  const DEFAULT_DEPTH = 3;
16
19
 
17
20
  const getMenuHandler =
18
- ({ depth, parent }: MenuHandlerParams = { depth: DEFAULT_DEPTH }) =>
21
+ ({
22
+ locale = ServerVariables.locale,
23
+ currency = ServerVariables.currency,
24
+ depth,
25
+ parent
26
+ }: MenuHandlerParams = {}) =>
19
27
  async () => {
20
- const response = await appFetch<MenuResponse>(misc.menus(depth, parent));
28
+ const response = await appFetch<MenuResponse>({
29
+ url: misc.menus(depth ?? DEFAULT_DEPTH, parent),
30
+ locale,
31
+ currency
32
+ });
21
33
 
22
34
  return response?.menu;
23
35
  };
@@ -30,6 +42,7 @@ const getMenuHandler =
30
42
  export const getMenu = async (params?: MenuHandlerParams) => {
31
43
  return Cache.wrap(
32
44
  CacheKey.Menu(params?.depth ?? DEFAULT_DEPTH, params?.parent),
45
+ params?.locale ?? ServerVariables.locale,
33
46
  getMenuHandler(params)
34
47
  );
35
48
  };
@@ -1,20 +1,22 @@
1
1
  import { Cache, CacheKey } from '../../lib/cache';
2
2
  import { product } from '../urls';
3
- import {
4
- BreadcrumbResultType,
5
- ProductCategoryResult,
6
- ProductResult
7
- } from '../../types';
3
+ import { ProductCategoryResult, ProductResult } from '../../types';
8
4
  import appFetch from '../../utils/app-fetch';
5
+ import { ServerVariables } from '../../utils/server-variables';
6
+ import logger from '../../utils/log';
9
7
 
10
8
  type GetProduct = {
11
9
  pk: number;
10
+ locale?: string;
11
+ currency?: string;
12
12
  searchParams?: URLSearchParams;
13
13
  groupProduct?: boolean;
14
14
  };
15
15
 
16
16
  const getProductDataHandler = ({
17
17
  pk,
18
+ locale,
19
+ currency,
18
20
  searchParams,
19
21
  groupProduct
20
22
  }: GetProduct) => {
@@ -31,33 +33,53 @@ const getProductDataHandler = ({
31
33
  .join('&');
32
34
  }
33
35
 
34
- const data = await appFetch<ProductResult>(url, {
35
- headers: {
36
- Accept: 'application/json',
37
- 'Content-Type': 'application/json'
36
+ const data = await appFetch<ProductResult>({
37
+ url,
38
+ locale,
39
+ currency,
40
+ init: {
41
+ headers: {
42
+ Accept: 'application/json',
43
+ 'Content-Type': 'application/json'
44
+ }
38
45
  }
39
46
  });
40
47
 
41
48
  const categoryUrl = product.categoryUrl(data.product.pk);
42
49
 
43
- const productCategoryData = await appFetch<ProductCategoryResult>(
44
- categoryUrl,
45
- {
50
+ const productCategoryData = await appFetch<ProductCategoryResult>({
51
+ url: categoryUrl,
52
+ locale,
53
+ currency,
54
+ init: {
46
55
  headers: {
47
56
  Accept: 'application/json',
48
57
  'Content-Type': 'application/json'
49
58
  }
50
59
  }
51
- );
60
+ });
61
+
62
+ const menuItemModel = productCategoryData?.results[0]?.menuitemmodel;
52
63
 
53
- const breadcrumbUrl = product.breadcrumbUrl(
54
- productCategoryData.results[0].menuitemmodel
55
- );
64
+ if (!menuItemModel) {
65
+ logger.warn('menuItemModel is undefined, skipping breadcrumbData fetch', {
66
+ handler: 'getProductDataHandler',
67
+ pk
68
+ });
69
+ return { data, breadcrumbData: undefined };
70
+ }
71
+
72
+ const breadcrumbUrl = product.breadcrumbUrl(menuItemModel);
56
73
 
57
- const breadcrumbData = await appFetch<any>(breadcrumbUrl, {
58
- headers: {
59
- Accept: 'application/json',
60
- 'Content-Type': 'application/json'
74
+ const breadcrumbData = await appFetch<any>({
75
+ url: breadcrumbUrl,
76
+ locale,
77
+ currency,
78
+ init: {
79
+ headers: {
80
+ Accept: 'application/json',
81
+ 'Content-Type': 'application/json'
82
+ }
61
83
  }
62
84
  });
63
85
 
@@ -70,6 +92,8 @@ const getProductDataHandler = ({
70
92
 
71
93
  export const getProductData = async ({
72
94
  pk,
95
+ locale = ServerVariables.locale,
96
+ currency = ServerVariables.currency,
73
97
  searchParams,
74
98
  groupProduct
75
99
  }: GetProduct) => {
@@ -78,7 +102,8 @@ export const getProductData = async ({
78
102
  pk,
79
103
  searchParams ?? new URLSearchParams()
80
104
  ),
81
- getProductDataHandler({ pk, searchParams, groupProduct }),
105
+ locale,
106
+ getProductDataHandler({ pk, locale, currency, searchParams, groupProduct }),
82
107
  {
83
108
  expire: 300
84
109
  }