@akinon/pz-similar-products 1.107.0-rc.86 → 1.108.0-rc.10
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 +3 -374
- package/README.md +0 -218
- package/package.json +1 -1
- package/src/data/endpoints.ts +9 -37
- package/src/hooks/index.ts +0 -1
- package/src/hooks/use-similar-products.ts +27 -166
- package/src/types/index.ts +0 -51
- package/src/utils/index.ts +3 -38
- package/src/views/filters.tsx +3 -27
- package/src/views/header-image-search-feature.tsx +1 -13
- package/src/views/image-search-button.tsx +18 -20
- package/src/views/main.tsx +5 -82
- package/src/views/product-image-search-feature.tsx +3 -17
- package/src/views/search-button.tsx +2 -12
- package/src/views/search-modal.tsx +10 -169
- package/src/hooks/use-text-search-feature.ts +0 -41
package/src/data/endpoints.ts
CHANGED
|
@@ -27,14 +27,9 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
27
27
|
endpoints: (build) => ({
|
|
28
28
|
getSimilarProductsByUrl: build.query<
|
|
29
29
|
SimilarProductsResponse,
|
|
30
|
-
{
|
|
31
|
-
url: string;
|
|
32
|
-
limit?: number;
|
|
33
|
-
excluded_product_ids?: number[];
|
|
34
|
-
text?: string;
|
|
35
|
-
}
|
|
30
|
+
{ url: string; limit?: number; excluded_product_ids?: number[] }
|
|
36
31
|
>({
|
|
37
|
-
query: ({ url, limit = 20, excluded_product_ids
|
|
32
|
+
query: ({ url, limit = 20, excluded_product_ids }) => {
|
|
38
33
|
const params = new URLSearchParams();
|
|
39
34
|
params.append('limit', String(limit));
|
|
40
35
|
params.append('url', url);
|
|
@@ -43,10 +38,6 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
43
38
|
params.append('excluded_product_ids', excluded_product_ids.join(','));
|
|
44
39
|
}
|
|
45
40
|
|
|
46
|
-
if (text) {
|
|
47
|
-
params.append('text', text);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
41
|
return {
|
|
51
42
|
url: `/api/similar-products?${params.toString()}`,
|
|
52
43
|
method: 'GET',
|
|
@@ -59,22 +50,12 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
59
50
|
|
|
60
51
|
getSimilarProductsByImage: build.mutation<
|
|
61
52
|
SimilarProductsResponse,
|
|
62
|
-
{
|
|
63
|
-
image: string;
|
|
64
|
-
limit?: number;
|
|
65
|
-
excluded_product_ids?: number[];
|
|
66
|
-
text?: string;
|
|
67
|
-
}
|
|
53
|
+
{ image: string; limit?: number; excluded_product_ids?: number[] }
|
|
68
54
|
>({
|
|
69
|
-
query: ({ image, limit = 20, excluded_product_ids
|
|
55
|
+
query: ({ image, limit = 20, excluded_product_ids }) => {
|
|
70
56
|
const params = new URLSearchParams();
|
|
71
57
|
params.append('limit', String(limit));
|
|
72
58
|
|
|
73
|
-
const bodyData: any = { image, excluded_product_ids };
|
|
74
|
-
if (text) {
|
|
75
|
-
bodyData.text = text;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
59
|
return {
|
|
79
60
|
url: `/api/similar-products?${params.toString()}`,
|
|
80
61
|
method: 'POST',
|
|
@@ -82,7 +63,7 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
82
63
|
'Content-Type': 'application/json',
|
|
83
64
|
Accept: 'application/json'
|
|
84
65
|
},
|
|
85
|
-
body: JSON.stringify(
|
|
66
|
+
body: JSON.stringify({ image, excluded_product_ids })
|
|
86
67
|
};
|
|
87
68
|
}
|
|
88
69
|
}),
|
|
@@ -91,21 +72,12 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
91
72
|
SimilarProductsListResponse,
|
|
92
73
|
{
|
|
93
74
|
filter: string;
|
|
94
|
-
searchParams?: Record<string, string
|
|
75
|
+
searchParams?: Record<string, string>;
|
|
95
76
|
isExclude?: boolean;
|
|
96
77
|
}
|
|
97
78
|
>({
|
|
98
79
|
query: ({ filter, searchParams = {}, isExclude = false }) => {
|
|
99
|
-
const params = new URLSearchParams();
|
|
100
|
-
|
|
101
|
-
Object.entries(searchParams).forEach(([key, value]) => {
|
|
102
|
-
if (Array.isArray(value)) {
|
|
103
|
-
value.forEach((v) => params.append(key, v));
|
|
104
|
-
} else {
|
|
105
|
-
params.append(key, value);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
80
|
+
const params = new URLSearchParams(searchParams);
|
|
109
81
|
const queryString = params.toString();
|
|
110
82
|
|
|
111
83
|
const headerName = isExclude
|
|
@@ -126,7 +98,7 @@ export const similarProductsApi = api.injectEndpoints({
|
|
|
126
98
|
.reduce((acc, key) => {
|
|
127
99
|
acc[key] = searchParams[key];
|
|
128
100
|
return acc;
|
|
129
|
-
}, {} as Record<string, string
|
|
101
|
+
}, {} as Record<string, string>);
|
|
130
102
|
|
|
131
103
|
return JSON.stringify({
|
|
132
104
|
filter,
|
|
@@ -147,4 +119,4 @@ export const {
|
|
|
147
119
|
useLazyGetSimilarProductsListQuery
|
|
148
120
|
} = similarProductsApi;
|
|
149
121
|
|
|
150
|
-
export type { Product, Facet, FacetChoice, SortOption, Pagination };
|
|
122
|
+
export type { Product, Facet, FacetChoice, SortOption, Pagination };
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useCallback
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { Product } from '@akinon/next/types';
|
|
3
3
|
import {
|
|
4
4
|
useLazyGetSimilarProductsByUrlQuery,
|
|
@@ -13,19 +13,17 @@ import {
|
|
|
13
13
|
validateImageFromDataUrl,
|
|
14
14
|
type ImageValidationResult
|
|
15
15
|
} from '../utils/image-validation';
|
|
16
|
-
import { debounce } from '../utils';
|
|
17
16
|
|
|
18
17
|
type SearchResults = SimilarProductsListResponse;
|
|
19
18
|
|
|
20
19
|
interface SearchParams {
|
|
21
|
-
[key: string]: string
|
|
20
|
+
[key: string]: string;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
export function useSimilarProducts(product: Product) {
|
|
25
24
|
const { t } = useLocalization();
|
|
26
25
|
const [currentImageUrl, setCurrentImageUrl] = useState('');
|
|
27
26
|
const [fileError, setFileError] = useState('');
|
|
28
|
-
const [searchText, setSearchText] = useState('');
|
|
29
27
|
const [searchResults, setSearchResults] = useState<SearchResults | null>(
|
|
30
28
|
null
|
|
31
29
|
);
|
|
@@ -35,16 +33,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
35
33
|
const [isCropProcessing, setIsCropProcessing] = useState(false);
|
|
36
34
|
const [loadedPages, setLoadedPages] = useState<Set<number>>(new Set([1]));
|
|
37
35
|
const [allLoadedProducts, setAllLoadedProducts] = useState<Product[]>([]);
|
|
38
|
-
const [currentImageBase64, setCurrentImageBase64] = useState<string>('');
|
|
39
|
-
const [hasCroppedImage, setHasCroppedImage] = useState(false);
|
|
40
|
-
|
|
41
|
-
const searchTextRef = useRef<string>('');
|
|
42
|
-
const hasUploadedImageRef = useRef<boolean>(false);
|
|
43
|
-
|
|
44
|
-
const setSearchTextWithRef = useCallback((text: string) => {
|
|
45
|
-
setSearchText(text);
|
|
46
|
-
searchTextRef.current = text;
|
|
47
|
-
}, []);
|
|
48
36
|
|
|
49
37
|
const [fetchSimilarProductsByUrl, { isLoading: isUrlSearchLoading }] =
|
|
50
38
|
useLazyGetSimilarProductsByUrlQuery();
|
|
@@ -115,7 +103,7 @@ export function useSimilarProducts(product: Product) {
|
|
|
115
103
|
String(choice.value)
|
|
116
104
|
);
|
|
117
105
|
const searchKey = String(facet.search_key || facet.key);
|
|
118
|
-
searchParams[searchKey] = values.
|
|
106
|
+
searchParams[searchKey] = values.join(',');
|
|
119
107
|
}
|
|
120
108
|
});
|
|
121
109
|
}
|
|
@@ -350,9 +338,7 @@ export function useSimilarProducts(product: Product) {
|
|
|
350
338
|
const productIds = extractProductIds(data);
|
|
351
339
|
|
|
352
340
|
if (productIds.length > 0) {
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
const result = await executeProductSearch(productIds, searchParams);
|
|
341
|
+
const result = await executeProductSearch(productIds);
|
|
356
342
|
if (result) {
|
|
357
343
|
const resultWithCorrectSorterState = {
|
|
358
344
|
...result,
|
|
@@ -371,11 +357,7 @@ export function useSimilarProducts(product: Product) {
|
|
|
371
357
|
executeProductSearch,
|
|
372
358
|
updateSorterState,
|
|
373
359
|
updateResultsAndKey,
|
|
374
|
-
createEmptySearchResults
|
|
375
|
-
searchText,
|
|
376
|
-
searchTextRef,
|
|
377
|
-
buildSearchParams,
|
|
378
|
-
searchResults
|
|
360
|
+
createEmptySearchResults
|
|
379
361
|
]
|
|
380
362
|
);
|
|
381
363
|
|
|
@@ -444,24 +426,17 @@ export function useSimilarProducts(product: Product) {
|
|
|
444
426
|
);
|
|
445
427
|
|
|
446
428
|
const fetchSimilarProductsByImageUrl = useCallback(
|
|
447
|
-
async (imageUrl: string
|
|
429
|
+
async (imageUrl: string) => {
|
|
448
430
|
setFileError('');
|
|
449
|
-
|
|
450
431
|
try {
|
|
451
432
|
const productPk = product?.pk;
|
|
452
433
|
const excludedIds = productPk ? [productPk] : undefined;
|
|
453
434
|
|
|
454
|
-
const
|
|
455
|
-
overrideText !== undefined ? overrideText : searchTextRef.current;
|
|
456
|
-
|
|
457
|
-
const requestParams = {
|
|
435
|
+
const result = await fetchSimilarProductsByUrl({
|
|
458
436
|
url: imageUrl,
|
|
459
437
|
limit: 20,
|
|
460
|
-
excluded_product_ids: excludedIds
|
|
461
|
-
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
const result = await fetchSimilarProductsByUrl(requestParams).unwrap();
|
|
438
|
+
excluded_product_ids: excludedIds
|
|
439
|
+
}).unwrap();
|
|
465
440
|
|
|
466
441
|
await handleSearchResults(result);
|
|
467
442
|
return result;
|
|
@@ -475,8 +450,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
475
450
|
[
|
|
476
451
|
fetchSimilarProductsByUrl,
|
|
477
452
|
product?.pk,
|
|
478
|
-
searchText,
|
|
479
|
-
searchTextRef,
|
|
480
453
|
handleSearchResults,
|
|
481
454
|
updateResultsAndKey,
|
|
482
455
|
createEmptySearchResults,
|
|
@@ -489,62 +462,31 @@ export function useSimilarProducts(product: Product) {
|
|
|
489
462
|
if (product?.productimage_set?.length > 0) {
|
|
490
463
|
const initialImageUrl = product.productimage_set[0].image;
|
|
491
464
|
setCurrentImageUrl(initialImageUrl);
|
|
492
|
-
setHasCroppedImage(false);
|
|
493
|
-
setCurrentImageBase64('');
|
|
494
|
-
setHasUploadedImage(false);
|
|
495
|
-
hasUploadedImageRef.current = false;
|
|
496
465
|
}
|
|
497
466
|
}, [product]);
|
|
498
467
|
|
|
499
468
|
const fetchSimilarProductsByBase64 = useCallback(
|
|
500
|
-
async (
|
|
501
|
-
base64Image: string,
|
|
502
|
-
overrideText?: string,
|
|
503
|
-
forceExclude?: boolean
|
|
504
|
-
) => {
|
|
469
|
+
async (base64Image: string) => {
|
|
505
470
|
const base64Data = base64Image.startsWith('data:')
|
|
506
471
|
? base64Image.split(',')[1]
|
|
507
472
|
: base64Image;
|
|
508
473
|
|
|
509
|
-
const textToUse =
|
|
510
|
-
overrideText !== undefined ? overrideText : searchTextRef.current;
|
|
511
|
-
|
|
512
|
-
const shouldExclude =
|
|
513
|
-
forceExclude !== undefined ? forceExclude : !hasUploadedImage;
|
|
514
|
-
|
|
515
|
-
const requestData = {
|
|
516
|
-
image: base64Data,
|
|
517
|
-
limit: 20,
|
|
518
|
-
excluded_product_ids: shouldExclude
|
|
519
|
-
? product?.pk
|
|
520
|
-
? [product.pk]
|
|
521
|
-
: undefined
|
|
522
|
-
: undefined,
|
|
523
|
-
text: textToUse || undefined
|
|
524
|
-
};
|
|
525
|
-
|
|
526
474
|
return handleImageSearch(
|
|
527
|
-
async () =>
|
|
475
|
+
async () =>
|
|
476
|
+
getSimilarProductsByImage({
|
|
477
|
+
image: base64Data,
|
|
478
|
+
limit: 20
|
|
479
|
+
}).unwrap(),
|
|
528
480
|
base64Image,
|
|
529
481
|
'Image search'
|
|
530
482
|
);
|
|
531
483
|
},
|
|
532
|
-
[
|
|
533
|
-
getSimilarProductsByImage,
|
|
534
|
-
searchText,
|
|
535
|
-
searchTextRef,
|
|
536
|
-
handleImageSearch,
|
|
537
|
-
hasUploadedImage,
|
|
538
|
-
product?.pk
|
|
539
|
-
]
|
|
484
|
+
[getSimilarProductsByImage, handleImageSearch]
|
|
540
485
|
);
|
|
541
486
|
|
|
542
487
|
const fetchSimilarProductsByImageCrop = useCallback(
|
|
543
|
-
async (dataString: string
|
|
488
|
+
async (dataString: string) => {
|
|
544
489
|
setFileError('');
|
|
545
|
-
|
|
546
|
-
setCurrentImageBase64(dataString);
|
|
547
|
-
setHasCroppedImage(true);
|
|
548
490
|
if (dataString.startsWith('data:application/x-cors-fallback;base64,')) {
|
|
549
491
|
try {
|
|
550
492
|
const fallbackDataEncoded = dataString.replace(
|
|
@@ -607,12 +549,9 @@ export function useSimilarProducts(product: Product) {
|
|
|
607
549
|
getSimilarProductsByImage({
|
|
608
550
|
image: base64Data,
|
|
609
551
|
limit: 20,
|
|
610
|
-
excluded_product_ids:
|
|
611
|
-
? product
|
|
612
|
-
|
|
613
|
-
: undefined
|
|
614
|
-
: undefined,
|
|
615
|
-
text: searchTextRef.current || undefined
|
|
552
|
+
excluded_product_ids: product?.pk
|
|
553
|
+
? [product.pk]
|
|
554
|
+
: undefined
|
|
616
555
|
}).unwrap(),
|
|
617
556
|
croppedBase64,
|
|
618
557
|
'Proxy crop search'
|
|
@@ -662,12 +601,7 @@ export function useSimilarProducts(product: Product) {
|
|
|
662
601
|
getSimilarProductsByImage({
|
|
663
602
|
image: base64Data,
|
|
664
603
|
limit: 20,
|
|
665
|
-
excluded_product_ids:
|
|
666
|
-
? product?.pk
|
|
667
|
-
? [product.pk]
|
|
668
|
-
: undefined
|
|
669
|
-
: undefined,
|
|
670
|
-
text: searchTextRef.current || undefined
|
|
604
|
+
excluded_product_ids: product?.pk ? [product.pk] : undefined
|
|
671
605
|
}).unwrap(),
|
|
672
606
|
dataString,
|
|
673
607
|
'Image crop search'
|
|
@@ -675,14 +609,11 @@ export function useSimilarProducts(product: Product) {
|
|
|
675
609
|
},
|
|
676
610
|
[
|
|
677
611
|
getSimilarProductsByImage,
|
|
678
|
-
searchText,
|
|
679
|
-
searchTextRef,
|
|
680
612
|
handleImageSearch,
|
|
681
613
|
product,
|
|
682
614
|
fetchSimilarProductsByImageUrl,
|
|
683
615
|
setFileError,
|
|
684
|
-
t
|
|
685
|
-
hasUploadedImage
|
|
616
|
+
t
|
|
686
617
|
]
|
|
687
618
|
);
|
|
688
619
|
|
|
@@ -693,8 +624,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
693
624
|
const file = event.target.files?.[0];
|
|
694
625
|
if (!file) return;
|
|
695
626
|
|
|
696
|
-
setSearchTextWithRef('');
|
|
697
|
-
|
|
698
627
|
try {
|
|
699
628
|
let processedFile = file;
|
|
700
629
|
|
|
@@ -721,9 +650,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
721
650
|
const dataUrl = e.target?.result as string;
|
|
722
651
|
setCurrentImageUrl(dataUrl);
|
|
723
652
|
setHasUploadedImage(true);
|
|
724
|
-
hasUploadedImageRef.current = true;
|
|
725
|
-
setHasCroppedImage(false);
|
|
726
|
-
setCurrentImageBase64('');
|
|
727
653
|
|
|
728
654
|
const metadataValidation = await validateImageFromDataUrl(dataUrl);
|
|
729
655
|
if (!metadataValidation.isValid) {
|
|
@@ -732,7 +658,7 @@ export function useSimilarProducts(product: Product) {
|
|
|
732
658
|
);
|
|
733
659
|
return;
|
|
734
660
|
}
|
|
735
|
-
fetchSimilarProductsByBase64(dataUrl
|
|
661
|
+
fetchSimilarProductsByBase64(dataUrl);
|
|
736
662
|
};
|
|
737
663
|
|
|
738
664
|
reader.onerror = () =>
|
|
@@ -753,8 +679,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
753
679
|
|
|
754
680
|
try {
|
|
755
681
|
setCurrentImageUrl(base64Image);
|
|
756
|
-
setCurrentImageBase64(base64Image);
|
|
757
|
-
setHasCroppedImage(true);
|
|
758
682
|
|
|
759
683
|
const metadataValidation = await validateImageFromDataUrl(base64Image);
|
|
760
684
|
if (!metadataValidation.isValid) {
|
|
@@ -764,14 +688,10 @@ export function useSimilarProducts(product: Product) {
|
|
|
764
688
|
return;
|
|
765
689
|
}
|
|
766
690
|
|
|
767
|
-
if (
|
|
768
|
-
await fetchSimilarProductsByBase64(
|
|
769
|
-
base64Image,
|
|
770
|
-
searchTextRef.current,
|
|
771
|
-
false
|
|
772
|
-
);
|
|
691
|
+
if (hasUploadedImage) {
|
|
692
|
+
await fetchSimilarProductsByBase64(base64Image);
|
|
773
693
|
} else {
|
|
774
|
-
await fetchSimilarProductsByImageCrop(base64Image
|
|
694
|
+
await fetchSimilarProductsByImageCrop(base64Image);
|
|
775
695
|
}
|
|
776
696
|
} catch (error) {
|
|
777
697
|
setFileError(t('common.similar_products.errors.crop_processing_error'));
|
|
@@ -962,11 +882,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
962
882
|
setLoadedPages(new Set([1]));
|
|
963
883
|
}, []);
|
|
964
884
|
|
|
965
|
-
const resetCropState = useCallback(() => {
|
|
966
|
-
setHasCroppedImage(false);
|
|
967
|
-
setCurrentImageBase64('');
|
|
968
|
-
}, []);
|
|
969
|
-
|
|
970
885
|
const clearFileInput = useCallback(
|
|
971
886
|
(fileInputRef: React.RefObject<HTMLInputElement>) => {
|
|
972
887
|
if (fileInputRef.current) {
|
|
@@ -976,55 +891,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
976
891
|
[]
|
|
977
892
|
);
|
|
978
893
|
|
|
979
|
-
const handleTextSearch = useCallback(async () => {
|
|
980
|
-
const textToUse = searchTextRef.current || searchText;
|
|
981
|
-
|
|
982
|
-
if (hasCroppedImage && currentImageBase64) {
|
|
983
|
-
await fetchSimilarProductsByBase64(
|
|
984
|
-
currentImageBase64,
|
|
985
|
-
textToUse,
|
|
986
|
-
!hasUploadedImage
|
|
987
|
-
);
|
|
988
|
-
} else if (hasUploadedImage && currentImageUrl) {
|
|
989
|
-
await fetchSimilarProductsByBase64(currentImageUrl, textToUse, false);
|
|
990
|
-
} else if (currentImageUrl) {
|
|
991
|
-
await fetchSimilarProductsByImageUrl(currentImageUrl, textToUse);
|
|
992
|
-
}
|
|
993
|
-
}, [
|
|
994
|
-
searchText,
|
|
995
|
-
searchTextRef,
|
|
996
|
-
currentImageUrl,
|
|
997
|
-
currentImageBase64,
|
|
998
|
-
hasCroppedImage,
|
|
999
|
-
hasUploadedImage,
|
|
1000
|
-
fetchSimilarProductsByImageUrl,
|
|
1001
|
-
fetchSimilarProductsByBase64
|
|
1002
|
-
]);
|
|
1003
|
-
|
|
1004
|
-
const handleClearText = useCallback(async () => {
|
|
1005
|
-
setSearchTextWithRef('');
|
|
1006
|
-
|
|
1007
|
-
if (hasCroppedImage && currentImageBase64) {
|
|
1008
|
-
await fetchSimilarProductsByBase64(
|
|
1009
|
-
currentImageBase64,
|
|
1010
|
-
'',
|
|
1011
|
-
!hasUploadedImage
|
|
1012
|
-
);
|
|
1013
|
-
} else if (hasUploadedImage && currentImageUrl) {
|
|
1014
|
-
await fetchSimilarProductsByBase64(currentImageUrl, '', false);
|
|
1015
|
-
} else if (currentImageUrl) {
|
|
1016
|
-
await fetchSimilarProductsByImageUrl(currentImageUrl, '');
|
|
1017
|
-
}
|
|
1018
|
-
}, [
|
|
1019
|
-
hasCroppedImage,
|
|
1020
|
-
currentImageBase64,
|
|
1021
|
-
currentImageUrl,
|
|
1022
|
-
hasUploadedImage,
|
|
1023
|
-
fetchSimilarProductsByBase64,
|
|
1024
|
-
fetchSimilarProductsByImageUrl,
|
|
1025
|
-
setSearchTextWithRef
|
|
1026
|
-
]);
|
|
1027
|
-
|
|
1028
894
|
const handleLoadMore = async () => {
|
|
1029
895
|
if (!searchResults?.pagination || isLoading) return;
|
|
1030
896
|
|
|
@@ -1065,8 +931,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
1065
931
|
setCurrentImageUrl,
|
|
1066
932
|
isLoading,
|
|
1067
933
|
fileError,
|
|
1068
|
-
searchText,
|
|
1069
|
-
setSearchText: setSearchTextWithRef,
|
|
1070
934
|
searchResults,
|
|
1071
935
|
resultsKey,
|
|
1072
936
|
hasUploadedImage,
|
|
@@ -1085,9 +949,6 @@ export function useSimilarProducts(product: Product) {
|
|
|
1085
949
|
allLoadedProducts,
|
|
1086
950
|
clearError,
|
|
1087
951
|
clearResults,
|
|
1088
|
-
clearFileInput
|
|
1089
|
-
handleTextSearch,
|
|
1090
|
-
handleClearText,
|
|
1091
|
-
resetCropState
|
|
952
|
+
clearFileInput
|
|
1092
953
|
};
|
|
1093
954
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -58,10 +58,6 @@ export interface SimilarProductsModalProps {
|
|
|
58
58
|
showResetButton?: boolean;
|
|
59
59
|
settings?: any;
|
|
60
60
|
className?: string;
|
|
61
|
-
searchText?: string;
|
|
62
|
-
setSearchText?: (text: string) => void;
|
|
63
|
-
handleTextSearch?: () => void;
|
|
64
|
-
handleClearText?: () => void;
|
|
65
61
|
}
|
|
66
62
|
|
|
67
63
|
export interface FilterSidebarProps {
|
|
@@ -71,8 +67,6 @@ export interface FilterSidebarProps {
|
|
|
71
67
|
isLoading: boolean;
|
|
72
68
|
handleFacetChange: (facetKey: string, choiceValue: string | number) => void;
|
|
73
69
|
removeFacetFilter: (facetKey: string, choiceValue: string | number) => void;
|
|
74
|
-
searchText?: string;
|
|
75
|
-
setSearchText?: (text: string) => void;
|
|
76
70
|
currentImageUrl: string;
|
|
77
71
|
isCropping: boolean;
|
|
78
72
|
imageRef: React.RefObject<HTMLImageElement>;
|
|
@@ -132,8 +126,6 @@ export interface CustomRendererProps {
|
|
|
132
126
|
onSortChange: (value: string) => void;
|
|
133
127
|
onFilterMenuToggle: () => void;
|
|
134
128
|
isLoading: boolean;
|
|
135
|
-
searchText?: string;
|
|
136
|
-
setSearchText?: (text: string) => void;
|
|
137
129
|
}) => React.ReactNode;
|
|
138
130
|
renderSortDropdown?: (props: {
|
|
139
131
|
sorters: SortOption[];
|
|
@@ -149,17 +141,6 @@ export interface CustomRendererProps {
|
|
|
149
141
|
onClick: () => void;
|
|
150
142
|
isLoading: boolean;
|
|
151
143
|
}) => React.ReactNode;
|
|
152
|
-
renderModalSearchInput?: (props: {
|
|
153
|
-
searchText: string;
|
|
154
|
-
setSearchText: (text: string) => void;
|
|
155
|
-
isLoading: boolean;
|
|
156
|
-
placeholder: string;
|
|
157
|
-
onSearch?: () => void;
|
|
158
|
-
}) => React.ReactNode;
|
|
159
|
-
renderSearchIcon?: (props: {
|
|
160
|
-
disabled: boolean;
|
|
161
|
-
onClick?: () => void;
|
|
162
|
-
}) => React.ReactNode;
|
|
163
144
|
renderEmptyState?: () => React.ReactNode;
|
|
164
145
|
};
|
|
165
146
|
filterSidebar?: {
|
|
@@ -238,12 +219,6 @@ export interface CustomRendererProps {
|
|
|
238
219
|
onClearAll: () => void;
|
|
239
220
|
isLoading: boolean;
|
|
240
221
|
}) => React.ReactNode;
|
|
241
|
-
renderTextSearch?: (props: {
|
|
242
|
-
searchText: string;
|
|
243
|
-
setSearchText: (text: string) => void;
|
|
244
|
-
isLoading: boolean;
|
|
245
|
-
placeholder: string;
|
|
246
|
-
}) => React.ReactNode;
|
|
247
222
|
};
|
|
248
223
|
resultsGrid?: {
|
|
249
224
|
renderGrid?: (props: ResultsGridProps) => React.ReactNode;
|
|
@@ -334,7 +309,6 @@ export interface SimilarProductsSettings {
|
|
|
334
309
|
resultsPerPage?: number;
|
|
335
310
|
enableCropping?: boolean;
|
|
336
311
|
enableFileUpload?: boolean;
|
|
337
|
-
enableTextSearch?: boolean;
|
|
338
312
|
paginationType?: 'pagination' | 'load-more' | 'infinite-scroll';
|
|
339
313
|
loadMoreText?: string;
|
|
340
314
|
loadMoreStyle?: 'button' | 'auto';
|
|
@@ -355,22 +329,10 @@ export interface SimilarProductsSettings {
|
|
|
355
329
|
controlsContainer?: string;
|
|
356
330
|
controlsInner?: string;
|
|
357
331
|
controlsLeft?: string;
|
|
358
|
-
controlsCenter?: string;
|
|
359
332
|
controlsRight?: string;
|
|
360
333
|
itemCount?: string;
|
|
361
334
|
sortDropdown?: string;
|
|
362
335
|
filterToggleButton?: string;
|
|
363
|
-
modalSearchInput?: string;
|
|
364
|
-
modalSearchContainer?: string;
|
|
365
|
-
modalSearchButton?: string;
|
|
366
|
-
modalSearchIcon?: string;
|
|
367
|
-
modalSearchClearButton?: string;
|
|
368
|
-
modalSearchClearIcon?: string;
|
|
369
|
-
searchButtonIcon?: string;
|
|
370
|
-
modalCloseIcon?: string;
|
|
371
|
-
filterIcon?: string;
|
|
372
|
-
filterRemoveIcon?: string;
|
|
373
|
-
imageSearchButtonIcon?: string;
|
|
374
336
|
|
|
375
337
|
filterSidebarMobileHeader?: string;
|
|
376
338
|
filterSidebarMobileTitle?: string;
|
|
@@ -452,19 +414,6 @@ export interface SimilarProductsSettings {
|
|
|
452
414
|
mobileActiveFilterTag?: string;
|
|
453
415
|
mobileClearAllButton?: string;
|
|
454
416
|
filterSidebarMobileOverlay?: string;
|
|
455
|
-
|
|
456
|
-
textSearchContainer?: string;
|
|
457
|
-
textSearchLabel?: string;
|
|
458
|
-
textSearchInput?: string;
|
|
459
|
-
};
|
|
460
|
-
iconNames?: {
|
|
461
|
-
searchButton?: string;
|
|
462
|
-
modalClose?: string;
|
|
463
|
-
filter?: string;
|
|
464
|
-
filterRemove?: string;
|
|
465
|
-
modalSearch?: string;
|
|
466
|
-
modalSearchClear?: string;
|
|
467
|
-
imageSearchButton?: string;
|
|
468
417
|
};
|
|
469
418
|
customRenderers?: {
|
|
470
419
|
Modal?: React.ComponentType<SimilarProductsModalProps>;
|
package/src/utils/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export const defaultSettings: Required<SimilarProductsSettings> = {
|
|
|
7
7
|
resultsPerPage: 20,
|
|
8
8
|
enableCropping: true,
|
|
9
9
|
enableFileUpload: true,
|
|
10
|
-
enableTextSearch: false,
|
|
11
10
|
customStyles: {
|
|
12
11
|
modal: '',
|
|
13
12
|
filterSidebar: '',
|
|
@@ -16,31 +15,7 @@ export const defaultSettings: Required<SimilarProductsSettings> = {
|
|
|
16
15
|
productItem: '',
|
|
17
16
|
pagination: '',
|
|
18
17
|
filterGroup: '',
|
|
19
|
-
imageSection: ''
|
|
20
|
-
textSearchContainer: '',
|
|
21
|
-
textSearchLabel: '',
|
|
22
|
-
textSearchInput: '',
|
|
23
|
-
controlsCenter: '',
|
|
24
|
-
modalSearchInput: '',
|
|
25
|
-
modalSearchContainer: '',
|
|
26
|
-
modalSearchButton: '',
|
|
27
|
-
modalSearchIcon: '',
|
|
28
|
-
modalSearchClearButton: '',
|
|
29
|
-
modalSearchClearIcon: '',
|
|
30
|
-
searchButtonIcon: '',
|
|
31
|
-
modalCloseIcon: '',
|
|
32
|
-
filterIcon: '',
|
|
33
|
-
filterRemoveIcon: '',
|
|
34
|
-
imageSearchButtonIcon: ''
|
|
35
|
-
},
|
|
36
|
-
iconNames: {
|
|
37
|
-
searchButton: 'search',
|
|
38
|
-
modalClose: 'close',
|
|
39
|
-
filter: 'filter',
|
|
40
|
-
filterRemove: 'close',
|
|
41
|
-
modalSearch: 'search',
|
|
42
|
-
modalSearchClear: 'close',
|
|
43
|
-
imageSearchButton: 'search'
|
|
18
|
+
imageSection: ''
|
|
44
19
|
},
|
|
45
20
|
customRenderers: {
|
|
46
21
|
render: {}
|
|
@@ -68,10 +43,6 @@ export function mergeSettings(
|
|
|
68
43
|
...defaultSettings.customStyles,
|
|
69
44
|
...userSettings.customStyles
|
|
70
45
|
},
|
|
71
|
-
iconNames: {
|
|
72
|
-
...defaultSettings.iconNames,
|
|
73
|
-
...userSettings.iconNames
|
|
74
|
-
},
|
|
75
46
|
customRenderers: {
|
|
76
47
|
...defaultSettings.customRenderers,
|
|
77
48
|
...userSettings.customRenderers,
|
|
@@ -129,19 +100,13 @@ export function validateImageFile(
|
|
|
129
100
|
export function debounce<T extends (...args: any[]) => any>(
|
|
130
101
|
func: T,
|
|
131
102
|
wait: number
|
|
132
|
-
): (
|
|
103
|
+
): (...args: Parameters<T>) => void {
|
|
133
104
|
let timeout: NodeJS.Timeout;
|
|
134
105
|
|
|
135
|
-
|
|
106
|
+
return (...args: Parameters<T>) => {
|
|
136
107
|
clearTimeout(timeout);
|
|
137
108
|
timeout = setTimeout(() => func(...args), wait);
|
|
138
109
|
};
|
|
139
|
-
|
|
140
|
-
debounced.cancel = () => {
|
|
141
|
-
clearTimeout(timeout);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
return debounced as ((...args: Parameters<T>) => void) & { cancel: () => void };
|
|
145
110
|
}
|
|
146
111
|
|
|
147
112
|
export function dataURLToBlob(dataURL: string): Blob {
|