commercetools-8.x-1.2-alpha1/modules/commercetools_decoupled/js/templates/ProductCatalog.js

modules/commercetools_decoupled/js/templates/ProductCatalog.js
class ProductCatalog extends HTMLElement {
  constructor() {
    super();
    this.currentPage = 0;
    this.activeFilters = {};
    this.initialLoad = true;
    this.config = this.loadConfig();
    this.handlePageChange = this.handlePageChange.bind(this);
    this.handlerFilterChange = this.handlerFilterChange.bind(this);
    this.applyProductListToFilters = this.applyProductListToFilters.bind(this);
    document.addEventListener('ct.filters.change', this.handlerFilterChange);
    document.addEventListener(
      'DOMContentLoaded',
      this.applyProductListToFilters,
    );
  }

  loadConfig() {
    const defaultSettings = window.drupalSettings.commercetoolsDecoupled || {};
    const settings = window.commercetools.getComponentConfig(this);
    if (!settings?.productListConfigs?.itemsPerPage) {
      settings.productListConfigs.itemsPerPage = defaultSettings.itemsPerPage;
    }
    if (!settings?.productListConfigs?.totalLimit) {
      settings.productListConfigs.totalLimit = 0;
    }
    if (!settings?.productListIndex) {
      settings.productListIndex = 0;
    }
    return settings;
  }

  async connectedCallback() {
    const productListConfig = this.config.productListConfigs;
    this.classList.add('commercetools-product-catalog');
    if (
      !productListConfig.itemsPerPage ||
      productListConfig.itemsPerPage <= 0
    ) {
      new Drupal.Message().add(
        Drupal.t('Invalid configuration for items per page.'),
        { type: 'error' },
      );
      return;
    }
    // Placeholder for the products data.
    this.productsData = {
      total: -1,
      products: Array(productListConfig.itemsPerPage).fill({}),
    };
  }

  applyProductListConfiguration(configuration) {
    const productListConfig = this.config.productListConfigs;
    let limitForThisCall;
    if (productListConfig.totalLimit > 0) {
      const totalItemsToShow = productListConfig.totalLimit;
      const remainingItems =
        totalItemsToShow - this.currentPage * productListConfig.itemsPerPage;
      limitForThisCall = Math.min(
        productListConfig.itemsPerPage,
        remainingItems,
      );
    } else {
      limitForThisCall = productListConfig.itemsPerPage;
    }

    const productQueryParams = {
      offset: this.currentPage * productListConfig.itemsPerPage,
      limit: limitForThisCall,
    };
    if (productListConfig.sortBy || productListConfig.sortOrder) {
      productQueryParams.sorts = `${productListConfig.sortBy} ${productListConfig.sortOrder}`;
    }
    const activeFilters = this.prepareFilters();
    configuration.queryFilters = [];
    activeFilters.forEach((filter) => configuration.queryFilters.push(filter));
    return { ...configuration, ...productQueryParams };
  }

  applyProductListToFilters() {
    // Loading the real products data.
    const url = new URL(window.location);
    this.currentPage = Number(url.searchParams.get('page')) || 0;
    this.updateProductData(url.searchParams);
  }

  setLoadingState(state) {
    this.productList.setLoadingState(state);
  }

  renderComponent() {
    if (this.isReloading) {
      this.setLoadingState('reload');
      return;
    }

    this.innerHTML = /* html */ `
      <div class="container">
        <div class="row">
          <div class="col-md-12 col-12 ps-0">
            <div class="ct-product-catalog"></div>
          </div>
        </div>
        <div class="ct-pager"></div>
      </div>
    `;

    const productListConfig = this.config.productListConfigs;
    this.productList = document.createElement(
      `ct-product-${this.config.productListConfigs.style}`,
    );
    this.productList.products = this.productsData.products;
    this.productList.isLoading = this.isLoading;
    this.productList.columnsNumber =
      this.config.productListConfigs.columnsNumber;
    if (productListConfig.totalLimit <= 0) {
      productListConfig.totalLimit = this.productsData.total;
    }
    this.querySelector('.ct-product-catalog').appendChild(this.productList);

    if (this.productsData.products.length > 0) {
      const pager = document.createElement('ct-pager');
      const totalPages = Math.ceil(
        Math.min(productListConfig.totalLimit, this.productsData.total) /
          productListConfig.itemsPerPage,
      );
      if (totalPages > 1) {
        pager.setPager(this.currentPage, totalPages);
        pager.addEventListener('page-change', this.handlePageChange.bind(this));
        this.querySelector('.ct-pager').appendChild(pager);
      }
    } else if (this.currentPage > 0) {
      // If we're not on the first page - showing that the page does not exist.
      this.innerHTML = '<ct-page-not-found>';
    } else {
      this.innerHTML = '<ct-no-products-found>';
    }
    this.initialLoad = false;
    this.isLoading = false;
  }

  async handlePageChange(event) {
    this.currentPage = event.detail.page;
    const urlParams = new URLSearchParams(window.location.search);
    urlParams.set('page', this.currentPage);
    window.commercetools.resetProductListResult(this.config.productListIndex);
    try {
      await this.updateProductData(urlParams);
    } catch (error) {
      new Drupal.Message().add(
        Drupal.t('An error occurred while changing the page.'),
        {
          type: 'error',
        },
      );
      throw error;
    }
  }

  handlerFilterChange(e) {
    const { productListIndex } = e.detail;
    if (productListIndex !== e.detail.productListIndex) {
      return;
    }
    const { newUrl } = e.detail;
    this.currentPage = 0;
    this.updateProductData(newUrl.searchParams);
  }

  async updateProductData(newSearchParams = null) {
    const productListConfig = this.config.productListConfigs;
    this.isLoading = true;
    this.isReloading = !this.initialLoad;
    this.renderComponent();

    if (this.config.totalLimit > 0) {
      const totalItemsToShow = this.config.totalLimit;
      const maxPageNumber = Math.ceil(
        totalItemsToShow / this.config.itemsPerPage,
      );
      if (this.currentPage >= maxPageNumber) {
        this.productsData.products = [];
        this.isLoading = false;
        this.renderComponent();
        return;
      }
    }

    try {
      const response = await window.commercetools.getProductListResult(
        this.config.productListIndex,
      );
      if (productListConfig.totalLimit > 0) {
        response.total = Math.min(response.total, productListConfig.totalLimit);
      }
      this.productsData = response;

      // Trigger an event to update other dependent components.
      const changeEvent = new CustomEvent('ct.product-catalog.response', {
        detail: {
          productListIndex: this.config.productListIndex,
          activeFilters: this.activeFilters,
          response,
        },
      });
      document.dispatchEvent(changeEvent);
    } finally {
      this.isLoading = false;
      this.isReloading = false;
      this.renderComponent();

      if (newSearchParams) {
        const url = Drupal.url(
          `${drupalSettings.path.currentPath}?${newSearchParams.toString()}`,
        );
        window.history.pushState({ path: url }, '', url);
      }
    }
  }

  prepareFilters() {
    const productListConfig = this.config.productListConfigs;
    const activeFilters = [];

    // Handle category filters
    let categoryValues = [];
    if (
      productListConfig.categories &&
      Object.keys(productListConfig.categories).length > 0
    ) {
      categoryValues = [
        ...new Set(
          Object.values(productListConfig.categories).map((categoryId) =>
            String(categoryId),
          ),
        ),
      ];
    } else {
      // If no category options provided in configuration, check the query.
      const categoryInQuery = window.commercetools.getQueryParamByIndex(
        'category',
        this.config.productListIndex,
      );
      if (categoryInQuery) {
        categoryValues.push(String(categoryInQuery));
      }
    }
    if (categoryValues.length > 0) {
      activeFilters.push(
        window.commercetools.buildFilter(
          'categories.id',
          categoryValues,
          'tree',
        ),
      );
    }

    // Handle filtering by SKU.
    if (productListConfig.skus && productListConfig.skus.length > 0) {
      const skuValues = productListConfig.skus.map((sku) => String(sku));
      activeFilters.push(
        window.commercetools.buildFilter('variants.sku', skuValues),
      );
    }

    if (productListConfig.customFilters) {
      const conditions = Array.isArray(productListConfig.customFilters)
        ? productListConfig.customFilters
        : [productListConfig.customFilters];
      conditions.forEach((condition) => {
        if (typeof condition === 'string') {
          condition = JSON.parse(condition);
        }
        activeFilters.push(condition);
      });
    }

    return activeFilters;
  }
}

customElements.define('ct-product-catalog', ProductCatalog);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc