@woopze/react-native-sdk 0.1.0

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/assets/cam-icon.d.ts +2 -0
  4. package/dist/assets/cam-icon.js +7 -0
  5. package/dist/assets/cam-icon.js.map +1 -0
  6. package/dist/assets/cam-icon.png +0 -0
  7. package/dist/assets/chevron-icon.d.ts +2 -0
  8. package/dist/assets/chevron-icon.js +7 -0
  9. package/dist/assets/chevron-icon.js.map +1 -0
  10. package/dist/assets/chevron-icon.png +0 -0
  11. package/dist/assets/close-icon.d.ts +2 -0
  12. package/dist/assets/close-icon.js +7 -0
  13. package/dist/assets/close-icon.js.map +1 -0
  14. package/dist/assets/close-icon.png +0 -0
  15. package/dist/assets/filter-icon.d.ts +2 -0
  16. package/dist/assets/filter-icon.js +7 -0
  17. package/dist/assets/filter-icon.js.map +1 -0
  18. package/dist/assets/filter-icon.png +0 -0
  19. package/dist/assets/search-icon.d.ts +2 -0
  20. package/dist/assets/search-icon.js +7 -0
  21. package/dist/assets/search-icon.js.map +1 -0
  22. package/dist/assets/search-icon.png +0 -0
  23. package/dist/cam-icon-II34AEJC.png +0 -0
  24. package/dist/chevron-icon-7YWXX66A.png +0 -0
  25. package/dist/close-icon-VE65QPHD.png +0 -0
  26. package/dist/comments/AllCommentsModal.d.ts +11 -0
  27. package/dist/comments/AllCommentsModal.js +84 -0
  28. package/dist/comments/AllCommentsModal.js.map +1 -0
  29. package/dist/comments/index.d.ts +9 -0
  30. package/dist/comments/index.js +67 -0
  31. package/dist/comments/index.js.map +1 -0
  32. package/dist/components/ProductCard.d.ts +16 -0
  33. package/dist/components/ProductCard.js +123 -0
  34. package/dist/components/ProductCard.js.map +1 -0
  35. package/dist/components/SearchInput.d.ts +16 -0
  36. package/dist/components/SearchInput.js +186 -0
  37. package/dist/components/SearchInput.js.map +1 -0
  38. package/dist/constants.d.ts +7 -0
  39. package/dist/constants.js +31 -0
  40. package/dist/constants.js.map +1 -0
  41. package/dist/filter-icon-TNVJNKA2.png +0 -0
  42. package/dist/index.d.ts +18 -0
  43. package/dist/index.js +22 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/search/FilterModal.d.ts +28 -0
  46. package/dist/search/FilterModal.js +444 -0
  47. package/dist/search/FilterModal.js.map +1 -0
  48. package/dist/search/index.d.ts +39 -0
  49. package/dist/search/index.js +652 -0
  50. package/dist/search/index.js.map +1 -0
  51. package/dist/search-icon-6SVD6L4Q.png +0 -0
  52. package/dist/tracking.d.ts +11 -0
  53. package/dist/tracking.js +79 -0
  54. package/dist/tracking.js.map +1 -0
  55. package/dist/types.d.ts +14 -0
  56. package/dist/types.js +4 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +47 -0
@@ -0,0 +1,652 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativeSafeAreaContext = require('react-native-safe-area-context');
6
+ var FilterModal = require('./FilterModal');
7
+ var ProductCard = require('../components/ProductCard');
8
+ var constants = require('../constants');
9
+ var SearchInput = require('../components/SearchInput');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ var React__default = /*#__PURE__*/_interopDefault(React);
14
+ var FilterModal__default = /*#__PURE__*/_interopDefault(FilterModal);
15
+ var ProductCard__default = /*#__PURE__*/_interopDefault(ProductCard);
16
+ var SearchInput__default = /*#__PURE__*/_interopDefault(SearchInput);
17
+
18
+ const recentSearches = [
19
+ "\xC7\u0131kar\u0131labilir Bro\u015F Detayl\u0131 Cepli Giy \xC7\u0131k",
20
+ "etek",
21
+ "mont",
22
+ "ayakkab\u0131",
23
+ "k\xFCrk"
24
+ ];
25
+ const popularSearches = ["Tunik Tak\u0131m", "Elbise", "Ferace", "Kaban", "Triko"];
26
+ const DEFAULT_SEARCH_THEME = {
27
+ backgroundColor: "#FFFFFF",
28
+ inputBackgroundColor: "#efefef",
29
+ borderColor: "#1f1f1f",
30
+ textPrimaryColor: "#111",
31
+ textSecondaryColor: "#333",
32
+ mutedTextColor: "#6f6f6f",
33
+ chipBackgroundColor: "#efefef",
34
+ buttonTextColor: "#6a6a6a",
35
+ accentColor: "#000",
36
+ dangerColor: "#d00000",
37
+ iconTintColor: "#111",
38
+ cameraButtonBackgroundColor: "#fff"
39
+ };
40
+ const SEARCH_API_URL = "https://search.woopze.com/api/mod7/search";
41
+ const DEBOUNCE_MS = 800;
42
+ const EMPTY_FILTERS = {
43
+ categories: [],
44
+ facets: {},
45
+ minPrice: null,
46
+ maxPrice: null
47
+ };
48
+ const formatPrice = (value) => `${value.toLocaleString("tr-TR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} TL`;
49
+ const parsePriceBounds = (facetDistribution) => {
50
+ const entries = Object.keys((facetDistribution == null ? void 0 : facetDistribution.price) || {}).map((key) => Number(key)).filter((value) => Number.isFinite(value) && value > 0).sort((a, b) => a - b);
51
+ if (entries.length === 0) {
52
+ return { min: 0, max: 0 };
53
+ }
54
+ return {
55
+ min: Math.floor(entries[0]),
56
+ max: Math.ceil(entries[entries.length - 1])
57
+ };
58
+ };
59
+ const escapeFilterValue = (value) => value.replace(/'/g, "\\'");
60
+ const buildFilterQuery = (applied, defaultMin, defaultMax) => {
61
+ const clauses = [];
62
+ if (applied.categories.length === 1) {
63
+ clauses.push(`product_group = '${applied.categories[0]}'`);
64
+ } else if (applied.categories.length > 1) {
65
+ const categoryExpression = applied.categories.map((category) => `product_group = '${category}'`).join(" OR ");
66
+ clauses.push(`(${categoryExpression})`);
67
+ }
68
+ if (defaultMin > 0 && defaultMax > 0 && applied.minPrice !== null && applied.maxPrice !== null && (applied.minPrice !== defaultMin || applied.maxPrice !== defaultMax)) {
69
+ clauses.push(`price>=${Math.floor(applied.minPrice)}`);
70
+ clauses.push(`price<=${Math.ceil(applied.maxPrice)}`);
71
+ }
72
+ Object.entries(applied.facets).forEach(([facetKey, values]) => {
73
+ if (!values.length) return;
74
+ if (values.length === 1) {
75
+ clauses.push(`${facetKey} = '${escapeFilterValue(values[0])}'`);
76
+ return;
77
+ }
78
+ const facetExpression = values.map((value) => `${facetKey} = '${escapeFilterValue(value)}'`).join(" OR ");
79
+ clauses.push(`(${facetExpression})`);
80
+ });
81
+ return clauses.join(" AND ");
82
+ };
83
+ const mapApiProduct = (item) => {
84
+ const oldPriceValue = item.market_price > item.discount_price ? item.market_price : 0;
85
+ const discountRate = oldPriceValue > 0 ? Math.round(
86
+ (oldPriceValue - item.discount_price) / oldPriceValue * 100
87
+ ) : 0;
88
+ return {
89
+ id: String(item.id),
90
+ imageUrl: item.photo,
91
+ title: item.name,
92
+ oldPrice: oldPriceValue > 0 ? formatPrice(oldPriceValue) : "",
93
+ discount: discountRate > 0 ? `%${discountRate}` : "",
94
+ newPrice: formatPrice(item.discount_price || item.price),
95
+ url: item.url,
96
+ model_code: item.model_code,
97
+ photo_embedding: item.photo_embedding,
98
+ ids: item.ids
99
+ };
100
+ };
101
+ function WoopzeSearchScreen({
102
+ apiKey,
103
+ uid,
104
+ originDomain,
105
+ onProductPressed,
106
+ onClosePress,
107
+ hideHeaderCloseIcon = false,
108
+ hideRecentSearchCloseIcon = false,
109
+ theme,
110
+ containerStyle,
111
+ route
112
+ }) {
113
+ var _a;
114
+ if (!apiKey || !uid || !originDomain) {
115
+ throw new Error(
116
+ "Woopze.Search requires `apiKey`, `uid`, and `originDomain` props."
117
+ );
118
+ }
119
+ const origin = `https://${originDomain}`;
120
+ const mergedTheme = React.useMemo(
121
+ () => ({ ...DEFAULT_SEARCH_THEME, ...theme || {} }),
122
+ [theme]
123
+ );
124
+ const [query, setQuery] = React.useState("");
125
+ const [debouncedQuery, setDebouncedQuery] = React.useState("");
126
+ const [items, setItems] = React.useState([]);
127
+ const [page, setPage] = React.useState(0);
128
+ const [isLoading, setIsLoading] = React.useState(false);
129
+ const [isLoadingMore, setIsLoadingMore] = React.useState(false);
130
+ const [hasMore, setHasMore] = React.useState(false);
131
+ const [totalCount, setTotalCount] = React.useState(0);
132
+ const [errorText, setErrorText] = React.useState("");
133
+ const [baseFacetDistribution, setBaseFacetDistribution] = React.useState({});
134
+ const [facetConfig, setFacetConfig] = React.useState({});
135
+ const [isFilterModalVisible, setIsFilterModalVisible] = React.useState(false);
136
+ const [defaultMinPrice, setDefaultMinPrice] = React.useState(0);
137
+ const [defaultMaxPrice, setDefaultMaxPrice] = React.useState(0);
138
+ const [appliedFiltersState, setAppliedFiltersState] = React.useState(EMPTY_FILTERS);
139
+ const [appliedFilter, setAppliedFilter] = React.useState("");
140
+ const [activeQuery, setActiveQuery] = React.useState("");
141
+ const isPaginatingRef = React.useRef(false);
142
+ const inFlightRequestSignaturesRef = React.useRef(/* @__PURE__ */ new Set());
143
+ React.useEffect(() => {
144
+ const timeout = setTimeout(() => {
145
+ setDebouncedQuery(query.trim());
146
+ }, DEBOUNCE_MS);
147
+ return () => clearTimeout(timeout);
148
+ }, [query]);
149
+ const searchProducts = React.useCallback(
150
+ async (nextQuery, nextPage, filterExpression) => {
151
+ const requestSignature = `${nextQuery}::${nextPage}::${filterExpression}`;
152
+ if (inFlightRequestSignaturesRef.current.has(requestSignature)) {
153
+ return;
154
+ }
155
+ inFlightRequestSignaturesRef.current.add(requestSignature);
156
+ const isFirstPage = nextPage === 0;
157
+ if (isFirstPage) {
158
+ setIsLoading(true);
159
+ setErrorText("");
160
+ } else {
161
+ setIsLoadingMore(true);
162
+ }
163
+ try {
164
+ const response = await fetch(SEARCH_API_URL, {
165
+ method: "POST",
166
+ headers: {
167
+ "content-type": "application/json",
168
+ "x-origin-domain": originDomain,
169
+ "x-woopze-api-key": apiKey,
170
+ "x-woopze-uid": uid
171
+ },
172
+ body: JSON.stringify({
173
+ apiKey,
174
+ q: nextQuery,
175
+ page: nextPage,
176
+ filter: filterExpression,
177
+ response_time: null
178
+ })
179
+ });
180
+ if (!response.ok) {
181
+ throw new Error(`Request failed with status ${response.status}`);
182
+ }
183
+ const json = await response.json();
184
+ const mapped = json.hits.map(mapApiProduct);
185
+ const loadedCount = (nextPage + 1) * json.limit;
186
+ const moreAvailable = loadedCount < json.total;
187
+ setItems((prev) => isFirstPage ? mapped : [...prev, ...mapped]);
188
+ setPage(json.page);
189
+ setTotalCount(json.total);
190
+ setHasMore(moreAvailable);
191
+ if (isFirstPage && !filterExpression) {
192
+ setBaseFacetDistribution(json.facetDistribution || {});
193
+ setFacetConfig(json.facetConfig || {});
194
+ }
195
+ if (isFirstPage && !filterExpression) {
196
+ const { min, max } = parsePriceBounds(json.facetDistribution);
197
+ if (min > 0 && max > 0) {
198
+ setDefaultMinPrice(min);
199
+ setDefaultMaxPrice(max);
200
+ }
201
+ }
202
+ } catch (e) {
203
+ console.log(e, "<--- woopze search error", " send body", {
204
+ apiKey,
205
+ q: nextQuery,
206
+ page: nextPage,
207
+ filter: filterExpression,
208
+ response_time: null
209
+ });
210
+ setErrorText("Arama s\u0131ras\u0131nda bir hata olu\u015Ftu.");
211
+ if (isFirstPage) {
212
+ setItems([]);
213
+ }
214
+ setHasMore(false);
215
+ } finally {
216
+ inFlightRequestSignaturesRef.current.delete(requestSignature);
217
+ setIsLoading(false);
218
+ setIsLoadingMore(false);
219
+ isPaginatingRef.current = false;
220
+ }
221
+ },
222
+ [apiKey, origin, originDomain, uid]
223
+ );
224
+ React.useEffect(() => {
225
+ var _a2;
226
+ console.log(route, "<-- route from woopze");
227
+ if ((_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.model_code) {
228
+ console.log("visual search working");
229
+ handleVisualSearch(route.params.model_code);
230
+ }
231
+ }, [(_a = route == null ? void 0 : route.params) == null ? void 0 : _a.model_code]);
232
+ React.useEffect(() => {
233
+ if (!debouncedQuery) {
234
+ if (query.trim().length > 0) {
235
+ return;
236
+ }
237
+ setAppliedFilter("");
238
+ setAppliedFiltersState(EMPTY_FILTERS);
239
+ setActiveQuery("");
240
+ setItems([]);
241
+ setPage(0);
242
+ setTotalCount(0);
243
+ setHasMore(false);
244
+ setErrorText("");
245
+ isPaginatingRef.current = false;
246
+ searchProducts("", 0, "");
247
+ return;
248
+ }
249
+ setAppliedFilter("");
250
+ setAppliedFiltersState(EMPTY_FILTERS);
251
+ setActiveQuery(debouncedQuery);
252
+ setItems([]);
253
+ setPage(0);
254
+ setTotalCount(0);
255
+ setHasMore(false);
256
+ isPaginatingRef.current = false;
257
+ searchProducts(debouncedQuery, 0, "");
258
+ }, [debouncedQuery, query, searchProducts]);
259
+ const loadNextPage = React.useCallback(() => {
260
+ if (isLoading || isLoadingMore || !hasMore || isPaginatingRef.current) {
261
+ return;
262
+ }
263
+ isPaginatingRef.current = true;
264
+ searchProducts(activeQuery, page + 1, appliedFilter);
265
+ }, [
266
+ activeQuery,
267
+ appliedFilter,
268
+ hasMore,
269
+ isLoading,
270
+ isLoadingMore,
271
+ page,
272
+ searchProducts
273
+ ]);
274
+ const onScroll = React.useCallback(
275
+ (event) => {
276
+ const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
277
+ const threshold = 180;
278
+ const isCloseToBottom = layoutMeasurement.height + contentOffset.y >= contentSize.height - threshold;
279
+ if (isCloseToBottom) {
280
+ loadNextPage();
281
+ }
282
+ },
283
+ [loadNextPage]
284
+ );
285
+ const hasTypedQuery = query.trim().length > 0;
286
+ const isResultsMode = hasTypedQuery || debouncedQuery.length > 0;
287
+ const showResultsHeader = debouncedQuery.length > 0 && !errorText;
288
+ const showInitialSections = !showResultsHeader && query.trim().length === 0 && debouncedQuery.length === 0;
289
+ const applyFilters = (nextFilters) => {
290
+ if (!debouncedQuery) return;
291
+ const expression = buildFilterQuery(
292
+ nextFilters,
293
+ defaultMinPrice,
294
+ defaultMaxPrice
295
+ );
296
+ setAppliedFiltersState(nextFilters);
297
+ setAppliedFilter(expression);
298
+ setItems([]);
299
+ setPage(0);
300
+ setHasMore(false);
301
+ isPaginatingRef.current = false;
302
+ searchProducts(debouncedQuery, 0, expression);
303
+ };
304
+ const resetFilters = () => {
305
+ setAppliedFiltersState(EMPTY_FILTERS);
306
+ setAppliedFilter("");
307
+ if (debouncedQuery) {
308
+ setItems([]);
309
+ setPage(0);
310
+ setHasMore(false);
311
+ isPaginatingRef.current = false;
312
+ searchProducts(debouncedQuery, 0, "");
313
+ }
314
+ };
315
+ const clearSearch = () => {
316
+ setQuery("");
317
+ setDebouncedQuery("");
318
+ setItems([]);
319
+ setPage(0);
320
+ setTotalCount(0);
321
+ setHasMore(false);
322
+ setErrorText("");
323
+ setBaseFacetDistribution({});
324
+ setFacetConfig({});
325
+ setAppliedFiltersState(EMPTY_FILTERS);
326
+ setDefaultMinPrice(0);
327
+ setDefaultMaxPrice(0);
328
+ };
329
+ const handleVisualSearch = async (model_code) => {
330
+ var _a2;
331
+ try {
332
+ const result = await constants.fetchVisualSearch({ apiKey, model_code });
333
+ if ((_a2 = result == null ? void 0 : result.results) == null ? void 0 : _a2.length) {
334
+ const mapped = result.results.map(mapApiProduct);
335
+ setItems(mapped);
336
+ setPage(1);
337
+ setTotalCount(result.results.length);
338
+ setHasMore(false);
339
+ }
340
+ } catch (e) {
341
+ console.log(e, "<--- woopze visual search error", " send body", {
342
+ apiKey,
343
+ model_code
344
+ });
345
+ setErrorText("Arama s\u0131ras\u0131nda bir hata olu\u015Ftu.");
346
+ setItems([]);
347
+ setHasMore(false);
348
+ }
349
+ };
350
+ return /* @__PURE__ */ React__default.default.createElement(
351
+ reactNativeSafeAreaContext.SafeAreaView,
352
+ {
353
+ style: [
354
+ styles.outer,
355
+ { backgroundColor: mergedTheme.backgroundColor },
356
+ containerStyle
357
+ ]
358
+ },
359
+ /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: styles.contentWrap }, /* @__PURE__ */ React__default.default.createElement(
360
+ SearchInput__default.default,
361
+ {
362
+ query,
363
+ hideHeaderCloseIcon,
364
+ setQuery,
365
+ isResultsMode,
366
+ clearSearch,
367
+ onClosePress,
368
+ mergedTheme
369
+ }
370
+ ), /* @__PURE__ */ React__default.default.createElement(
371
+ reactNative.ScrollView,
372
+ {
373
+ contentContainerStyle: [
374
+ styles.content,
375
+ {
376
+ backgroundColor: mergedTheme.backgroundColor,
377
+ paddingBottom: 120
378
+ }
379
+ ],
380
+ showsVerticalScrollIndicator: false,
381
+ keyboardShouldPersistTaps: "handled",
382
+ keyboardDismissMode: "none",
383
+ onScroll,
384
+ scrollEventThrottle: 16
385
+ },
386
+ query ? /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
387
+ reactNative.Text,
388
+ {
389
+ style: [
390
+ styles.resultsCountText,
391
+ { color: mergedTheme.textPrimaryColor }
392
+ ]
393
+ },
394
+ '"',
395
+ query,
396
+ '" ile ilgili',
397
+ " ",
398
+ /* @__PURE__ */ React__default.default.createElement(reactNative.Text, { style: styles.resultsCountBold }, totalCount),
399
+ " \xFCr\xFCn listelendi."
400
+ ), /* @__PURE__ */ React__default.default.createElement(
401
+ reactNative.TouchableOpacity,
402
+ {
403
+ activeOpacity: 0.7,
404
+ style: styles.filterRow,
405
+ onPress: () => setIsFilterModalVisible(true)
406
+ },
407
+ /* @__PURE__ */ React__default.default.createElement(
408
+ reactNative.Text,
409
+ {
410
+ style: [
411
+ styles.filterText,
412
+ { color: mergedTheme.textPrimaryColor }
413
+ ]
414
+ },
415
+ "Filtreyi G\xF6ster"
416
+ ),
417
+ /* @__PURE__ */ React__default.default.createElement(
418
+ reactNative.Image,
419
+ {
420
+ source: require("../assets/filter-icon.png"),
421
+ style: [
422
+ styles.filterIcon,
423
+ { tintColor: mergedTheme.iconTintColor }
424
+ ]
425
+ }
426
+ )
427
+ )) : null,
428
+ showInitialSections ? /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
429
+ reactNative.Text,
430
+ {
431
+ style: [
432
+ styles.sectionTitle,
433
+ { color: mergedTheme.accentColor }
434
+ ]
435
+ },
436
+ "Son Aramalar"
437
+ ), /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: styles.chipWrap }, recentSearches.map((label) => /* @__PURE__ */ React__default.default.createElement(
438
+ reactNative.TouchableOpacity,
439
+ {
440
+ key: label,
441
+ activeOpacity: 0.7,
442
+ onPress: () => setQuery(label),
443
+ style: [
444
+ styles.chip,
445
+ { backgroundColor: mergedTheme.chipBackgroundColor }
446
+ ]
447
+ },
448
+ /* @__PURE__ */ React__default.default.createElement(
449
+ reactNative.Text,
450
+ {
451
+ numberOfLines: 1,
452
+ style: [
453
+ styles.chipText,
454
+ { color: mergedTheme.textSecondaryColor }
455
+ ]
456
+ },
457
+ label
458
+ ),
459
+ !hideRecentSearchCloseIcon ? /* @__PURE__ */ React__default.default.createElement(reactNative.TouchableOpacity, { style: styles.chipCloseContainer }, /* @__PURE__ */ React__default.default.createElement(
460
+ reactNative.Image,
461
+ {
462
+ source: require("../assets/close-icon.png"),
463
+ style: [
464
+ styles.chipClose,
465
+ { tintColor: mergedTheme.iconTintColor }
466
+ ]
467
+ }
468
+ )) : null
469
+ ))), /* @__PURE__ */ React__default.default.createElement(
470
+ reactNative.Text,
471
+ {
472
+ style: [
473
+ styles.sectionTitle,
474
+ { color: mergedTheme.accentColor }
475
+ ]
476
+ },
477
+ "Pop\xFCler Aramalar"
478
+ ), /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: styles.popularWrap }, popularSearches.map((item) => /* @__PURE__ */ React__default.default.createElement(
479
+ reactNative.TouchableOpacity,
480
+ {
481
+ activeOpacity: 0.7,
482
+ onPress: () => setQuery(item),
483
+ key: item
484
+ },
485
+ /* @__PURE__ */ React__default.default.createElement(
486
+ reactNative.Text,
487
+ {
488
+ style: [
489
+ styles.popularText,
490
+ { color: mergedTheme.textSecondaryColor }
491
+ ]
492
+ },
493
+ item
494
+ )
495
+ )))) : null,
496
+ items.length > 0 ? /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: styles.grid }, items.map((item) => /* @__PURE__ */ React__default.default.createElement(
497
+ ProductCard__default.default,
498
+ {
499
+ key: item.id,
500
+ item,
501
+ onProductPress: (product) => onProductPressed == null ? void 0 : onProductPressed(product),
502
+ onVisualSearchPress: () => handleVisualSearch(item.model_code),
503
+ theme: mergedTheme
504
+ }
505
+ ))) : null,
506
+ !isLoading && !errorText && debouncedQuery.length > 0 && items.length === 0 ? /* @__PURE__ */ React__default.default.createElement(
507
+ reactNative.Text,
508
+ {
509
+ style: [styles.emptyText, { color: mergedTheme.mutedTextColor }]
510
+ },
511
+ "Sonu\xE7 bulunamad\u0131."
512
+ ) : null,
513
+ isLoadingMore ? /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: styles.statusWrap }, /* @__PURE__ */ React__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: mergedTheme.accentColor })) : null,
514
+ errorText ? /* @__PURE__ */ React__default.default.createElement(
515
+ reactNative.Text,
516
+ {
517
+ style: [styles.errorText, { color: mergedTheme.dangerColor }]
518
+ },
519
+ errorText
520
+ ) : null
521
+ )),
522
+ /* @__PURE__ */ React__default.default.createElement(
523
+ FilterModal__default.default,
524
+ {
525
+ visible: isFilterModalVisible,
526
+ onClose: () => setIsFilterModalVisible(false),
527
+ facetDistribution: baseFacetDistribution,
528
+ facetConfig,
529
+ defaultMinPrice,
530
+ defaultMaxPrice,
531
+ appliedFilters: appliedFiltersState,
532
+ onApply: applyFilters,
533
+ onReset: resetFilters
534
+ }
535
+ )
536
+ );
537
+ }
538
+ const styles = reactNative.StyleSheet.create({
539
+ outer: {
540
+ flex: 1,
541
+ backgroundColor: "#FFFFFF",
542
+ padding: 16
543
+ },
544
+ content: {
545
+ backgroundColor: "#FFFFFF",
546
+ minHeight: "100%"
547
+ },
548
+ contentWrap: {
549
+ flex: 1,
550
+ position: "relative"
551
+ },
552
+ sectionTitle: {
553
+ marginTop: 28,
554
+ marginBottom: 12,
555
+ fontSize: 12,
556
+ fontWeight: "700",
557
+ color: "#000"
558
+ },
559
+ chipWrap: {
560
+ flexDirection: "row",
561
+ flexWrap: "wrap",
562
+ gap: 10
563
+ },
564
+ chip: {
565
+ flexDirection: "row",
566
+ alignItems: "center",
567
+ backgroundColor: "#efefef",
568
+ borderRadius: 3,
569
+ paddingLeft: 12,
570
+ paddingRight: 8,
571
+ paddingVertical: 7,
572
+ maxWidth: "100%"
573
+ },
574
+ chipText: {
575
+ fontSize: 13,
576
+ fontWeight: "500",
577
+ color: "#333",
578
+ marginRight: 8
579
+ },
580
+ chipCloseContainer: {
581
+ width: 16,
582
+ height: 16,
583
+ alignItems: "center",
584
+ justifyContent: "center"
585
+ },
586
+ chipClose: {
587
+ width: 8,
588
+ height: 8
589
+ },
590
+ popularWrap: {
591
+ flexDirection: "row",
592
+ alignItems: "center",
593
+ gap: 22,
594
+ marginBottom: 20
595
+ },
596
+ popularText: {
597
+ fontSize: 12,
598
+ color: "#333",
599
+ fontWeight: "500"
600
+ },
601
+ resultsCountText: {
602
+ marginTop: 56,
603
+ marginBottom: 18,
604
+ fontSize: 15,
605
+ color: "#111"
606
+ },
607
+ resultsCountBold: {
608
+ fontWeight: "700"
609
+ },
610
+ filterRow: {
611
+ flexDirection: "row",
612
+ alignItems: "center",
613
+ marginBottom: 22
614
+ },
615
+ filterText: {
616
+ fontSize: 15,
617
+ color: "#111",
618
+ fontWeight: "600",
619
+ marginRight: 8
620
+ },
621
+ filterIcon: {
622
+ width: 18,
623
+ height: 18
624
+ },
625
+ grid: {
626
+ flexDirection: "row",
627
+ flexWrap: "wrap",
628
+ justifyContent: "space-between",
629
+ rowGap: 28
630
+ },
631
+ statusWrap: {
632
+ paddingVertical: 16,
633
+ alignItems: "center",
634
+ justifyContent: "center"
635
+ },
636
+ errorText: {
637
+ color: "#d00000",
638
+ textAlign: "center",
639
+ fontSize: 12,
640
+ marginTop: 12
641
+ },
642
+ emptyText: {
643
+ color: "#666",
644
+ textAlign: "center",
645
+ fontSize: 12,
646
+ marginTop: 16
647
+ }
648
+ });
649
+
650
+ module.exports = WoopzeSearchScreen;
651
+ //# sourceMappingURL=index.js.map
652
+ //# sourceMappingURL=index.js.map