@nyris/nyris-webapp 0.3.86 → 0.3.88
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/index.html +1 -1
- package/build/js/settings.example.js +1 -0
- package/build/static/css/main.ba1c7479.css +4 -0
- package/build/static/css/main.ba1c7479.css.map +1 -0
- package/build/static/js/main.e861b336.js +3 -0
- package/build/static/js/{main.1e617139.js.map → main.e861b336.js.map} +1 -1
- package/package.json +3 -3
- package/public/js/settings.example.js +1 -0
- package/src/components/Carousel/ImagePreviewCarousel.tsx +1 -1
- package/src/components/CustomCameraDrawer.tsx +73 -3
- package/src/components/DragDropFile.tsx +121 -46
- package/src/components/Header.tsx +17 -12
- package/src/components/Hint.tsx +98 -0
- package/src/components/ImagePreview.tsx +79 -10
- package/src/components/Inquiry/InquiryModal.tsx +40 -9
- package/src/components/PreFilter/PreFilter.tsx +14 -0
- package/src/components/Product/Product.tsx +3 -3
- package/src/components/Product/ProductDetailView.tsx +2 -4
- package/src/components/Product/ProductList.tsx +0 -5
- package/src/components/SidePanel.tsx +77 -84
- package/src/components/TextSearch.tsx +161 -9
- package/src/layouts/AppLayout.tsx +14 -10
- package/src/pages/Home.tsx +20 -2
- package/src/pages/Result.tsx +84 -65
- package/src/stores/request/requestStore.ts +5 -1
- package/src/stores/request/specifications/specifications.initialState.ts +9 -0
- package/src/stores/request/specifications/specifications.slice.ts +15 -0
- package/src/stores/types.ts +16 -0
- package/src/styles/common.scss +15 -0
- package/src/styles/product.scss +13 -1
- package/src/translations.ts +27 -0
- package/src/types.ts +1 -0
- package/build/static/css/main.a0a44a64.css +0 -4
- package/build/static/css/main.a0a44a64.css.map +0 -1
- package/build/static/js/main.1e617139.js +0 -3
- /package/build/static/js/{main.1e617139.js.LICENSE.txt → main.e861b336.js.LICENSE.txt} +0 -0
|
@@ -13,6 +13,7 @@ import { AutosizeTextarea } from 'components/AutosizeTextArea';
|
|
|
13
13
|
import Tooltip from 'components/Tooltip/TooltipComponent';
|
|
14
14
|
|
|
15
15
|
import { useTranslation } from 'react-i18next';
|
|
16
|
+
import { createImage } from '../../services/visualSearch';
|
|
16
17
|
interface Props {
|
|
17
18
|
requestImage: any;
|
|
18
19
|
selectedRegion: any;
|
|
@@ -44,6 +45,8 @@ export default function InquiryModal({
|
|
|
44
45
|
}: Props) {
|
|
45
46
|
const settings = window.settings;
|
|
46
47
|
const preFilter = useRequestStore(state => state.preFilter);
|
|
48
|
+
const specifications = useRequestStore(state => state.specifications);
|
|
49
|
+
const nameplateImage = useRequestStore(state => state.nameplateImage);
|
|
47
50
|
|
|
48
51
|
const preFilterValues = Object.keys(preFilter) as string[];
|
|
49
52
|
|
|
@@ -60,6 +63,25 @@ export default function InquiryModal({
|
|
|
60
63
|
);
|
|
61
64
|
const { t } = useTranslation();
|
|
62
65
|
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
function omitKeys(obj: any, keys: string[]) {
|
|
68
|
+
return Object.fromEntries(
|
|
69
|
+
Object.entries(obj).filter(([key]) => !keys.includes(key))
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
const omittedSpecification = omitKeys(specifications, ['is_nameplate', 'prefilter_value']);
|
|
73
|
+
setInformation(
|
|
74
|
+
Object
|
|
75
|
+
.entries(omittedSpecification)
|
|
76
|
+
.reduce((acc, [k, v]) =>
|
|
77
|
+
v == null || (typeof v === 'string' && v.trim() === '')
|
|
78
|
+
? acc
|
|
79
|
+
: `${acc}${k}: ${v}\n`,
|
|
80
|
+
''
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
}, [specifications]);
|
|
84
|
+
|
|
63
85
|
useEffect(() => emailjs.init('SMGihPnuEGcYLm0V4'), []);
|
|
64
86
|
useEffect(() => {
|
|
65
87
|
if (email)
|
|
@@ -72,19 +94,28 @@ export default function InquiryModal({
|
|
|
72
94
|
const croppedImage = requestImage
|
|
73
95
|
? getCroppedCanvas(requestImage, selectedRegion)
|
|
74
96
|
: null;
|
|
97
|
+
const nameplateImageCanvas = nameplateImage ? await createImage(nameplateImage) : null;
|
|
98
|
+
|
|
75
99
|
const serviceId = 'service_zfsxshi';
|
|
76
100
|
setIsInquiryModalOpen(false);
|
|
77
101
|
const templateId = settings.support?.emailTemplateId;
|
|
78
102
|
if (templateId) {
|
|
103
|
+
const body = !specifications?.is_nameplate ? {
|
|
104
|
+
email_id: email.trim(),
|
|
105
|
+
information_text: information ? information : '<not specified>',
|
|
106
|
+
request_image: croppedImage?.toDataURL(),
|
|
107
|
+
prefilter_values: preFilterValues?.length
|
|
108
|
+
? preFilterValues.join(', ')
|
|
109
|
+
: '<not specified>',
|
|
110
|
+
} : {
|
|
111
|
+
email_id: email.trim(),
|
|
112
|
+
information_text: information,
|
|
113
|
+
request_image: croppedImage?.toDataURL() || '',
|
|
114
|
+
typeplate_image: nameplateImageCanvas?.toDataURL() || '',
|
|
115
|
+
prefilter_values: specifications.prefilter_value,
|
|
116
|
+
};
|
|
79
117
|
try {
|
|
80
|
-
await emailjs.send(serviceId, templateId,
|
|
81
|
-
email_id: email.trim(),
|
|
82
|
-
information_text: information ? information : '<not specified>',
|
|
83
|
-
request_image: croppedImage?.toDataURL(),
|
|
84
|
-
prefilter_values: preFilterValues?.length
|
|
85
|
-
? preFilterValues.join(', ')
|
|
86
|
-
: '<not specified>',
|
|
87
|
-
});
|
|
118
|
+
await emailjs.send(serviceId, templateId, body);
|
|
88
119
|
ToastHelper.success(t('Request sent successfully'));
|
|
89
120
|
} catch (error) {
|
|
90
121
|
toast(
|
|
@@ -260,7 +291,7 @@ export default function InquiryModal({
|
|
|
260
291
|
color: '#2B2C46',
|
|
261
292
|
}}
|
|
262
293
|
>
|
|
263
|
-
{settings.
|
|
294
|
+
{settings.preFilterTitle}
|
|
264
295
|
</p>
|
|
265
296
|
<Tooltip
|
|
266
297
|
content={t(
|
|
@@ -10,6 +10,8 @@ import { truncateString } from 'utils/truncateString';
|
|
|
10
10
|
import { twMerge } from 'tailwind-merge';
|
|
11
11
|
import Tooltip from 'components/Tooltip/TooltipComponent';
|
|
12
12
|
import { Skeleton } from 'components/Skeleton';
|
|
13
|
+
import { useNavigate } from 'react-router';
|
|
14
|
+
import useResultStore from "../../stores/result/resultStore";
|
|
13
15
|
|
|
14
16
|
interface Props {
|
|
15
17
|
handleClose?: any;
|
|
@@ -34,10 +36,14 @@ const PreFilterComponent = (props: Props) => {
|
|
|
34
36
|
|
|
35
37
|
const setPreFilter = useRequestStore(state => state.setPreFilter);
|
|
36
38
|
const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
|
|
39
|
+
const specification = useRequestStore(state => state.specifications);
|
|
40
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
41
|
+
const setImageAnalysis = useResultStore(state => state.setImageAnalysis);
|
|
37
42
|
|
|
38
43
|
const [keyFilter, setKeyFilter] = useState<Record<string, boolean>>(
|
|
39
44
|
keyFilterState || {},
|
|
40
45
|
);
|
|
46
|
+
const navigate = useNavigate();
|
|
41
47
|
|
|
42
48
|
const selectedFilter = useMemo(
|
|
43
49
|
() =>
|
|
@@ -72,6 +78,7 @@ const PreFilterComponent = (props: Props) => {
|
|
|
72
78
|
}, {});
|
|
73
79
|
setResultFilter(newResult);
|
|
74
80
|
setColumns(Object.keys(newResult).length);
|
|
81
|
+
|
|
75
82
|
})
|
|
76
83
|
.catch((e: any) => {
|
|
77
84
|
console.log('err getDataFilterDesktop', e);
|
|
@@ -124,6 +131,13 @@ const PreFilterComponent = (props: Props) => {
|
|
|
124
131
|
: '';
|
|
125
132
|
setAlgoliaFilter(filter);
|
|
126
133
|
|
|
134
|
+
if (preFilterValues?.length && preFilterValues[0] !== specification?.prefilter_value) {
|
|
135
|
+
setSpecifications({ prefilter_value: preFilterValues?.join(', ') || ''});
|
|
136
|
+
}
|
|
137
|
+
if (specification?.is_nameplate) {
|
|
138
|
+
setImageAnalysis({});
|
|
139
|
+
}
|
|
140
|
+
|
|
127
141
|
handleClose();
|
|
128
142
|
|
|
129
143
|
if (requestImages.length === 0) {
|
|
@@ -280,7 +280,7 @@ function Product(props: Props) {
|
|
|
280
280
|
'justify-between',
|
|
281
281
|
'flex',
|
|
282
282
|
'flex-col',
|
|
283
|
-
'bg-[#
|
|
283
|
+
'bg-[#fff]',
|
|
284
284
|
'flex-grow',
|
|
285
285
|
'z-10',
|
|
286
286
|
'pt-2',
|
|
@@ -416,7 +416,7 @@ function Product(props: Props) {
|
|
|
416
416
|
background:
|
|
417
417
|
settings.secondaryCTAButton?.secondaryCTAButtonColor ||
|
|
418
418
|
'#2B2C46',
|
|
419
|
-
borderRadius:
|
|
419
|
+
borderRadius: 4,
|
|
420
420
|
padding: '0px 8px',
|
|
421
421
|
marginBottom: settings.CTAButton?.CTAButton ? 8 : 0,
|
|
422
422
|
display: 'flex',
|
|
@@ -493,7 +493,7 @@ function Product(props: Props) {
|
|
|
493
493
|
background:
|
|
494
494
|
settings.CTAButton?.CTAButtonColor ||
|
|
495
495
|
settings.theme?.primaryColor,
|
|
496
|
-
borderRadius:
|
|
496
|
+
borderRadius: 4,
|
|
497
497
|
padding: '0px 8px',
|
|
498
498
|
display: 'flex',
|
|
499
499
|
justifyItems: 'center',
|
|
@@ -169,9 +169,7 @@ function ProductDetailView(props: Props) {
|
|
|
169
169
|
</div>
|
|
170
170
|
|
|
171
171
|
<div
|
|
172
|
-
className={`overflow-y-auto max-h-[90svh] px-4 pb-4
|
|
173
|
-
settings.simpleCardView ? 'bg-[#FaFafa]' : 'bg-[#f3f3f5]'
|
|
174
|
-
} mt-1`}
|
|
172
|
+
className={`overflow-y-auto max-h-[90svh] px-4 pb-4 'bg-[#fff] mt-1`}
|
|
175
173
|
>
|
|
176
174
|
{settings.simpleCardView ? (
|
|
177
175
|
<div className="info-container">
|
|
@@ -186,7 +184,7 @@ function ProductDetailView(props: Props) {
|
|
|
186
184
|
) : (
|
|
187
185
|
<div className="box-content flex flex-col bg-[#F3F3F5] mt-4">
|
|
188
186
|
<div className="box-top">
|
|
189
|
-
<div className="bg-[#
|
|
187
|
+
<div className="bg-[#fff] flex flex-col justify-between">
|
|
190
188
|
<div className="gap-1.5 flex flex-wrap w-full">
|
|
191
189
|
<div className="w-full">
|
|
192
190
|
{settings.mainTitle && (
|
|
@@ -6,7 +6,6 @@ import useRequestStore from 'stores/request/requestStore';
|
|
|
6
6
|
import useUiStore from 'stores/ui/uiStore';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import { twMerge } from 'tailwind-merge';
|
|
9
|
-
import { useCurrentRefinements } from 'react-instantsearch';
|
|
10
9
|
import { filterProducts } from 'utils/specificationFilter';
|
|
11
10
|
|
|
12
11
|
interface Props {
|
|
@@ -36,10 +35,6 @@ function ProductList({ sendFeedBackAction }: Props): JSX.Element {
|
|
|
36
35
|
state => state.specificationFilter,
|
|
37
36
|
);
|
|
38
37
|
|
|
39
|
-
const specificationFilteredProducts = useResultStore(
|
|
40
|
-
state => state.specificationFilteredProducts,
|
|
41
|
-
);
|
|
42
|
-
|
|
43
38
|
const getUrlToCanvasFile = async (url: string) => {
|
|
44
39
|
setQuery('');
|
|
45
40
|
setValueInput('');
|
|
@@ -6,18 +6,9 @@ import PostFilterComponent from './PostFilter/PostFilterComponent';
|
|
|
6
6
|
import useResultStore from 'stores/result/resultStore';
|
|
7
7
|
import { Icon } from '@nyris/nyris-react-components';
|
|
8
8
|
import Tooltip from './Tooltip/TooltipComponent';
|
|
9
|
-
import { filterProducts } from 'utils/specificationFilter';
|
|
10
|
-
import { useEffect } from 'react';
|
|
11
9
|
|
|
12
10
|
export default function SidePanel({ className }: { className?: string }) {
|
|
13
11
|
const requestImages = useRequestStore(state => state.requestImages);
|
|
14
|
-
const setSpecificationFilteredProducts = useResultStore(
|
|
15
|
-
state => state.setSpecificationFilteredProducts,
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
const productsFromAlgolia = useResultStore(
|
|
19
|
-
state => state.productsFromAlgolia,
|
|
20
|
-
);
|
|
21
12
|
|
|
22
13
|
const specificationFilter = useRequestStore(
|
|
23
14
|
state => state.specificationFilter,
|
|
@@ -66,7 +57,7 @@ export default function SidePanel({ className }: { className?: string }) {
|
|
|
66
57
|
{requestImages[0] && <ImagePreview />}
|
|
67
58
|
</div>
|
|
68
59
|
|
|
69
|
-
{(imageAnalysis?.imageDescription ||
|
|
60
|
+
{window.settings.showImageDetails && (imageAnalysis?.imageDescription ||
|
|
70
61
|
Object.keys(imageAnalysis?.specification || {}).length > 0) && (
|
|
71
62
|
<div className="self-stretch p-4 bg-[#f3f3f5] rounded inline-flex flex-col justify-start items-start gap-1.5 mt-4 mx-4 ">
|
|
72
63
|
{imageAnalysis?.imageDescription !== 'No description available' && (
|
|
@@ -84,90 +75,92 @@ export default function SidePanel({ className }: { className?: string }) {
|
|
|
84
75
|
Identified Attributes
|
|
85
76
|
</div>
|
|
86
77
|
|
|
87
|
-
{Object.keys(imageAnalysis?.specification || {})
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
: 'Click to apply as a search filter.'
|
|
106
|
-
}
|
|
107
|
-
delayDuration={1000}
|
|
108
|
-
disabled={!value}
|
|
109
|
-
>
|
|
110
|
-
<div
|
|
111
|
-
className={twMerge(
|
|
112
|
-
`px-1 py-1 bg-[#e4e3ff] rounded-[1px] flex justify-center items-center gap-1.5`,
|
|
113
|
-
'border border-solid border-transparent hover:border-[#3E36DC]',
|
|
114
|
-
'cursor-pointer',
|
|
78
|
+
{Object.keys(imageAnalysis?.specification || {})
|
|
79
|
+
.filter((key) => (key !== 'is_nameplate' && key !== 'prefilter_value'))
|
|
80
|
+
.map(key => {
|
|
81
|
+
const value = imageAnalysis?.specification[key];
|
|
82
|
+
if (!value) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
key={key}
|
|
88
|
+
className="flex justify-between w-full gap-2 items-center"
|
|
89
|
+
>
|
|
90
|
+
<div className="self-stretch inline-flex justify-start items-center gap-1.5">
|
|
91
|
+
<div className="justify-start text-black text-xs font-semibold">
|
|
92
|
+
{key}:
|
|
93
|
+
</div>
|
|
94
|
+
<Tooltip
|
|
95
|
+
content={
|
|
115
96
|
specificationFilter[key]
|
|
116
|
-
? '
|
|
117
|
-
: ''
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const setSpecificationFilter =
|
|
124
|
-
useRequestStore.getState().setSpecificationFilter;
|
|
125
|
-
|
|
126
|
-
const setSpecificationFilteredProducts =
|
|
127
|
-
useResultStore.getState()
|
|
128
|
-
.setSpecificationFilteredProducts;
|
|
129
|
-
|
|
130
|
-
if (specificationFilter[key]) {
|
|
131
|
-
setSpecificationFilter({});
|
|
132
|
-
setSpecificationFilteredProducts([]);
|
|
133
|
-
// setProducts(results);
|
|
134
|
-
} else {
|
|
135
|
-
setSpecificationFilter({
|
|
136
|
-
[key]: value,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}}
|
|
97
|
+
? 'Filter applied. Clear to choose a different value.'
|
|
98
|
+
: 'Click to apply as a search filter.'
|
|
99
|
+
}
|
|
100
|
+
delayDuration={1000}
|
|
101
|
+
disabled={!value}
|
|
140
102
|
>
|
|
141
103
|
<div
|
|
142
104
|
className={twMerge(
|
|
143
|
-
|
|
144
|
-
'
|
|
105
|
+
`px-1 py-1 bg-[#e4e3ff] rounded-[1px] flex justify-center items-center gap-1.5`,
|
|
106
|
+
'border border-solid border-transparent hover:border-[#3E36DC]',
|
|
107
|
+
'cursor-pointer',
|
|
145
108
|
specificationFilter[key]
|
|
146
|
-
? '
|
|
109
|
+
? 'border-[#3E36DC] bg-[#3E36DC] '
|
|
147
110
|
: '',
|
|
148
|
-
'max-line-1',
|
|
149
111
|
)}
|
|
112
|
+
onClick={() => {
|
|
113
|
+
if (!value) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const setSpecificationFilter =
|
|
117
|
+
useRequestStore.getState().setSpecificationFilter;
|
|
118
|
+
|
|
119
|
+
const setSpecificationFilteredProducts =
|
|
120
|
+
useResultStore.getState()
|
|
121
|
+
.setSpecificationFilteredProducts;
|
|
122
|
+
|
|
123
|
+
if (specificationFilter[key]) {
|
|
124
|
+
setSpecificationFilter({});
|
|
125
|
+
setSpecificationFilteredProducts([]);
|
|
126
|
+
// setProducts(results);
|
|
127
|
+
} else {
|
|
128
|
+
setSpecificationFilter({
|
|
129
|
+
[key]: value,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}}
|
|
150
133
|
>
|
|
151
|
-
|
|
134
|
+
<div
|
|
135
|
+
className={twMerge(
|
|
136
|
+
'justify-start text-[#3e36dc] text-[10px] leading-none px-0.5',
|
|
137
|
+
'font-normal hover:font-bold hover:px-0',
|
|
138
|
+
specificationFilter[key]
|
|
139
|
+
? 'font-bold text-white hover:px-0.5'
|
|
140
|
+
: '',
|
|
141
|
+
'max-line-1',
|
|
142
|
+
)}
|
|
143
|
+
>
|
|
144
|
+
{imageAnalysis?.specification[key] || 'N/A'}
|
|
145
|
+
</div>
|
|
152
146
|
</div>
|
|
153
|
-
</
|
|
154
|
-
</
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
147
|
+
</Tooltip>
|
|
148
|
+
</div>
|
|
149
|
+
<div
|
|
150
|
+
onClick={() => {
|
|
151
|
+
navigator.clipboard.writeText(
|
|
152
|
+
imageAnalysis?.specification[key] || '',
|
|
153
|
+
);
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
<Icon
|
|
157
|
+
name="copy"
|
|
158
|
+
className="text-[#AAABB5] w-[12px] h-[12px] hover:text-[#3E36DC] cursor-pointer"
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
167
161
|
</div>
|
|
168
|
-
|
|
169
|
-
)
|
|
170
|
-
})}
|
|
162
|
+
);
|
|
163
|
+
})}
|
|
171
164
|
</div>
|
|
172
165
|
)}
|
|
173
166
|
{showPostFilter && (
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import { isEmpty, debounce } from 'lodash';
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { isEmpty, debounce, clone } from 'lodash';
|
|
4
3
|
import { twMerge } from 'tailwind-merge';
|
|
5
4
|
import { useAuth0 } from '@auth0/auth0-react';
|
|
6
5
|
import { useLocation, useNavigate } from 'react-router';
|
|
@@ -15,6 +14,8 @@ import PreFilterModal from './PreFilter/PreFilterModal';
|
|
|
15
14
|
import useRequestStore from 'stores/request/requestStore';
|
|
16
15
|
import Tooltip from './Tooltip/TooltipComponent';
|
|
17
16
|
import UploadDisclaimer from './UploadDisclaimer';
|
|
17
|
+
import { getFilters } from '../services/filter';
|
|
18
|
+
import { useMediaQuery } from 'react-responsive';
|
|
18
19
|
|
|
19
20
|
function TextSearch({
|
|
20
21
|
className,
|
|
@@ -27,12 +28,15 @@ function TextSearch({
|
|
|
27
28
|
const user = useAuth0().user;
|
|
28
29
|
|
|
29
30
|
const focusInp: any = useRef<HTMLDivElement | null>(null);
|
|
31
|
+
const iconRef = useRef<HTMLDivElement>(null);
|
|
30
32
|
|
|
31
33
|
const { t } = useTranslation();
|
|
32
34
|
|
|
33
35
|
const location = useLocation();
|
|
34
36
|
const navigate = useNavigate();
|
|
35
37
|
|
|
38
|
+
const [resultFilter, setResultFilter] = useState<any>([]);
|
|
39
|
+
|
|
36
40
|
const preFilter = useRequestStore(state => state.preFilter);
|
|
37
41
|
const requestImages = useRequestStore(state => state.requestImages);
|
|
38
42
|
const setQuery = useRequestStore(state => state.setQuery);
|
|
@@ -40,8 +44,19 @@ function TextSearch({
|
|
|
40
44
|
const valueInput = useRequestStore(state => state.valueInput);
|
|
41
45
|
const setValueInput = useRequestStore(state => state.setValueInput);
|
|
42
46
|
const setMetaFilter = useRequestStore(state => state.setMetaFilter);
|
|
47
|
+
const specifications = useRequestStore(state => state.specifications);
|
|
48
|
+
const nameplateNotificationText = useRequestStore(state => state.nameplateNotificationText);
|
|
49
|
+
const isMobile = useMediaQuery({ query: '(max-width: 776px)' });
|
|
43
50
|
|
|
44
51
|
const regions = useRequestStore(state => state.regions);
|
|
52
|
+
const setRequestImages = useRequestStore(state => state.setRequestImages);
|
|
53
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
54
|
+
const setShowLoading = useRequestStore(state => state.setShowLoading);
|
|
55
|
+
const setNameplateNotificationText = useRequestStore(state => state.setNameplateNotificationText);
|
|
56
|
+
const setShowNotMatchedError = useRequestStore(state => state.setShowNotMatchedError);
|
|
57
|
+
const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
|
|
58
|
+
const setPreFilter = useRequestStore(state => state.setPreFilter);
|
|
59
|
+
const setNameplateImage = useRequestStore(state => state.setNameplateImage);
|
|
45
60
|
|
|
46
61
|
const [isOpenModalFilterDesktop, setToggleModalFilterDesktop] =
|
|
47
62
|
useState<boolean>(false);
|
|
@@ -84,7 +99,7 @@ function TextSearch({
|
|
|
84
99
|
const searchOrRedirect = useCallback(
|
|
85
100
|
debounce((value: any) => {
|
|
86
101
|
setQuery(value);
|
|
87
|
-
if (requestImages.length === 0 && value === '') {
|
|
102
|
+
if (requestImages.length === 0 && value === '' && !specifications) {
|
|
88
103
|
navigate('/');
|
|
89
104
|
return;
|
|
90
105
|
}
|
|
@@ -109,32 +124,91 @@ function TextSearch({
|
|
|
109
124
|
setValueInput(event.currentTarget.value);
|
|
110
125
|
searchOrRedirect(event.currentTarget.value);
|
|
111
126
|
|
|
112
|
-
if (event.currentTarget.value === '') {
|
|
127
|
+
if (event.currentTarget.value === '' && !specifications) {
|
|
113
128
|
setValueInput('');
|
|
114
129
|
setQuery('');
|
|
115
130
|
}
|
|
116
131
|
};
|
|
117
132
|
|
|
118
133
|
const { cadSearch } = useCadSearch();
|
|
134
|
+
|
|
135
|
+
const getPreFilters = async () => {
|
|
136
|
+
getFilters(1000, settings)
|
|
137
|
+
.then(res => {
|
|
138
|
+
setResultFilter(res);
|
|
139
|
+
})
|
|
140
|
+
.catch((e: any) => {
|
|
141
|
+
console.log('err getDataFilterDesktop', e);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
getPreFilters()
|
|
147
|
+
}, []);
|
|
119
148
|
|
|
120
149
|
const handleUpload = (files: File[]) => {
|
|
121
150
|
setValueInput('');
|
|
122
151
|
setQuery('');
|
|
123
152
|
|
|
124
|
-
navigate('/result');
|
|
125
|
-
|
|
126
153
|
if (isCadFile(files[0])) {
|
|
127
154
|
cadSearch({ file: files[0], settings, newSearch: true }).then(res => {});
|
|
128
155
|
|
|
129
156
|
return;
|
|
130
157
|
}
|
|
131
158
|
|
|
159
|
+
setShowLoading(true);
|
|
160
|
+
|
|
132
161
|
singleImageSearch({
|
|
133
162
|
image: files[0],
|
|
134
163
|
settings: window.settings,
|
|
135
164
|
showFeedback: true,
|
|
136
165
|
newSearch: true,
|
|
137
|
-
}).then(() => {
|
|
166
|
+
}).then((singleImageResp) => {
|
|
167
|
+
const specificationPrefilter = singleImageResp.image_analysis?.specification?.prefilter_value || null;
|
|
168
|
+
const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
|
|
169
|
+
if (specificationPrefilter) {
|
|
170
|
+
setRequestImages([]);
|
|
171
|
+
setShowNotMatchedError(false);
|
|
172
|
+
if (hasPrefilter.length) {
|
|
173
|
+
setSpecifications(clone(singleImageResp.image_analysis.specification));
|
|
174
|
+
setNameplateImage(files[0]);
|
|
175
|
+
setPreFilter({[singleImageResp.image_analysis?.specification?.prefilter_value]: true});
|
|
176
|
+
setAlgoliaFilter(`${settings.alogoliaFilterField}:'${singleImageResp.image_analysis?.specification?.prefilter_value}'`);
|
|
177
|
+
|
|
178
|
+
setShowLoading(false);
|
|
179
|
+
navigate('/result');
|
|
180
|
+
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
setNameplateNotificationText(t('We have successfully defined the search criteria', { prefilter_value: specificationPrefilter, preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
183
|
+
}, 1000);
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
setNameplateNotificationText('');
|
|
186
|
+
}, 6000);
|
|
187
|
+
}
|
|
188
|
+
if (!hasPrefilter.length && showPreFilter) {
|
|
189
|
+
setSpecifications(clone({...singleImageResp.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
|
|
190
|
+
navigate('/result');
|
|
191
|
+
setPreFilter({});
|
|
192
|
+
setAlgoliaFilter('');
|
|
193
|
+
setShowLoading(false);
|
|
194
|
+
setShowNotMatchedError(true);
|
|
195
|
+
setTimeout(() => {
|
|
196
|
+
setNameplateNotificationText(t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
197
|
+
}, 1000);
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
setNameplateNotificationText('');
|
|
200
|
+
}, 6000);
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
if (specifications?.is_nameplate) {
|
|
204
|
+
setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
|
|
205
|
+
} else {
|
|
206
|
+
setSpecifications({...specifications, is_nameplate: false});
|
|
207
|
+
}
|
|
208
|
+
setShowLoading(false);
|
|
209
|
+
navigate('/result');
|
|
210
|
+
}
|
|
211
|
+
});
|
|
138
212
|
};
|
|
139
213
|
|
|
140
214
|
return (
|
|
@@ -159,7 +233,6 @@ function TextSearch({
|
|
|
159
233
|
'flex',
|
|
160
234
|
'h-full',
|
|
161
235
|
'justify-between',
|
|
162
|
-
'overflow-hidden',
|
|
163
236
|
'p-0',
|
|
164
237
|
'rounded-3xl',
|
|
165
238
|
'w-full',
|
|
@@ -207,6 +280,7 @@ function TextSearch({
|
|
|
207
280
|
}
|
|
208
281
|
>
|
|
209
282
|
<div
|
|
283
|
+
ref={iconRef}
|
|
210
284
|
className={twMerge(
|
|
211
285
|
'p-2 desktop:p-3',
|
|
212
286
|
location.pathname === '/result' && 'desktop:p-2',
|
|
@@ -228,6 +302,82 @@ function TextSearch({
|
|
|
228
302
|
</div>
|
|
229
303
|
</Tooltip>
|
|
230
304
|
)}
|
|
305
|
+
{nameplateNotificationText && (
|
|
306
|
+
<div
|
|
307
|
+
style={{
|
|
308
|
+
position: 'fixed',
|
|
309
|
+
backgroundColor:
|
|
310
|
+
nameplateNotificationText !== t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() })
|
|
311
|
+
? '#E4E3FF' : '#FFDBB3',
|
|
312
|
+
border: '1px solid',
|
|
313
|
+
borderColor: nameplateNotificationText !== t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }) ? '#3E36DC' : '#FF8800',
|
|
314
|
+
fontSize: 13,
|
|
315
|
+
borderRadius: 24,
|
|
316
|
+
color: '#545987',
|
|
317
|
+
padding: '8px 16px',
|
|
318
|
+
margin: 'auto',
|
|
319
|
+
display: 'flex',
|
|
320
|
+
alignItems: 'center',
|
|
321
|
+
justifyContent: 'center',
|
|
322
|
+
marginLeft: 8,
|
|
323
|
+
zIndex: 999999,
|
|
324
|
+
top: !isMobile ? 60 : 'unset',
|
|
325
|
+
bottom: isMobile ? 76 : 'unset',
|
|
326
|
+
maxWidth: 510,
|
|
327
|
+
width: !isMobile ? 'unset' : '90%',
|
|
328
|
+
left: !isMobile ? 'unset' : 0,
|
|
329
|
+
}}
|
|
330
|
+
>
|
|
331
|
+
<div
|
|
332
|
+
style={{
|
|
333
|
+
position: 'absolute',
|
|
334
|
+
top: !isMobile ? -7 : 'unset',
|
|
335
|
+
bottom: isMobile ? -7 : 'unset',
|
|
336
|
+
left: !isMobile ? '50%' : 30,
|
|
337
|
+
transform: 'translateX(-50%)',
|
|
338
|
+
width: 0,
|
|
339
|
+
height: 0,
|
|
340
|
+
borderLeft: '7px solid transparent',
|
|
341
|
+
borderRight: '7px solid transparent',
|
|
342
|
+
borderTop: isMobile
|
|
343
|
+
? `7px solid ${
|
|
344
|
+
nameplateNotificationText !== t('Extracted details from the nameplate could not be matched',
|
|
345
|
+
{ preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }) ? '#3E36DC' : '#FF8800'
|
|
346
|
+
}`
|
|
347
|
+
: 'unset',
|
|
348
|
+
borderBottom: !isMobile
|
|
349
|
+
? `7px solid ${
|
|
350
|
+
nameplateNotificationText !== t('Extracted details from the nameplate could not be matched',
|
|
351
|
+
{ preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }) ? '#3E36DC' : '#FF8800'
|
|
352
|
+
}`
|
|
353
|
+
: 'unset',
|
|
354
|
+
}}
|
|
355
|
+
/>
|
|
356
|
+
|
|
357
|
+
<div
|
|
358
|
+
style={{
|
|
359
|
+
position: 'absolute',
|
|
360
|
+
top: !isMobile ? -6 : 'unset',
|
|
361
|
+
bottom: isMobile ? -6 : 'unset',
|
|
362
|
+
left: !isMobile ? '50%' : 30,
|
|
363
|
+
transform: 'translateX(-50%)',
|
|
364
|
+
width: 0,
|
|
365
|
+
height: 0,
|
|
366
|
+
borderLeft: '6px solid transparent',
|
|
367
|
+
borderRight: '6px solid transparent',
|
|
368
|
+
borderTop: isMobile
|
|
369
|
+
? `6px solid ${nameplateNotificationText !== t('Extracted details from the nameplate could not be matched',
|
|
370
|
+
{ preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }) ? '#E4E3FF' : '#FFDBB3'}`
|
|
371
|
+
: 'unset',
|
|
372
|
+
borderBottom: !isMobile
|
|
373
|
+
? `6px solid ${nameplateNotificationText !== t('Extracted details from the nameplate could not be matched',
|
|
374
|
+
{ preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }) ? '#E4E3FF' : '#FFDBB3'}`
|
|
375
|
+
: 'unset',
|
|
376
|
+
}}
|
|
377
|
+
/>
|
|
378
|
+
{nameplateNotificationText}
|
|
379
|
+
</div>
|
|
380
|
+
)}
|
|
231
381
|
{!showPreFilter && (
|
|
232
382
|
<div className="p-2 hidden desktop:block">
|
|
233
383
|
<Icon name="search" width={16} height={16} />
|
|
@@ -311,6 +461,7 @@ function TextSearch({
|
|
|
311
461
|
}
|
|
312
462
|
return;
|
|
313
463
|
}
|
|
464
|
+
setSpecifications(null);
|
|
314
465
|
setQuery('');
|
|
315
466
|
setValueInput('');
|
|
316
467
|
navigate('/');
|
|
@@ -356,6 +507,7 @@ function TextSearch({
|
|
|
356
507
|
}
|
|
357
508
|
onClick={e => {
|
|
358
509
|
if (!showDisclaimerDisabled) {
|
|
510
|
+
// disclaimer
|
|
359
511
|
setShowDisclaimer(true);
|
|
360
512
|
} else if (onCameraClick) {
|
|
361
513
|
onCameraClick();
|