@nyris/nyris-webapp 0.3.91 → 0.3.92
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.5ea01690.css +4 -0
- package/build/static/css/main.5ea01690.css.map +1 -0
- package/build/static/js/main.36b77705.js +3 -0
- package/build/static/js/{main.f2255597.js.map → main.36b77705.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/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 +124 -91
- 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 +198 -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 +3 -7
- 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.36b77705.js.LICENSE.txt} +0 -0
|
@@ -4,22 +4,26 @@ import { twMerge } from 'tailwind-merge';
|
|
|
4
4
|
import { useAuth0 } from '@auth0/auth0-react';
|
|
5
5
|
import { useLocation, useNavigate } from 'react-router';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
|
-
|
|
8
7
|
import { Icon } from '@nyris/nyris-react-components';
|
|
9
|
-
|
|
10
8
|
import { useImageSearch } from 'hooks/useImageSearch';
|
|
11
9
|
import PreFilterModal from './PreFilter/PreFilterModal';
|
|
12
10
|
import useRequestStore from 'stores/request/requestStore';
|
|
13
11
|
import Tooltip from './Tooltip/TooltipComponent';
|
|
14
12
|
import { useMediaQuery } from 'react-responsive';
|
|
15
13
|
import ImageUpload from './ImageUpload';
|
|
14
|
+
import useUiStore from 'stores/ui/uiStore';
|
|
15
|
+
import useConversationStore from 'stores/chat/conversationStore';
|
|
16
16
|
|
|
17
17
|
function TextSearch({
|
|
18
18
|
className,
|
|
19
19
|
onCameraClick,
|
|
20
|
+
showImageUpload = true,
|
|
21
|
+
aiMode = false,
|
|
20
22
|
}: {
|
|
21
23
|
className?: string;
|
|
22
24
|
onCameraClick?: () => void;
|
|
25
|
+
showImageUpload?: boolean;
|
|
26
|
+
aiMode?: boolean;
|
|
23
27
|
}) {
|
|
24
28
|
const settings = window.settings;
|
|
25
29
|
const user = useAuth0().user;
|
|
@@ -32,6 +36,13 @@ function TextSearch({
|
|
|
32
36
|
const location = useLocation();
|
|
33
37
|
const navigate = useNavigate();
|
|
34
38
|
|
|
39
|
+
const toggleAiMode = useUiStore(state => state.toggleAiMode);
|
|
40
|
+
const isAiModeOpen = useUiStore(state => state.isAiModeOpen);
|
|
41
|
+
const hasAiNotification = useConversationStore(
|
|
42
|
+
state => state.hasNotification,
|
|
43
|
+
);
|
|
44
|
+
const setIsChatOpen = useConversationStore(state => state.setIsOpen);
|
|
45
|
+
|
|
35
46
|
const preFilter = useRequestStore(state => state.preFilter);
|
|
36
47
|
const requestImages = useRequestStore(state => state.requestImages);
|
|
37
48
|
const setQuery = useRequestStore(state => state.setQuery);
|
|
@@ -50,6 +61,7 @@ function TextSearch({
|
|
|
50
61
|
|
|
51
62
|
const [isOpenModalFilterDesktop, setToggleModalFilterDesktop] =
|
|
52
63
|
useState<boolean>(false);
|
|
64
|
+
const [isInputFocused, setIsInputFocused] = useState(false);
|
|
53
65
|
|
|
54
66
|
const showPreFilter = useMemo(() => {
|
|
55
67
|
if (settings.shouldUseUserMetadata && user) {
|
|
@@ -114,27 +126,26 @@ function TextSearch({
|
|
|
114
126
|
return (
|
|
115
127
|
<div
|
|
116
128
|
className={twMerge(
|
|
117
|
-
'w-[
|
|
129
|
+
'w-[636px]',
|
|
118
130
|
'h-12',
|
|
119
|
-
location.pathname === '/result' && 'desktop:h-
|
|
131
|
+
location.pathname === '/result' && 'desktop:h-[52px]',
|
|
120
132
|
className,
|
|
121
133
|
)}
|
|
122
134
|
>
|
|
123
135
|
<div
|
|
124
136
|
className={twMerge([
|
|
125
137
|
'bg-white',
|
|
126
|
-
'
|
|
127
|
-
|
|
128
|
-
'
|
|
129
|
-
'
|
|
130
|
-
'
|
|
131
|
-
'shadow-
|
|
132
|
-
'desktop:shadow-none',
|
|
138
|
+
location.pathname === '/result' &&
|
|
139
|
+
'desktop:bg-[#E7E8F1] desktop:has-[input:focus]:bg-[#FFFFFF] desktop:has-[input:focus]:shadow-ds-2',
|
|
140
|
+
'border border-solid',
|
|
141
|
+
'border-[#DDDEE7]',
|
|
142
|
+
location.pathname !== '/result' && 'shadow-ds-2',
|
|
143
|
+
location.pathname === '/result' && 'shadow-ds-2 desktop:shadow-none',
|
|
133
144
|
'flex',
|
|
134
145
|
'h-full',
|
|
135
146
|
'justify-between',
|
|
136
|
-
'
|
|
137
|
-
'rounded-
|
|
147
|
+
'pr-1.5',
|
|
148
|
+
'rounded-[32px]',
|
|
138
149
|
'w-full',
|
|
139
150
|
])}
|
|
140
151
|
>
|
|
@@ -154,15 +165,12 @@ function TextSearch({
|
|
|
154
165
|
'flex',
|
|
155
166
|
'py-2',
|
|
156
167
|
'px-2',
|
|
157
|
-
'desktop:py-1',
|
|
158
|
-
'desktop:pl-1',
|
|
159
|
-
'pr-
|
|
168
|
+
'desktop:py-1.5',
|
|
169
|
+
'desktop:pl-1.5',
|
|
170
|
+
'pr-1.5',
|
|
160
171
|
'h-full',
|
|
161
172
|
'justify-center',
|
|
162
173
|
'items-center',
|
|
163
|
-
'desktop:border-r',
|
|
164
|
-
'border-solid',
|
|
165
|
-
'border-[#CACAD1]',
|
|
166
174
|
])}
|
|
167
175
|
style={{
|
|
168
176
|
cursor: showPreFilter ? 'pointer' : 'default',
|
|
@@ -183,11 +191,11 @@ function TextSearch({
|
|
|
183
191
|
ref={iconRef}
|
|
184
192
|
className={twMerge(
|
|
185
193
|
'p-2 desktop:p-3',
|
|
186
|
-
location.pathname === '/result' && 'desktop:p-
|
|
194
|
+
location.pathname === '/result' && 'desktop:p-3',
|
|
187
195
|
`flex rounded-full bg-[#f3f3f5]`,
|
|
188
196
|
!isEmpty(preFilter)
|
|
189
197
|
? 'desktop:bg-theme-primary'
|
|
190
|
-
: 'desktop:bg-[#
|
|
198
|
+
: 'desktop:bg-[#FAFAFA]',
|
|
191
199
|
)}
|
|
192
200
|
>
|
|
193
201
|
<Icon
|
|
@@ -196,7 +204,7 @@ function TextSearch({
|
|
|
196
204
|
!isEmpty(preFilter)
|
|
197
205
|
? 'fill-theme-primary'
|
|
198
206
|
: 'fill-[#2B2C46]',
|
|
199
|
-
`desktop:fill-
|
|
207
|
+
`desktop:fill-[#3B3E5F]`,
|
|
200
208
|
)}
|
|
201
209
|
/>
|
|
202
210
|
</div>
|
|
@@ -374,62 +382,118 @@ function TextSearch({
|
|
|
374
382
|
fontSize: 14,
|
|
375
383
|
color: '#2B2C46',
|
|
376
384
|
}}
|
|
377
|
-
className=
|
|
385
|
+
className={twMerge(
|
|
386
|
+
'peer pl-1.5 outline-none',
|
|
387
|
+
'bg-white',
|
|
388
|
+
location.pathname === '/result' &&
|
|
389
|
+
'desktop:bg-[#E7E8F1] focus:bg-[#FFFFFF]',
|
|
390
|
+
)}
|
|
378
391
|
placeholder={t('Search')}
|
|
379
392
|
value={valueInput}
|
|
380
393
|
onChange={onChangeText}
|
|
394
|
+
onFocus={() => setIsInputFocused(true)}
|
|
395
|
+
onBlur={() => setIsInputFocused(false)}
|
|
381
396
|
ref={focusInp}
|
|
382
397
|
/>
|
|
383
398
|
</div>
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
399
|
+
<div className="flex gap-2">
|
|
400
|
+
{location.pathname === '/result' && (valueInput || query) && (
|
|
401
|
+
<Tooltip content={t('Clear text search')}>
|
|
402
|
+
<button
|
|
403
|
+
className={twMerge([
|
|
404
|
+
'flex',
|
|
405
|
+
'justify-center',
|
|
406
|
+
'items-center',
|
|
407
|
+
'rounded-full',
|
|
408
|
+
'cursor-pointer',
|
|
409
|
+
'min-w-10 min-h-10',
|
|
410
|
+
'z-10',
|
|
411
|
+
'hover:bg-gray-100',
|
|
412
|
+
location.pathname === '/result' &&
|
|
413
|
+
'desktop:min-w-10 desktop:min-h-10',
|
|
414
|
+
])}
|
|
415
|
+
onPointerDown={event => {
|
|
416
|
+
// Keep focus on input until click runs so mobile AI button doesn't pop in first.
|
|
417
|
+
event.preventDefault();
|
|
418
|
+
}}
|
|
419
|
+
onClick={() => {
|
|
420
|
+
if (visualSearch) {
|
|
421
|
+
navigate('/result');
|
|
422
|
+
setValueInput('');
|
|
423
|
+
setQuery('');
|
|
424
|
+
if (
|
|
425
|
+
!window.settings?.algolia.enabled &&
|
|
426
|
+
requestImages.length === 0
|
|
427
|
+
) {
|
|
428
|
+
singleImageSearch({
|
|
429
|
+
image: requestImages[0],
|
|
430
|
+
imageRegion: regions[0],
|
|
431
|
+
text: '',
|
|
432
|
+
settings,
|
|
433
|
+
showFeedback: false,
|
|
434
|
+
newSearch: false,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
return;
|
|
418
438
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
439
|
+
setSpecifications(null);
|
|
440
|
+
setQuery('');
|
|
441
|
+
setValueInput('');
|
|
442
|
+
navigate('/');
|
|
443
|
+
}}
|
|
444
|
+
>
|
|
445
|
+
<Icon name="close" className="w-3 h-3 text-primary" />
|
|
446
|
+
</button>
|
|
447
|
+
</Tooltip>
|
|
448
|
+
)}
|
|
449
|
+
{showImageUpload && <ImageUpload onCameraClick={onCameraClick} />}
|
|
450
|
+
{aiMode &&
|
|
451
|
+
window.settings.vizo?.chat &&
|
|
452
|
+
requestImages.length !== 0 &&
|
|
453
|
+
!(isMobile && isInputFocused) && (
|
|
454
|
+
<div className="relative">
|
|
455
|
+
<button
|
|
456
|
+
type="button"
|
|
457
|
+
className={twMerge(
|
|
458
|
+
'px-[10px] h-10 rounded-full text-[14px] text-[#989BB7] flex items-center justify-center gap-2 whitespace-nowrap bg-[#FAFAFA] border border-solid border-transparent',
|
|
459
|
+
!isAiModeOpen &&
|
|
460
|
+
'hover:bg-gradient-to-r hover:from-white hover:to-[#E4E3FF]',
|
|
461
|
+
!isAiModeOpen &&
|
|
462
|
+
'hover:border-[#DDDEE7] hover:text-[#3B3E5F]',
|
|
463
|
+
isAiModeOpen &&
|
|
464
|
+
'bg-[#3B3E5F] text-white hover:bg-[#3B3E5F]',
|
|
465
|
+
)}
|
|
466
|
+
onClick={() => {
|
|
467
|
+
const nextIsAiModeOpen = !isAiModeOpen;
|
|
468
|
+
toggleAiMode();
|
|
469
|
+
setIsChatOpen(nextIsAiModeOpen);
|
|
470
|
+
}}
|
|
471
|
+
>
|
|
472
|
+
<Icon
|
|
473
|
+
name="search_ai"
|
|
474
|
+
width={14}
|
|
475
|
+
height={14}
|
|
476
|
+
className={twMerge(
|
|
477
|
+
'text-[#3B3E5F]',
|
|
478
|
+
isAiModeOpen && 'text-white',
|
|
479
|
+
)}
|
|
480
|
+
/>
|
|
481
|
+
AI mode
|
|
482
|
+
</button>
|
|
431
483
|
|
|
432
|
-
|
|
484
|
+
{hasAiNotification && !isAiModeOpen && (
|
|
485
|
+
<>
|
|
486
|
+
<span
|
|
487
|
+
className="absolute -top-0.5 right-1 w-3 h-3 rounded-full border-2 border-solid border-white"
|
|
488
|
+
style={{
|
|
489
|
+
background: window.settings?.theme?.primaryColor,
|
|
490
|
+
}}
|
|
491
|
+
/>
|
|
492
|
+
</>
|
|
493
|
+
)}
|
|
494
|
+
</div>
|
|
495
|
+
)}
|
|
496
|
+
</div>
|
|
433
497
|
</div>
|
|
434
498
|
</div>
|
|
435
499
|
|