@nyris/nyris-webapp 0.3.89 → 0.3.91

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 (70) hide show
  1. package/build/_headers +2 -0
  2. package/build/asset-manifest.json +6 -6
  3. package/build/index.html +1 -1
  4. package/build/js/settings.example.js +17 -0
  5. package/build/static/css/main.734b52e1.css +4 -0
  6. package/build/static/css/main.734b52e1.css.map +1 -0
  7. package/build/static/js/main.f2255597.js +3 -0
  8. package/build/static/js/{main.ca8b95bc.js.map → main.f2255597.js.map} +1 -1
  9. package/package.json +3 -3
  10. package/public/_headers +2 -0
  11. package/public/index.html +1 -1
  12. package/public/js/settings.example.js +17 -0
  13. package/src/App.tsx +5 -3
  14. package/src/components/Cart.tsx +321 -0
  15. package/src/components/CustomCameraDrawer.tsx +4 -22
  16. package/src/components/DragDropFile.tsx +57 -38
  17. package/src/components/ExperienceVisualSearch/ExperienceVisualSearch.tsx +6 -1
  18. package/src/components/ExperienceVisualSearch/ExperienceVisualSearchTrigger.tsx +2 -2
  19. package/src/components/GroundingSpecs.tsx +47 -0
  20. package/src/components/Header.tsx +94 -93
  21. package/src/components/HitsPerPage.tsx +4 -2
  22. package/src/components/ImagePreview.tsx +64 -31
  23. package/src/components/ImageUpload.tsx +247 -0
  24. package/src/components/ItemSpecification.tsx +164 -0
  25. package/src/components/MatchNotificationBanner.tsx +165 -0
  26. package/src/components/PostFilter/PostFilter.tsx +22 -1
  27. package/src/components/PostFilter/PostFilterComponent.tsx +59 -26
  28. package/src/components/PostFilter/PostFilterFindApi.tsx +242 -0
  29. package/src/components/PoweredBy.tsx +16 -0
  30. package/src/components/PreFilter/PreFilter.tsx +77 -54
  31. package/src/components/Product/Product.tsx +186 -28
  32. package/src/components/Product/ProductAttribute.tsx +2 -2
  33. package/src/components/Product/ProductDetailView.tsx +123 -18
  34. package/src/components/Product/ProductDetailViewModal.tsx +3 -0
  35. package/src/components/Product/ProductList.tsx +78 -8
  36. package/src/components/SidePanel.tsx +212 -120
  37. package/src/components/TextSearch.tsx +82 -203
  38. package/src/components/Toaster.tsx +34 -15
  39. package/src/helpers/ToastHelper.ts +6 -2
  40. package/src/hooks/useCadSearch.ts +5 -0
  41. package/src/hooks/useImageSearch.ts +102 -13
  42. package/src/index.css +59 -0
  43. package/src/layouts/AppLayout.tsx +16 -14
  44. package/src/pages/Home.tsx +61 -13
  45. package/src/pages/Result.tsx +287 -295
  46. package/src/services/vizo.ts +161 -0
  47. package/src/stores/request/Misc/misc.initialstate.ts +1 -0
  48. package/src/stores/request/Misc/misc.slice.ts +1 -0
  49. package/src/stores/request/filter/filter.initialState.ts +3 -0
  50. package/src/stores/request/filter/filter.slice.ts +23 -0
  51. package/src/stores/result/prodcuts/products.initialState.ts +4 -0
  52. package/src/stores/result/prodcuts/products.slice.ts +15 -0
  53. package/src/stores/types.ts +27 -1
  54. package/src/stores/ui/loading/loading.initialState.ts +1 -0
  55. package/src/stores/ui/loading/loading.slice.ts +4 -0
  56. package/src/stores/ui/sidePanel/sidePanel.initialState.ts +5 -0
  57. package/src/stores/ui/sidePanel/sidePanel.slice.ts +11 -0
  58. package/src/stores/ui/uiStore.ts +4 -1
  59. package/src/styles/Cart.scss +210 -0
  60. package/src/styles/common.scss +10 -0
  61. package/src/translations.ts +4 -4
  62. package/src/types.ts +11 -3
  63. package/src/utils/prepareImageList.ts +6 -5
  64. package/src/utils/textSearchFilter.ts +203 -0
  65. package/tailwind.config.js +1 -0
  66. package/build/static/css/main.ba1c7479.css +0 -4
  67. package/build/static/css/main.ba1c7479.css.map +0 -1
  68. package/build/static/js/main.ca8b95bc.js +0 -3
  69. package/src/components/Footer.tsx +0 -21
  70. /package/build/static/js/{main.ca8b95bc.js.LICENSE.txt → main.f2255597.js.LICENSE.txt} +0 -0
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@nyris/nyris-webapp",
3
- "version": "0.3.89",
3
+ "version": "0.3.91",
4
4
  "dependencies": {
5
5
  "@auth0/auth0-react": "^2.2.4",
6
6
  "@emailjs/browser": "^4.3.3",
7
- "@nyris/nyris-api": "^0.3.89",
8
- "@nyris/nyris-react-components": "^0.3.89",
7
+ "@nyris/nyris-api": "^0.3.91",
8
+ "@nyris/nyris-react-components": "^0.3.91",
9
9
  "@radix-ui/react-accordion": "^1.2.2",
10
10
  "@radix-ui/react-dialog": "^1.1.4",
11
11
  "@radix-ui/react-popover": "^1.1.4",
@@ -0,0 +1,2 @@
1
+ /*
2
+ X-Robots-Tag: noindex, nofollow
package/public/index.html CHANGED
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
+ <meta name="robots" content="noindex, nofollow">
4
5
  <meta charset="utf-8" />
5
6
  <meta
6
7
  name="viewport"
@@ -22,7 +23,6 @@
22
23
  document.documentElement.style.setProperty('--secondary-color', window.settings.theme.secondaryColor);
23
24
  </script>
24
25
  <script>
25
- window.settings.algolia.enabled = true;
26
26
  let vh = window.innerHeight * 0.01;
27
27
  document.documentElement.style.setProperty("--vh", `${vh}px`);
28
28
 
@@ -6,6 +6,7 @@ var settings = {
6
6
  supportEmail: '',
7
7
  },
8
8
  algolia: {
9
+ enabled: false,
9
10
  apiKey: '',
10
11
  appId: '',
11
12
  indexName: '',
@@ -23,6 +24,7 @@ var settings = {
23
24
  ],
24
25
  // Nyris - visual search
25
26
  apiKey: '',
27
+ aiApiKey: '',
26
28
  baseUrl: 'https://api.nyris.io',
27
29
  jpegQuality: 0.9,
28
30
  maxHeight: 1024,
@@ -31,6 +33,20 @@ var settings = {
31
33
  responseFormat: 'application/offers.complete+json',
32
34
  visualSearchFilterKey: '',
33
35
  shouldUseUserMetadata: '',
36
+ requestContentType: 'multipart/form-data', // use 'image/jpeg' for elastic search
37
+ textSearchScoring: {
38
+ sku: { exactMatch: 50, startsWith: 30 },
39
+ customIds: { exactMatch: 40, startsWith: 6, partial: 2 },
40
+ title: { exactMatch: 25, partial: 10 },
41
+ brand: { exactMatch: 15, startsWith: 6, partial: 2 },
42
+ links: { searchable: false },
43
+ 'customIds.gtin': { searchable: false }, // for nested fields use dot notation
44
+ otherFields: { exactMatch: 8, startsWith: 6, partial: 2 },
45
+ },
46
+ vizo: {
47
+ groundingEnabled: false,
48
+ fallbackToElasticSearch: false,
49
+ },
34
50
  // UI - theme
35
51
  theme: {
36
52
  appBarLogoUrl: '',
@@ -79,6 +95,7 @@ var settings = {
79
95
  },
80
96
  ],
81
97
  // features
98
+ cart: false,
82
99
  showPoweredByNyris: '',
83
100
  postFilterOption: '',
84
101
  preFilterOption: '',
package/src/App.tsx CHANGED
@@ -7,8 +7,8 @@ import { InstantSearch } from 'react-instantsearch';
7
7
 
8
8
  function App() {
9
9
  const algoliaClient = algoliasearch(
10
- window.settings.algolia.appId,
11
- window.settings.algolia.apiKey,
10
+ window.settings.algolia.appId || '0',
11
+ window.settings.algolia.apiKey || '0',
12
12
  );
13
13
 
14
14
  return (
@@ -20,7 +20,9 @@ function App() {
20
20
  ...algoliaClient,
21
21
  search(requests: any) {
22
22
  if (
23
- requests?.every(({ params }: any) => !params.query && !params.filters)
23
+ requests?.every(
24
+ ({ params }: any) => !params.query && !params.filters,
25
+ )
24
26
  ) {
25
27
  return Promise.resolve({
26
28
  results: requests.map(() => ({
@@ -0,0 +1,321 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import Tooltip from './Tooltip/TooltipComponent';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import toast from 'react-hot-toast';
6
+ import { Icon } from '@nyris/nyris-react-components';
7
+
8
+ const Cart = () => {
9
+ const [isCartOpen, setIsCartOpen] = useState(false);
10
+ const [cartParts, setCartParts] = useState<any[]>([]);
11
+ const [amountOfParts, setAmountOfParts] = useState(0);
12
+ const [quantityEdits, setQuantityEdits] = useState<Record<string, string>>(
13
+ {},
14
+ );
15
+
16
+ const updateCount = () => {
17
+ const cart = sessionStorage.getItem('cart');
18
+ if (cart) {
19
+ const parsedCart = JSON.parse(cart);
20
+ setCartParts(parsedCart);
21
+ const amount = parsedCart.reduce(
22
+ (total: number, part: any) => total + (part.quantity || 1),
23
+ 0,
24
+ );
25
+ setAmountOfParts(amount);
26
+ } else {
27
+ setCartParts([]);
28
+ setAmountOfParts(0);
29
+ }
30
+ };
31
+
32
+ useEffect(() => {
33
+ updateCount();
34
+
35
+ window.addEventListener('cart-updated', updateCount);
36
+
37
+ return () => {
38
+ window.removeEventListener('cart-updated', updateCount);
39
+ };
40
+ }, []);
41
+
42
+ const onToggleCart = (isOpen: boolean) => {
43
+ setIsCartOpen(isOpen);
44
+ if (isOpen) {
45
+ document.body.classList.add('overflow-hidden');
46
+ } else {
47
+ document.body.classList.remove('overflow-hidden');
48
+ }
49
+ };
50
+
51
+ const clearSessionProducts = () => {
52
+ sessionStorage.removeItem('cart');
53
+ window.dispatchEvent(new Event('cart-updated'));
54
+ };
55
+
56
+ const removePartBySku = (skuToRemove: string): void => {
57
+ const updatedCart = cartParts.filter((p: any) => p.sku !== skuToRemove);
58
+ if (!updatedCart.length) {
59
+ setIsCartOpen(false);
60
+ }
61
+ sessionStorage.setItem('cart', JSON.stringify(updatedCart));
62
+ window.dispatchEvent(new Event('cart-updated'));
63
+ };
64
+
65
+ const updateQuantity = (sku: string, delta: number) => {
66
+ const updated = cartParts
67
+ .map((part: any) => {
68
+ if (part.sku !== sku) return part;
69
+ const newQuantity = (part.quantity || 1) + delta;
70
+ return newQuantity > 0 ? { ...part, quantity: newQuantity } : null;
71
+ })
72
+ .filter(Boolean);
73
+ setQuantityEdits(prev => {
74
+ if (!Object.prototype.hasOwnProperty.call(prev, sku)) return prev;
75
+ const next = { ...prev };
76
+ delete next[sku];
77
+ return next;
78
+ });
79
+ setCartParts(updated);
80
+ if (!updated.length) {
81
+ setIsCartOpen(false);
82
+ }
83
+ sessionStorage.setItem('cart', JSON.stringify(updated));
84
+ window.dispatchEvent(new Event('cart-updated'));
85
+ };
86
+
87
+ const getQuantityDisplayValue = (sku: string, quantity: number) =>
88
+ quantityEdits[sku] ?? String(quantity || 1);
89
+
90
+ const generateCSVContent = (): string => {
91
+ const rows = [['Product Sku', 'Product Name', 'Quantity']];
92
+ cartParts.forEach((part: any) => {
93
+ rows.push([part.sku, part.title, (part.quantity || 1).toString()]);
94
+ });
95
+ return rows.map(row => row.map(cell => `"${cell}"`).join(',')).join('\n');
96
+ };
97
+
98
+ const downloadCSV = () => {
99
+ const csvContent = generateCSVContent();
100
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
101
+ const url = URL.createObjectURL(blob);
102
+
103
+ const link = document.createElement('a');
104
+ link.href = url;
105
+ link.setAttribute('download', 'products.csv');
106
+ document.body.appendChild(link);
107
+ link.click();
108
+ document.body.removeChild(link);
109
+ // clearSessionProducts();
110
+
111
+ toast.success('Your data has been downloaded.');
112
+ };
113
+
114
+ return (
115
+ <>
116
+ <Tooltip
117
+ content="The basket is currently empty"
118
+ disabled={!!amountOfParts}
119
+ >
120
+ <button
121
+ className={twMerge(
122
+ 'relative flex items-center justify-center rounded-2xl border border-solid border-[#DDDEE7]',
123
+ 'h-8 w-8',
124
+ )}
125
+ style={{
126
+ backgroundColor:
127
+ amountOfParts > 0
128
+ ? window.settings.theme.primaryColor
129
+ : '#FAFAFA',
130
+ }}
131
+ onClick={() => onToggleCart(true)}
132
+ >
133
+ {amountOfParts ? (
134
+ <div
135
+ className={twMerge(
136
+ 'absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full border-2 border-white border-solid text-white',
137
+ 'text-[9px]',
138
+ )}
139
+ style={{
140
+ backgroundColor: window.settings.theme.primaryColor,
141
+ }}
142
+ >
143
+ {amountOfParts}
144
+ </div>
145
+ ) : (
146
+ ''
147
+ )}
148
+ <Icon
149
+ name="cart"
150
+ className={twMerge(
151
+ amountOfParts > 0 ? 'fill-white text-white' : 'text-black',
152
+ )}
153
+ />
154
+ </button>
155
+ </Tooltip>
156
+ {isCartOpen &&
157
+ createPortal(
158
+ <div className={twMerge('fixed inset-0 z-[51]')}>
159
+ <div
160
+ className="absolute inset-0 bg-black/20"
161
+ onClick={() => onToggleCart(false)}
162
+ />
163
+ <div
164
+ className={twMerge(
165
+ 'absolute right-0 flex h-full w-[410px] max-w-full flex-col bg-transparent',
166
+ )}
167
+ >
168
+ <div className="flex h-full max-w-full flex-col bg-white">
169
+ <div className="flex h-[52px] items-center justify-between px-4 py-2 border-b border-solid border-[#DDDEE7]">
170
+ <div className="text-xl font-semibold">
171
+ Your cart ({amountOfParts} items)
172
+ </div>
173
+ <div className="flex items-center">
174
+ {amountOfParts > 0 ? (
175
+ <button
176
+ type="button"
177
+ className="mr-4 flex items-center gap-1 rounded border border-[#E31B5D] px-2 py-1 text-[9px] font-normal text-[#E31B5D]"
178
+ onClick={() => {
179
+ clearSessionProducts();
180
+ setIsCartOpen(false);
181
+ }}
182
+ >
183
+ <Icon name="trash" />
184
+ Clear All
185
+ </button>
186
+ ) : (
187
+ ''
188
+ )}
189
+ <button className="p-0" onClick={() => onToggleCart(false)}>
190
+ <Icon name="close" className="h-5 w-5 fill-[#55566B]" />
191
+ </button>
192
+ </div>
193
+ </div>
194
+ <div className="overflow-x-auto p-4 flex flex-col gap-2.5">
195
+ {amountOfParts === 0 ? (
196
+ <div className="flex h-full w-full flex-col items-center justify-center">
197
+ <div className="text-base text-[#CACAD1]">
198
+ No items have been added
199
+ </div>
200
+ </div>
201
+ ) : (
202
+ ''
203
+ )}
204
+ {cartParts.map((part: any, i: number) => (
205
+ <div
206
+ key={part.sku + i}
207
+ className={twMerge(
208
+ 'flex h-fit w-full items-center justify-between rounded-lg border border-solid border-[#DDDEE7] bg-[#F3F4F8]',
209
+ 'p-2',
210
+ 'gap-2',
211
+ )}
212
+ >
213
+ <div className="flex flex-1 items-center">
214
+ <img
215
+ src={
216
+ !window.settings.algolia.enabled
217
+ ? part['image']
218
+ : part['image(main_similarity)']
219
+ ? part['image(main_similarity)']
220
+ : part['main_image_link']
221
+ }
222
+ key={part.sku + i}
223
+ alt={`product ${i}`}
224
+ className="mr-2 h-[50px] w-[50px] bg-white object-contain"
225
+ />
226
+ <div>
227
+ <div className="max-w-[175px] break-words text-[9px] font-normal">
228
+ {part.sku}
229
+ </div>
230
+ <div className="max-w-[175px] break-words text-xs font-semibold">
231
+ {part.title}
232
+ </div>
233
+ </div>
234
+ </div>
235
+ <div className="flex items-center">
236
+ <div className="ml-auto flex items-center gap-4 pr-4">
237
+ <button
238
+ className="h-4 w-4 rounded-full bg-[#FAFAFA]"
239
+ onClick={() => updateQuantity(part.sku, -1)}
240
+ >
241
+ <Icon name="minus" width="16" height="16" />
242
+ </button>
243
+ <input
244
+ className="flex h-[22px] w-[22px] items-center justify-center rounded border border-solid border-[#DDDEE7] bg-white text-center"
245
+ value={getQuantityDisplayValue(
246
+ part.sku,
247
+ part.quantity,
248
+ )}
249
+ onChange={e => {
250
+ const rawValue = e.target.value;
251
+ if (rawValue === '') {
252
+ setQuantityEdits(prev => ({
253
+ ...prev,
254
+ [part.sku]: '',
255
+ }));
256
+ return;
257
+ }
258
+
259
+ if (!/^[0-9]+$/.test(rawValue)) return;
260
+
261
+ const newValue = Number(rawValue);
262
+ if (newValue < 1) return;
263
+
264
+ setQuantityEdits(prev => ({
265
+ ...prev,
266
+ [part.sku]: rawValue,
267
+ }));
268
+ updateQuantity(
269
+ part.sku,
270
+ newValue - (part.quantity || 0),
271
+ );
272
+ }}
273
+ onBlur={() => {
274
+ if (quantityEdits[part.sku] === '') {
275
+ setQuantityEdits(prev => {
276
+ const updated = { ...prev };
277
+ delete updated[part.sku];
278
+ return updated;
279
+ });
280
+ }
281
+ }}
282
+ />
283
+ <button
284
+ className="h-4 w-4 rounded-full bg-[#FAFAFA] flex items-center justify-center"
285
+ onClick={() => updateQuantity(part.sku, 1)}
286
+ >
287
+ <Icon name="plus" width="10" height="10" />
288
+ </button>
289
+ </div>
290
+ <button
291
+ className="h-7 w-7 rounded bg-[#FFE5EF4D] p-1.5"
292
+ onClick={() => removePartBySku(part.sku)}
293
+ >
294
+ <Icon name="trash" color="#E31B5D" />
295
+ </button>
296
+ </div>
297
+ </div>
298
+ ))}
299
+ {amountOfParts > 0 ? (
300
+ <button
301
+ className="flex h-12 w-full items-center justify-center rounded-lg bg-[#3E36DC] text-base font-semibold text-white"
302
+ type="button"
303
+ onClick={downloadCSV}
304
+ >
305
+ <Icon name="download" />
306
+ <span className="ml-2">Download all data</span>
307
+ </button>
308
+ ) : (
309
+ ''
310
+ )}
311
+ </div>
312
+ </div>
313
+ </div>
314
+ </div>,
315
+ document.body,
316
+ )}
317
+ </>
318
+ );
319
+ };
320
+
321
+ export default Cart;
@@ -19,7 +19,6 @@ import {
19
19
  import { useCadSearch } from 'hooks/useCadSearch';
20
20
  import { isCadFile } from '@nyris/nyris-api';
21
21
  import { clone } from 'lodash';
22
- import { getFilters } from '../services/filter';
23
22
  import { useTranslation } from 'react-i18next';
24
23
 
25
24
  interface Props {
@@ -40,6 +39,7 @@ function CustomCamera(props: Props) {
40
39
  const { cadSearch } = useCadSearch();
41
40
  const { t } = useTranslation();
42
41
 
42
+ const preFilterList = useRequestStore(state => state.preFilterList);
43
43
  const requestImages = useRequestStore(state => state.requestImages);
44
44
  const specifications = useRequestStore(state => state.specifications);
45
45
  const setSpecifications = useRequestStore(state => state.setSpecifications);
@@ -53,27 +53,12 @@ function CustomCamera(props: Props) {
53
53
  const [capturedImages, setCapturedImages] = useState<HTMLCanvasElement[]>([]);
54
54
  const [currentIndex, setCurrentIndex] = useState(0);
55
55
  const [imageCaptureHelpModal, setImageCaptureHelpModal] = useState(false);
56
- const [resultFilter, setResultFilter] = useState<any>([]);
57
56
 
58
57
  const videoConstraints = {
59
58
  width: 1080,
60
59
  aspectRatio: 1.11111,
61
60
  };
62
61
 
63
- const getPreFilters = async () => {
64
- getFilters(1000, settings)
65
- .then(res => {
66
- setResultFilter(res);
67
- })
68
- .catch((e: any) => {
69
- console.log('err getDataFilterDesktop', e);
70
- });
71
- }
72
-
73
- useEffect(() => {
74
- getPreFilters()
75
- }, []);
76
-
77
62
  const handlerFindImage = async (image: any) => {
78
63
  if (location.pathname !== '/result') {
79
64
  navigate('/result');
@@ -94,7 +79,7 @@ function CustomCamera(props: Props) {
94
79
  showFeedback: true,
95
80
  }).then((singleImageResp) => {
96
81
  const specificationPrefilter = singleImageResp.image_analysis?.specification?.prefilter_value || null;
97
- const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
82
+ const hasPrefilter = preFilterList.filter((filter: any) => filter.values.includes(specificationPrefilter));
98
83
  if (specificationPrefilter) {
99
84
  setRequestImages([]);
100
85
  setShowNotMatchedError(false);
@@ -113,7 +98,7 @@ function CustomCamera(props: Props) {
113
98
  }, 5000);
114
99
  }
115
100
  if (!hasPrefilter.length && window.settings.preFilterOption) {
116
- setSpecifications(clone({...singleImageResp.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
101
+ setSpecifications(clone({...singleImageResp.image_analysis.specification, specificationPrefilter}));
117
102
  setPreFilter({});
118
103
  setAlgoliaFilter('');
119
104
  setShowLoading(false);
@@ -127,16 +112,13 @@ function CustomCamera(props: Props) {
127
112
  }, 6000);
128
113
  }
129
114
  } else {
130
- if (specifications?.is_nameplate) {
131
- setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
132
- } else {
115
+ if (!specifications?.is_nameplate) {
133
116
  setSpecifications({...specifications, is_nameplate: false});
134
117
  }
135
118
  setShowLoading(false);
136
119
  handleClose();
137
120
  }
138
121
  });
139
-
140
122
  };
141
123
 
142
124
  const handleClose = () => {
@@ -1,4 +1,4 @@
1
- import { memo, useEffect, useState } from 'react';
1
+ import { memo } from 'react';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
@@ -11,7 +11,6 @@ import { isCadFile } from '@nyris/nyris-api';
11
11
  import Hint from './Hint';
12
12
  import { clone } from 'lodash';
13
13
  import useRequestStore from '../stores/request/requestStore';
14
- import { getFilters } from '../services/filter';
15
14
 
16
15
  interface Props {
17
16
  onChangeLoading?: any;
@@ -26,34 +25,22 @@ function DragDropFile(props: Props) {
26
25
  const { singleImageSearch } = useImageSearch();
27
26
  const { cadSearch } = useCadSearch();
28
27
 
29
- const [resultFilter, setResultFilter] = useState<any>([]);
30
-
28
+ const preFilterList = useRequestStore(state => state.preFilterList);
31
29
  const specifications = useRequestStore(state => state.specifications);
32
30
  const setRequestImages = useRequestStore(state => state.setRequestImages);
33
31
  const setSpecifications = useRequestStore(state => state.setSpecifications);
34
- const setNameplateNotificationText = useRequestStore(state => state.setNameplateNotificationText);
35
- const setShowNotMatchedError = useRequestStore(state => state.setShowNotMatchedError);
32
+ const setNameplateNotificationText = useRequestStore(
33
+ state => state.setNameplateNotificationText,
34
+ );
35
+ const setShowNotMatchedError = useRequestStore(
36
+ state => state.setShowNotMatchedError,
37
+ );
36
38
  const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
37
39
  const setPreFilter = useRequestStore(state => state.setPreFilter);
38
40
  const setShowLoading = useRequestStore(state => state.setShowLoading);
39
41
  const setNameplateImage = useRequestStore(state => state.setNameplateImage);
40
42
 
41
- const getPreFilters = async () => {
42
- getFilters(1000, window.settings)
43
- .then(res => {
44
- setResultFilter(res);
45
- })
46
- .catch((e: any) => {
47
- console.log('err getDataFilterDesktop', e);
48
- });
49
- }
50
-
51
- useEffect(() => {
52
- getPreFilters()
53
- }, []);
54
-
55
43
  const handleUpload = (file: File) => {
56
-
57
44
  if (isCadFile(file)) {
58
45
  cadSearch({
59
46
  file: file,
@@ -70,47 +57,73 @@ function DragDropFile(props: Props) {
70
57
  image: file,
71
58
  settings: window.settings,
72
59
  showFeedback: true,
73
- }).then((singleImageResp) => {
74
- const specificationPrefilter = singleImageResp.image_analysis?.specification?.prefilter_value || null;
75
- const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
60
+ clearPostFilter: true,
61
+ newSearch: true,
62
+ }).then(singleImageResp => {
63
+ const specificationPrefilter =
64
+ singleImageResp.image_analysis?.specification?.prefilter_value || null;
65
+ const hasPrefilter = preFilterList.filter((filter: any) =>
66
+ filter.values.includes(specificationPrefilter),
67
+ );
76
68
  if (specificationPrefilter) {
77
69
  setRequestImages([]);
78
70
  setShowNotMatchedError(false);
79
71
  if (hasPrefilter.length) {
80
- setSpecifications(clone(singleImageResp.image_analysis.specification));
72
+ setSpecifications(
73
+ clone(singleImageResp.image_analysis.specification),
74
+ );
81
75
  setNameplateImage(file);
82
- setPreFilter({[singleImageResp.image_analysis?.specification?.prefilter_value]: true});
83
- setAlgoliaFilter(`${window.settings.alogoliaFilterField}:'${singleImageResp.image_analysis?.specification?.prefilter_value}'`);
76
+ setPreFilter({
77
+ [singleImageResp.image_analysis?.specification?.prefilter_value]:
78
+ true,
79
+ });
80
+ setAlgoliaFilter(
81
+ `${window.settings.alogoliaFilterField}:'${singleImageResp.image_analysis?.specification?.prefilter_value}'`,
82
+ );
84
83
 
85
84
  setShowLoading(false);
86
85
  navigate('/result');
87
86
 
88
87
  setTimeout(() => {
89
- setNameplateNotificationText(t('We have successfully defined the search criteria', { prefilter_value: specificationPrefilter, preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
88
+ setNameplateNotificationText(
89
+ t('We have successfully defined the search criteria', {
90
+ prefilter_value: specificationPrefilter,
91
+ preFilterTitle:
92
+ window.settings.preFilterTitle?.toLocaleLowerCase(),
93
+ }),
94
+ );
90
95
  }, 1000);
91
96
  setTimeout(() => {
92
97
  setNameplateNotificationText('');
93
98
  }, 6000);
94
99
  }
95
100
  if (!hasPrefilter.length && window.settings.preFilterOption) {
96
- setSpecifications(clone({...singleImageResp.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
101
+ setSpecifications(
102
+ clone({
103
+ ...singleImageResp.image_analysis.specification,
104
+ specificationPrefilter,
105
+ }),
106
+ );
97
107
  navigate('/result');
98
108
  setPreFilter({});
99
109
  setAlgoliaFilter('');
100
110
  setShowLoading(false);
101
111
  setShowNotMatchedError(true);
102
112
  setTimeout(() => {
103
- setNameplateNotificationText(t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
113
+ setNameplateNotificationText(
114
+ t('Extracted details from the nameplate could not be matched', {
115
+ preFilterTitle:
116
+ window.settings.preFilterTitle?.toLocaleLowerCase(),
117
+ }),
118
+ );
104
119
  }, 1000);
105
120
  setTimeout(() => {
106
121
  setNameplateNotificationText('');
107
122
  }, 6000);
108
123
  }
109
124
  } else {
110
- if (specifications?.is_nameplate) {
111
- setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
112
- } else {
113
- setSpecifications({...specifications, is_nameplate: false});
125
+ if (!specifications?.is_nameplate) {
126
+ setSpecifications({ ...specifications, is_nameplate: false });
114
127
  }
115
128
  setShowLoading(false);
116
129
  navigate('/result');
@@ -131,9 +144,11 @@ function DragDropFile(props: Props) {
131
144
  }
132
145
  >
133
146
  {isLoading && <Loading />}
134
-
147
+
135
148
  <div
136
- className={'relative flex flex-col items-center justify-center w-full'}
149
+ className={
150
+ 'relative flex flex-col items-center justify-center w-full'
151
+ }
137
152
  {...dragProps}
138
153
  >
139
154
  <div
@@ -146,7 +161,9 @@ function DragDropFile(props: Props) {
146
161
  ])}
147
162
  >
148
163
  <div className="" style={{ fontSize: 14 }}>
149
- <span className="font-bold text-sm pr-1">{t('Drag and drop')}</span>
164
+ <span className="font-bold text-sm pr-1">
165
+ {t('Drag and drop')}
166
+ </span>
150
167
  {t('an image here')}
151
168
  </div>
152
169
  <Hint />
@@ -164,7 +181,9 @@ function DragDropFile(props: Props) {
164
181
  id="select_file"
165
182
  className="absolute z-[-1] opacity-0"
166
183
  placeholder="Choose photo"
167
- accept={'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,.pdf,image/*'}
184
+ accept={
185
+ '.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,.pdf,image/*'
186
+ }
168
187
  />
169
188
  </div>
170
189
  </div>