@nyris/nyris-webapp 0.3.57 → 0.3.59

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 (94) hide show
  1. package/build/asset-manifest.json +15 -16
  2. package/build/index.html +1 -1
  3. package/build/js/settings.example.js +1 -0
  4. package/build/static/css/main.cb6e2cfd.css +4 -0
  5. package/build/static/css/main.cb6e2cfd.css.map +1 -0
  6. package/build/static/js/main.a1e24447.js +3 -0
  7. package/build/static/js/{main.5143aa56.js.LICENSE.txt → main.a1e24447.js.LICENSE.txt} +55 -0
  8. package/build/static/js/main.a1e24447.js.map +1 -0
  9. package/build/static/media/camera_simple.bff4194954bbb5f4bc33bd99014a93e8.svg +3 -0
  10. package/build/static/media/collpase.50dae91fff891c46b10dfc281344d0ef.svg +6 -0
  11. package/build/static/media/crop.0676ebbbdc1375ed67e32bba890ce941.svg +3 -0
  12. package/build/static/media/{download.8007f7c72e2080a9ffa96fa63d480dcf.svg → download.a8452bc23334e9f8e53fe1225742d216.svg} +1 -1
  13. package/build/static/media/gallery.15d1f3308921480a8c9d96d9a77c9966.svg +3 -0
  14. package/build/static/media/{logout.b544fcd2969edf431a1e998333119834.svg → logout.bab56bd407f25eb34d6eff401a436ce1.svg} +1 -1
  15. package/build/static/media/next-arrow.b13263d05d107ceb5e99bc4fabb41279.svg +3 -0
  16. package/build/static/media/plus.329672cb2feb55345490589e91481b88.svg +3 -0
  17. package/package.json +8 -5
  18. package/public/index.html +0 -3
  19. package/public/js/settings.example.js +1 -0
  20. package/src/Router.tsx +2 -2
  21. package/src/Store/Store.ts +2 -0
  22. package/src/Store/requestStore.ts +70 -0
  23. package/src/Store/resultStore.ts +25 -0
  24. package/src/Store/search/Search.ts +2 -33
  25. package/src/Store/search/search.initialState.ts +1 -4
  26. package/src/Store/search/types.ts +0 -5
  27. package/src/common/assets/icons/arrow_enter.svg +3 -0
  28. package/src/common/assets/icons/camera_simple.svg +3 -0
  29. package/src/common/assets/icons/collpase.svg +6 -0
  30. package/src/common/assets/icons/crop.svg +3 -0
  31. package/src/common/assets/icons/download.svg +1 -1
  32. package/src/common/assets/icons/gallery.svg +3 -0
  33. package/src/common/assets/icons/logout.svg +1 -1
  34. package/src/common/assets/icons/next-arrow.svg +3 -0
  35. package/src/common/assets/icons/plus.svg +3 -0
  36. package/src/components/CadenasWebViewer.tsx +1 -1
  37. package/src/components/DragDropFile.tsx +17 -77
  38. package/src/components/Experience-visual-search/ExperienceVisualSearch.tsx +47 -71
  39. package/src/components/Feedback.tsx +23 -9
  40. package/src/components/GoBackButton.tsx +15 -18
  41. package/src/components/HeaderMobile.tsx +342 -246
  42. package/src/components/ImageCaptureHelpModal.tsx +63 -65
  43. package/src/components/ImagePreview.tsx +564 -0
  44. package/src/components/Inquiry/InquiryBanner.tsx +1 -1
  45. package/src/components/Inquiry/InquiryModal.tsx +4 -7
  46. package/src/components/Layout.tsx +9 -18
  47. package/src/components/MobileLayout.tsx +51 -0
  48. package/src/components/MobilePostFilter.tsx +9 -3
  49. package/src/components/PanelResult/PostFilterAlgolia.tsx +4 -32
  50. package/src/components/PanelResult/expandable-panel.tsx +3 -16
  51. package/src/components/PanelResult/virtual-state-results.ts +17 -22
  52. package/src/components/ProductDetailView.tsx +1 -1
  53. package/src/components/SidePanel.tsx +7 -97
  54. package/src/components/UploadDisclaimer.tsx +85 -0
  55. package/src/components/appMobile.scss +2 -2
  56. package/src/components/common.scss +57 -27
  57. package/src/components/drawer/cameraCustom.tsx +389 -231
  58. package/src/components/icon-label/icon-label.tsx +1 -1
  59. package/src/components/input/inputSearch.tsx +197 -338
  60. package/src/components/pre-filter/index.tsx +70 -72
  61. package/src/components/results/ItemResult.tsx +34 -17
  62. package/src/components/rfq/RfqBanner.tsx +1 -4
  63. package/src/components/rfq/RfqModal.tsx +10 -10
  64. package/src/hooks/useFilteredRegions.ts +1 -1
  65. package/src/hooks/useImageSearch.ts +189 -0
  66. package/src/hooks/useSearchOrRedirect.ts +84 -0
  67. package/src/index.css +4 -0
  68. package/src/page/landingPage/Home.tsx +49 -0
  69. package/src/page/landingPage/{AppMD.tsx → HomeDesktop.tsx} +7 -34
  70. package/src/page/landingPage/{AppMobile.tsx → HomeMobile.tsx} +8 -37
  71. package/src/page/landingPage/common.scss +9 -1
  72. package/src/page/result/index.tsx +118 -232
  73. package/src/services/Feedback.ts +4 -5
  74. package/src/services/image.ts +19 -0
  75. package/src/types.ts +9 -7
  76. package/src/utils.ts +44 -0
  77. package/tailwind.config.js +54 -0
  78. package/build/static/css/main.67965609.css +0 -2
  79. package/build/static/css/main.67965609.css.map +0 -1
  80. package/build/static/js/main.5143aa56.js +0 -3
  81. package/build/static/js/main.5143aa56.js.map +0 -1
  82. package/build/static/media/arrow_down.f417689ce292978a8292a7f00407fdd5.svg +0 -3
  83. package/build/static/media/arrow_left.73d03a534eaf9b99ab196e0fb67da602.svg +0 -3
  84. package/build/static/media/arrow_right.59a4594a3a1657037537dbae1eee0251.svg +0 -3
  85. package/build/static/media/arrow_up.85dbe70bc51ec32c8894a06499330f14.svg +0 -3
  86. package/build/static/media/home.9ffb65a9c0be8fc5a502ba05cf5f719c.svg +0 -3
  87. package/build/static/media/icon_camera_mobile.6772053c4dfef487255649d2a05cc9d4.svg +0 -3
  88. package/build/static/media/reverse_camera.cee0200b151941cc83c182167a85d667.svg +0 -5
  89. package/src/App.tsx +0 -18
  90. package/src/components/AppMobile.tsx +0 -117
  91. package/src/components/FooterMobile.tsx +0 -230
  92. package/src/components/ImagePreviewMobile.tsx +0 -237
  93. /package/build/static/media/{add.2b72cedb98c4c89c954266d2356c166c.svg → add-rounded.2b72cedb98c4c89c954266d2356c166c.svg} +0 -0
  94. /package/src/common/assets/icons/{add.svg → add-rounded.svg} +0 -0
@@ -1,63 +1,88 @@
1
1
  // @ts-nocheck
2
+
3
+ import cx from 'classnames';
4
+
2
5
  import { Drawer } from '@material-ui/core';
3
- import IconButton from '@material-ui/core/IconButton';
4
- import CloseIcon from '@material-ui/icons/Close';
5
- import PhotoLibraryIcon from '@material-ui/icons/PhotoLibrary';
6
- import { RectCoords } from '@nyris/nyris-api';
7
- import ReverseCamera from 'common/assets/icons/reverse_camera.svg';
8
- import { isEmpty } from 'lodash';
9
- import React, { useCallback, useRef, useState } from 'react';
6
+ import { useRef, useState, useEffect } from 'react';
10
7
  import { useHistory } from 'react-router-dom';
11
8
  import Webcam from 'react-webcam';
12
- import { createImage, find, findRegions } from 'services/image';
9
+ import { createImage } from 'services/image';
13
10
  import {
14
11
  onToggleModalItemDetail,
15
- setImageSearchInput,
16
- setRequestImage,
17
- setSearchResults,
18
12
  updateStatusLoading,
19
13
  loadingActionResults,
20
- setRegions,
21
- setSelectedRegion,
22
- setShowFeedback,
23
- setFirstSearchResults,
24
- setFirstSearchImage,
25
- setFirstSearchPrefilters,
26
- setFirstSearchThumbSearchInput
27
14
  } from 'Store/search/Search';
28
15
  import { useAppDispatch, useAppSelector } from 'Store/Store';
29
16
 
17
+ import { ReactComponent as IconInfo } from 'common/assets/icons/info-tooltip.svg';
18
+ import { ReactComponent as CloseIcon } from 'common/assets/icons/close.svg';
19
+ import { ReactComponent as GalleryIcon } from 'common/assets/icons/gallery.svg';
20
+ import { ReactComponent as NextArrowIcon } from 'common/assets/icons/next-arrow.svg';
21
+
22
+ import useRequestStore from 'Store/requestStore';
23
+ import { useImageSearch } from 'hooks/useImageSearch';
24
+ import ImageCaptureHelpModal from 'components/ImageCaptureHelpModal';
25
+ import { createPortal } from 'react-dom';
26
+ import { compressImage } from 'utils';
27
+
30
28
  interface Props {
31
- isToggle: boolean;
32
- onToggleModal?: any;
29
+ show: boolean;
30
+ onClose: any;
31
+ newSearch?: boolean;
33
32
  }
34
33
 
35
34
  const FACING_MODE_USER = 'environment';
36
- const FACING_MODE_ENVIRONMENT = 'user';
37
35
 
38
36
  function CameraCustom(props: Props) {
39
- const { isToggle, onToggleModal } = props;
37
+ const { show: isToggle, onClose: onToggleModal, newSearch } = props;
40
38
  const webcamRef: any = useRef(null);
41
- const [facingMode, setFacingMode] = useState(FACING_MODE_USER);
42
- const [scaleCamera, setScaleCamera] = useState<number>(1);
43
- const stateGlobal = useAppSelector(state => state);
44
- const { search, settings } = stateGlobal;
39
+ const settings = useAppSelector(state => state.settings);
45
40
  const history = useHistory();
46
41
  const dispatch = useAppDispatch();
47
- const { preFilter } = search;
42
+
43
+ const { singleImageSearch, multiImageSearch } = useImageSearch();
44
+
45
+ const { requestImages, setRequestImages, regions } = useRequestStore(
46
+ state => ({
47
+ requestImages: state.requestImages,
48
+ setRequestImages: state.setRequestImages,
49
+ regions: state.regions,
50
+ }),
51
+ );
52
+
53
+ const [capturedImages, setCapturedImages] = useState<HTMLCanvasElement[]>([]);
54
+ const [currentIndex, setCurrentIndex] = useState(0);
55
+ const [imageCaptureHelpModal, setImageCaptureHelpModal] = useState(false);
56
+
57
+ const multiImageUpload = requestImages.length > 0 && !newSearch;
58
+ const canMultiImageSearch = capturedImages.length !== requestImages.length;
48
59
 
49
60
  const videoConstraints = {
50
61
  width: 1080,
51
62
  aspectRatio: 1.11111,
52
63
  };
53
64
 
54
- const handleClick = useCallback(() => {
55
- setFacingMode(prevState =>
56
- prevState === FACING_MODE_USER
57
- ? FACING_MODE_ENVIRONMENT
58
- : FACING_MODE_USER,
59
- );
60
- }, []);
65
+ const addCapturedImage = async (image: any) => {
66
+ const compressedBase64 = await compressImage(image);
67
+ let imageConvert = await createImage(compressedBase64);
68
+ setCapturedImages(state => [...state, imageConvert]);
69
+ };
70
+
71
+ const handleMultiImageSearch = () => {
72
+ setRequestImages(capturedImages);
73
+ dispatch(updateStatusLoading(true));
74
+ dispatch(loadingActionResults());
75
+
76
+ multiImageSearch({
77
+ images: capturedImages,
78
+ regions: regions,
79
+ settings,
80
+ }).then(() => {
81
+ dispatch(updateStatusLoading(false));
82
+ });
83
+
84
+ handleClose();
85
+ };
61
86
 
62
87
  const handlerFindImage = async (image: any) => {
63
88
  dispatch(updateStatusLoading(true));
@@ -65,218 +90,351 @@ function CameraCustom(props: Props) {
65
90
  if (history.location.pathname !== '/result') {
66
91
  history.push('/result');
67
92
  }
68
- let region: RectCoords | undefined;
69
- let imageConvert = await createImage(image);
70
- dispatch(setRequestImage(imageConvert));
71
- dispatch(onToggleModalItemDetail(false));
72
- handlerCloseModal();
73
93
 
74
- try {
75
- if (settings.regions) {
76
- let res = await findRegions(imageConvert, settings);
77
- dispatch(setRegions(res.regions));
78
- region = res.selectedRegion;
79
- dispatch(setSelectedRegion(region));
80
- }
81
- } catch (error) {
82
- } finally {
83
- const preFilterValues = [
84
- {
85
- key: settings.visualSearchFilterKey,
86
- values: Object.keys(preFilter),
87
- },
88
- ];
89
- let filters: any[] = [];
94
+ singleImageSearch({
95
+ image: image,
96
+ settings,
97
+ newSearch,
98
+ showFeedback: true,
99
+ }).then(() => {
100
+ dispatch(updateStatusLoading(false));
101
+ });
90
102
 
91
- find({
92
- image: imageConvert,
93
- settings,
94
- filters: !isEmpty(preFilter) ? preFilterValues : undefined,
95
- region,
96
- })
97
- .then((res: any) => {
98
- res?.results.forEach((item: any) => {
99
- filters.push({
100
- sku: item.sku,
101
- score: item.score,
102
- });
103
- });
104
- const payload = {
105
- ...res,
106
- filters,
107
- };
108
- dispatch(setSearchResults(payload));
109
- dispatch(updateStatusLoading(false));
110
- dispatch(setShowFeedback(true));
111
- // go back
112
- dispatch(setFirstSearchResults(payload));
113
- dispatch(setFirstSearchImage(imageConvert));
114
- dispatch(setFirstSearchPrefilters(preFilter));
115
- dispatch(setFirstSearchThumbSearchInput(image));
116
- })
117
- .catch((e: any) => {
118
- console.log('error input search', e);
119
- dispatch(updateStatusLoading(false));
120
- });
121
- }
103
+ dispatch(onToggleModalItemDetail(false));
104
+ handleClose();
122
105
  };
123
106
 
124
- const handlerCloseModal = () => {
125
- setFacingMode('environment');
126
- setScaleCamera(1);
107
+ const handleClose = () => {
127
108
  onToggleModal();
128
109
  };
129
110
 
130
- return (
131
- <div className="box-camera-custom">
132
- <Drawer
133
- anchor={'bottom'}
134
- open={isToggle}
135
- onClose={handlerCloseModal}
136
- className="modal-togggle-cam"
137
- >
138
- <div className="wrap-camera">
139
- <button
140
- className="btn-close-modal right"
141
- style={{
142
- backgroundColor: '#666666',
143
- }}
144
- onClick={handlerCloseModal}
145
- >
146
- <CloseIcon style={{ fontSize: 20, color: '#fff' }} />
147
- </button>
111
+ useEffect(() => {
112
+ if (newSearch) {
113
+ setCapturedImages([]);
114
+ setCurrentIndex(0);
115
+ } else {
116
+ setCapturedImages([...requestImages]);
117
+ setCurrentIndex(requestImages.length);
118
+ }
119
+ }, [requestImages, newSearch, isToggle]);
148
120
 
149
- <div
150
- style={{
151
- display: 'flex',
152
- justifyContent: 'center',
153
- alignItems: 'center',
154
- overflow: 'hidden',
155
- width: '100%',
156
- }}
157
- className="full-height"
158
- >
159
- <Webcam
160
- audio={false}
161
- width={'100%'}
162
- className="full-height"
163
- imageSmoothing={true}
164
- screenshotFormat="image/jpeg"
165
- forceScreenshotSourceSize={true}
166
- videoConstraints={{
167
- ...videoConstraints,
168
- facingMode,
169
- }}
170
- ref={webcamRef}
171
- style={{
172
- height: '100%',
173
- width: '100%',
174
- objectFit: 'cover',
175
- transform: `scale(${scaleCamera})`,
176
- }}
177
- screenshotQuality={1}
121
+ return (
122
+ <>
123
+ {imageCaptureHelpModal && (
124
+ <>
125
+ {createPortal(
126
+ <>
127
+ <div
128
+ className={
129
+ 'wrap-filter-desktop absolute top-0 flex items-center justify-center bg-black/50 w-screen h-screen z-[9999]'
130
+ }
131
+ >
132
+ <ImageCaptureHelpModal
133
+ handleClose={() => setImageCaptureHelpModal(s => !s)}
134
+ />
135
+ </div>
136
+ </>,
137
+ document.body,
138
+ )}
139
+ </>
140
+ )}
141
+ <div className="box-camera-custom">
142
+ <Drawer
143
+ anchor={'bottom'}
144
+ open={isToggle}
145
+ onClose={() => handleClose()}
146
+ className="modal-togggle-cam !bg-[#2B2C46]"
147
+ >
148
+ <div className="h-full flex flex-col overflow-hidden">
149
+ <div className="min-h-[60px] bg-[#2B2C46] flex justify-end">
150
+ <div
151
+ className="h-[60px] w-[60px] flex justify-center items-center"
152
+ onClick={() => {
153
+ setImageCaptureHelpModal(s => !s);
154
+ }}
155
+ >
156
+ <IconInfo className="text-white w-4 h-4" />
157
+ </div>
158
+ <div
159
+ className="h-[60px] w-[60px] flex justify-center items-center"
160
+ onClick={() => handleClose()}
161
+ >
162
+ <CloseIcon className="text-white w-4 h-4" />
163
+ </div>
164
+ </div>
165
+ <div
166
+ className={cx([
167
+ 'flex',
168
+ 'justify-center',
169
+ 'items-center',
170
+ 'h-full',
171
+ 'overflow-hidden',
172
+ 'px-2',
173
+ 'rounded-lg',
174
+ ])}
178
175
  >
179
- {({ getScreenshot }: any) => (
180
- <button
181
- onClick={() => {
182
- const imageSrc = getScreenshot();
183
- handlerFindImage(imageSrc);
184
- dispatch(setImageSearchInput(imageSrc));
176
+ <div className="wrap-camera h-full w-full !bg-[#55566B] rounded-lg">
177
+ <div
178
+ style={{
179
+ display: 'flex',
180
+ justifyContent: 'center',
181
+ alignItems: 'center',
182
+ overflow: 'hidden',
183
+ width: '100%',
185
184
  }}
186
- className="btn-capture-camera"
185
+ className="h-full rounded-lg"
187
186
  >
188
- <svg
189
- width="63"
190
- height="63"
191
- viewBox="0 0 63 63"
192
- fill="none"
193
- xmlns="http://www.w3.org/2000/svg"
187
+ {currentIndex < capturedImages.length && (
188
+ <img
189
+ className="h-full object-contain"
190
+ src={capturedImages[currentIndex].toDataURL()}
191
+ alt=""
192
+ />
193
+ )}
194
+ <Webcam
195
+ audio={false}
196
+ width={'100%'}
197
+ className="rounded-lg"
198
+ imageSmoothing={true}
199
+ screenshotFormat="image/jpeg"
200
+ forceScreenshotSourceSize={true}
201
+ videoConstraints={{
202
+ ...videoConstraints,
203
+ facingMode: FACING_MODE_USER,
204
+ }}
205
+ ref={webcamRef}
206
+ style={{
207
+ height: '100%',
208
+ width: '100%',
209
+ objectFit: 'cover',
210
+ transform: `scale(${1})`,
211
+ display:
212
+ currentIndex < capturedImages.length ? 'none' : '',
213
+ }}
214
+ screenshotQuality={1}
194
215
  >
195
- <circle cx="31.5" cy="31.5" r="31.5" fill="white" />
196
- </svg>
197
- </button>
198
- )}
199
- </Webcam>
200
- </div>
216
+ {({ getScreenshot }: any) => (
217
+ <div
218
+ className={cx([
219
+ 'absolute',
220
+ 'left-0',
221
+ 'right-0',
222
+ 'mx-auto',
223
+ 'bottom-8',
224
+ 'items-center',
225
+ 'justify-center',
226
+ 'gap-x-8',
227
+ 'mr-16',
228
+ currentIndex < capturedImages.length
229
+ ? 'hidden'
230
+ : 'flex',
231
+ ])}
232
+ >
233
+ <div>
234
+ <input
235
+ id="icon-button-file"
236
+ type="file"
237
+ style={{ display: 'none' }}
238
+ onChange={(fs: any) => {
239
+ const file = fs.target?.files[0];
240
+ if (!file) return;
201
241
 
202
- <button className="btn-switch-camera" onClick={handleClick}>
203
- <img src={ReverseCamera} alt="" width={52} height={52} />
204
- </button>
242
+ if (multiImageUpload) {
243
+ setCurrentIndex(state =>
244
+ Math.min(state + 1, 2),
245
+ );
205
246
 
206
- <div
207
- className="box-scale-camera"
208
- style={{
209
- backgroundColor: settings.theme?.secondaryColor,
210
- }}
211
- >
212
- <button
213
- className={`${scaleCamera === 1 && 'active'}`}
214
- style={{
215
- backgroundColor: scaleCamera === 1 && 'active' ? 'white' : '',
216
- color: scaleCamera === 1 && 'active' ? 'black' : 'white',
217
- }}
218
- onClick={() => setScaleCamera(1)}
219
- >
220
- 1
221
- </button>
222
- <button
223
- className={`${scaleCamera === 1.5 && 'active'}`}
224
- style={{
225
- backgroundColor: scaleCamera === 1.5 && 'active' ? 'white' : '',
226
- color: scaleCamera === 1.5 && 'active' ? 'black' : 'white',
227
- }}
228
- onClick={() => setScaleCamera(1.5)}
229
- >
230
- 1.5
231
- </button>
232
- <button
233
- className={`${scaleCamera === 2 && 'active'}`}
234
- style={{
235
- backgroundColor: scaleCamera === 2 && 'active' ? 'white' : '',
236
- color: scaleCamera === 2 && 'active' ? 'black' : 'white',
237
- }}
238
- onClick={() => setScaleCamera(2)}
239
- >
240
- 2
241
- </button>
242
- </div>
243
- <div className="wrap-box-input-mobile custom-library">
244
- <input
245
- id="icon-button-file"
246
- type="file"
247
- style={{ display: 'none' }}
248
- onChange={(fs: any) => {
249
- const file = fs.target?.files[0];
250
- if (!file) return;
251
- dispatch(setImageSearchInput(URL.createObjectURL(file)));
252
- handlerFindImage(file);
253
- }}
254
- accept="image/jpeg,image/png,image/webp"
255
- onClick={event => {
256
- // @ts-ignore
257
- event.target.value = '';
258
- }}
259
- />
260
- <label htmlFor="icon-button-file">
261
- <IconButton
262
- color="primary"
263
- aria-label="upload picture"
264
- component="span"
265
- style={{
266
- width: 32,
267
- height: 32,
268
- borderRadius: '100%',
269
- padding: 7,
270
- backgroundColor: '#F3F3F5',
271
- }}
272
- >
273
- <PhotoLibraryIcon style={{ fontSize: 20, color: 'red' }} />
274
- </IconButton>
275
- </label>
247
+ addCapturedImage(file);
248
+ } else {
249
+ handlerFindImage(file);
250
+ }
251
+ }}
252
+ accept="image/jpeg,image/png,image/webp"
253
+ onClick={event => {
254
+ // @ts-ignore
255
+ event.target.value = '';
256
+ }}
257
+ />
258
+ <label htmlFor="icon-button-file">
259
+ <div className="w-12 h-12 bg-[#615e669f] rounded-full border-2 border-solid border-white flex justify-center items-center">
260
+ <GalleryIcon className="text-white w-4 h-4" />
261
+ </div>
262
+ </label>
263
+ </div>
264
+
265
+ <button
266
+ onClick={() => {
267
+ const imageSrc = getScreenshot();
268
+ if (multiImageUpload) {
269
+ addCapturedImage(imageSrc);
270
+ setCurrentIndex(state => Math.min(state + 1, 2));
271
+ } else {
272
+ handlerFindImage(imageSrc);
273
+ }
274
+ }}
275
+ className={cx([
276
+ 'w-fit',
277
+ 'bg-transparent',
278
+ 'border',
279
+ 'border-white',
280
+ 'rounded-full',
281
+ 'flex',
282
+ 'justify-center',
283
+ 'items-center',
284
+ 'p-0.5',
285
+ ])}
286
+ >
287
+ <svg
288
+ width="63"
289
+ height="63"
290
+ viewBox="0 0 63 63"
291
+ fill="none"
292
+ xmlns="http://www.w3.org/2000/svg"
293
+ >
294
+ <circle cx="31.5" cy="31.5" r="31.5" fill="white" />
295
+ </svg>
296
+ </button>
297
+ </div>
298
+ )}
299
+ </Webcam>
300
+ </div>
301
+ </div>
302
+ </div>
303
+
304
+ {capturedImages.length === 0 && (
305
+ <div
306
+ className={cx([
307
+ 'min-h-[60px]',
308
+ 'bg-[#2B2C46]',
309
+ 'flex',
310
+ 'justify-end',
311
+ ])}
312
+ />
313
+ )}
314
+
315
+ {capturedImages.length > 0 && settings.multiImageSearch && (
316
+ <>
317
+ <div
318
+ className={cx([
319
+ 'min-h-[106px]',
320
+ 'bg-primary',
321
+ 'flex',
322
+ 'justify-center',
323
+ 'items-center',
324
+ 'gap-x-1',
325
+ ])}
326
+ >
327
+ {capturedImages?.map((image, index) => {
328
+ return (
329
+ <div
330
+ key={index}
331
+ className={cx([
332
+ 'rounded-md',
333
+ 'p-1.5',
334
+ currentIndex === index
335
+ ? ' bg-[#3E36DC]'
336
+ : 'bg-transparent',
337
+ ])}
338
+ >
339
+ <img
340
+ className={cx([
341
+ 'w-[70px]',
342
+ 'h-[70px]',
343
+ 'rounded-md',
344
+ 'object-cover',
345
+ ])}
346
+ src={image.toDataURL()}
347
+ alt=""
348
+ onClick={() => {
349
+ setCurrentIndex(index);
350
+ }}
351
+ />
352
+ </div>
353
+ );
354
+ })}
355
+
356
+ {[...Array(3 - capturedImages.length)]?.map((val, index) => {
357
+ return (
358
+ <div
359
+ key={index}
360
+ className={cx([
361
+ 'rounded-md',
362
+ 'p-1.5',
363
+ currentIndex === index + capturedImages.length
364
+ ? ' bg-[#3E36DC]'
365
+ : 'bg-transparent',
366
+ ])}
367
+ >
368
+ <div
369
+ className={cx([
370
+ 'w-[70px]',
371
+ 'h-[70px]',
372
+ 'flex',
373
+ 'justify-center',
374
+ 'items-center',
375
+ 'rounded-md',
376
+ currentIndex === index + capturedImages.length
377
+ ? 'bg-primary'
378
+ : 'border border-[#AAABB5] border-dashed bg-[#55566B]',
379
+ ])}
380
+ key={index}
381
+ onClick={() => {
382
+ setCurrentIndex(index + capturedImages.length);
383
+ }}
384
+ ></div>
385
+ </div>
386
+ );
387
+ })}
388
+ </div>
389
+ <div className="w-full flex justify-center pb-6 bg-primary">
390
+ <div
391
+ className={cx([
392
+ '',
393
+ 'h-11',
394
+ 'w-full',
395
+ 'px-7',
396
+ 'max-w-[351px]',
397
+ 'flex',
398
+ 'justify-center',
399
+ 'items-center',
400
+ 'gap-x-4',
401
+ 'rounded-3xl',
402
+ canMultiImageSearch
403
+ ? 'bg-secondary drop-shadow-md'
404
+ : 'bg-primary',
405
+ ])}
406
+ onClick={() => {
407
+ if (canMultiImageSearch) {
408
+ handleMultiImageSearch();
409
+ }
410
+ }}
411
+ >
412
+ <div
413
+ className={cx([
414
+ 'text-base',
415
+ 'text-[#55566B]',
416
+ canMultiImageSearch ? 'text-white' : 'text-[#55566B]',
417
+ ])}
418
+ >
419
+ Multi-Image Search for better matches
420
+ </div>
421
+ <NextArrowIcon
422
+ className={cx([
423
+ 'text-[#55566B]',
424
+ canMultiImageSearch ? 'text-white' : 'text-[#55566B]',
425
+ ])}
426
+ />
427
+ </div>
428
+ </div>
429
+ </>
430
+ )}
276
431
  </div>
277
- </div>
278
- </Drawer>
279
- </div>
432
+ </Drawer>
433
+ </div>
434
+ {/* {!imageCaptureHelpModal && (
435
+
436
+ )} */}
437
+ </>
280
438
  );
281
439
  }
282
440