frontends icon indicating copy to clipboard operation
frontends copied to clipboard

[BUG] useListing missing error handling

Open SampoVirmasalo opened this issue 1 year ago • 1 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current Behavior

Currently calling useListing-composable for example from a component, unhandled error happens.

See code below:

/**
 * @public
 */
export function useListing(params?: {
  listingType: ListingType;
  categoryId?: string;
  defaultSearchCriteria?: RequestParameters<"searchPage">;
}): UseListingReturn {
  const listingType = params?.listingType || "categoryListing";

  // const { getDefaults } = useDefaults({ defaultsKey: contextName }); // ⚠️ necessary?
  const { apiClient } = useShopwareContext();

  let searchMethod;
  if (listingType === "productSearchListing") {
    searchMethod = async (searchCriteria: RequestParameters<"searchPage">) => {
      return apiClient.invoke("searchPage post /search", {
        ...searchCriteria,
      });
    };
  } else {
    const { category } = useCategory(); // 🚨 This causes unhandled error when category context is not present.

    searchMethod = async (searchCriteria: RequestParameters<"searchPage">) => {
      if (!category.value?.id) {
        throw new Error(
          "[useListing][search] Search category id does not exist.",
        );
      }
      return apiClient.invoke(
        "readProductListing post /product-listing/{categoryId} sw-include-seo-urls",
        {
          "sw-include-seo-urls": true,
          ...searchCriteria,
          categoryId: category.value.id,
        },
      );
    };
  }

  return createListingComposable({
    listingKey: listingType,
    searchMethod,
    searchDefaults:
      params?.defaultSearchCriteria || ({} as RequestParameters<"searchPage">), //getDefaults(),
  });
}

Expected Behavior

If Category context is not present, the code should use the params.categoryId if exists. If params.categoryId does not exsist, then it should cracefully throw an handled error.

** Fix proposition **

/**
 * @public
 */
export function useListing(params?: {
  listingType: ListingType;
  categoryId?: string;
  defaultSearchCriteria?: RequestParameters<"searchPage">;
}): UseListingReturn {
  const listingType = params?.listingType || "categoryListing";

  const { apiClient } = useShopwareContext();

  let searchMethod;
  if (listingType === "productSearchListing") {
    searchMethod = async (searchCriteria: RequestParameters<"searchPage">) => {
      return apiClient.invoke("searchPage post /search", {
        ...searchCriteria,
      });
    };
  } else {
    let resourceId: string | undefined;
    try {
      const { category } = useCategory();
      resourceId = category.value?.id;
    }catch(error) {
      if (error instanceof ContextError) {
        resourceId = params?.categoryId;
      } else {
        console.error(error);
      }
    }

    searchMethod = async (searchCriteria: RequestParameters<"searchPage">) => {
      if (!resourceId) {
        throw new Error(
          "[useListing][search] Search category id does not exist.",
        );
      }
      return apiClient.invoke(
        "readProductListing post /product-listing/{categoryId} sw-include-seo-urls",
        {
          "sw-include-seo-urls": true,
          ...searchCriteria,
          categoryId: resourceId,
        },
      );
    };
  }

  return createListingComposable({
    listingKey: listingType,
    searchMethod,
    searchDefaults:
      params?.defaultSearchCriteria || ({} as RequestParameters<"searchPage">), //getDefaults(),
  });
}

Steps To Reproduce

  1. Create Nuxt project with Shopware frontends modules and add proper configs
  2. Create some page
  3. Create component listing-example.vue
  4. Add following code to the component
<template>
<!-- No need to add anything here in this example -->
</template>
<script lang="ts" setup>

const {
    search,
    getElements,
} = useListing({
    listingType: "categoryListing",
    categoryId: <your-category-id>, // entrypoint to browse
    defaultSearchCriteria: { // set the default criteria
        search: "", // Add the 'search' property with an empty string value
        limit: 25,
        p: 1,
    },
});

await search({ search: '' });
</script>

### Environment

```markdown
- OS: Latest MacOS Sonoma
- Node: 18.18.0
- Yarn: 1.22.19

Anything else?

No response

SampoVirmasalo avatar Apr 29 '24 12:04 SampoVirmasalo

Hi @SampoVirmasalo thank you for the reporting issue and proposition of the solution

mdanilowicz avatar May 08 '24 14:05 mdanilowicz