@nyris/nyris-webapp 0.2.4 → 0.3.1

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 (199) hide show
  1. package/build/asset-manifest.json +32 -18
  2. package/build/index.html +1 -1
  3. package/build/js/test.js +62 -0
  4. package/build/{precache-manifest.211a3df6baece8bbe3672765faa0d629.js → precache-manifest.3e7aa489925304848e8f04e3015d8567.js} +89 -13
  5. package/build/service-worker.js +1 -1
  6. package/build/static/css/2.8285176a.chunk.css +2 -0
  7. package/build/static/css/2.8285176a.chunk.css.map +1 -0
  8. package/build/static/css/main.b731b101.chunk.css +2 -0
  9. package/build/static/css/main.b731b101.chunk.css.map +1 -0
  10. package/build/static/js/2.8297cb74.chunk.js +3 -0
  11. package/build/static/js/2.8297cb74.chunk.js.LICENSE.txt +133 -0
  12. package/build/static/js/2.8297cb74.chunk.js.map +1 -0
  13. package/build/static/js/main.05909665.chunk.js +2 -0
  14. package/build/static/js/main.05909665.chunk.js.map +1 -0
  15. package/build/static/js/{runtime-main.f5553a9b.js → runtime-main.b418ff16.js} +1 -1
  16. package/build/static/js/{runtime-main.f5553a9b.js.map → runtime-main.b418ff16.js.map} +1 -1
  17. package/build/static/media/Fill.37094b44.svg +3 -0
  18. package/build/static/media/Montserrat-Bold.5a052e98.otf +0 -0
  19. package/build/static/media/Montserrat-Light.21789e89.otf +0 -0
  20. package/build/static/media/Montserrat-Medium.a53e0373.otf +0 -0
  21. package/build/static/media/Montserrat-Regular.71cdc681.otf +0 -0
  22. package/build/static/media/Montserrat-SemiBold.f613d915.otf +0 -0
  23. package/build/static/media/Rectangle.4dd8b747.png +0 -0
  24. package/build/static/media/admin.9529c7f6.svg +3 -0
  25. package/build/static/media/bg-support-page.6ac55268.svg +9 -0
  26. package/build/static/media/book_mark.8e294c0b.svg +3 -0
  27. package/build/static/media/icon_dislike.94607ca6.svg +3 -0
  28. package/build/static/media/icon_like.a4fb1b18.svg +3 -0
  29. package/build/static/media/icon_modal_image.3068d0ea.svg +21 -0
  30. package/build/static/media/icon_search_image.c2c728c0.svg +3 -0
  31. package/build/static/media/nyris_logo.22d8f250.svg +3 -0
  32. package/build/static/media/reload_icon.4b579a74.svg +3 -0
  33. package/build/static/media/save_search.bebaeebf.svg +3 -0
  34. package/build/static/media/support.289c3a3c.svg +3 -0
  35. package/build/static/media/translate_icon.f0492297.svg +3 -0
  36. package/package.json +31 -6
  37. package/public/js/test.js +62 -0
  38. package/src/App.css +27 -11
  39. package/src/App.tsx +19 -217
  40. package/src/Router.tsx +97 -0
  41. package/src/Store/Auth.ts +44 -0
  42. package/src/Store/Nyris.ts +77 -0
  43. package/src/Store/Search.ts +269 -0
  44. package/src/Store/Store.ts +46 -0
  45. package/src/Store/common.d.ts +10 -0
  46. package/src/{epics → Store/epics}/feedback.ts +0 -0
  47. package/src/{epics → Store/epics}/types.ts +1 -1
  48. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Bold.otf +0 -0
  49. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Light.otf +0 -0
  50. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Medium.otf +0 -0
  51. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Regular.otf +0 -0
  52. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-SemiBold.otf +0 -0
  53. package/src/{fonts → common/assets/fonts}/roboto-bold-webfont.woff +0 -0
  54. package/src/{fonts → common/assets/fonts}/roboto-bold-webfont.woff2 +0 -0
  55. package/src/{fonts → common/assets/fonts}/roboto-italic-webfont.woff +0 -0
  56. package/src/{fonts → common/assets/fonts}/roboto-italic-webfont.woff2 +0 -0
  57. package/src/{fonts → common/assets/fonts}/roboto-regular-webfont.woff +0 -0
  58. package/src/{fonts → common/assets/fonts}/roboto-regular-webfont.woff2 +0 -0
  59. package/src/{fonts → common/assets/fonts}/robotocondensed-bold-webfont.woff +0 -0
  60. package/src/{fonts → common/assets/fonts}/robotocondensed-bold-webfont.woff2 +0 -0
  61. package/src/{fonts → common/assets/fonts}/robotocondensed-bolditalic-webfont.woff +0 -0
  62. package/src/{fonts → common/assets/fonts}/robotocondensed-bolditalic-webfont.woff2 +0 -0
  63. package/src/common/assets/icons/Fill.png +0 -0
  64. package/src/common/assets/icons/Fill.svg +3 -0
  65. package/src/common/assets/icons/Icon_wechat.png +0 -0
  66. package/src/common/assets/icons/Icon_whatsapp.png +0 -0
  67. package/src/common/assets/icons/admin.png +0 -0
  68. package/src/common/assets/icons/admin.svg +3 -0
  69. package/src/common/assets/icons/book_mark.png +0 -0
  70. package/src/common/assets/icons/book_mark.svg +3 -0
  71. package/src/common/assets/icons/icon_barcode.png +0 -0
  72. package/src/common/assets/icons/icon_camera.png +0 -0
  73. package/src/common/assets/icons/icon_dislike.svg +3 -0
  74. package/src/common/assets/icons/icon_disslike.png +0 -0
  75. package/src/common/assets/icons/icon_email.png +0 -0
  76. package/src/common/assets/icons/icon_like.png +0 -0
  77. package/src/common/assets/icons/icon_like.svg +3 -0
  78. package/src/common/assets/icons/icon_modal_image.png +0 -0
  79. package/src/common/assets/icons/icon_modal_image.svg +21 -0
  80. package/src/common/assets/icons/icon_picture.png +0 -0
  81. package/src/common/assets/icons/icon_search_image.png +0 -0
  82. package/src/common/assets/icons/icon_search_image.svg +3 -0
  83. package/src/common/assets/icons/nyris_logo.svg +3 -0
  84. package/src/common/assets/icons/reload_icon.png +0 -0
  85. package/src/common/assets/icons/reload_icon.svg +3 -0
  86. package/src/common/assets/icons/save_search.png +0 -0
  87. package/src/common/assets/icons/save_search.svg +3 -0
  88. package/src/common/assets/icons/setting_search_icon.png +0 -0
  89. package/src/common/assets/icons/support.png +0 -0
  90. package/src/common/assets/icons/support.svg +3 -0
  91. package/src/common/assets/icons/translate_icon.png +0 -0
  92. package/src/common/assets/icons/translate_icon.svg +3 -0
  93. package/src/common/assets/icons/view_off.png +0 -0
  94. package/src/common/assets/images/Rectangle.png +0 -0
  95. package/src/common/assets/images/bg-support-page.svg +9 -0
  96. package/src/{images → common/assets/images}/fav/android-icon-192x192.png +0 -0
  97. package/src/{images → common/assets/images}/fav/apple-icon-114x114.png +0 -0
  98. package/src/{images → common/assets/images}/fav/apple-icon-120x120.png +0 -0
  99. package/src/{images → common/assets/images}/fav/apple-icon-144x144.png +0 -0
  100. package/src/{images → common/assets/images}/fav/apple-icon-152x152.png +0 -0
  101. package/src/{images → common/assets/images}/fav/apple-icon-180x180.png +0 -0
  102. package/src/{images → common/assets/images}/fav/apple-icon-57x57.png +0 -0
  103. package/src/{images → common/assets/images}/fav/apple-icon-60x60.png +0 -0
  104. package/src/{images → common/assets/images}/fav/apple-icon-72x72.png +0 -0
  105. package/src/{images → common/assets/images}/fav/apple-icon-76x76.png +0 -0
  106. package/src/{images → common/assets/images}/fav/browserconfig.xml +0 -0
  107. package/src/{images → common/assets/images}/fav/favicon-16x16.png +0 -0
  108. package/src/{images → common/assets/images}/fav/favicon-32x32.png +0 -0
  109. package/src/{images → common/assets/images}/fav/favicon-96x96.png +0 -0
  110. package/src/{images → common/assets/images}/fav/manifest.json +0 -0
  111. package/src/{images → common/assets/images}/ic_cam.png +0 -0
  112. package/src/{images → common/assets/images}/ic_cam.svg +0 -0
  113. package/src/{images → common/assets/images}/ic_cam_large.png +0 -0
  114. package/src/{images → common/assets/images}/ic_cam_large.svg +0 -0
  115. package/src/{images → common/assets/images}/ic_cam_large_noimage.png +0 -0
  116. package/src/{images → common/assets/images}/ic_close_feedback.png +0 -0
  117. package/src/{images → common/assets/images}/ic_close_feedback.svg +0 -0
  118. package/src/{images → common/assets/images}/ic_shopNow.png +0 -0
  119. package/src/{images → common/assets/images}/ic_shopNow.svg +0 -0
  120. package/src/{images → common/assets/images}/ic_shopNowLight.png +0 -0
  121. package/src/{images → common/assets/images}/ic_shopNowLight.svg +0 -0
  122. package/src/common/assets/images/image_test.png +0 -0
  123. package/src/{images → common/assets/images}/nyris_logo.png +0 -0
  124. package/src/{images → common/assets/images}/rewe.svg +0 -0
  125. package/src/{images → common/assets/images}/sectionTransBack.png +0 -0
  126. package/src/{images → common/assets/images}/sectionTransBack.svg +0 -0
  127. package/src/{images → common/assets/images}/sectionTransTop.png +0 -0
  128. package/src/{images → common/assets/images}/sectionTransTop.svg +0 -0
  129. package/src/components/DetailItem.tsx +175 -0
  130. package/src/components/DragDropFile.tsx +188 -0
  131. package/src/components/ExampleImages.tsx +32 -17
  132. package/src/components/Feedback.tsx +87 -48
  133. package/src/components/FilterComponent.tsx +47 -0
  134. package/src/components/Footer.tsx +29 -0
  135. package/src/components/FooterMD.tsx +54 -0
  136. package/src/components/FooterNewVersion.tsx +12 -0
  137. package/src/components/FooterResult.tsx +47 -0
  138. package/src/components/Header.tsx +35 -0
  139. package/src/components/HeaderMd.tsx +39 -0
  140. package/src/components/HeaderNewVersion.tsx +92 -0
  141. package/src/components/Layout.tsx +46 -0
  142. package/src/components/LoadingScreen/index.tsx +42 -0
  143. package/src/components/Navigation.tsx +34 -0
  144. package/src/components/Panigation/Pagination.tsx +140 -0
  145. package/src/components/Panigation/cx.js +3 -0
  146. package/src/components/Panigation/isModifierClick.js +10 -0
  147. package/src/components/Result.tsx +186 -113
  148. package/src/components/Saved/AllItem.tsx +32 -0
  149. package/src/components/Saved/Category.tsx +16 -0
  150. package/src/components/carousel/DefaultCarousel.tsx +48 -0
  151. package/src/components/common.d.ts +9 -0
  152. package/src/components/common.scss +54 -0
  153. package/src/components/default-select.tsx +45 -0
  154. package/src/components/hitItem/hits.tsx +50 -0
  155. package/src/components/hitItem/infinitiHits.tsx +33 -0
  156. package/src/components/input/inputSearch.tsx +77 -0
  157. package/src/components/modal/DefaultModal.tsx +28 -0
  158. package/src/components/preview/preview.tsx +433 -0
  159. package/src/components/results/ItemResult.tsx +155 -0
  160. package/src/components/search/ListSearch.tsx +209 -0
  161. package/src/defaults.ts +4 -3
  162. package/src/index.css +577 -306
  163. package/src/index.tsx +39 -186
  164. package/src/modules/LandingPage/common.scss +1288 -0
  165. package/src/modules/LandingPage/indexApp.tsx +474 -0
  166. package/src/modules/LandingPage/indexAppMD.tsx +494 -0
  167. package/src/modules/LandingPage/indexNewVersion.tsx +118 -0
  168. package/src/page/Auth/login.tsx +7 -0
  169. package/src/page/Exception/404.tsx +11 -0
  170. package/src/page/History/index.tsx +76 -0
  171. package/src/page/Profile/index.tsx +87 -0
  172. package/src/page/Saved/MockData.ts +223 -0
  173. package/src/page/Saved/index.tsx +166 -0
  174. package/src/page/Support/index.tsx +160 -0
  175. package/src/page/result/MockData.ts +36 -0
  176. package/src/page/result/index.tsx +482 -0
  177. package/src/services/Feedback.ts +65 -0
  178. package/src/services/findByImage.ts +24 -0
  179. package/src/services/findRegionsCustom.ts +212 -0
  180. package/src/services/image.ts +110 -0
  181. package/src/services/nyris.ts +123 -0
  182. package/src/services/session.ts +20 -0
  183. package/src/services/types.ts +96 -0
  184. package/src/types.ts +43 -3
  185. package/tsconfig.json +3 -8
  186. package/build/static/css/2.43a1c8b7.chunk.css +0 -2
  187. package/build/static/css/2.43a1c8b7.chunk.css.map +0 -1
  188. package/build/static/css/main.f6ed5f12.chunk.css +0 -2
  189. package/build/static/css/main.f6ed5f12.chunk.css.map +0 -1
  190. package/build/static/js/2.b56c1bca.chunk.js +0 -3
  191. package/build/static/js/2.b56c1bca.chunk.js.LICENSE.txt +0 -79
  192. package/build/static/js/2.b56c1bca.chunk.js.map +0 -1
  193. package/build/static/js/main.a9ea9ea5.chunk.js +0 -2
  194. package/build/static/js/main.a9ea9ea5.chunk.js.map +0 -1
  195. package/src/AppMD.tsx +0 -320
  196. package/src/actions/nyrisAppActions.ts +0 -76
  197. package/src/actions/searchActions.ts +0 -135
  198. package/src/epics/index.ts +0 -133
  199. package/src/epics/search.ts +0 -114
@@ -0,0 +1,474 @@
1
+ import "App.css";
2
+ import React, { useCallback, useEffect, useState } from "react";
3
+ import Result from "components/Result";
4
+ import ExampleImages from "components/ExampleImages";
5
+ import CategoryFilter from "components/CategoryFilter";
6
+ import PredictedCategories from "components/PredictedCategories";
7
+ import Codes from "components/Codes";
8
+ import {
9
+ Code,
10
+ CategoryPrediction,
11
+ RectCoords,
12
+ Region,
13
+ cadExtensions,
14
+ isCadFile,
15
+ isImageFile,
16
+ ImageSearchOptions,
17
+ } from "@nyris/nyris-api";
18
+ import { useDropzone } from "react-dropzone";
19
+ import classNames from "classnames";
20
+ import { Animate, NodeGroup } from "react-move";
21
+ import { AppSettings, MDSettings, CanvasWithId } from "types";
22
+ import {
23
+ makeFileHandler,
24
+ Capture,
25
+ Preview,
26
+ } from "@nyris/nyris-react-components";
27
+ import { Snackbar } from "@material-ui/core";
28
+ import MuiAlert, { AlertProps } from "@material-ui/lab/Alert";
29
+
30
+ import { useAppDispatch, useAppSelector } from "Store/Store";
31
+ import {
32
+ loadCadFileLoad,
33
+ loadFile,
34
+ loadFileSelectRegion,
35
+ loadingActionRegions,
36
+ loadingActionResults,
37
+ searchFileImageNonRegion,
38
+ selectionChanged,
39
+ } from "Store/Search";
40
+ import {
41
+ NyrisAppPart,
42
+ NyrisFeedbackState,
43
+ showCamera,
44
+ showFeedback,
45
+ showResults,
46
+ showStart,
47
+ } from "Store/Nyris";
48
+ import { serviceImage, serviceImageNonRegion } from "services/image";
49
+ import { findByImage } from "services/findByImage";
50
+ import { debounce, isEmpty } from "lodash";
51
+ import { feedbackClickEpic } from "services/Feedback";
52
+ export interface AppHandlers {
53
+ onExampleImageClick: (url: string) => void;
54
+ onImageClick: (position: number, url: string) => void;
55
+ onLinkClick: (position: number, url: string) => void;
56
+ onFileDropped: (file: File) => void;
57
+ onCaptureComplete: (image: HTMLCanvasElement) => void;
58
+ onCaptureCanceled: () => void;
59
+ onSelectFile: (f: File) => void;
60
+ onCameraClick: () => void;
61
+ onShowStart: () => void;
62
+ onSelectionChange: (r: RectCoords) => void;
63
+ onPositiveFeedback: () => void;
64
+ onNegativeFeedback: () => void;
65
+ onCloseFeedback: () => void;
66
+ }
67
+
68
+ export interface AppProps {
69
+ search: {
70
+ results: any[];
71
+ requestId?: string;
72
+ duration?: number;
73
+ categoryPredictions: CategoryPrediction[];
74
+ codes: Code[];
75
+ filterOptions: string[];
76
+ errorMessage?: string;
77
+ regions: Region[];
78
+ previewSelection: RectCoords;
79
+ toastErrorMessage?: string;
80
+ };
81
+ previewImage?: CanvasWithId;
82
+ settings: AppSettings;
83
+ loading: boolean;
84
+ showPart: NyrisAppPart;
85
+ feedbackState: NyrisFeedbackState;
86
+ handlers: AppHandlers;
87
+ mdSettings: MDSettings;
88
+ }
89
+
90
+ function Alert(props: AlertProps) {
91
+ return <MuiAlert elevation={6} variant="filled" {...props} />;
92
+ }
93
+
94
+ const LandingPageApp = () => {
95
+ const dispatch = useAppDispatch();
96
+ const searchState = useAppSelector((state) => state);
97
+ const [toastOpen, setToastOpen] = useState(false);
98
+ const [rectCoords, setRectCoords] = useState<any>(undefined);
99
+ const { settings, search, nyris } = searchState;
100
+ const {
101
+ errorMessage,
102
+ results,
103
+ requestId,
104
+ fetchingRegions,
105
+ fetchingResults,
106
+ requestImage,
107
+ regions,
108
+ selectedRegion,
109
+ categoryPredictions,
110
+ codes,
111
+ filterOptions,
112
+ duration,
113
+ } = search;
114
+ const { showPart } = nyris;
115
+
116
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
117
+ onDrop: (fs: File[]) => {
118
+ // console.log("fsssssssss", fs);
119
+ serviceImage(fs[0], searchState).then((res) => {
120
+ dispatch(loadFile(res));
121
+ return dispatch(showFeedback(""));
122
+ });
123
+ // return dispatch(loadFile(fs[0]));
124
+ },
125
+ });
126
+ const minPreviewHeight = 400;
127
+ const halfOfTheScreenHeight = Math.floor(window.innerHeight * 0.45);
128
+ const maxPreviewHeight = Math.max(minPreviewHeight, halfOfTheScreenHeight);
129
+
130
+ useEffect(() => {
131
+ if (isEmpty(rectCoords)) {
132
+ return;
133
+ }
134
+ onSearchOffersForImage(rectCoords);
135
+ // eslint-disable-next-line react-hooks/exhaustive-deps
136
+ }, [rectCoords]);
137
+
138
+ const acceptTypes = ["image/*"]
139
+ .concat(settings.cadSearch ? cadExtensions : [])
140
+ .join(",");
141
+
142
+ useEffect(() => {
143
+ if (errorMessage !== "") {
144
+ setToastOpen(true);
145
+ }
146
+ }, [errorMessage]);
147
+
148
+ function scrollTop() {
149
+ // TODO might require polyfill for ios and edge
150
+ window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
151
+ }
152
+
153
+ const onShowStart = () => {
154
+ dispatch(showStart(""));
155
+ scrollTop();
156
+ };
157
+
158
+ const onLinkClick = (_position: number, url: string) => {
159
+ feedbackClickEpic(searchState, _position);
160
+ if (url) {
161
+ window.open(url);
162
+ }
163
+ };
164
+
165
+ const isCheckImageFile = (file: any) => {
166
+ dispatch(showResults(""));
167
+ dispatch(loadingActionResults(""));
168
+ dispatch(showFeedback(""));
169
+ if (isImageFile(file) || typeof file === "string") {
170
+ return serviceImage(file, searchState).then((res) => {
171
+ return dispatch(loadFile(res));
172
+ });
173
+ }
174
+ if (isCadFile(file)) {
175
+ return dispatch(loadCadFileLoad(file));
176
+ }
177
+ };
178
+
179
+ const getUrlToCanvasFile = (url: string, position?: number) => {
180
+ dispatch(showResults(""));
181
+ dispatch(loadingActionResults(""));
182
+ if (position) {
183
+ feedbackClickEpic(searchState, position);
184
+ }
185
+
186
+ if (settings.regions) {
187
+ serviceImage(url, searchState).then((res) => {
188
+ dispatch(loadFile(res));
189
+ return dispatch(showFeedback(""));
190
+ });
191
+ } else {
192
+ serviceImageNonRegion(url, searchState, rectCoords).then((res) => {
193
+ dispatch(searchFileImageNonRegion(res));
194
+ });
195
+ }
196
+ };
197
+
198
+ const handlerRectCoords = debounce((value) => {
199
+ return setRectCoords(value);
200
+ }, 1200);
201
+
202
+ const debounceRectCoords = useCallback(
203
+ (value) => handlerRectCoords(value),
204
+ // eslint-disable-next-line react-hooks/exhaustive-deps
205
+ []
206
+ );
207
+
208
+ const onSearchOffersForImage = (r: RectCoords) => {
209
+ const { canvas }: any = requestImage;
210
+ let options: ImageSearchOptions = {
211
+ cropRect: r,
212
+ };
213
+ dispatch(loadingActionRegions(""));
214
+ return findByImage(canvas, options, settings).then((res) => {
215
+ dispatch(loadFileSelectRegion(res));
216
+ return dispatch(showFeedback(""));
217
+ });
218
+ };
219
+
220
+
221
+ return (
222
+ <div>
223
+ {showPart === "camera" && (
224
+ <Capture
225
+ onCaptureComplete={(image: HTMLCanvasElement) => {
226
+ return isCheckImageFile(image);
227
+ }}
228
+ onCaptureCanceled={() => dispatch(showStart)}
229
+ useAppText="Use default camera app"
230
+ />
231
+ )}
232
+ <div
233
+ className={classNames("headSection", {
234
+ hidden: showPart === "results",
235
+ })}
236
+ id="headSection"
237
+ >
238
+ <div
239
+ {...getRootProps({
240
+ onClick: (e) => {
241
+ e.stopPropagation();
242
+ },
243
+ })}
244
+ className={classNames("wrapper", "dragAndDropActionArea", {
245
+ fileIsHover: isDragActive,
246
+ })}
247
+ >
248
+ <div className="contentWrap">
249
+ <section className="uploadImage">
250
+ <input
251
+ type="button"
252
+ name="file"
253
+ id="capture"
254
+ className="inputfile"
255
+ accept="image/*"
256
+ capture="environment"
257
+ onClick={() => dispatch(showCamera)}
258
+ />
259
+ <input
260
+ type="file"
261
+ name="file"
262
+ id="capture_file"
263
+ className="inputfile"
264
+ accept={acceptTypes}
265
+ capture="environment"
266
+ />
267
+ <input
268
+ {...getInputProps()}
269
+ type="file"
270
+ name="file"
271
+ id="select_file"
272
+ className="inputfile"
273
+ accept={acceptTypes}
274
+ onChange={makeFileHandler((e) => {
275
+ return isCheckImageFile(e);
276
+ })}
277
+ />
278
+ <div className="onDesktop">
279
+ Drop an image
280
+ <div className="smallText">or</div>
281
+ </div>
282
+ <div className="onMobile camIcon">
283
+ <img src="./images/ic_cam_large.svg" alt="Camera" />
284
+ </div>
285
+ <label
286
+ htmlFor="capture"
287
+ className="btn primary onMobile"
288
+ style={{ marginBottom: "2em", width: "22em" }}
289
+ >
290
+ <span className="onMobile">Take a picture</span>
291
+ </label>
292
+ <br />
293
+ <label
294
+ htmlFor="select_file"
295
+ className="btn primary"
296
+ style={{ width: "22em" }}
297
+ >
298
+ <span>Select a file</span>
299
+ </label>
300
+ <label
301
+ htmlFor="capture"
302
+ className="mobileUploadHandler onMobile"
303
+ />
304
+ </section>
305
+ <ExampleImages
306
+ images={settings.exampleImages}
307
+ onExampleImageClicked={(url: string) => {
308
+ return getUrlToCanvasFile(url);
309
+ }}
310
+ />
311
+ </div>
312
+ </div>
313
+ <div
314
+ className={classNames("tryDifferent", {
315
+ hidden: showPart !== "results",
316
+ })}
317
+ onClick={() => onShowStart()}
318
+ >
319
+ <div className="icIcon"></div>
320
+ <div className="textDesc"> Try a different image</div>
321
+ <br style={{ clear: "both" }} />
322
+ </div>
323
+ <div className="headerSeparatorTop" />
324
+ <div className="headerSeparatorBack" />
325
+ </div>
326
+
327
+ <section
328
+ className={classNames(
329
+ "results",
330
+ { resultsActive: showPart === "results" },
331
+ results.length === 1 ? "singleProduct" : "multipleProducts"
332
+ )}
333
+ >
334
+ {errorMessage && (
335
+ <div className="errorMsg">
336
+ {errorMessage}
337
+ <div
338
+ style={{
339
+ textAlign: "center",
340
+ fontSize: "0.7em",
341
+ paddingTop: "0.8em",
342
+ }}
343
+ >
344
+ <span>
345
+ Make sure to include the request ID when reporting a problem:{" "}
346
+ {requestId}
347
+ </span>
348
+ </div>
349
+ </div>
350
+ )}
351
+ <Animate
352
+ show={fetchingRegions || fetchingResults}
353
+ start={{ opacity: 0.0 }}
354
+ enter={{ opacity: [1.0], timing: { duration: 300 } }}
355
+ leave={{ opacity: [0.0], timing: { duration: 300 } }}
356
+ >
357
+ {(s) => (
358
+ <div className="loadingOverlay" style={{ ...s }}>
359
+ <div className="loading" />
360
+ </div>
361
+ )}
362
+ </Animate>
363
+ {settings.preview && requestImage && (
364
+ <div className="preview">
365
+ <Preview
366
+ key={requestImage?.id}
367
+ maxWidth={document.body.clientWidth}
368
+ maxHeight={maxPreviewHeight}
369
+ dotColor="#4C8F9F"
370
+ onSelectionChange={(r: RectCoords) => {
371
+ dispatch(selectionChanged(r));
372
+ return debounceRectCoords(r);
373
+ }}
374
+ regions={regions}
375
+ selection={selectedRegion}
376
+ image={requestImage.canvas}
377
+ />
378
+ </div>
379
+ )}
380
+ <div className="predicted-categories">
381
+ <PredictedCategories cs={categoryPredictions} />
382
+ </div>
383
+ <div className="predicted-categories">
384
+ <Codes codes={codes} />
385
+ </div>
386
+ <CategoryFilter cats={filterOptions} />
387
+
388
+ <div className="wrapper">
389
+ <NodeGroup
390
+ data={results}
391
+ keyAccessor={(r) => r.sku}
392
+ start={(r, i) => ({ opacity: 0, translateX: -100 })}
393
+ enter={(r, i) => ({
394
+ opacity: [1],
395
+ translateX: [0],
396
+ timing: { delay: i * 100, duration: 300 },
397
+ })}
398
+ >
399
+ {(rs) => (
400
+ <>
401
+ {rs.map(({ key, data, state }) => (
402
+ <Result
403
+ key={key}
404
+ noImageUrl={settings.noImageUrl}
405
+ template={settings.resultTemplate}
406
+ onImageClick={(_pos, url) => {
407
+ return getUrlToCanvasFile(url, _pos);
408
+ }}
409
+ onLinkClick={onLinkClick}
410
+ result={data}
411
+ style={{
412
+ opacity: state.opacity,
413
+ transform: `translateX(${state.translateX}%)`,
414
+ }}
415
+ />
416
+ ))}
417
+ </>
418
+ )}
419
+ </NodeGroup>
420
+
421
+ {(results.length === 0 &&
422
+ showPart === "results" &&
423
+ fetchingRegions) ||
424
+ (fetchingResults && (
425
+ <div className="noResults">
426
+ We did not find anything{" "}
427
+ <span role="img" aria-label="sad face">
428
+ 😕
429
+ </span>
430
+ </div>
431
+ ))}
432
+
433
+ <br style={{ clear: "both" }} />
434
+
435
+ {duration && showPart === "results" && (
436
+ <div
437
+ style={{
438
+ textAlign: "center",
439
+ fontSize: "0.7em",
440
+ paddingTop: "0.8em",
441
+ }}
442
+ >
443
+ Search took {duration.toFixed(2)} seconds
444
+ </div>
445
+ )}
446
+
447
+ {requestId && showPart === "results" && (
448
+ <div
449
+ style={{
450
+ textAlign: "center",
451
+ fontSize: "0.7em",
452
+ paddingTop: "0.8em",
453
+ }}
454
+ >
455
+ Request identifier {requestId}
456
+ </div>
457
+ )}
458
+ </div>
459
+ </section>
460
+
461
+ <Snackbar
462
+ open={toastOpen}
463
+ autoHideDuration={3000}
464
+ onClose={() => setToastOpen(false)}
465
+ >
466
+ <Alert onClose={() => setToastOpen(false)} severity="error">
467
+ {errorMessage}
468
+ </Alert>
469
+ </Snackbar>
470
+ </div>
471
+ );
472
+ };
473
+
474
+ export default LandingPageApp;