@akinon/next 1.62.0 → 1.64.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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 1.64.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c53ea3e: ZERO-2609: Reset additional form fields when selectedFormType is not company
8
+ - d3474c6: ZERO-2655: Add data source shipping option
9
+
10
+ ## 1.63.0
11
+
12
+ ### Minor Changes
13
+
14
+ - a4c8d6a: ZERO-2663: Fix the image url for gif and svgs and return them without options
15
+ - fda5b92: ZERO-2725: fix invalid import
16
+ - 0d3a913: ZERO-2725: Update decimal scale in Price component
17
+ - c45b62c: ZERO-2818: Add upload and download support for b2b package
18
+ - d409996: ZERO-2781: Refactor buildClientRequestUrl function to support caching and options
19
+ - dcc8a15: ZERO-2694: added build step to RC branch pipeline
20
+
3
21
  ## 1.62.0
4
22
 
5
23
  ### Minor Changes
@@ -1,11 +1,13 @@
1
1
  import { useMemo } from 'react';
2
- import NumberFormat, { NumberFormatProps } from 'react-number-format';
2
+ // @ts-ignore
3
+ import { NumericFormat, NumericFormatProps } from 'react-number-format';
3
4
  import { getCurrency } from '@akinon/next/utils';
4
5
 
5
6
  import { useLocalization } from '@akinon/next/hooks';
6
7
  import { PriceProps } from '../types';
8
+ import Settings from 'settings';
7
9
 
8
- export const Price = (props: NumberFormatProps & PriceProps) => {
10
+ export const Price = (props: NumericFormatProps & PriceProps) => {
9
11
  const {
10
12
  value,
11
13
  currencyCode,
@@ -27,6 +29,10 @@ export const Price = (props: NumberFormatProps & PriceProps) => {
27
29
  // TODO: This is very bad practice. It broke decimalScale.
28
30
  const _value = value?.toString().replace('.', ',');
29
31
 
32
+ const currentCurrencyDecimalScale = Settings.localization.currencies.find(
33
+ (currency) => currency.code === currencyCode_
34
+ ).decimalScale;
35
+
30
36
  const currency = useMemo(
31
37
  () =>
32
38
  getCurrency({
@@ -39,14 +45,14 @@ export const Price = (props: NumberFormatProps & PriceProps) => {
39
45
  );
40
46
 
41
47
  return (
42
- <NumberFormat
48
+ <NumericFormat
43
49
  value={useNegative ? `-${useNegativeSpace}${_value}` : _value}
44
50
  {...{
45
51
  [useCurrencyAfterPrice ? 'suffix' : 'prefix']: currency
46
52
  }}
47
53
  displayType={displayType}
48
54
  thousandSeparator={thousandSeparator}
49
- decimalScale={decimalScale}
55
+ decimalScale={currentCurrencyDecimalScale ?? decimalScale}
50
56
  decimalSeparator={decimalSeparator}
51
57
  fixedDecimalScale={fixedDecimalScale}
52
58
  {...rest}
@@ -12,7 +12,9 @@ import {
12
12
  SaveBasketParams,
13
13
  UpdateProductParams,
14
14
  DeleteProductParams,
15
- CreateQuotationParams
15
+ CreateQuotationParams,
16
+ BasketStatusResponse,
17
+ ExportBasketResponse
16
18
  } from '../../types';
17
19
 
18
20
  const b2bApi = api.injectEndpoints({
@@ -89,6 +91,34 @@ const b2bApi = api.injectEndpoints({
89
91
  }),
90
92
  invalidatesTags: ['BasketB2b', 'DraftsB2b']
91
93
  }),
94
+ exportBasket: build.mutation<ExportBasketResponse, string>({
95
+ query: (queryString) => {
96
+ return {
97
+ url: buildClientRequestUrl(b2b.basketExport(queryString)),
98
+ method: 'GET'
99
+ };
100
+ }
101
+ }),
102
+ getBasketStatus: build.mutation<BasketStatusResponse, string>({
103
+ query: (cacheKey) => {
104
+ return {
105
+ url: buildClientRequestUrl(b2b.statusBasket(cacheKey)),
106
+ method: 'GET'
107
+ };
108
+ }
109
+ }),
110
+ uploadFile: build.mutation<void, FormData>({
111
+ query: (body) => {
112
+ return {
113
+ url: buildClientRequestUrl(b2b.basketImport, {
114
+ useFormData: true
115
+ }),
116
+ method: 'POST',
117
+ body
118
+ };
119
+ },
120
+ invalidatesTags: ['BasketB2b']
121
+ })
92
122
  }),
93
123
  overrideExisting: true
94
124
  });
@@ -102,5 +132,8 @@ export const {
102
132
  useLoadBasketMutation,
103
133
  useUpdateProductMutation,
104
134
  useDeleteProductMutation,
105
- useCreateQuotationMutation
135
+ useCreateQuotationMutation,
136
+ useGetBasketStatusMutation,
137
+ useExportBasketMutation,
138
+ useUploadFileMutation
106
139
  } = b2bApi;
@@ -380,6 +380,22 @@ export const checkoutApi = api.injectEndpoints({
380
380
  dispatch(setShippingStepBusy(false));
381
381
  }
382
382
  }),
383
+ setDataSourceShippingOptions: build.mutation<CheckoutResponse, number[]>({
384
+ query: (pks) => ({
385
+ url: buildClientRequestUrl(checkout.setDataSourceShippingOption, {
386
+ useFormData: true
387
+ }),
388
+ method: 'POST',
389
+ body: {
390
+ data_source_shipping_options: JSON.stringify(pks)
391
+ }
392
+ }),
393
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
394
+ dispatch(setShippingStepBusy(true));
395
+ await queryFulfilled;
396
+ dispatch(setShippingStepBusy(false));
397
+ }
398
+ }),
383
399
  setRetailStore: build.mutation<CheckoutResponse, SetRetailStoreParams>({
384
400
  query: ({ retailStorePk, billingAddressPk }) => ({
385
401
  url: buildClientRequestUrl(
@@ -712,6 +728,7 @@ export const {
712
728
  useSetDeliveryOptionMutation,
713
729
  useSetAddressesMutation,
714
730
  useSetShippingOptionMutation,
731
+ useSetDataSourceShippingOptionsMutation,
715
732
  useSetPaymentOptionMutation,
716
733
  useSetBinNumberMutation,
717
734
  useSetInstallmentOptionMutation,
package/data/urls.ts CHANGED
@@ -83,6 +83,8 @@ export const checkout = {
83
83
  setDeliveryOption: '/orders/checkout/?page=DeliveryOptionSelectionPage',
84
84
  setAddresses: '/orders/checkout/?page=AddressSelectionPage',
85
85
  setShippingOption: '/orders/checkout/?page=ShippingOptionSelectionPage',
86
+ setDataSourceShippingOption:
87
+ '/orders/checkout/?page=DataSourceShippingOptionSelectionPage',
86
88
  setPaymentOption: '/orders/checkout/?page=PaymentOptionSelectionPage',
87
89
  setBinNumber: '/orders/checkout/?page=BinNumberPage',
88
90
  setMasterpassBinNumber: '/orders/checkout/?page=MasterpassBinNumberPage',
@@ -199,7 +201,10 @@ export const b2b = {
199
201
  draftBaskets: '/b2b/basket/drafts/',
200
202
  divisions: '/b2b/my-divisions/',
201
203
  myQuotations: '/b2b/my-quotations/',
202
- loadBasket: (id) => `/b2b/basket/${id}/load/`
204
+ loadBasket: (id) => `/b2b/basket/${id}/load/`,
205
+ statusBasket: (cacheKey) => `/b2b/basket/?status_cache_key=${cacheKey}`,
206
+ basketExport: (queryString) => `/b2b/basket/?upload=true&${queryString}`,
207
+ basketImport: '/b2b/basket/bulk-import/'
203
208
  };
204
209
 
205
210
  export const widgets = {
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.62.0",
4
+ "version": "1.64.0",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "set-cookie-parser": "2.6.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@akinon/eslint-plugin-projectzero": "1.62.0",
33
+ "@akinon/eslint-plugin-projectzero": "1.64.0",
34
34
  "@types/react-redux": "7.1.30",
35
35
  "@types/set-cookie-parser": "2.4.7",
36
36
  "@typescript-eslint/eslint-plugin": "6.7.4",
@@ -16,6 +16,7 @@ import {
16
16
  setPreOrder,
17
17
  setRetailStores,
18
18
  setShippingOptions,
19
+ setDataSourceShippingOptions,
19
20
  setShippingStepCompleted,
20
21
  setCreditPaymentOptions
21
22
  } from '../../redux/reducers/checkout';
@@ -73,6 +74,7 @@ export const preOrderMiddleware: Middleware = ({
73
74
  deliveryOptions,
74
75
  addressList: addresses,
75
76
  shippingOptions,
77
+ dataSourceShippingOptions,
76
78
  paymentOptions,
77
79
  installmentOptions
78
80
  } = getState().checkout;
@@ -126,6 +128,22 @@ export const preOrderMiddleware: Middleware = ({
126
128
  dispatch(apiEndpoints.setShippingOption.initiate(shippingOptions[0].pk));
127
129
  }
128
130
 
131
+ if (
132
+ dataSourceShippingOptions.length > 0 &&
133
+ !preOrder.data_source_shipping_options
134
+ ) {
135
+ const selectedDataSourceShippingOptionsPks =
136
+ dataSourceShippingOptions.map(
137
+ (opt) => opt.data_source_shipping_options[0].pk
138
+ );
139
+
140
+ dispatch(
141
+ apiEndpoints.setDataSourceShippingOptions.initiate(
142
+ selectedDataSourceShippingOptionsPks
143
+ )
144
+ );
145
+ }
146
+
129
147
  if (!preOrder.payment_option && paymentOptions.length > 0) {
130
148
  dispatch(apiEndpoints.setPaymentOption.initiate(paymentOptions[0].pk));
131
149
  }
@@ -164,7 +182,6 @@ export const contextListMiddleware: Middleware = ({
164
182
  if (result?.payload?.context_list) {
165
183
  result.payload.context_list.forEach((context) => {
166
184
  const redirectUrl = context.page_context.redirect_url;
167
-
168
185
  if (redirectUrl) {
169
186
  const currentLocale = getCookie('pz-locale');
170
187
 
@@ -221,6 +238,12 @@ export const contextListMiddleware: Middleware = ({
221
238
  dispatch(setShippingOptions(context.page_context.shipping_options));
222
239
  }
223
240
 
241
+ if (context.page_context.data_sources) {
242
+ dispatch(
243
+ setDataSourceShippingOptions(context.page_context.data_sources)
244
+ );
245
+ }
246
+
224
247
  if (context.page_context.payment_options) {
225
248
  dispatch(setPaymentOptions(context.page_context.payment_options));
226
249
  }
@@ -14,7 +14,8 @@ import {
14
14
  CheckoutCreditPaymentOption,
15
15
  PreOrder,
16
16
  RetailStore,
17
- ShippingOption
17
+ ShippingOption,
18
+ DataSource
18
19
  } from '../../types';
19
20
 
20
21
  export interface CheckoutState {
@@ -36,6 +37,7 @@ export interface CheckoutState {
36
37
  addressList: Address[];
37
38
  deliveryOptions: DeliveryOption[];
38
39
  shippingOptions: ShippingOption[];
40
+ dataSourceShippingOptions: DataSource[];
39
41
  paymentOptions: PaymentOption[];
40
42
  creditPaymentOptions: CheckoutCreditPaymentOption[];
41
43
  selectedCreditPaymentPk: number;
@@ -67,6 +69,7 @@ const initialState: CheckoutState = {
67
69
  addressList: [],
68
70
  deliveryOptions: [],
69
71
  shippingOptions: [],
72
+ dataSourceShippingOptions: [],
70
73
  paymentOptions: [],
71
74
  creditPaymentOptions: [],
72
75
  selectedCreditPaymentPk: null,
@@ -121,6 +124,9 @@ const checkoutSlice = createSlice({
121
124
  setShippingOptions(state, { payload }) {
122
125
  state.shippingOptions = payload;
123
126
  },
127
+ setDataSourceShippingOptions(state, { payload }) {
128
+ state.dataSourceShippingOptions = payload;
129
+ },
124
130
  setPaymentOptions(state, { payload }) {
125
131
  state.paymentOptions = payload;
126
132
  },
@@ -168,6 +174,7 @@ export const {
168
174
  setAddressList,
169
175
  setDeliveryOptions,
170
176
  setShippingOptions,
177
+ setDataSourceShippingOptions,
171
178
  setPaymentOptions,
172
179
  setCreditPaymentOptions,
173
180
  setSelectedCreditPaymentPk,
@@ -17,7 +17,7 @@ export type AddressFormType = {
17
17
  line: string;
18
18
  postcode: string;
19
19
  company_name?: string;
20
- tax_no?: number;
20
+ tax_no?: string;
21
21
  tax_office?: string;
22
22
  e_bill_taxpayer?: boolean;
23
23
  country_code?: string;
@@ -72,7 +72,7 @@ export type BasketItemType = {
72
72
  divisions: BasketItemDivision[];
73
73
  product: ProductB2b;
74
74
  product_remote_id: number;
75
- }
75
+ };
76
76
 
77
77
  export type BasketParams = {
78
78
  division: string;
@@ -91,7 +91,7 @@ export type CreateQuotationParams = {
91
91
  export type UpdateProductParams = {
92
92
  product_remote_id: number;
93
93
  division: number;
94
- quantity: number
94
+ quantity: number;
95
95
  };
96
96
 
97
97
  export type DeleteProductParams = {
@@ -115,3 +115,13 @@ export type DraftResponse = {
115
115
  total_amount: number;
116
116
  total_quantity: number;
117
117
  };
118
+
119
+ export type BasketStatusResponse = {
120
+ is_ready: boolean;
121
+ status: string;
122
+ url: string;
123
+ };
124
+
125
+ export type ExportBasketResponse = {
126
+ cache_key: string;
127
+ };
@@ -34,6 +34,23 @@ export interface ShippingOption {
34
34
  slug: string;
35
35
  }
36
36
 
37
+ export interface DataSource {
38
+ pk: number;
39
+ name: string;
40
+ data_source_shipping_options: DataSourceShippingOption[];
41
+ }
42
+
43
+ export interface DataSourceShippingOption {
44
+ pk: number;
45
+ shipping_amount: string;
46
+ shipping_option_name: string;
47
+ shipping_option_logo: string | null;
48
+ data_source: {
49
+ pk: number;
50
+ title: string | null;
51
+ };
52
+ }
53
+
37
54
  export interface CheckoutAddressType {
38
55
  label: string;
39
56
  text: string;
@@ -79,6 +96,7 @@ export interface PreOrder {
79
96
  retail_store?: RetailStore;
80
97
  gift_box?: GiftBox;
81
98
  credit_payment_option?: CheckoutCreditPaymentOption;
99
+ data_source_shipping_options: any;
82
100
  bags?: Product[];
83
101
  bags_fee?: string;
84
102
  extra_field?: ExtraField;
package/types/index.ts CHANGED
@@ -68,6 +68,13 @@ 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 {
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
- if (url.includes('?')) {
72
- url += '&';
73
- } else {
74
- url += '?';
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
- url += `options=${encodeURIComponent(JSON.stringify(options))}`;
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) {