@bonlineza/luxity-lib 2.37.8 → 2.38.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.
@@ -298,7 +298,7 @@
298
298
  };
299
299
 
300
300
  var SearchResults = function SearchResults(_ref) {
301
- var _searchResults$brands, _searchResults$produc, _searchResults$brands2, _searchResults$produc2, _initialSearchData$tr, _initialSearchData$la, _limitBrands, _limitBrands2, _initialSearchData$la2, _searchResults$produc3;
301
+ var _searchResults$brands, _searchResults$produc, _initialSearchData$tr, _initialSearchData$la, _limitBrands, _limitBrands2, _initialSearchData$la2, _searchResults$produc2;
302
302
 
303
303
  var searchValue = _ref.searchValue,
304
304
  searchResults = _ref.searchResults,
@@ -312,7 +312,10 @@
312
312
  currency = _ref.currency,
313
313
  currencySymbol = _ref.currencySymbol,
314
314
  onProductSearchResultClick = _ref.onProductSearchResultClick,
315
- onBrandSearchResultClick = _ref.onBrandSearchResultClick;
315
+ onBrandSearchResultClick = _ref.onBrandSearchResultClick,
316
+ onCreateInterests = _ref.onCreateInterests,
317
+ noResultsImage = _ref.noResultsImage,
318
+ showNoResults = _ref.showNoResults;
316
319
 
317
320
  var _useState = React.useState(false),
318
321
  _useState2 = _slicedToArray(_useState, 2),
@@ -330,15 +333,16 @@
330
333
  window.removeEventListener('resize', checkIfMobile);
331
334
  };
332
335
  }, []);
333
- var shouldShowInitialData = isSearchFocused && (!searchValue || searchValue.trim().length < 3) || (searchValue === null || searchValue === void 0 ? void 0 : searchValue.trim().length) >= 3 && !(searchResults !== null && searchResults !== void 0 && (_searchResults$brands = searchResults.brands) !== null && _searchResults$brands !== void 0 && _searchResults$brands.length) && !(searchResults !== null && searchResults !== void 0 && (_searchResults$produc = searchResults.products) !== null && _searchResults$produc !== void 0 && _searchResults$produc.length);
334
- var hasResults = (searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$brands2 = searchResults.brands) === null || _searchResults$brands2 === void 0 ? void 0 : _searchResults$brands2.length) > 0 || (searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$produc2 = searchResults.products) === null || _searchResults$produc2 === void 0 ? void 0 : _searchResults$produc2.length) > 0;
336
+ var hasSearchBeenPerformed = (searchValue === null || searchValue === void 0 ? void 0 : searchValue.trim().length) >= 3;
337
+ var hasResults = (searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$brands = searchResults.brands) === null || _searchResults$brands === void 0 ? void 0 : _searchResults$brands.length) > 0 || (searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$produc = searchResults.products) === null || _searchResults$produc === void 0 ? void 0 : _searchResults$produc.length) > 0;
335
338
  var hasInitialData = (initialSearchData === null || initialSearchData === void 0 ? void 0 : (_initialSearchData$tr = initialSearchData.trending_brands) === null || _initialSearchData$tr === void 0 ? void 0 : _initialSearchData$tr.length) > 0 || (initialSearchData === null || initialSearchData === void 0 ? void 0 : (_initialSearchData$la = initialSearchData.latest_products) === null || _initialSearchData$la === void 0 ? void 0 : _initialSearchData$la.length) > 0;
339
+ var shouldShowInitialData = isSearchFocused && (!hasSearchBeenPerformed || !hasResults && !showNoResults);
336
340
 
337
- if (!hasResults && !hasInitialData) {
341
+ if (!isSearchFocused) {
338
342
  return null;
339
343
  }
340
344
 
341
- if (!isSearchFocused) {
345
+ if (!hasResults && !hasInitialData && !showNoResults) {
342
346
  return null;
343
347
  }
344
348
 
@@ -357,6 +361,8 @@
357
361
  price: product.price,
358
362
  retail_price: product.est_retail_price
359
363
  };
364
+ var displayPrice = product.on_promotion && product.promotion_price ? product.promotion_price : selectedPrice.price;
365
+ var hasPromotion = product.on_promotion && product.promotion_price;
360
366
  return /*#__PURE__*/React__default.createElement("a", {
361
367
  key: product.link,
362
368
  href: product.link,
@@ -384,15 +390,23 @@
384
390
  className: "product-card__name"
385
391
  }, shouldShowInitialData ? /*#__PURE__*/React__default.createElement("span", null, /*#__PURE__*/React__default.createElement("span", {
386
392
  className: "product-card__brand-name"
387
- }, product.brand.toUpperCase()), ' ', product.name) : product.name), /*#__PURE__*/React__default.createElement("div", {
393
+ }, product.brand.toUpperCase()), ' ', product.name) : /*#__PURE__*/React__default.createElement("span", null, /*#__PURE__*/React__default.createElement("span", {
394
+ className: "product-card__brand-name"
395
+ }, product.brand.toUpperCase()), ' ', product.name)), /*#__PURE__*/React__default.createElement("div", {
388
396
  className: "product-card__info-row"
389
397
  }, /*#__PURE__*/React__default.createElement("div", {
390
398
  className: "product-card__price-group"
399
+ }, hasPromotion ? /*#__PURE__*/React__default.createElement("div", {
400
+ className: "product-card__price-with-promotion"
391
401
  }, /*#__PURE__*/React__default.createElement("div", {
402
+ className: "product-card__price product-card__price--promotion"
403
+ }, formatPrice(displayPrice)), /*#__PURE__*/React__default.createElement("div", {
404
+ className: "product-card__price product-card__price--original"
405
+ }, formatPrice(selectedPrice.price))) : /*#__PURE__*/React__default.createElement("div", {
392
406
  className: "product-card__price"
393
- }, formatPrice(selectedPrice.price)), selectedPrice.retail_price > 1 && /*#__PURE__*/React__default.createElement("div", {
407
+ }, formatPrice(displayPrice)), selectedPrice.retail_price > 1 && selectedPrice.retail_price > displayPrice && /*#__PURE__*/React__default.createElement("div", {
394
408
  className: "product-card__retail-price"
395
- }, "Est. Retail: ", formatPrice(selectedPrice.retail_price))), /*#__PURE__*/React__default.createElement("div", {
409
+ }, "Est. Retail: ", formatPrice(selectedPrice.retail_price))), product.condition && /*#__PURE__*/React__default.createElement("div", {
396
410
  className: "product-card__condition"
397
411
  }, /*#__PURE__*/React__default.createElement("span", {
398
412
  className: "product-card__condition-label"
@@ -409,7 +423,36 @@
409
423
  }
410
424
 
411
425
  return brands;
412
- };
426
+ }; // Show no results state
427
+
428
+
429
+ if (showNoResults) {
430
+ return /*#__PURE__*/React__default.createElement("div", {
431
+ className: "search-results",
432
+ ref: searchResultsRef
433
+ }, /*#__PURE__*/React__default.createElement("div", {
434
+ className: "search-results__no-results"
435
+ }, /*#__PURE__*/React__default.createElement("h2", {
436
+ className: "search-results__header"
437
+ }, "TOP MATCHES"), /*#__PURE__*/React__default.createElement("div", {
438
+ className: "search-results__no-results-content"
439
+ }, /*#__PURE__*/React__default.createElement("div", {
440
+ className: "search-results__no-results-image"
441
+ }, /*#__PURE__*/React__default.createElement("img", {
442
+ src: noResultsImage,
443
+ alt: "No results"
444
+ })), /*#__PURE__*/React__default.createElement("div", {
445
+ className: "search-results__no-results-text"
446
+ }, /*#__PURE__*/React__default.createElement("p", {
447
+ className: "search-results__no-results-title"
448
+ }, "There are currently no products in stock that match your selection"), /*#__PURE__*/React__default.createElement("p", {
449
+ className: "search-results__no-results-description"
450
+ }, "Create an interest now and receive instant notifications as your interests list."))), /*#__PURE__*/React__default.createElement("button", {
451
+ type: "button",
452
+ className: "search-results__create-interest-button",
453
+ onClick: onCreateInterests
454
+ }, "Create Interests")));
455
+ }
413
456
 
414
457
  return /*#__PURE__*/React__default.createElement("div", {
415
458
  className: "search-results",
@@ -466,7 +509,7 @@
466
509
  }
467
510
  }, "View all items")), /*#__PURE__*/React__default.createElement("div", {
468
511
  className: "search-results__product-list"
469
- }, shouldShowInitialData ? initialSearchData === null || initialSearchData === void 0 ? void 0 : (_initialSearchData$la2 = initialSearchData.latest_products) === null || _initialSearchData$la2 === void 0 ? void 0 : _initialSearchData$la2.map(renderProductCard) : searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$produc3 = searchResults.products) === null || _searchResults$produc3 === void 0 ? void 0 : _searchResults$produc3.map(renderProductCard)), /*#__PURE__*/React__default.createElement("button", {
512
+ }, shouldShowInitialData ? initialSearchData === null || initialSearchData === void 0 ? void 0 : (_initialSearchData$la2 = initialSearchData.latest_products) === null || _initialSearchData$la2 === void 0 ? void 0 : _initialSearchData$la2.map(renderProductCard) : searchResults === null || searchResults === void 0 ? void 0 : (_searchResults$produc2 = searchResults.products) === null || _searchResults$produc2 === void 0 ? void 0 : _searchResults$produc2.map(renderProductCard)), /*#__PURE__*/React__default.createElement("button", {
470
513
  type: "button",
471
514
  className: "search-results__view-all-button",
472
515
  onClick: function onClick() {
@@ -684,22 +727,36 @@
684
727
  }))));
685
728
  };
686
729
 
687
- var searchProducts = function searchProducts(search, limit, currencyCode) {
730
+ var searchBrandsAggregations = function searchBrandsAggregations(search, currencyCode) {
688
731
  return {
689
- query: "\n query SearchProducts($search: String!, $limit: Int!, $currencyCode: String!) {\n luxity_products_serach_results(search: $search, limit: $limit, currency_code: $currencyCode) {\n brands {\n name\n link\n }\n products {\n name\n link\n price\n est_retail_price\n condition\n featured_image\n }\n luxity_product_ids\n }\n }\n ",
732
+ query: "\n query GetProductFilterAggregations($search: String!) {\n luxity_products_aggregations(search: $search) {\n luxity_brand {\n name\n }\n }\n }\n ",
733
+ variables: {
734
+ search: search,
735
+ currency_code: currencyCode
736
+ }
737
+ };
738
+ }; // NEW: Get top products for search dropdown (right side)
739
+
740
+ var searchProductsFilter = function searchProductsFilter(search, limit, currencyCode) {
741
+ return {
742
+ query: "\n query LUXITY_PRODUCTS_FILTER(\n $search: String!\n $limit: Int!\n $page: Int!\n $sort_by: String!\n $with_sold: Boolean!\n $currency_code: String!\n ) {\n luxity_products_filter(\n search: $search\n limit: $limit\n page: $page\n sort_by: $sort_by\n with_sold: $with_sold\n ) {\n data {\n id\n product {\n sku\n name\n price(currency_code: $currency_code)\n promotion_price(currency_code: $currency_code)\n est_retail_price(currency_code: $currency_code)\n condition\n currency_symbol(currency_code: $currency_code)\n }\n category_type\n gender\n status\n featured_image\n on_promotion\n promotion_discount\n luxity_brand {\n id\n name\n slug\n }\n }\n total\n }\n }\n ",
690
743
  variables: {
691
744
  search: search,
692
745
  limit: limit,
693
- currencyCode: currencyCode
746
+ page: 1,
747
+ sort_by: 'newest',
748
+ with_sold: false,
749
+ currency_code: currencyCode
694
750
  }
695
751
  };
696
752
  };
697
753
 
698
754
  var useSearch = function useSearch(_ref) {
699
755
  var endpoint = _ref.endpoint,
700
- onProductIdsReceived = _ref.onProductIdsReceived,
756
+ onSearchLoading = _ref.onSearchLoading,
701
757
  currency = _ref.currency,
702
- onSearchPreview = _ref.onSearchPreview;
758
+ onSearchPreview = _ref.onSearchPreview,
759
+ onNoResults = _ref.onNoResults;
703
760
  var currentSearchRequestToken = React.useRef(null);
704
761
  var debounce = React.useCallback(function (func, wait) {
705
762
  var timeout;
@@ -735,9 +792,13 @@
735
792
  if (!searchQuery || searchQuery.trim() === '') {
736
793
  setSearchResults({
737
794
  brands: [],
738
- products: [],
739
- luxity_product_ids: []
740
- });
795
+ products: []
796
+ }); // Reset no results state when clearing search
797
+
798
+ if (typeof onNoResults === 'function') {
799
+ onNoResults(false);
800
+ }
801
+
741
802
  return;
742
803
  } // Cancel any ongoing search request to prevent race conditions
743
804
 
@@ -748,22 +809,81 @@
748
809
 
749
810
 
750
811
  var newSearchToken = axios.CancelToken.source();
751
- currentSearchRequestToken.current = newSearchToken;
752
- axios.post(endpoint, searchProducts(searchQuery, 3, currency), {
812
+ currentSearchRequestToken.current = newSearchToken; // Reset no results state when starting new search (user is typing)
813
+
814
+ if (typeof onNoResults === 'function') {
815
+ onNoResults(false);
816
+ } // Set loading to true when starting the search request
817
+
818
+
819
+ if (typeof onSearchLoading === 'function') {
820
+ onSearchLoading(true);
821
+ } // Make TWO parallel queries: brands aggregations + products filter
822
+
823
+
824
+ Promise.all([// Query 1: Get brands aggregations
825
+ axios.post(endpoint, searchBrandsAggregations(searchQuery, currency), {
826
+ cancelToken: newSearchToken.token
827
+ }), // Query 2: Get top 3 products
828
+ axios.post(endpoint, searchProductsFilter(searchQuery, 3, currency), {
753
829
  cancelToken: newSearchToken.token
754
- }).then(function (response) {
830
+ })]).then(function (_ref3) {
831
+ var _ref4 = _slicedToArray(_ref3, 2),
832
+ brandsResponse = _ref4[0],
833
+ productsResponse = _ref4[1];
834
+
755
835
  if (currentSearchRequestToken.current === newSearchToken) {
756
- var searchResults = response.data.data.luxity_products_serach_results;
757
- setSearchResults(searchResults);
836
+ var _brandsResponse$data$, _productsResponse$dat, _productsResponse$dat2;
837
+
838
+ // Extract brands from aggregations
839
+ var brandsData = ((_brandsResponse$data$ = brandsResponse.data.data.luxity_products_aggregations) === null || _brandsResponse$data$ === void 0 ? void 0 : _brandsResponse$data$.luxity_brand) || []; // Extract products from filter
840
+
841
+ var productsData = ((_productsResponse$dat = productsResponse.data.data.luxity_products_filter) === null || _productsResponse$dat === void 0 ? void 0 : _productsResponse$dat.data) || [];
842
+ var totalResults = ((_productsResponse$dat2 = productsResponse.data.data.luxity_products_filter) === null || _productsResponse$dat2 === void 0 ? void 0 : _productsResponse$dat2.total) || 0; // Map brands to old structure: { name, link }
843
+
844
+ var brands = brandsData.slice(0, 10).map(function (brand) {
845
+ return {
846
+ name: brand.name,
847
+ link: "/products/brands/".concat(brand.name.toLowerCase().replace(/\s+/g, '-')) // Convert to slug
848
+
849
+ };
850
+ }); // Map products to old structure with prices
851
+
852
+ var products = productsData.map(function (product) {
853
+ return {
854
+ name: product.product.name,
855
+ brand: product.luxity_brand.name,
856
+ link: "/products/".concat(product.id),
857
+ // Using product ID for link
858
+ price: product.product.price || 0,
859
+ promotion_price: product.product.promotion_price || null,
860
+ est_retail_price: product.product.est_retail_price || 0,
861
+ condition: product.product.condition || '',
862
+ currency_symbol: product.product.currency_symbol || '',
863
+ featured_image: product.featured_image,
864
+ on_promotion: product.on_promotion || false,
865
+ promotion_discount: product.promotion_discount || 0,
866
+ // Keep new fields for potential future use
867
+ id: product.id,
868
+ category_type: product.category_type,
869
+ luxity_brand: product.luxity_brand
870
+ };
871
+ });
872
+ var searchResults = {
873
+ brands: brands,
874
+ products: products,
875
+ total: totalResults
876
+ };
877
+ setSearchResults(searchResults); // Check if we have no results (empty aggregations)
878
+
879
+ var hasNoResults = brandsData.length === 0 && productsData.length === 0;
758
880
 
759
- if (searchResults && searchResults.luxity_product_ids) {
760
- onProductIdsReceived(searchResults.luxity_product_ids);
881
+ if (typeof onNoResults === 'function') {
882
+ onNoResults(hasNoResults);
761
883
  }
762
884
 
763
885
  if (typeof onSearchPreview === 'function') {
764
- var _searchResults$brands, _searchResults$produc;
765
-
766
- var hasResults = ((_searchResults$brands = searchResults.brands) === null || _searchResults$brands === void 0 ? void 0 : _searchResults$brands.length) > 0 || ((_searchResults$produc = searchResults.products) === null || _searchResults$produc === void 0 ? void 0 : _searchResults$produc.length) > 0;
886
+ var hasResults = brands.length > 0 || products.length > 0;
767
887
  onSearchPreview({
768
888
  search_string: searchQuery,
769
889
  has_results: hasResults
@@ -776,13 +896,12 @@
776
896
  if (!axios.isCancel(error)) {
777
897
  setSearchResults({
778
898
  brands: [],
779
- products: [],
780
- luxity_product_ids: []
899
+ products: []
781
900
  });
782
901
  currentSearchRequestToken.current = null;
783
902
  }
784
903
  });
785
- }, [endpoint, currency, onSearchPreview, onProductIdsReceived]);
904
+ }, [endpoint, currency, onSearchPreview, onSearchLoading, onNoResults]);
786
905
  var debouncedSearch = React.useMemo(function () {
787
906
  return debounce(function (searchQuery, setSearchResults) {
788
907
  return performSearch(searchQuery, setSearchResults);
@@ -922,7 +1041,7 @@
922
1041
  onSearchPreview = _ref.onSearchPreview,
923
1042
  onProductSearchResultClick = _ref.onProductSearchResultClick,
924
1043
  onBrandSearchResultClick = _ref.onBrandSearchResultClick,
925
- onProductIdsReceived = _ref.onProductIdsReceived,
1044
+ onSearchLoading = _ref.onSearchLoading,
926
1045
  currency = _ref.currency,
927
1046
  currencySymbol = _ref.currencySymbol,
928
1047
  currencyOptions = _ref.currencyOptions,
@@ -936,17 +1055,9 @@
936
1055
  isExclusive = _ref.isExclusive,
937
1056
  shop = _ref.shop,
938
1057
  app = _ref.app,
939
- categoryConfig = _ref.categoryConfig;
940
-
941
- var _useSearch = useSearch({
942
- endpoint: endpoint,
943
- onProductIdsReceived: onProductIdsReceived,
944
- currency: currency,
945
- onSearchPreview: onSearchPreview
946
- }),
947
- fetchInitialSearchData = _useSearch.fetchInitialSearchData,
948
- createDebouncedSearch = _useSearch.createDebouncedSearch,
949
- createImmediateSearch = _useSearch.createImmediateSearch;
1058
+ categoryConfig = _ref.categoryConfig,
1059
+ onCreateInterests = _ref.onCreateInterests,
1060
+ noResultsImage = _ref.noResultsImage;
950
1061
 
951
1062
  var _useState = React.useState(''),
952
1063
  _useState2 = _slicedToArray(_useState, 2),
@@ -997,7 +1108,24 @@
997
1108
  cachedResults = _useState16[0],
998
1109
  setCachedResults = _useState16[1];
999
1110
 
1111
+ var _useState17 = React.useState(false),
1112
+ _useState18 = _slicedToArray(_useState17, 2),
1113
+ showNoResults = _useState18[0],
1114
+ setShowNoResults = _useState18[1];
1115
+
1000
1116
  var searchResultsRef = React.useRef(null);
1117
+
1118
+ var _useSearch = useSearch({
1119
+ endpoint: endpoint,
1120
+ onSearchLoading: onSearchLoading,
1121
+ currency: currency,
1122
+ onSearchPreview: onSearchPreview,
1123
+ onNoResults: setShowNoResults
1124
+ }),
1125
+ fetchInitialSearchData = _useSearch.fetchInitialSearchData,
1126
+ createDebouncedSearch = _useSearch.createDebouncedSearch,
1127
+ createImmediateSearch = _useSearch.createImmediateSearch;
1128
+
1001
1129
  var debouncedSearch = createDebouncedSearch(function (results) {
1002
1130
  setSearchResults(results);
1003
1131
  setCachedResults(results);
@@ -1130,6 +1258,7 @@
1130
1258
  products: []
1131
1259
  });
1132
1260
  setIsSearchFocused(false);
1261
+ setShowNoResults(false);
1133
1262
  },
1134
1263
  searchResultsRef: searchResultsRef,
1135
1264
  onSearchSubmit: onSearchSubmit,
@@ -1140,7 +1269,10 @@
1140
1269
  currency: currency,
1141
1270
  currencySymbol: currencySymbol,
1142
1271
  onProductSearchResultClick: onProductSearchResultClick,
1143
- onBrandSearchResultClick: onBrandSearchResultClick
1272
+ onBrandSearchResultClick: onBrandSearchResultClick,
1273
+ onCreateInterests: onCreateInterests,
1274
+ noResultsImage: noResultsImage,
1275
+ showNoResults: showNoResults
1144
1276
  }), /*#__PURE__*/React__default.createElement("nav", {
1145
1277
  className: "navbar__nav-links navbar__nav-links--wrap"
1146
1278
  }, renderDropdownLinks(), !!stores.length && /*#__PURE__*/React__default.createElement("li", {