@akinon/projectzero 1.40.0-rc.0 → 1.40.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,11 +1,6 @@
1
1
  # @akinon/projectzero
2
2
 
3
- ## 1.40.0-rc.0
4
-
5
- ### Minor Changes
6
-
7
- - 9b6bf91: ZERO-2660: Change campaings to campaigns
8
- - 00ffde2: ZERO-2637: enhance create command with improved messaging
3
+ ## 1.40.0
9
4
 
10
5
  ## 1.39.0
11
6
 
@@ -24,36 +19,6 @@
24
19
  - cd78ddc: ZERO-2661: rename .npmignore to .gitignore during project creation
25
20
  - 735f4f0: ZERO-2661: create .npmignore in app-template
26
21
 
27
- ## 1.34.0-rc.16
28
-
29
- ### Minor Changes
30
-
31
- - cd78ddc: ZERO-2661: rename .npmignore to .gitignore during project creation
32
-
33
- ## 1.34.0-rc.15
34
-
35
- ### Minor Changes
36
-
37
- - 735f4f0: ZERO-2661: create .npmignore in app-template
38
-
39
- ## 1.34.0-rc.14
40
-
41
- ## 1.34.0-rc.13
42
-
43
- ## 1.34.0-rc.12
44
-
45
- ## 1.34.0-rc.11
46
-
47
- ## 1.34.0-rc.10
48
-
49
- ## 1.34.0-rc.9
50
-
51
- ## 1.34.0-rc.8
52
-
53
- ## 1.34.0-rc.7
54
-
55
- ## 1.34.0-rc.6
56
-
57
22
  ## 1.33.2
58
23
 
59
24
  ### Patch Changes
@@ -1,44 +1,22 @@
1
1
  # projectzeronext
2
2
 
3
- ## 1.40.0-rc.0
3
+ ## 1.40.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - c53ea3e: ZERO-2609: Reset additional form fields when selectedFormType is not company
8
- - 27a5296: ZERO-2631:Fix Checkbox Click
9
- - 9b6bf91: ZERO-2660: Change campaings to campaigns
10
- - 74a1269: ZERO-2658:Edit product name clickability on completed order page
11
- - 75080fd: ZERO-2630: Add max limit to postcode area
12
- - 91265bb: ZERO-2551: Improve pretty url and caching performance
13
- - 902d828: ZERO-2621:edit position of loaderSpinner in favorites page
14
- - 7a4bb76: ZERO-2610:Refactor FilterItem component for better readability and efficiency
15
- - dff0d59: ZERO-2659: add formData support to proxy api requests
16
- - beb499e: ZERO-2551: Add new tsconfig paths
17
- - 4614eee: ZERO-2602: The script that checks the build for standalone projects
18
7
  - 306d9d8: ZERO-2705: Add checkout-with-token regex to matcher
19
- - f046f8e: ZERO-2575: update version for react-number-format
20
8
 
21
9
  ### Patch Changes
22
10
 
23
- - Updated dependencies [a4c8d6a]
24
- - Updated dependencies [c53ea3e]
25
- - Updated dependencies [c53ef7b]
26
- - Updated dependencies [1448a96]
27
11
  - Updated dependencies [b5d5c5c]
28
- - Updated dependencies [75080fd]
29
- - Updated dependencies [91265bb]
30
- - Updated dependencies [bbe18b9]
31
12
  - Updated dependencies [05b1fe1]
32
- - Updated dependencies [dff0d59]
33
- - Updated dependencies [beb499e]
34
- - Updated dependencies [f046f8e]
35
- - @akinon/next@1.40.0-rc.0
36
- - @akinon/pz-b2b@1.40.0-rc.0
37
- - @akinon/pz-gpay@1.40.0-rc.0
38
- - @akinon/pz-masterpass@1.40.0-rc.0
39
- - @akinon/pz-one-click-checkout@1.40.0-rc.0
40
- - @akinon/pz-otp@1.40.0-rc.0
41
- - @akinon/pz-pay-on-delivery@1.40.0-rc.0
13
+ - @akinon/next@1.40.0
14
+ - @akinon/pz-b2b@1.40.0
15
+ - @akinon/pz-gpay@1.40.0
16
+ - @akinon/pz-masterpass@1.40.0
17
+ - @akinon/pz-one-click-checkout@1.40.0
18
+ - @akinon/pz-otp@1.40.0
19
+ - @akinon/pz-pay-on-delivery@1.40.0
42
20
 
43
21
  ## 1.39.0
44
22
 
@@ -143,301 +121,13 @@
143
121
 
144
122
  ### Patch Changes
145
123
 
146
- - Updated dependencies [a4c8d6a]
147
- - Updated dependencies [d09b677]
148
- - Updated dependencies [6d4aadb]
149
- - Updated dependencies [8e6e8cf]
150
- - Updated dependencies [c53ef7b]
151
- - Updated dependencies [ebb63ce]
152
- - Updated dependencies [7cebe87]
153
- - Updated dependencies [616690d]
154
- - Updated dependencies [f3b595e]
155
- - Updated dependencies [91265bb]
156
- - Updated dependencies [59fb7c3]
157
- - Updated dependencies [bbe18b9]
158
- - Updated dependencies [f0c23bc]
159
- - Updated dependencies [3420416]
160
- - Updated dependencies [495d155]
161
- - Updated dependencies [beb499e]
162
- - Updated dependencies [6c18543]
163
- - Updated dependencies [40ad73e]
164
- - Updated dependencies [495d155]
165
- - Updated dependencies [f046f8e]
166
- - Updated dependencies [6b2972b]
167
- - Updated dependencies [3e68768]
168
- - @akinon/next@1.34.0-rc.20
169
- - @akinon/pz-masterpass@1.34.0-rc.20
170
- - @akinon/pz-one-click-checkout@1.34.0-rc.20
171
- - @akinon/pz-b2b@1.34.0-rc.20
172
- - @akinon/pz-gpay@1.34.0-rc.20
173
- - @akinon/pz-otp@1.34.0-rc.20
174
- - @akinon/pz-pay-on-delivery@1.34.0-rc.20
175
-
176
- ## 1.34.0-rc.19
177
-
178
- ### Patch Changes
179
-
180
- - Updated dependencies [c53ef7b]
181
- - @akinon/next@1.34.0-rc.19
182
- - @akinon/pz-b2b@1.34.0-rc.19
183
- - @akinon/pz-gpay@1.34.0-rc.19
184
- - @akinon/pz-masterpass@1.34.0-rc.19
185
- - @akinon/pz-one-click-checkout@1.34.0-rc.19
186
- - @akinon/pz-otp@1.34.0-rc.19
187
- - @akinon/pz-pay-on-delivery@1.34.0-rc.19
188
-
189
- ## 1.34.0-rc.18
190
-
191
- ### Minor Changes
192
-
193
- - 9b6bf91: ZERO-2660: Change campaings to campaigns
194
- - 902d828: ZERO-2621:edit position of loaderSpinner in favorites page
195
-
196
- ### Patch Changes
197
-
198
- - Updated dependencies [a4c8d6a]
199
- - @akinon/next@1.34.0-rc.18
200
- - @akinon/pz-b2b@1.34.0-rc.18
201
- - @akinon/pz-gpay@1.34.0-rc.18
202
- - @akinon/pz-masterpass@1.34.0-rc.18
203
- - @akinon/pz-one-click-checkout@1.34.0-rc.18
204
- - @akinon/pz-otp@1.34.0-rc.18
205
- - @akinon/pz-pay-on-delivery@1.34.0-rc.18
206
-
207
- ## 1.34.0-rc.17
208
-
209
- ### Minor Changes
210
-
211
- - 567e4c1: ZERO-2580:Add checked attribute from props to checkbox
212
- - d09b677: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
213
- - 27a5296: ZERO-2631:Fix Checkbox Click
214
- - ebb63ce: ZERO-2525: Fix category facet removal bug and add close icon to active filters
215
- - 74a1269: ZERO-2658:Edit product name clickability on completed order page
216
- - 0d0f36c: ZERO-2598: Fix eslint warnings and update dependencies
217
- - 91265bb: ZERO-2551: Improve pretty url and caching performance
218
- - f0c23bc: ZERO-2135: add custom not found page
219
- - 3420416: ZERO-2533: extend eslint config from @akinon/next
220
- - beb499e: ZERO-2551: Add new tsconfig paths
221
- - 6c18543: ZERO-2542:Refactor and show error in OneClickCheckoutButtons
222
- - 202f84e: ZERO-2569: Fix static keys
223
- - 4614eee: ZERO-2602: The script that checks the build for standalone projects
224
- - f046f8e: ZERO-2575: update version for react-number-format
225
- - 12c10a4: ZERO-2570: Category filters routes to absolute url
226
-
227
- ### Patch Changes
228
-
229
- - Updated dependencies [d09b677]
230
- - Updated dependencies [6d4aadb]
231
- - Updated dependencies [8e6e8cf]
232
- - Updated dependencies [ebb63ce]
233
- - Updated dependencies [7cebe87]
234
- - Updated dependencies [616690d]
235
- - Updated dependencies [f3b595e]
236
- - Updated dependencies [91265bb]
237
- - Updated dependencies [59fb7c3]
238
- - Updated dependencies [bbe18b9]
239
- - Updated dependencies [f0c23bc]
240
- - Updated dependencies [3420416]
241
- - Updated dependencies [495d155]
242
- - Updated dependencies [beb499e]
243
- - Updated dependencies [6c18543]
244
- - Updated dependencies [40ad73e]
245
- - Updated dependencies [495d155]
246
- - Updated dependencies [f046f8e]
247
- - Updated dependencies [6b2972b]
248
- - Updated dependencies [3e68768]
249
- - @akinon/next@1.34.0-rc.17
250
- - @akinon/pz-masterpass@1.34.0-rc.17
251
- - @akinon/pz-one-click-checkout@1.34.0-rc.17
252
- - @akinon/pz-b2b@1.34.0-rc.17
253
- - @akinon/pz-gpay@1.34.0-rc.17
254
- - @akinon/pz-otp@1.34.0-rc.17
255
- - @akinon/pz-pay-on-delivery@1.34.0-rc.17
256
-
257
- ## 1.34.0-rc.16
258
-
259
- ### Patch Changes
260
-
261
- - @akinon/next@1.34.0-rc.16
262
- - @akinon/pz-b2b@1.34.0-rc.16
263
- - @akinon/pz-gpay@1.34.0-rc.16
264
- - @akinon/pz-masterpass@1.34.0-rc.16
265
- - @akinon/pz-one-click-checkout@1.34.0-rc.16
266
- - @akinon/pz-otp@1.34.0-rc.16
267
- - @akinon/pz-pay-on-delivery@1.34.0-rc.16
268
-
269
- ## 1.34.0-rc.15
270
-
271
- ### Patch Changes
272
-
273
- - @akinon/next@1.34.0-rc.15
274
- - @akinon/pz-b2b@1.34.0-rc.15
275
- - @akinon/pz-gpay@1.34.0-rc.15
276
- - @akinon/pz-masterpass@1.34.0-rc.15
277
- - @akinon/pz-one-click-checkout@1.34.0-rc.15
278
- - @akinon/pz-otp@1.34.0-rc.15
279
- - @akinon/pz-pay-on-delivery@1.34.0-rc.15
280
-
281
- ## 1.34.0-rc.14
282
-
283
- ### Minor Changes
284
-
285
- - 4614eee: ZERO-2602: The script that checks the build for standalone projects
286
-
287
- ### Patch Changes
288
-
289
- - @akinon/next@1.34.0-rc.14
290
- - @akinon/pz-b2b@1.34.0-rc.14
291
- - @akinon/pz-gpay@1.34.0-rc.14
292
- - @akinon/pz-masterpass@1.34.0-rc.14
293
- - @akinon/pz-one-click-checkout@1.34.0-rc.14
294
- - @akinon/pz-otp@1.34.0-rc.14
295
- - @akinon/pz-pay-on-delivery@1.34.0-rc.14
296
-
297
- ## 1.34.0-rc.13
298
-
299
- ### Minor Changes
300
-
301
- - 74a1269: ZERO-2658:Edit product name clickability on completed order page
302
-
303
- ### Patch Changes
304
-
305
- - @akinon/next@1.34.0-rc.13
306
- - @akinon/pz-b2b@1.34.0-rc.13
307
- - @akinon/pz-gpay@1.34.0-rc.13
308
- - @akinon/pz-masterpass@1.34.0-rc.13
309
- - @akinon/pz-one-click-checkout@1.34.0-rc.13
310
- - @akinon/pz-otp@1.34.0-rc.13
311
- - @akinon/pz-pay-on-delivery@1.34.0-rc.13
312
-
313
- ## 1.34.0-rc.12
314
-
315
- ### Patch Changes
316
-
317
- - Updated dependencies [616690d]
318
- - @akinon/next@1.34.0-rc.12
319
- - @akinon/pz-b2b@1.34.0-rc.12
320
- - @akinon/pz-gpay@1.34.0-rc.12
321
- - @akinon/pz-masterpass@1.34.0-rc.12
322
- - @akinon/pz-one-click-checkout@1.34.0-rc.12
323
- - @akinon/pz-otp@1.34.0-rc.12
324
- - @akinon/pz-pay-on-delivery@1.34.0-rc.12
325
-
326
- ## 1.34.0-rc.11
327
-
328
- ### Patch Changes
329
-
330
- - Updated dependencies [8e6e8cf]
331
- - @akinon/next@1.34.0-rc.11
332
- - @akinon/pz-b2b@1.34.0-rc.11
333
- - @akinon/pz-gpay@1.34.0-rc.11
334
- - @akinon/pz-masterpass@1.34.0-rc.11
335
- - @akinon/pz-one-click-checkout@1.34.0-rc.11
336
- - @akinon/pz-otp@1.34.0-rc.11
337
- - @akinon/pz-pay-on-delivery@1.34.0-rc.11
338
-
339
- ## 1.34.0-rc.10
340
-
341
- ### Patch Changes
342
-
343
- - Updated dependencies [bbe18b9]
344
- - @akinon/next@1.34.0-rc.10
345
- - @akinon/pz-b2b@1.34.0-rc.10
346
- - @akinon/pz-gpay@1.34.0-rc.10
347
- - @akinon/pz-masterpass@1.34.0-rc.10
348
- - @akinon/pz-one-click-checkout@1.34.0-rc.10
349
- - @akinon/pz-otp@1.34.0-rc.10
350
- - @akinon/pz-pay-on-delivery@1.34.0-rc.10
351
-
352
- ## 1.34.0-rc.9
353
-
354
- ### Minor Changes
355
-
356
- - beb499e: ZERO-2551: Add new tsconfig paths
357
-
358
- ### Patch Changes
359
-
360
- - Updated dependencies [beb499e]
361
- - @akinon/next@1.34.0-rc.9
362
- - @akinon/pz-b2b@1.34.0-rc.9
363
- - @akinon/pz-gpay@1.34.0-rc.9
364
- - @akinon/pz-masterpass@1.34.0-rc.9
365
- - @akinon/pz-one-click-checkout@1.34.0-rc.9
366
- - @akinon/pz-otp@1.34.0-rc.9
367
- - @akinon/pz-pay-on-delivery@1.34.0-rc.9
368
-
369
- ## 1.34.0-rc.8
370
-
371
- ### Minor Changes
372
-
373
- - 91265bb: ZERO-2551: Improve pretty url and caching performance
374
-
375
- ### Patch Changes
376
-
377
- - Updated dependencies [91265bb]
378
- - @akinon/next@1.34.0-rc.8
379
- - @akinon/pz-b2b@1.34.0-rc.8
380
- - @akinon/pz-gpay@1.34.0-rc.8
381
- - @akinon/pz-masterpass@1.34.0-rc.8
382
- - @akinon/pz-one-click-checkout@1.34.0-rc.8
383
- - @akinon/pz-otp@1.34.0-rc.8
384
- - @akinon/pz-pay-on-delivery@1.34.0-rc.8
385
-
386
- ## 1.34.0-rc.7
387
-
388
- ### Minor Changes
389
-
390
- - 0d0f36c: ZERO-2598: Fix eslint warnings and update dependencies
391
-
392
- ### Patch Changes
393
-
394
- - @akinon/next@1.34.0-rc.7
395
- - @akinon/pz-b2b@1.34.0-rc.7
396
- - @akinon/pz-gpay@1.34.0-rc.7
397
- - @akinon/pz-masterpass@1.34.0-rc.7
398
- - @akinon/pz-one-click-checkout@1.34.0-rc.7
399
- - @akinon/pz-otp@1.34.0-rc.7
400
- - @akinon/pz-pay-on-delivery@1.34.0-rc.7
401
-
402
- ## 1.34.0-rc.6
403
-
404
- ### Minor Changes
405
-
406
- - 567e4c1: ZERO-2580:Add checked attribute from props to checkbox
407
- - d09b677: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
408
- - 27a5296: ZERO-2631:Fix Checkbox Click
409
- - ebb63ce: ZERO-2525: Fix category facet removal bug and add close icon to active filters
410
- - f0c23bc: ZERO-2135: add custom not found page
411
- - 3420416: ZERO-2533: extend eslint config from @akinon/next
412
- - 6c18543: ZERO-2542:Refactor and show error in OneClickCheckoutButtons
413
- - 202f84e: ZERO-2569: Fix static keys
414
- - f046f8e: ZERO-2575: update version for react-number-format
415
- - 12c10a4: ZERO-2570: Category filters routes to absolute url
416
-
417
- ### Patch Changes
418
-
419
- - Updated dependencies [d09b677]
420
- - Updated dependencies [6d4aadb]
421
- - Updated dependencies [ebb63ce]
422
- - Updated dependencies [7cebe87]
423
- - Updated dependencies [f3b595e]
424
- - Updated dependencies [59fb7c3]
425
- - Updated dependencies [f0c23bc]
426
- - Updated dependencies [3420416]
427
- - Updated dependencies [495d155]
428
- - Updated dependencies [6c18543]
429
- - Updated dependencies [40ad73e]
430
- - Updated dependencies [495d155]
431
- - Updated dependencies [f046f8e]
432
- - Updated dependencies [6b2972b]
433
- - Updated dependencies [3e68768]
434
- - @akinon/next@1.34.0-rc.6
435
- - @akinon/pz-masterpass@1.34.0-rc.6
436
- - @akinon/pz-one-click-checkout@1.34.0-rc.6
437
- - @akinon/pz-b2b@1.34.0-rc.6
438
- - @akinon/pz-gpay@1.34.0-rc.6
439
- - @akinon/pz-otp@1.34.0-rc.6
440
- - @akinon/pz-pay-on-delivery@1.34.0-rc.6
124
+ - @akinon/next@1.34.0
125
+ - @akinon/pz-b2b@1.34.0
126
+ - @akinon/pz-gpay@1.34.0
127
+ - @akinon/pz-masterpass@1.34.0
128
+ - @akinon/pz-one-click-checkout@1.34.0
129
+ - @akinon/pz-otp@1.34.0
130
+ - @akinon/pz-pay-on-delivery@1.34.0
441
131
 
442
132
  ## 1.33.2
443
133
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projectzeronext",
3
- "version": "1.40.0-rc.0",
3
+ "version": "1.40.0",
4
4
  "private": true,
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -22,13 +22,13 @@
22
22
  "prestart": "pz-prestart"
23
23
  },
24
24
  "dependencies": {
25
- "@akinon/next": "1.40.0-rc.0",
26
- "@akinon/pz-b2b": "1.40.0-rc.0",
27
- "@akinon/pz-gpay": "1.40.0-rc.0",
28
- "@akinon/pz-masterpass": "1.40.0-rc.0",
29
- "@akinon/pz-one-click-checkout": "1.40.0-rc.0",
30
- "@akinon/pz-otp": "1.40.0-rc.0",
31
- "@akinon/pz-pay-on-delivery": "1.40.0-rc.0",
25
+ "@akinon/next": "1.40.0",
26
+ "@akinon/pz-b2b": "1.40.0",
27
+ "@akinon/pz-gpay": "1.40.0",
28
+ "@akinon/pz-masterpass": "1.40.0",
29
+ "@akinon/pz-one-click-checkout": "1.40.0",
30
+ "@akinon/pz-otp": "1.40.0",
31
+ "@akinon/pz-pay-on-delivery": "1.40.0",
32
32
  "@hookform/resolvers": "2.9.0",
33
33
  "@next/third-parties": "14.1.0",
34
34
  "@react-google-maps/api": "2.17.1",
@@ -53,7 +53,7 @@
53
53
  "yup": "0.32.11"
54
54
  },
55
55
  "devDependencies": {
56
- "@akinon/eslint-plugin-projectzero": "1.40.0-rc.0",
56
+ "@akinon/eslint-plugin-projectzero": "1.40.0",
57
57
  "@semantic-release/changelog": "6.0.2",
58
58
  "@semantic-release/exec": "6.0.3",
59
59
  "@semantic-release/git": "10.0.1",
@@ -80,7 +80,7 @@
80
80
  "jest-css-modules-transform": "4.3.0",
81
81
  "lint-staged": "13.1.0",
82
82
  "prettier": "2.6.2",
83
- "react-number-format": "5.3.4",
83
+ "react-number-format": "4.9.3",
84
84
  "sass": "1.49.9",
85
85
  "semantic-release": "19.0.5",
86
86
  "server-only": "0.0.1",
@@ -286,11 +286,11 @@
286
286
  "empty_coupon": "You don't have any coupons"
287
287
  },
288
288
  "title": {
289
- "campaigns": {
289
+ "campaings": {
290
290
  "active": "Active Campaigns",
291
- "to_be_active": "Campaigns to be Active",
292
- "expired": "Expired Campaigns",
293
- "used": "Used Campaigns"
291
+ "to_be_active": "Campaings to be Active",
292
+ "expired": "Expired Campaings",
293
+ "used": "Used Campaings"
294
294
  },
295
295
  "coupons": {
296
296
  "active": "Active Coupons",
@@ -286,7 +286,7 @@
286
286
  "empty_coupon": "Herhangi bir kuponunuz yok"
287
287
  },
288
288
  "title": {
289
- "campaigns": {
289
+ "campaings": {
290
290
  "active": "Aktif Kampanyalar",
291
291
  "to_be_active": "Aktif Olacak Kampanyalar",
292
292
  "expired": "Süresi Dolmuş Kampanyalar",
@@ -51,7 +51,7 @@ export default function Page() {
51
51
  {basketOffersLoading && <LoaderSpinner className="mb-8" />}
52
52
  {basketOffersSuccess && (
53
53
  <CouponItem
54
- mainTitle={t('account.my_vouchers.title.campaigns.active')}
54
+ mainTitle={t('account.my_vouchers.title.campaings.active')}
55
55
  subTitles={[
56
56
  t('account.my_vouchers.card.campaign_name'),
57
57
  t('account.my_vouchers.card.starting_date'),
@@ -68,7 +68,7 @@ export default function Page() {
68
68
  {futureBasketOffersLoading && <LoaderSpinner className="mb-8" />}
69
69
  {futureBasketOffersSuccess && (
70
70
  <CouponItem
71
- mainTitle={t('account.my_vouchers.title.campaigns.to_be_active')}
71
+ mainTitle={t('account.my_vouchers.title.campaings.to_be_active')}
72
72
  subTitles={[
73
73
  t('account.my_vouchers.card.campaign_name'),
74
74
  t('account.my_vouchers.card.starting_date'),
@@ -85,7 +85,7 @@ export default function Page() {
85
85
  {expiredBasketOffersLoading && <LoaderSpinner className="mb-8" />}
86
86
  {expiredBasketOffersSuccess && (
87
87
  <CouponItem
88
- mainTitle={t('account.my_vouchers.title.campaigns.expired')}
88
+ mainTitle={t('account.my_vouchers.title.campaings.expired')}
89
89
  subTitles={[
90
90
  t('account.my_vouchers.card.campaign_name'),
91
91
  t('account.my_vouchers.card.starting_date'),
@@ -102,7 +102,7 @@ export default function Page() {
102
102
  {discountItemsLoading && <LoaderSpinner className="mb-8" />}
103
103
  {discountItemsSuccess && (
104
104
  <CouponItem
105
- mainTitle={t('account.my_vouchers.title.campaigns.used')}
105
+ mainTitle={t('account.my_vouchers.title.campaings.used')}
106
106
  subTitles={[
107
107
  t('account.my_vouchers.card.campaign_name'),
108
108
  t('account.my_vouchers.card.starting_date'),
@@ -247,7 +247,6 @@ export default function Page() {
247
247
  className="mb-5"
248
248
  required
249
249
  />
250
-
251
250
  <div className="mb-5">
252
251
  <Input
253
252
  label={t('account.my_profile.form.phone.placeholder')}
@@ -182,25 +182,21 @@ const CheckoutCompleted = ({
182
182
  }}
183
183
  >
184
184
  {data.order.orderitem_set.map((item) => (
185
- <div
186
- key={`order-item-${item.id}`}
187
- className="flex justify-between gap-x-4 w-full"
188
- >
189
- <Link
190
- className="flex justify-between gap-x-4 flex-1 items-center transition-all text-xs text-black-800 hover:text-secondary"
191
- href={item.product.absolute_url}
192
- passHref
193
- >
185
+ <div key={`order-item-${item.id}`} className="flex">
186
+ <Link href={item.product.absolute_url} passHref>
194
187
  <Image
195
188
  src={item.product.image}
196
189
  alt={item.product.name}
197
190
  width={64}
198
191
  height={96}
199
192
  />
200
-
201
- <span>{item.product.name}</span>
202
193
  </Link>
203
- <div className="flex justify-end items-center">
194
+ <div className="flex justify-between flex-1 items-center ml-4">
195
+ <>
196
+ <div className="text-xs text-black-800 transition-all w-full hover:text-secondary">
197
+ {item.product.name}
198
+ </div>
199
+ </>
204
200
  <div>
205
201
  {item.retail_price !== item.price && (
206
202
  <div className="text-black-800 line-through text-xs min-w-max sm:text-sm">
@@ -3,7 +3,7 @@ import { CheckboxProps } from '@theme/components/types';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
 
5
5
  const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
6
- const { children, checked = false, error, ...rest } = props;
6
+ const { children, checked, error, ...rest } = props;
7
7
 
8
8
  return (
9
9
  <label className={twMerge('flex flex-col text-xs', props.className)}>
@@ -12,7 +12,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
12
12
  type="checkbox"
13
13
  {...rest}
14
14
  ref={ref}
15
- defaultChecked={checked}
15
+ checked={checked ?? false}
16
16
  className="w-4 h-4 shrink-0"
17
17
  />
18
18
  {children && <span className="ml-2">{children}</span>}
@@ -1,28 +1,17 @@
1
1
  import clsx from 'clsx';
2
- import { forwardRef, FocusEvent, useState, Ref } from 'react';
2
+ import { forwardRef, FocusEvent, useState } from 'react';
3
3
  import { Controller } from 'react-hook-form';
4
- import { PatternFormat, PatternFormatProps } from 'react-number-format';
4
+ import NumberFormat, { NumberFormatProps } from 'react-number-format';
5
5
  import { InputProps } from '@theme/components/types';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
 
8
- const PatternFormatWithRef = forwardRef(
9
- (props: PatternFormatProps, ref: Ref<HTMLInputElement>) => {
10
- return <PatternFormat {...props} getInputRef={ref} />;
11
- }
12
- );
13
- PatternFormatWithRef.displayName = 'PatternFormatWithRef';
14
-
15
8
  export const Input = forwardRef<
16
9
  HTMLInputElement,
17
10
  InputProps &
18
11
  Pick<
19
- PatternFormatProps,
20
- 'mask' | 'allowEmptyFormatting' | 'onValueChange'
21
- > & {
22
- format?: string;
23
- defaultValue?: string;
24
- type?: string;
25
- }
12
+ NumberFormatProps,
13
+ 'format' | 'mask' | 'allowEmptyFormatting' | 'onValueChange'
14
+ >
26
15
  >((props, ref) => {
27
16
  const [focused, setFocused] = useState(false);
28
17
  const [hasValue, setHasValue] = useState(false);
@@ -48,7 +37,6 @@ export const Input = forwardRef<
48
37
  ),
49
38
  props.className
50
39
  );
51
-
52
40
  const inputProps: any = {
53
41
  id,
54
42
  ref,
@@ -91,14 +79,14 @@ export const Input = forwardRef<
91
79
  <Controller
92
80
  name={props.name ?? ''}
93
81
  control={props.control}
82
+ defaultValue={false}
94
83
  render={({ field }) => (
95
- <PatternFormatWithRef
84
+ <NumberFormat
96
85
  format={format}
97
86
  mask={mask ?? ''}
98
87
  {...rest}
99
88
  {...field}
100
89
  {...inputProps}
101
- type={props.type as 'text' | 'password' | 'tel'}
102
90
  />
103
91
  )}
104
92
  />
@@ -1,10 +1,10 @@
1
1
  import { useMemo } from 'react';
2
- import { NumericFormat, NumericFormatProps } from 'react-number-format';
2
+ import NumberFormat, { NumberFormatProps } from 'react-number-format';
3
3
  import { getCurrency } from '@akinon/next/utils';
4
4
  import { PriceProps } from '@theme/types';
5
5
  import { useLocalization } from '@akinon/next/hooks';
6
6
 
7
- export const Price = (props: NumericFormatProps & PriceProps) => {
7
+ export const Price = (props: NumberFormatProps & PriceProps) => {
8
8
  const {
9
9
  value,
10
10
  currencyCode,
@@ -38,7 +38,7 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
38
38
  );
39
39
 
40
40
  return (
41
- <NumericFormat
41
+ <NumberFormat
42
42
  value={useNegative ? `-${useNegativeSpace}${_value}` : _value}
43
43
  {...{
44
44
  [useCurrencyAfterPrice ? 'suffix' : 'prefix']: currency
@@ -31,7 +31,7 @@ interface Props {
31
31
  onSubmit: (data: any) => void;
32
32
  }
33
33
 
34
- const makeAddressFormSchema = (t, { phoneNumberLength, postCodeLength }) =>
34
+ const makeAddressFormSchema = (t, { phoneNumberLength }) =>
35
35
  yup.object().shape({
36
36
  title: yup.string().required(t('account.address_book.form.error.required')),
37
37
  first_name: yup
@@ -65,9 +65,8 @@ const makeAddressFormSchema = (t, { phoneNumberLength, postCodeLength }) =>
65
65
  .max(255, t('account.address_book.form.error.line_max')),
66
66
  postcode: yup
67
67
  .string()
68
- .transform((value: string) => value.replace(/_/g, '').replace(/ /g, ''))
69
- .min(postCodeLength, t('account.address_book.form.error.postcode_min'))
70
- .max(postCodeLength, t('account.address_book.form.error.postcode_max'))
68
+ .min(5, t('account.address_book.form.error.postcode_min'))
69
+ .max(5, t('account.address_book.form.error.postcode_max'))
71
70
  .required(t('account.address_book.form.error.required')),
72
71
  company_name: yup.string().nullable(),
73
72
  tax_no: yup.string().nullable(),
@@ -81,8 +80,7 @@ export const AddressForm = (props: Props) => {
81
80
  const { data, onSubmit } = props;
82
81
  const config = useAppSelector((state) => state.config);
83
82
  const addressFormSchema = makeAddressFormSchema(t, {
84
- phoneNumberLength: config.user_phone_format.length,
85
- postCodeLength: config.user_post_code_format.length
83
+ phoneNumberLength: config.user_phone_format.length
86
84
  });
87
85
  const {
88
86
  register,
@@ -183,22 +181,12 @@ export const AddressForm = (props: Props) => {
183
181
  if (data && country) {
184
182
  reset({
185
183
  ...data,
186
- is_corporate: String(data.is_corporate)
184
+ is_corporate:
185
+ String(data.is_corporate) === AddressType.company ? 'true' : 'false' // TODO: Fix this! This hack for radio buttons can't be set to boolean value
187
186
  });
188
187
  }
189
188
  }, [data, country, reset]);
190
189
 
191
- useEffect(() => {
192
- if (selectedFormType !== AddressType.company) {
193
- reset({
194
- ...watch(),
195
- company_name: '',
196
- tax_office: '',
197
- tax_no: ''
198
- });
199
- }
200
- }, [selectedFormType, reset, watch]);
201
-
202
190
  return (
203
191
  <form
204
192
  onSubmit={handleSubmit(onSubmit)}
@@ -334,15 +322,12 @@ export const AddressForm = (props: Props) => {
334
322
  )}
335
323
  </label>
336
324
  <Input
325
+ type="number"
337
326
  label={t('account.address_book.form.post_code.placeholder')}
338
327
  {...register('postcode')}
339
328
  error={errors.postcode}
340
329
  data-testid="address-form-post-code"
341
330
  required
342
- format={config.user_post_code_format.replaceAll(/\9/g, '#')}
343
- control={control}
344
- mask="_"
345
- allowEmptyFormatting
346
331
  />
347
332
  {selectedFormType === AddressType.company && (
348
333
  <>
@@ -3,9 +3,9 @@ import {
3
3
  Button,
4
4
  FileInput,
5
5
  Input,
6
- Link,
7
6
  LoaderSpinner,
8
- Select
7
+ Select,
8
+ Link
9
9
  } from '@theme/components';
10
10
  import { useSession } from 'next-auth/react';
11
11
  import { useEffect, useState } from 'react';
@@ -45,8 +45,7 @@ const contactFormSchema = (t) =>
45
45
  .when('subject', {
46
46
  is: (value) => value === '2',
47
47
  then: yup.string().required(t('account.contact.form.error.required'))
48
- }),
49
- file: yup.mixed()
48
+ })
50
49
  });
51
50
 
52
51
  const ContactForm = () => {
@@ -111,18 +110,8 @@ const ContactForm = () => {
111
110
  resolver: yupResolver(contactFormSchema(t))
112
111
  });
113
112
 
114
- const onSubmit: SubmitHandler<ContactFormType> = (data, event) => {
115
- const formData = new FormData()
116
-
117
- Object.keys(data ?? {}).forEach((key) => {
118
- if (key === "file" && data[key]){
119
- formData.append(key, data[key][0]);
120
- } else if (data[key]) {
121
- formData.append(key, data[key]);
122
- }
123
- });
124
-
125
- sendContact(formData);
113
+ const onSubmit: SubmitHandler<ContactFormType> = (data) => {
114
+ sendContact(data);
126
115
  };
127
116
 
128
117
  const handleChange = (e) => {
@@ -253,12 +242,7 @@ const ContactForm = () => {
253
242
  <label className="text-xs text-gray-800 mb-2 block">
254
243
  {t('account.contact.form.file.title')}
255
244
  </label>
256
- <FileInput
257
- name="file"
258
- title="file"
259
- className="w-full mb-5"
260
- {...register('file')}
261
- />
245
+ <FileInput className="w-full mb-5" title="test" />
262
246
  <Button type="submit" className="w-full font-medium">
263
247
  {t('account.contact.form.submit_button')}
264
248
  </Button>
@@ -30,11 +30,7 @@ const FavoriteProductsList = () => {
30
30
  }
31
31
 
32
32
  if (isLoading || isFetching) {
33
- return (
34
- <div className="flex items-center justify-center h-80">
35
- <LoaderSpinner />
36
- </div>
37
- );
33
+ return <LoaderSpinner />; // TODO: Fix loader spinner position
38
34
  }
39
35
 
40
36
  return (
@@ -1,14 +1,26 @@
1
1
  'use client';
2
2
 
3
+ import { WIDGET_TYPE } from '@theme/types';
3
4
  import clsx from 'clsx';
4
5
 
5
- import { Button, Icon } from '@theme/components';
6
- import { useLocalization } from '@akinon/next/hooks';
6
+ import { Accordion, Button, Checkbox, Icon, Radio } from '@theme/components';
7
+ import { SizeFilter } from './size-filter';
8
+
9
+ import { useLocalization, useRouter } from '@akinon/next/hooks';
10
+ import { Facet, FacetChoice } from '@akinon/next/types';
7
11
  import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
8
- import { resetSelectedFacets } from '@theme/redux/reducers/category';
12
+ import {
13
+ resetSelectedFacets,
14
+ toggleFacet
15
+ } from '@theme/redux/reducers/category';
9
16
  import CategoryActiveFilters from '@theme/views/category/category-active-filters';
10
17
  import { useMemo } from 'react';
11
- import { FilterItem } from './filter-item';
18
+ import { commonProductAttributes } from '@theme/settings';
19
+
20
+ const COMPONENT_TYPES = {
21
+ [WIDGET_TYPE.category]: Radio,
22
+ [WIDGET_TYPE.multiselect]: Checkbox
23
+ };
12
24
 
13
25
  interface Props {
14
26
  isMenuOpen: boolean;
@@ -16,11 +28,31 @@ interface Props {
16
28
  }
17
29
 
18
30
  export const Filters = (props: Props) => {
31
+ const router = useRouter();
19
32
  const facets = useAppSelector((state) => state.category.facets);
20
33
  const dispatch = useAppDispatch();
21
34
  const { t } = useLocalization();
22
35
  const { isMenuOpen, setIsMenuOpen } = props;
23
36
 
37
+ const handleSelectFilter = ({
38
+ facet,
39
+ choice
40
+ }: {
41
+ facet: Facet;
42
+ choice: FacetChoice;
43
+ }) => {
44
+ if (facet.key === 'category_ids') {
45
+ router.push(choice.url);
46
+ } else {
47
+ dispatch(
48
+ toggleFacet({
49
+ facet,
50
+ choice
51
+ })
52
+ );
53
+ }
54
+ };
55
+
24
56
  const haveFilter = useMemo(() => {
25
57
  return (
26
58
  facets.filter(
@@ -34,6 +66,10 @@ export const Filters = (props: Props) => {
34
66
  dispatch(resetSelectedFacets());
35
67
  };
36
68
 
69
+ const sizeKey = commonProductAttributes.find(
70
+ (item) => item.translationKey === 'size'
71
+ ).key;
72
+
37
73
  return (
38
74
  <div
39
75
  className={clsx(
@@ -52,7 +88,71 @@ export const Filters = (props: Props) => {
52
88
  <span>{t('category.filters.ready_to_wear')}</span>
53
89
  </div>
54
90
  {facets.map((facet) => {
55
- return <FilterItem key={facet.key} facet={facet} />;
91
+ let Component = null;
92
+ const choices = [...facet.data.choices];
93
+
94
+ if (facet.key === sizeKey) {
95
+ // If it's a size facet, use the custom size filter component
96
+ Component = SizeFilter;
97
+
98
+ const order = ['xs', 's', 'm', 'l', 'xl'];
99
+ choices.sort((a, b) => {
100
+ return (
101
+ order.indexOf(a.label.toLowerCase()) -
102
+ order.indexOf(b.label.toLowerCase())
103
+ );
104
+ });
105
+ } else {
106
+ Component =
107
+ COMPONENT_TYPES[facet.widget_type] ||
108
+ COMPONENT_TYPES[WIDGET_TYPE.category];
109
+ }
110
+
111
+ return (
112
+ <Accordion
113
+ key={facet.key}
114
+ title={facet.name}
115
+ isCollapse={choices.some((choice) => choice.is_selected)}
116
+ dataTestId={`filter-${facet.name}`}
117
+ >
118
+ <div
119
+ className={clsx(
120
+ 'flex gap-4 flex-wrap',
121
+ facet.key === sizeKey ? 'flex-row' : 'flex-col' // TODO: This condition must be refactor to a better way
122
+ )}
123
+ >
124
+ {choices.map((choice, index) => (
125
+ <Component // TODO: This dynamic component can be a hook or higher order component so it props can be standardized
126
+ key={choice.label}
127
+ data={choice}
128
+ name={facet.key}
129
+ onChange={() => {
130
+ if (facet.key !== sizeKey) {
131
+ // TODO: This condition must be refactor to a better way
132
+ handleSelectFilter({ facet, choice });
133
+ }
134
+ }}
135
+ onClick={() => {
136
+ if (facet.key === sizeKey) {
137
+ // TODO: This condition must be refactor to a better way
138
+ handleSelectFilter({ facet, choice });
139
+ }
140
+ }}
141
+ checked={choice.is_selected}
142
+ data-testid={`${choice.label.trim()}`}
143
+ >
144
+ {choice.label} (
145
+ <span
146
+ data-testid={`filter-count-${facet.name.toLowerCase()}-${index}`}
147
+ >
148
+ {choice.quantity}
149
+ </span>
150
+ )
151
+ </Component>
152
+ ))}
153
+ </div>
154
+ </Accordion>
155
+ );
56
156
  })}
57
157
  <div className="lg:hidden">
58
158
  <CategoryActiveFilters />
@@ -3,19 +3,7 @@
3
3
  "display": "Default",
4
4
  "compilerOptions": {
5
5
  "baseUrl": "./src",
6
- "paths": {
7
- "@theme/*": ["./*"],
8
- "@root/*": ["./app/[commerce]/[locale]/[currency]/*"],
9
- "@product/*": ["./app/[commerce]/[locale]/[currency]/product/*"],
10
- "@group-product/*": [
11
- "./app/[commerce]/[locale]/[currency]/group-product/*"
12
- ],
13
- "@category/*": ["./app/[commerce]/[locale]/[currency]/category/*"],
14
- "@special-page/*": [
15
- "./app/[commerce]/[locale]/[currency]/special-page/*"
16
- ],
17
- "@flat-page/*": ["./app/[commerce]/[locale]/[currency]/flat-page/*"]
18
- },
6
+ "paths": { "@theme/*": ["./*"] },
19
7
  "allowSyntheticDefaultImports": true,
20
8
  "composite": false,
21
9
  "declaration": true,
@@ -52,5 +40,7 @@
52
40
  ".next/types/**/*.ts",
53
41
  "../../packages/**/*"
54
42
  ],
55
- "exclude": ["node_modules", "../../packages/projectzero/app-template"]
43
+ "exclude": ["node_modules",
44
+ "../../packages/projectzero/app-template"
45
+ ]
56
46
  }
@@ -3,7 +3,6 @@ import * as fs from 'fs';
3
3
  import * as readline from 'readline';
4
4
  import { slugify } from '../utils';
5
5
 
6
- const { execSync } = require('child_process');
7
6
  const loadingSpinner = require('loading-spinner');
8
7
 
9
8
  interface Question {
@@ -140,8 +139,7 @@ export default async (): Promise<void> => {
140
139
  const answers = await getAnswers();
141
140
  const brandName =
142
141
  answers.brandName === '.' ? path.basename(workingDir) : answers.brandName;
143
- const projectDir = answers.brandName === '.' ? workingDir : path.resolve(workingDir, slugify(brandName));
144
- const relativeProjectDir = answers.brandName === '.' ? '.' : slugify(brandName);
142
+ const projectDir = path.resolve(workingDir, slugify(brandName));
145
143
 
146
144
  if (!fs.existsSync(projectDir)) {
147
145
  fs.mkdirSync(projectDir, { recursive: true });
@@ -174,34 +172,12 @@ export default async (): Promise<void> => {
174
172
  name: slugify(brandName)
175
173
  });
176
174
 
177
-
178
- console.log('\x1b[34m%s\x1b[0m', '\n🚀 Installing packages...\n');
179
-
180
- execSync(`cd ${relativeProjectDir} && yarn install`, { stdio: 'ignore' });
181
-
182
175
  loadingSpinner.stop();
183
176
 
184
- const successMessage = `
185
- ✨ ${brandName} project is ready at \x1b[4m${projectDir}\x1b[0m
186
-
187
- Within the directory, the following commands are available:
188
-
189
- \x1b[35m$ yarn dev\x1b[0m
190
- \x1b[32mLaunches the development server.\x1b[0m
191
-
192
- \x1b[35m$ yarn build\x1b[0m
193
- \x1b[32mCompiles the app into static files for production.\x1b[0m
194
-
195
- \x1b[35m$ yarn start\x1b[0m
196
- \x1b[32mRuns the production server.\x1b[0m
197
- `;
198
-
199
- const getStartedMessage = answers.brandName === '.'
200
- ? 'To get started, you can type:\n\n \x1b[35m$ yarn dev\x1b[0m\n'
201
- : `To get started, you can type:\n\n \x1b[35m$ cd ${relativeProjectDir}\x1b[0m\n \x1b[35m$ yarn dev\x1b[0m\n`;
177
+ console.log(
178
+ '\x1b[32m%s\x1b[0m',
179
+ `\n ✓ ${answers.brandName} project is ready.\n`
180
+ );
202
181
 
203
- console.log('\x1b[32m%s\x1b[0m', successMessage);
204
- console.log('\x1b[36m%s\x1b[0m', getStartedMessage);
205
- console.log('\x1b[33m%s\x1b[0m', 'Project setup is complete\n');
206
182
  console.log('\x1b[33m%s\x1b[0m', 'Project Zero - Akinon\n');
207
183
  };
@@ -39,7 +39,6 @@ const path_1 = __importDefault(require("path"));
39
39
  const fs = __importStar(require("fs"));
40
40
  const readline = __importStar(require("readline"));
41
41
  const utils_1 = require("../utils");
42
- const { execSync } = require('child_process');
43
42
  const loadingSpinner = require('loading-spinner');
44
43
  const workingDir = path_1.default.resolve(process.cwd());
45
44
  const rl = readline.createInterface({
@@ -132,8 +131,7 @@ exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
132
131
  }
133
132
  const answers = yield getAnswers();
134
133
  const brandName = answers.brandName === '.' ? path_1.default.basename(workingDir) : answers.brandName;
135
- const projectDir = answers.brandName === '.' ? workingDir : path_1.default.resolve(workingDir, (0, utils_1.slugify)(brandName));
136
- const relativeProjectDir = answers.brandName === '.' ? '.' : (0, utils_1.slugify)(brandName);
134
+ const projectDir = path_1.default.resolve(workingDir, (0, utils_1.slugify)(brandName));
137
135
  if (!fs.existsSync(projectDir)) {
138
136
  fs.mkdirSync(projectDir, { recursive: true });
139
137
  }
@@ -155,28 +153,7 @@ exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
155
153
  updateFileContents(path_1.default.join(projectDir, 'package.json'), {
156
154
  name: (0, utils_1.slugify)(brandName)
157
155
  });
158
- console.log('\x1b[34m%s\x1b[0m', '\n🚀 Installing packages...\n');
159
- execSync(`cd ${relativeProjectDir} && yarn install`, { stdio: 'ignore' });
160
156
  loadingSpinner.stop();
161
- const successMessage = `
162
- ✨ ${brandName} project is ready at \x1b[4m${projectDir}\x1b[0m
163
-
164
- Within the directory, the following commands are available:
165
-
166
- \x1b[35m$ yarn dev\x1b[0m
167
- \x1b[32mLaunches the development server.\x1b[0m
168
-
169
- \x1b[35m$ yarn build\x1b[0m
170
- \x1b[32mCompiles the app into static files for production.\x1b[0m
171
-
172
- \x1b[35m$ yarn start\x1b[0m
173
- \x1b[32mRuns the production server.\x1b[0m
174
- `;
175
- const getStartedMessage = answers.brandName === '.'
176
- ? 'To get started, you can type:\n\n \x1b[35m$ yarn dev\x1b[0m\n'
177
- : `To get started, you can type:\n\n \x1b[35m$ cd ${relativeProjectDir}\x1b[0m\n \x1b[35m$ yarn dev\x1b[0m\n`;
178
- console.log('\x1b[32m%s\x1b[0m', successMessage);
179
- console.log('\x1b[36m%s\x1b[0m', getStartedMessage);
180
- console.log('\x1b[33m%s\x1b[0m', 'Project setup is complete\n');
157
+ console.log('\x1b[32m%s\x1b[0m', `\n ${answers.brandName} project is ready.\n`);
181
158
  console.log('\x1b[33m%s\x1b[0m', 'Project Zero - Akinon\n');
182
159
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/projectzero",
3
- "version": "1.40.0-rc.0",
3
+ "version": "1.40.0",
4
4
  "private": false,
5
5
  "description": "CLI tool to manage your Project Zero Next project",
6
6
  "bin": {
@@ -1,8 +0,0 @@
1
- import Page, {
2
- dynamic,
3
- revalidate,
4
- generateMetadata
5
- } from '@akinon/next/routes/pretty-url';
6
-
7
- export { dynamic, revalidate, generateMetadata };
8
- export default Page;
@@ -1,131 +0,0 @@
1
- import clsx from 'clsx';
2
- import { useAppDispatch } from '@akinon/next/redux/hooks';
3
- import { Facet, FacetChoice } from '@akinon/next/types';
4
- import { Accordion, Radio, Checkbox } from '../../../components';
5
- import { WIDGET_TYPE } from '../../../types';
6
- import { SizeFilter } from './size-filter';
7
- import { toggleFacet } from '@theme/redux/reducers/category';
8
- import { commonProductAttributes } from '@theme/settings';
9
- import { useRouter } from '@akinon/next/hooks';
10
-
11
- const COMPONENT_TYPES = {
12
- [WIDGET_TYPE.category]: Radio,
13
- [WIDGET_TYPE.multiselect]: Checkbox
14
- };
15
-
16
- const sizeKey = commonProductAttributes.find(
17
- (item) => item.translationKey === 'size'
18
- ).key;
19
-
20
- interface Props {
21
- facet: Facet;
22
- }
23
-
24
- const sortByPredefinedOrder = (
25
- aLabel: string,
26
- bLabel: string,
27
- order: string[]
28
- ) => {
29
- const aIndex = order.indexOf(aLabel);
30
- const bIndex = order.indexOf(bLabel);
31
-
32
- if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
33
- if (aIndex !== -1) return -1;
34
- if (bIndex !== -1) return 1;
35
-
36
- return null;
37
- };
38
-
39
- const sortByNumericValue = (aLabel: string, bLabel: string) => {
40
- const aNum = parseInt(aLabel, 10);
41
- const bNum = parseInt(bLabel, 10);
42
-
43
- if (!isNaN(aNum) && !isNaN(bNum)) return aNum - bNum;
44
- if (!isNaN(aNum)) return -1;
45
- if (!isNaN(bNum)) return 1;
46
-
47
- return null;
48
- };
49
-
50
- const sortChoices = (
51
- facetKey: string,
52
- choices: FacetChoice[]
53
- ): FacetChoice[] => {
54
- if (facetKey === sizeKey) {
55
- const order = ['xs', 's', 'm', 'l', 'xl'];
56
-
57
- return choices.sort((a, b) => {
58
- const aLabel = a.label.toLowerCase();
59
- const bLabel = b.label.toLowerCase();
60
-
61
- const orderComparison = sortByPredefinedOrder(aLabel, bLabel, order);
62
- if (orderComparison !== null) return orderComparison;
63
-
64
- const numericComparison = sortByNumericValue(aLabel, bLabel);
65
- if (numericComparison !== null) return numericComparison;
66
-
67
- return aLabel.localeCompare(bLabel);
68
- });
69
- }
70
-
71
- return choices;
72
- };
73
-
74
- const getComponentByWidgetType = (widgetType: string, facetKey: string) => {
75
- if (facetKey === sizeKey) {
76
- return SizeFilter;
77
- }
78
- return COMPONENT_TYPES[widgetType] || COMPONENT_TYPES[WIDGET_TYPE.category];
79
- };
80
-
81
- export const FilterItem = ({ facet }: Props) => {
82
- const dispatch = useAppDispatch();
83
- const router = useRouter();
84
-
85
- const handleSelectFilter = (choice: FacetChoice) => {
86
- if (facet.key === 'category_ids') {
87
- router.push(choice.url);
88
- } else {
89
- dispatch(toggleFacet({ facet, choice }));
90
- }
91
- };
92
-
93
- const Component = getComponentByWidgetType(facet.widget_type, facet.key);
94
- const choices = sortChoices(facet.key, [...facet.data.choices]);
95
-
96
- return (
97
- <Accordion
98
- key={facet.key}
99
- title={facet.name}
100
- isCollapse={choices.some((choice) => choice.is_selected)}
101
- dataTestId={`filter-${facet.name}`}
102
- >
103
- <div
104
- className={clsx('flex gap-4', {
105
- 'flex-wrap flex-row': facet.key === sizeKey,
106
- 'flex-col': facet.key !== sizeKey
107
- })}
108
- >
109
- {choices.map((choice, index) => (
110
- <Component
111
- key={choice.label}
112
- data={choice}
113
- name={facet.key}
114
- onChange={() => facet.key !== sizeKey && handleSelectFilter(choice)}
115
- onClick={() => facet.key === sizeKey && handleSelectFilter(choice)}
116
- checked={choice.is_selected}
117
- data-testid={`${choice.label.trim()}`}
118
- >
119
- {choice.label} (
120
- <span
121
- data-testid={`filter-count-${facet.name.toLowerCase()}-${index}`}
122
- >
123
- {choice.quantity}
124
- </span>
125
- )
126
- </Component>
127
- ))}
128
- </div>
129
- </Accordion>
130
- );
131
- };