@nyris/nyris-webapp 0.3.91 → 0.3.93
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/build/asset-manifest.json +6 -6
- package/build/data/related-parts.json +83 -0
- package/build/index.html +1 -1
- package/build/js/settings.example.js +3 -0
- package/build/static/css/main.fed38059.css +4 -0
- package/build/static/css/main.fed38059.css.map +1 -0
- package/build/static/js/main.c9bbbcb9.js +3 -0
- package/build/static/js/{main.f2255597.js.map → main.c9bbbcb9.js.map} +1 -1
- package/package.json +4 -3
- package/public/data/related-parts.json +83 -0
- package/public/js/settings.example.js +3 -0
- package/src/App.test.tsx +0 -1
- package/src/App.tsx +0 -1
- package/src/assets/arrow_down_expanded.svg +3 -0
- package/src/assets/arrow_enter.svg +3 -0
- package/src/assets/camera.svg +3 -0
- package/src/assets/close.svg +3 -0
- package/src/assets/enter.svg +3 -0
- package/src/assets/refresh.svg +3 -0
- package/src/assets/vizo_avatar.svg +16 -0
- package/src/components/Cadenas/CadenasWebViewer.tsx +1 -1
- package/src/components/Cart.tsx +48 -36
- package/src/components/ChatAssistant/ChatAssistant.tsx +289 -0
- package/src/components/ChatAssistant/MobileChatAssistant.tsx +291 -0
- package/src/components/ChatAssistant/OptionChip.tsx +78 -0
- package/src/components/ChatAssistant/index.ts +3 -0
- package/src/components/ChatAssistant/useChatAssistantLogic.ts +745 -0
- package/src/components/CurrentRefinements.tsx +2 -2
- package/src/components/CustomCameraDrawer.tsx +56 -13
- package/src/components/DragDropFile.tsx +5 -5
- package/src/components/ExperienceVisualSearch/ExperienceVisualSearch.tsx +1 -1
- package/src/components/Header.tsx +116 -96
- package/src/components/Hint.tsx +1 -2
- package/src/components/HitsPerPage.tsx +9 -3
- package/src/components/IdentifiedAttributes.tsx +159 -0
- package/src/components/ImagePreview.tsx +32 -17
- package/src/components/ImageUpload.tsx +16 -8
- package/src/components/Inquiry/InquiryBanner.tsx +1 -1
- package/src/components/Inquiry/InquiryModal.tsx +35 -29
- package/src/components/ItemSpecification.tsx +58 -126
- package/src/components/LocationInfoPopup.tsx +33 -33
- package/src/components/MatchNotificationBanner.tsx +90 -36
- package/src/components/PostFilter/PostFilter.tsx +1 -1
- package/src/components/PostFilter/PostFilterComponent.tsx +0 -1
- package/src/components/PostFilter/PostFilterFindApi.tsx +0 -1
- package/src/components/PoweredBy.tsx +1 -1
- package/src/components/PreFilter/PreFilter.tsx +14 -3
- package/src/components/PreFilter/PreFilterModal.tsx +0 -1
- package/src/components/Product/Product.tsx +15 -11
- package/src/components/Product/ProductAttribute.tsx +4 -5
- package/src/components/Product/ProductDetailViewModal.tsx +2 -4
- package/src/components/Product/ProductList.tsx +26 -13
- package/src/components/Rfq/RfqModal.tsx +1 -1
- package/src/components/SidePanel.tsx +128 -46
- package/src/components/SmartFilter.tsx +320 -0
- package/src/components/TextSearch.tsx +134 -70
- package/src/components/UploadDisclaimer.tsx +1 -1
- package/src/hooks/useBadResultsRecovery.ts +407 -0
- package/src/hooks/useEffectiveGroundingResults.ts +54 -0
- package/src/hooks/useGoodResultsChat.ts +651 -0
- package/src/hooks/useGroundedSearch.ts +88 -0
- package/src/hooks/useImageSearch.ts +139 -187
- package/src/hooks/useResultEvaluator.ts +417 -0
- package/src/index.css +1 -1
- package/src/index.tsx +0 -1
- package/src/layouts/AppLayout.tsx +53 -2
- package/src/pages/Home.tsx +11 -52
- package/src/pages/Login.tsx +1 -2
- package/src/pages/Logout.tsx +1 -1
- package/src/pages/Result.tsx +254 -200
- package/src/providers/AuthProvider.tsx +0 -1
- package/src/services/Feedback.ts +1 -1
- package/src/services/visualSearch.ts +0 -21
- package/src/services/vizo.ts +192 -4
- package/src/stores/chat/chatStore.ts +150 -0
- package/src/stores/chat/conversationStore.ts +300 -0
- package/src/stores/request/Misc/misc.slice.ts +2 -2
- package/src/stores/request/filter/filter.slice.ts +8 -8
- package/src/stores/request/query/query.slice.ts +2 -2
- package/src/stores/request/requestImage/requestImage.slice.ts +6 -6
- package/src/stores/request/specifications/specifications.slice.ts +10 -7
- package/src/stores/result/detectedRegions/detectedRegions.slice.ts +1 -1
- package/src/stores/result/prodcuts/products.initialState.ts +12 -0
- package/src/stores/result/prodcuts/products.slice.ts +28 -8
- package/src/stores/result/session/session.slice.ts +2 -2
- package/src/stores/smartFilters/smartFiltersStore.ts +270 -0
- package/src/stores/types.ts +41 -0
- package/src/stores/ui/ai/ai.initialState.ts +5 -0
- package/src/stores/ui/ai/ai.slice.ts +15 -0
- package/src/stores/ui/banner/banner.initialState.ts +6 -0
- package/src/stores/ui/banner/banner.slice.ts +14 -0
- package/src/stores/ui/feedback/feedback.slice.ts +1 -1
- package/src/stores/ui/loading/loading.slice.ts +4 -4
- package/src/stores/ui/uiStore.ts +7 -1
- package/src/styles/product.scss +0 -2
- package/src/types.ts +4 -8
- package/src/utils/cropImageToBase64.ts +32 -0
- package/src/utils/fetchProductImage.ts +109 -0
- package/src/utils/imageConverters.ts +124 -0
- package/src/utils/relatedParts.ts +35 -0
- package/src/utils/specificationFilter.ts +1 -5
- package/tailwind.config.js +3 -2
- package/build/static/css/main.734b52e1.css +0 -4
- package/build/static/css/main.734b52e1.css.map +0 -1
- package/build/static/js/main.f2255597.js +0 -3
- package/src/utils/addAssets.ts +0 -40
- /package/build/static/js/{main.f2255597.js.LICENSE.txt → main.c9bbbcb9.js.LICENSE.txt} +0 -0
|
@@ -108,7 +108,7 @@ function ImagePreviewComponent({
|
|
|
108
108
|
compress: false,
|
|
109
109
|
}).then((res: any) => {
|
|
110
110
|
const specificationPrefilter =
|
|
111
|
-
res
|
|
111
|
+
res?.image_analysis?.specification?.prefilter_value || null;
|
|
112
112
|
const hasPrefilter = preFilterList.filter((filter: any) =>
|
|
113
113
|
filter.values.includes(specificationPrefilter),
|
|
114
114
|
);
|
|
@@ -188,7 +188,7 @@ function ImagePreviewComponent({
|
|
|
188
188
|
|
|
189
189
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
190
|
const debouncedOnImageSelectionChange = useCallback(
|
|
191
|
-
debounce((r: RectCoords,
|
|
191
|
+
debounce((r: RectCoords, _index?: number) => {
|
|
192
192
|
findItemsInSelection(r, requestImages[0]);
|
|
193
193
|
}, 0),
|
|
194
194
|
[findItemsInSelection, requestImages, updateRegion],
|
|
@@ -200,7 +200,7 @@ function ImagePreviewComponent({
|
|
|
200
200
|
<div
|
|
201
201
|
ref={previewWrapperRef}
|
|
202
202
|
className={twMerge([
|
|
203
|
-
'bg-
|
|
203
|
+
'bg-[#545987]',
|
|
204
204
|
'justify-center',
|
|
205
205
|
isVisible ? (!isMultiImageSearchEnabled ? 'py-5' : 'pt-6') : '',
|
|
206
206
|
'px-7',
|
|
@@ -211,6 +211,7 @@ function ImagePreviewComponent({
|
|
|
211
211
|
'hidden',
|
|
212
212
|
'desktop:flex',
|
|
213
213
|
// 'rounded',
|
|
214
|
+
'rounded-[24px]',
|
|
214
215
|
])}
|
|
215
216
|
// style={{
|
|
216
217
|
// height: '100%',
|
|
@@ -228,9 +229,9 @@ function ImagePreviewComponent({
|
|
|
228
229
|
>
|
|
229
230
|
<div
|
|
230
231
|
className={twMerge([
|
|
231
|
-
// 'w-[243px]',
|
|
232
232
|
'w-full',
|
|
233
|
-
'bg-[#
|
|
233
|
+
'bg-[#545987] aspect-square flex just items-center',
|
|
234
|
+
'rounded-[24px]',
|
|
234
235
|
])}
|
|
235
236
|
>
|
|
236
237
|
<Preview
|
|
@@ -295,7 +296,7 @@ function ImagePreviewComponent({
|
|
|
295
296
|
{/* Image preview Mobile*/}
|
|
296
297
|
<div
|
|
297
298
|
className={twMerge([
|
|
298
|
-
'bg-
|
|
299
|
+
'bg-[#545987]',
|
|
299
300
|
'justify-center',
|
|
300
301
|
'p-5',
|
|
301
302
|
!editActive ? 'py-2' : '',
|
|
@@ -303,11 +304,13 @@ function ImagePreviewComponent({
|
|
|
303
304
|
'relative',
|
|
304
305
|
'flex',
|
|
305
306
|
'desktop:hidden',
|
|
307
|
+
!editActive && 'rounded-[32px]',
|
|
308
|
+
editActive && 'rounded-[24px]',
|
|
306
309
|
])}
|
|
307
310
|
>
|
|
308
311
|
<div
|
|
309
312
|
className={`w-full ${
|
|
310
|
-
editActive ? 'bg-[#
|
|
313
|
+
editActive ? 'bg-[#545987] ' : ''
|
|
311
314
|
} flex just items-center`}
|
|
312
315
|
>
|
|
313
316
|
<Preview
|
|
@@ -318,12 +321,12 @@ function ImagePreviewComponent({
|
|
|
318
321
|
selection={regions[currentIndex] || DEFAULT_REGION}
|
|
319
322
|
regions={detectedRegions[currentIndex] || []}
|
|
320
323
|
minWidth={Math.min(
|
|
321
|
-
|
|
324
|
+
40 *
|
|
322
325
|
(requestImages[currentIndex]?.width /
|
|
323
326
|
requestImages[currentIndex]?.height),
|
|
324
327
|
200,
|
|
325
328
|
)}
|
|
326
|
-
minHeight={
|
|
329
|
+
minHeight={40}
|
|
327
330
|
dotColor={editActive ? '#FBD914' : ''}
|
|
328
331
|
minCropWidth={editActive ? 30 : 5}
|
|
329
332
|
minCropHeight={editActive ? 30 : 5}
|
|
@@ -370,26 +373,38 @@ function ImagePreviewComponent({
|
|
|
370
373
|
)}
|
|
371
374
|
<div
|
|
372
375
|
onClick={() => setEditActive(s => !s)}
|
|
373
|
-
className={
|
|
374
|
-
|
|
375
|
-
|
|
376
|
+
className={twMerge(
|
|
377
|
+
`absolute right-1 ${
|
|
378
|
+
editActive ? 'bottom-1' : 'bottom-1'
|
|
379
|
+
} flex justify-center items-center desktop:hidden p-1`,
|
|
380
|
+
)}
|
|
376
381
|
>
|
|
377
|
-
<div
|
|
382
|
+
<div
|
|
383
|
+
className={twMerge(
|
|
384
|
+
'rounded-full w-6 h-6 flex justify-center items-center desktop:hidden',
|
|
385
|
+
editActive ? 'w-8 h-8 bg-white' : 'w-10 h-10 bg-transparent',
|
|
386
|
+
)}
|
|
387
|
+
>
|
|
378
388
|
{editActive && <Icon name="collapse" className="text-primary" />}
|
|
379
|
-
{!editActive && <Icon name="crop" className="text-
|
|
389
|
+
{!editActive && <Icon name="crop" className="text-white" />}
|
|
380
390
|
</div>
|
|
381
391
|
</div>
|
|
382
392
|
|
|
383
393
|
<div
|
|
384
394
|
onClick={() => onImageRemove()}
|
|
385
395
|
className={`absolute left-1 ${
|
|
386
|
-
editActive ? 'top-1' : 'top-
|
|
396
|
+
editActive ? 'top-1' : 'top-1'
|
|
387
397
|
} flex justify-center items-center desktop:hidden p-1`}
|
|
388
398
|
>
|
|
389
|
-
<div
|
|
399
|
+
<div
|
|
400
|
+
className={twMerge(
|
|
401
|
+
'rounded-full bg-[#FFE5EF] flex justify-center items-center desktop:hidden',
|
|
402
|
+
editActive ? 'w-8 h-8' : 'w-10 h-10',
|
|
403
|
+
)}
|
|
404
|
+
>
|
|
390
405
|
<Icon
|
|
391
406
|
name="trash"
|
|
392
|
-
className="text-
|
|
407
|
+
className="text-[#E31B5D]"
|
|
393
408
|
width={14}
|
|
394
409
|
height={14}
|
|
395
410
|
/>
|
|
@@ -12,7 +12,13 @@ import { useCadSearch } from 'hooks/useCadSearch';
|
|
|
12
12
|
import { isCadFile } from '@nyris/nyris-api';
|
|
13
13
|
import UploadDisclaimer from './UploadDisclaimer';
|
|
14
14
|
|
|
15
|
-
function ImageUpload({
|
|
15
|
+
function ImageUpload({
|
|
16
|
+
onCameraClick,
|
|
17
|
+
disableDisclaimer,
|
|
18
|
+
}: {
|
|
19
|
+
onCameraClick?: () => void;
|
|
20
|
+
disableDisclaimer?: boolean;
|
|
21
|
+
}) {
|
|
16
22
|
const settings = window.settings;
|
|
17
23
|
const user = useAuth0().user;
|
|
18
24
|
|
|
@@ -66,12 +72,13 @@ function ImageUpload({ onCameraClick }: { onCameraClick?: () => void }) {
|
|
|
66
72
|
]);
|
|
67
73
|
|
|
68
74
|
const showDisclaimerDisabled = useMemo(() => {
|
|
75
|
+
if (disableDisclaimer) return true;
|
|
69
76
|
const disclaimer = localStorage.getItem('upload-disclaimer-suite');
|
|
70
77
|
if (requestImages.length === 0) return true;
|
|
71
78
|
if (!disclaimer) return false;
|
|
72
79
|
return disclaimer === 'dont-show';
|
|
73
80
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
74
|
-
}, [showDisclaimer, requestImages]);
|
|
81
|
+
}, [showDisclaimer, requestImages, disableDisclaimer]);
|
|
75
82
|
|
|
76
83
|
const { singleImageSearch } = useImageSearch();
|
|
77
84
|
const { cadSearch } = useCadSearch();
|
|
@@ -81,7 +88,7 @@ function ImageUpload({ onCameraClick }: { onCameraClick?: () => void }) {
|
|
|
81
88
|
setQuery('');
|
|
82
89
|
|
|
83
90
|
if (isCadFile(files[0])) {
|
|
84
|
-
cadSearch({ file: files[0], settings, newSearch: true }).then(
|
|
91
|
+
cadSearch({ file: files[0], settings, newSearch: true }).then(() => {});
|
|
85
92
|
|
|
86
93
|
return;
|
|
87
94
|
}
|
|
@@ -191,14 +198,15 @@ function ImageUpload({ onCameraClick }: { onCameraClick?: () => void }) {
|
|
|
191
198
|
<Tooltip content={t('Search with an image')}>
|
|
192
199
|
<label
|
|
193
200
|
className={twMerge(
|
|
194
|
-
'
|
|
195
|
-
'w-10 h-10 flex justify-center items-center cursor-pointer rounded-full bg-gray-100 desktop:bg-transparent hover:bg-gray-100',
|
|
201
|
+
'min-w-10 min-h-10 flex justify-center items-center cursor-pointer rounded-full bg-gray-100 desktop:bg-transparent hover:bg-gray-100',
|
|
196
202
|
location.pathname === '/result' && 'desktop:w-8 desktop:h-8',
|
|
203
|
+
location.pathname !== '/result' &&
|
|
204
|
+
'desktop:bg-[#FAFAFA] desktop:hover:bg-[#FAFAFA]',
|
|
197
205
|
)}
|
|
198
206
|
htmlFor={
|
|
199
207
|
showDisclaimerDisabled && !onCameraClick ? 'icon-button-file' : ''
|
|
200
208
|
}
|
|
201
|
-
onClick={
|
|
209
|
+
onClick={() => {
|
|
202
210
|
if (!showDisclaimerDisabled) {
|
|
203
211
|
// disclaimer
|
|
204
212
|
setShowDisclaimer(true);
|
|
@@ -207,12 +215,12 @@ function ImageUpload({ onCameraClick }: { onCameraClick?: () => void }) {
|
|
|
207
215
|
}
|
|
208
216
|
}}
|
|
209
217
|
>
|
|
210
|
-
<Icon name="
|
|
218
|
+
<Icon name="camera_ai" width={16} height={16} fill="#3B3E5F" />
|
|
211
219
|
</label>
|
|
212
220
|
</Tooltip>
|
|
213
221
|
</div>
|
|
214
222
|
|
|
215
|
-
{showDisclaimer && (
|
|
223
|
+
{showDisclaimer && !disableDisclaimer && (
|
|
216
224
|
<UploadDisclaimer
|
|
217
225
|
onClose={() => {
|
|
218
226
|
setShowDisclaimer(false);
|
|
@@ -66,20 +66,22 @@ export default function InquiryModal({
|
|
|
66
66
|
useEffect(() => {
|
|
67
67
|
function omitKeys(obj: any, keys: string[]) {
|
|
68
68
|
return Object.fromEntries(
|
|
69
|
-
Object.entries(obj).filter(([key]) => !keys.includes(key))
|
|
69
|
+
Object.entries(obj).filter(([key]) => !keys.includes(key)),
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
|
-
const omittedSpecification = omitKeys(specifications, [
|
|
72
|
+
const omittedSpecification = omitKeys(specifications, [
|
|
73
|
+
'is_nameplate',
|
|
74
|
+
'prefilter_value',
|
|
75
|
+
]);
|
|
73
76
|
setInformation(
|
|
74
|
-
Object
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
77
|
+
Object.entries(omittedSpecification).reduce(
|
|
78
|
+
(acc, [k, v]) =>
|
|
79
|
+
v == null || (typeof v === 'string' && v.trim() === '')
|
|
80
|
+
? acc
|
|
81
|
+
: `${acc}${k}: ${v}\n`,
|
|
82
|
+
'',
|
|
83
|
+
),
|
|
84
|
+
);
|
|
83
85
|
}, [specifications]);
|
|
84
86
|
|
|
85
87
|
useEffect(() => emailjs.init('SMGihPnuEGcYLm0V4'), []);
|
|
@@ -94,32 +96,36 @@ export default function InquiryModal({
|
|
|
94
96
|
const croppedImage = requestImage
|
|
95
97
|
? getCroppedCanvas(requestImage, selectedRegion)
|
|
96
98
|
: null;
|
|
97
|
-
const nameplateImageCanvas = nameplateImage
|
|
98
|
-
|
|
99
|
+
const nameplateImageCanvas = nameplateImage
|
|
100
|
+
? await createImage(nameplateImage)
|
|
101
|
+
: null;
|
|
102
|
+
|
|
99
103
|
const serviceId = 'service_zfsxshi';
|
|
100
104
|
setIsInquiryModalOpen(false);
|
|
101
105
|
const templateId = settings.support?.emailTemplateId;
|
|
102
106
|
if (templateId) {
|
|
103
|
-
const body = !specifications?.is_nameplate
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
const body = !specifications?.is_nameplate
|
|
108
|
+
? {
|
|
109
|
+
email_id: email.trim(),
|
|
110
|
+
information_text: information ? information : '<not specified>',
|
|
111
|
+
request_image: croppedImage?.toDataURL(),
|
|
112
|
+
prefilter_values: preFilterValues?.length
|
|
113
|
+
? preFilterValues.join(', ')
|
|
114
|
+
: '<not specified>',
|
|
115
|
+
}
|
|
116
|
+
: {
|
|
117
|
+
email_id: email.trim(),
|
|
118
|
+
information_text: information,
|
|
119
|
+
request_image: croppedImage?.toDataURL() || '',
|
|
120
|
+
typeplate_image: nameplateImageCanvas?.toDataURL() || '',
|
|
121
|
+
prefilter_values: specifications.prefilter_value,
|
|
122
|
+
};
|
|
117
123
|
try {
|
|
118
124
|
await emailjs.send(serviceId, templateId, body);
|
|
119
125
|
ToastHelper.success(t('Request sent successfully'));
|
|
120
126
|
} catch (error) {
|
|
121
127
|
toast(
|
|
122
|
-
|
|
128
|
+
() => {
|
|
123
129
|
return (
|
|
124
130
|
<div
|
|
125
131
|
style={{
|
|
@@ -174,7 +180,7 @@ export default function InquiryModal({
|
|
|
174
180
|
return (
|
|
175
181
|
<Dialog
|
|
176
182
|
open={isInquiryModalOpen}
|
|
177
|
-
onOpenChange={(
|
|
183
|
+
onOpenChange={() => {
|
|
178
184
|
setIsInquiryModalOpen(false);
|
|
179
185
|
}}
|
|
180
186
|
>
|
|
@@ -4,7 +4,6 @@ import { twMerge } from 'tailwind-merge';
|
|
|
4
4
|
import useRequestStore from '../stores/request/requestStore';
|
|
5
5
|
import useResultStore from '../stores/result/resultStore';
|
|
6
6
|
import { Icon } from '@nyris/nyris-react-components';
|
|
7
|
-
import { useMediaQuery } from 'react-responsive';
|
|
8
7
|
|
|
9
8
|
const ItemSpecification = ({
|
|
10
9
|
attr,
|
|
@@ -16,7 +15,6 @@ const ItemSpecification = ({
|
|
|
16
15
|
return ref.header.toLocaleLowerCase() === attr.toLocaleLowerCase();
|
|
17
16
|
});
|
|
18
17
|
const attribute = refinement?.length ? refinement[0].attribute : 'none';
|
|
19
|
-
const isMobile = useMediaQuery({ query: '(max-width: 776px)' });
|
|
20
18
|
const { refine } = useRefinementList({
|
|
21
19
|
attribute,
|
|
22
20
|
operator: 'or',
|
|
@@ -24,140 +22,74 @@ const ItemSpecification = ({
|
|
|
24
22
|
limit: 1,
|
|
25
23
|
});
|
|
26
24
|
|
|
27
|
-
return
|
|
28
|
-
|
|
25
|
+
return (
|
|
26
|
+
<Tooltip
|
|
27
|
+
content={
|
|
28
|
+
specificationFilter[attr]
|
|
29
|
+
? 'Filter applied. Clear to choose a different value.'
|
|
30
|
+
: 'Click to apply as a search filter.'
|
|
31
|
+
}
|
|
32
|
+
delayDuration={1000}
|
|
33
|
+
disabled={!value}
|
|
34
|
+
>
|
|
29
35
|
<div
|
|
30
|
-
className=
|
|
31
|
-
|
|
36
|
+
className={twMerge(
|
|
37
|
+
`px-3.5 py-2 bg-[#E7E8F1] rounded-lg flex justify-center items-center gap-1.5`,
|
|
38
|
+
'border border-solid border-transparent hover:border-[#E7E8F1]',
|
|
39
|
+
'cursor-pointer',
|
|
40
|
+
'w-fit',
|
|
41
|
+
specificationFilter[attr]
|
|
42
|
+
? ' bg-[#545987] '
|
|
43
|
+
: 'hover:shadow-[0_0_6px_0_#DDDEE7]',
|
|
44
|
+
)}
|
|
45
|
+
onClick={() => {
|
|
46
|
+
if (!value) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (attribute !== 'none') {
|
|
50
|
+
refine(value);
|
|
51
|
+
} else {
|
|
52
|
+
const setSpecificationFilter =
|
|
53
|
+
useRequestStore.getState().setSpecificationFilter;
|
|
54
|
+
|
|
55
|
+
const setSpecificationFilteredProducts =
|
|
56
|
+
useResultStore.getState().setSpecificationFilteredProducts;
|
|
57
|
+
|
|
58
|
+
if (specificationFilter[attr]) {
|
|
59
|
+
setSpecificationFilter({});
|
|
60
|
+
setSpecificationFilteredProducts([]);
|
|
61
|
+
// setProducts(results);
|
|
62
|
+
} else {
|
|
63
|
+
setSpecificationFilter({
|
|
64
|
+
[attr]: value,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}}
|
|
32
69
|
>
|
|
33
|
-
<div className="pl-1 inline-flex justify-center items-center gap-2.5">
|
|
34
|
-
<div className="justify-start text-[#3B3E5F] text-sm font-semibold">
|
|
35
|
-
{attr}
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
70
|
<div
|
|
39
71
|
className={twMerge(
|
|
40
|
-
|
|
41
|
-
'
|
|
72
|
+
'justify-start text-[#767A9F] text-sm leading-none px-0.5',
|
|
73
|
+
'font-normal',
|
|
42
74
|
specificationFilter[attr]
|
|
43
|
-
? '
|
|
44
|
-
: '',
|
|
75
|
+
? 'text-white hover:px-0.5'
|
|
76
|
+
: 'hover:font-semibold',
|
|
77
|
+
'leading-4',
|
|
78
|
+
'flex gap-2 items-center',
|
|
45
79
|
)}
|
|
46
|
-
onClick={() => {
|
|
47
|
-
if (!value) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (attribute !== 'none') {
|
|
51
|
-
refine(value);
|
|
52
|
-
} else {
|
|
53
|
-
const setSpecificationFilter =
|
|
54
|
-
useRequestStore.getState().setSpecificationFilter;
|
|
55
|
-
|
|
56
|
-
const setSpecificationFilteredProducts =
|
|
57
|
-
useResultStore.getState().setSpecificationFilteredProducts;
|
|
58
|
-
|
|
59
|
-
if (specificationFilter[attr]) {
|
|
60
|
-
setSpecificationFilter({});
|
|
61
|
-
setSpecificationFilteredProducts([]);
|
|
62
|
-
// setProducts(results);
|
|
63
|
-
} else {
|
|
64
|
-
setSpecificationFilter({
|
|
65
|
-
[attr]: value,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}}
|
|
70
80
|
>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
name="close"
|
|
76
|
-
className={twMerge(
|
|
77
|
-
'w-3 h-3 text-white',
|
|
78
|
-
specificationFilter[attr] ? 'block' : 'hidden',
|
|
79
|
-
)}
|
|
80
|
-
/>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
</>
|
|
86
|
-
) : (
|
|
87
|
-
<div key={attr} className="flex justify-between w-full gap-2 items-center">
|
|
88
|
-
<div className="self-stretch inline-flex justify-start items-center gap-1.5">
|
|
89
|
-
<div className="justify-start text-[#3B3E5F] text-xs font-semibold">
|
|
90
|
-
{attr}:
|
|
91
|
-
</div>
|
|
92
|
-
<Tooltip
|
|
93
|
-
content={
|
|
94
|
-
specificationFilter[attr]
|
|
95
|
-
? 'Filter applied. Clear to choose a different value.'
|
|
96
|
-
: 'Click to apply as a search filter.'
|
|
97
|
-
}
|
|
98
|
-
delayDuration={1000}
|
|
99
|
-
disabled={!value}
|
|
100
|
-
>
|
|
101
|
-
<div
|
|
81
|
+
{imageAnalysis?.specification[attr] || 'N/A'}
|
|
82
|
+
|
|
83
|
+
<Icon
|
|
84
|
+
name="close"
|
|
102
85
|
className={twMerge(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
'cursor-pointer',
|
|
106
|
-
specificationFilter[attr] ? 'border-[#3E36DC] bg-[#3E36DC] ' : '',
|
|
86
|
+
'w-[10px] h-[10px] text-white',
|
|
87
|
+
specificationFilter[attr] ? 'block' : 'hidden',
|
|
107
88
|
)}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (attribute !== 'none') {
|
|
113
|
-
refine(value);
|
|
114
|
-
} else {
|
|
115
|
-
const setSpecificationFilter =
|
|
116
|
-
useRequestStore.getState().setSpecificationFilter;
|
|
117
|
-
|
|
118
|
-
const setSpecificationFilteredProducts =
|
|
119
|
-
useResultStore.getState().setSpecificationFilteredProducts;
|
|
120
|
-
|
|
121
|
-
if (specificationFilter[attr]) {
|
|
122
|
-
setSpecificationFilter({});
|
|
123
|
-
setSpecificationFilteredProducts([]);
|
|
124
|
-
// setProducts(results);
|
|
125
|
-
} else {
|
|
126
|
-
setSpecificationFilter({
|
|
127
|
-
[attr]: value,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}}
|
|
132
|
-
>
|
|
133
|
-
<div
|
|
134
|
-
className={twMerge(
|
|
135
|
-
'justify-start text-[#3e36dc] text-[10px] leading-none px-0.5',
|
|
136
|
-
'font-normal hover:font-bold hover:px-0',
|
|
137
|
-
specificationFilter[attr]
|
|
138
|
-
? 'font-bold text-white hover:px-0.5'
|
|
139
|
-
: '',
|
|
140
|
-
'max-line-1',
|
|
141
|
-
)}
|
|
142
|
-
>
|
|
143
|
-
{imageAnalysis?.specification[attr] || 'N/A'}
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
</Tooltip>
|
|
147
|
-
</div>
|
|
148
|
-
<div
|
|
149
|
-
onClick={() => {
|
|
150
|
-
navigator.clipboard.writeText(
|
|
151
|
-
imageAnalysis?.specification[attr] || '',
|
|
152
|
-
);
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
<Icon
|
|
156
|
-
name="copy"
|
|
157
|
-
className="text-[#AAABB5] w-[12px] h-[12px] hover:text-[#3E36DC] cursor-pointer"
|
|
158
|
-
/>
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
159
91
|
</div>
|
|
160
|
-
</
|
|
92
|
+
</Tooltip>
|
|
161
93
|
);
|
|
162
94
|
};
|
|
163
95
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
|
|
@@ -10,49 +10,49 @@ const LocationInfoPopup = () => {
|
|
|
10
10
|
const shown = sessionStorage.getItem('locationNoticeShown');
|
|
11
11
|
if (shown) return;
|
|
12
12
|
|
|
13
|
-
navigator.permissions
|
|
14
|
-
.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
});
|
|
13
|
+
navigator.permissions.query({ name: 'geolocation' }).then(result => {
|
|
14
|
+
if (result.state === 'prompt') {
|
|
15
|
+
setShowPopup(true);
|
|
16
|
+
} else if (result.state === 'granted') {
|
|
17
|
+
navigator.geolocation.getCurrentPosition(console.log, console.error);
|
|
18
|
+
sessionStorage.setItem('locationNoticeShown', 'true');
|
|
19
|
+
} else {
|
|
20
|
+
sessionStorage.setItem('locationNoticeShown', 'true');
|
|
21
|
+
}
|
|
22
|
+
});
|
|
25
23
|
}, []);
|
|
26
24
|
|
|
27
25
|
const closePopup = () => {
|
|
28
26
|
navigator.geolocation.getCurrentPosition(console.log, console.error);
|
|
29
27
|
sessionStorage.setItem('locationNoticeShown', 'true');
|
|
30
28
|
setShowPopup(false);
|
|
31
|
-
}
|
|
32
|
-
|
|
29
|
+
};
|
|
30
|
+
|
|
33
31
|
return (
|
|
34
32
|
<div>
|
|
35
|
-
{showPopup &&
|
|
36
|
-
|
|
37
|
-
className="custom-modal"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
className="custom-modal-body geolocation"
|
|
42
|
-
onClick={(e) => {
|
|
33
|
+
{showPopup &&
|
|
34
|
+
createPortal(
|
|
35
|
+
<div className="custom-modal" onClick={closePopup}>
|
|
36
|
+
<div
|
|
37
|
+
className="custom-modal-body geolocation"
|
|
38
|
+
onClick={e => {
|
|
43
39
|
e.preventDefault();
|
|
44
40
|
e.stopPropagation();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<div className="geolocation-title">
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<div className="geolocation-title">
|
|
44
|
+
{t('Please enable location services when prompted.')}
|
|
45
|
+
</div>
|
|
48
46
|
<div>{window.settings.geoLocationMessage}</div>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
<button type="button" onClick={closePopup}>
|
|
48
|
+
{t('I understand')}
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
</div>,
|
|
52
|
+
document.body,
|
|
53
|
+
)}
|
|
54
54
|
</div>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
57
|
|
|
58
58
|
export default LocationInfoPopup;
|