@tapcart/mobile-components 0.12.8 → 0.12.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAmBD,QAAA,MAAM,kBAAkB,yEASrB,sBAAsB,KAAG,uBAmH3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAmBD,QAAA,MAAM,kBAAkB,yEASrB,sBAAsB,KAAG,uBA2H3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -35,7 +35,13 @@ queryVariables, apiURL, }) => {
35
35
  ? query
36
36
  : (searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("recommendation")) || "";
37
37
  // Check if resolved recommendation meets minimum length requirement
38
- const shouldFetch = recommendation.length >= MIN_QUERY_LENGTH;
38
+ // Allow fetching when:
39
+ // - query is empty → show trending searches
40
+ // - query meets minimum length (≥3 chars)
41
+ // - searchClient has a customSearchConfig (e.g., filter-only queries on PDP)
42
+ const shouldFetch = !recommendation.trim().length ||
43
+ recommendation.length >= MIN_QUERY_LENGTH ||
44
+ (usingSearchClient && Boolean(customSearchConfig));
39
45
  const [cachedRecommendation, setCachedRecommendations] = React.useState(recommendationsLocalStorage.getCacheItem({
40
46
  id: `${recommendation}-${queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.language}`,
41
47
  }));
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-recommendations.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-recommendations.test.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { renderHook } from "@testing-library/react";
2
+ import { useRecommendations } from "./use-recommendations";
3
+ // Mock next/navigation
4
+ jest.mock("next/navigation", () => ({
5
+ useSearchParams: () => new URLSearchParams(),
6
+ }));
7
+ // Mock SWR to give us control over fetching behavior
8
+ jest.mock("swr", () => {
9
+ return {
10
+ __esModule: true,
11
+ default: (key, fetcher, _options) => {
12
+ // If key is null, SWR doesn't fetch
13
+ if (key === null) {
14
+ return { data: undefined, error: undefined, isLoading: false };
15
+ }
16
+ return { data: undefined, error: undefined, isLoading: true };
17
+ },
18
+ };
19
+ });
20
+ // Mock the local storage cache
21
+ jest.mock("../libs/cache/RecommendationsLocalStorage", () => {
22
+ return {
23
+ __esModule: true,
24
+ default: jest.fn().mockImplementation(() => ({
25
+ getCacheItem: jest.fn().mockReturnValue(null),
26
+ setCacheItem: jest.fn(),
27
+ })),
28
+ };
29
+ });
30
+ describe("useRecommendations", () => {
31
+ const mockSearchClient = {
32
+ getRecommendations: jest.fn().mockResolvedValue({
33
+ products: [{ id: "1", title: "Product 1" }],
34
+ searches: ["suggestion 1"],
35
+ facets: [],
36
+ totalResults: 1,
37
+ }),
38
+ };
39
+ const defaultProps = {
40
+ queryVariables: { appId: "test-app" },
41
+ apiURL: "http://test.com/recommendations",
42
+ };
43
+ beforeEach(() => {
44
+ jest.clearAllMocks();
45
+ });
46
+ it("should fetch trending recommendations when query is empty", () => {
47
+ const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "" }, defaultProps)));
48
+ // Empty query now triggers a trending recommendations fetch
49
+ expect(result.current.isLoading).toBe(true);
50
+ });
51
+ it("should not fetch when query is below MIN_QUERY_LENGTH and no customSearchConfig", () => {
52
+ const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "ab" }, defaultProps)));
53
+ expect(result.current.products).toEqual([]);
54
+ expect(result.current.isLoading).toBe(false);
55
+ });
56
+ it("should fetch trending when no searchClient and empty search params", () => {
57
+ const { result } = renderHook(() => useRecommendations(Object.assign({ query: "ab" }, defaultProps)));
58
+ // Without searchClient, recommendation comes from searchParams (empty string)
59
+ // Empty query now triggers a trending fetch
60
+ expect(result.current.isLoading).toBe(true);
61
+ });
62
+ it("should fetch when query meets MIN_QUERY_LENGTH", () => {
63
+ const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "abc" }, defaultProps)));
64
+ // SWR mock returns isLoading: true when key is not null
65
+ expect(result.current.isLoading).toBe(true);
66
+ });
67
+ it("should fetch when customSearchConfig is provided with searchClient even with empty query", () => {
68
+ const customSearchConfig = {
69
+ filter: 'attributes.mfield_bnb__seriesId = 584945 AND NOT id: ANY("9338273530096")',
70
+ pageSize: 6,
71
+ };
72
+ const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "", customSearchConfig }, defaultProps)));
73
+ // shouldFetch should be true due to customSearchConfig bypass, so SWR gets a key and returns isLoading: true
74
+ expect(result.current.isLoading).toBe(true);
75
+ });
76
+ it("should fetch trending when customSearchConfig is provided without searchClient and empty query", () => {
77
+ const customSearchConfig = {
78
+ filter: "attributes.mfield_bnb__seriesId = 584945",
79
+ pageSize: 6,
80
+ };
81
+ const { result } = renderHook(() => useRecommendations(Object.assign({ query: "", customSearchConfig }, defaultProps)));
82
+ // Empty query now triggers a trending fetch regardless of searchClient
83
+ expect(result.current.isLoading).toBe(true);
84
+ });
85
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"variablesCart.util.d.ts","sourceRoot":"","sources":["../../lib/variablesCart.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,6BAA6B,EAO9B,MAAM,kBAAkB,CAAA;AAEzB,eAAO,MAAM,2BAA2B;;cAM5B,MAAM;;0BAEI;YAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;YACzB,KAAK,EAAE,MAAM,CAAA;YACb,cAAc,CAAC,EAAE,MAAM,CAAA;SACxB,EAAE;;;;;;CAyBN,CAAA;AA4FD,eAAO,MAAM,6BAA6B,SAClC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAED,eAAO,MAAM,2BAA2B,SAChC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAoMD,MAAM,MAAM,uBAAuB,GAAG;IACpC,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;IACnD,gBAAgB,EAAE,6BAA6B,EAAE,CAAA;IACjD,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,iCAAiC,EAAE,uBAU/C,CAAA;AAED,eAAO,MAAM,8BAA8B,SACnC,SAAS,GAAG,IAAI,KACrB,uBAmCF,CAAA"}
1
+ {"version":3,"file":"variablesCart.util.d.ts","sourceRoot":"","sources":["../../lib/variablesCart.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,6BAA6B,EAO9B,MAAM,kBAAkB,CAAA;AAEzB,eAAO,MAAM,2BAA2B;;cAM5B,MAAM;;0BAEI;YAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;YACzB,KAAK,EAAE,MAAM,CAAA;YACb,cAAc,CAAC,EAAE,MAAM,CAAA;SACxB,EAAE;;;;;;CAyBN,CAAA;AA8FD,eAAO,MAAM,6BAA6B,SAClC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAED,eAAO,MAAM,2BAA2B,SAChC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAoMD,MAAM,MAAM,uBAAuB,GAAG;IACpC,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;IACnD,gBAAgB,EAAE,6BAA6B,EAAE,CAAA;IACjD,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,iCAAiC,EAAE,uBAU/C,CAAA;AAED,eAAO,MAAM,8BAA8B,SACnC,SAAS,GAAG,IAAI,KACrB,uBAmCF,CAAA"}
@@ -42,6 +42,9 @@ const getOrderLevelDiscounts = (cart) => {
42
42
  if (discount.code) {
43
43
  code = ((discount === null || discount === void 0 ? void 0 : discount.code) || "").toUpperCase();
44
44
  }
45
+ else if (discount.title) {
46
+ code = ((discount === null || discount === void 0 ? void 0 : discount.title) || "").toUpperCase();
47
+ }
45
48
  else if ((_b = (_a = discount.kind) === null || _a === void 0 ? void 0 : _a.manual) === null || _b === void 0 ? void 0 : _b.code) {
46
49
  code = (((_d = (_c = discount === null || discount === void 0 ? void 0 : discount.kind) === null || _c === void 0 ? void 0 : _c.manual) === null || _d === void 0 ? void 0 : _d.code) || "").toUpperCase();
47
50
  }
package/dist/styles.css CHANGED
@@ -1030,6 +1030,9 @@ video {
1030
1030
  .h-24 {
1031
1031
  height: 6rem;
1032
1032
  }
1033
+ .h-3 {
1034
+ height: 0.75rem;
1035
+ }
1033
1036
  .h-4 {
1034
1037
  height: 1rem;
1035
1038
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.12.8",
3
+ "version": "0.12.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "style": "dist/styles.css",