commercetools-8.x-1.2-alpha1/modules/commercetools_decoupled/js/molecules/ProductDetails.js

modules/commercetools_decoupled/js/molecules/ProductDetails.js
class ProductDetails extends HTMLElement {
  constructor() {
    super();

    // It will be used on loading products.
    this.placeholderProduct = {
      name: 'Placeholder for title',
      masterVariant: {
        images: [{ url: '' }],
        price: { localizedPrice: '$1000' },
        availability: {
          noChannel: {
            availableQuantity:
              window.drupalSettings.commercetoolsDecoupled.unavailableDataText,
          },
        },
        attributes: [
          { name: 'designer', value: { label: 'Placeholder designer' } },
          { name: 'color', value: { label: { en: 'Placeholder color' } } },
          { name: 'style', value: { label: 'Placeholder style' } },
        ],
      },
      isLoading: true,
    };

    this.handleSkuChange = this.handleSkuChange.bind(this);
  }

  connectedCallback() {
    this.renderComponent();
  }

  renderComponent() {
    const product =
      this.product.isLoading !== true ? this.product : this.placeholderProduct;
    const currentVariant =
      product?.variants?.find(
        (variant) => variant.sku === this.product.currentSku,
      ) || product.masterVariant;

    this.name = product.name;
    this.images = currentVariant?.images;
    this.price = currentVariant.price;
    this.availability =
      currentVariant.availability.noChannel?.availableQuantity || 0;
    this.isLoading = product.isLoading;

    this.innerHTML = /* html */ `
    <article class="product row my-4${this.isLoading ? ' placeholderify' : ''}">
      <div class="col-12 col-md-6">
        <div class="card-img-wrapper text-center" style="overflow:hidden; height: 100%;">
          ${
            this.isLoading
              ? `
            <img src="${this.image}" alt="${
              this.name
            }" style="max-height: 24rem; width: 100%; object-fit: contain; height: 100%;" />
          `
              : ''
          }
        </div>
      </div>

      <div class="col-12 col-md-6 mt-4 mt-md-0">
        <div class="card-body">
          <p class="product-price fs-4">
            ${
              this.price.discounted
                ? `
              <del>${this.price.localizedPrice}</del>
              <span class="discount text-danger">${this.price.discounted.localizedPrice}</span>
            `
                : this.price.localizedPrice
            }
          </p>
          <div class="product-availability mt-2 mb-2"><span>${this.availability} ${Drupal.t('available')}</span></div>
          <div class="ct-add-to-cart-form"></div>
        </div>
      </div>
    </article>
    `;

    if (this.images && !this.isLoading) {
      // Build full-screen image popup.
      const imageCarousel = document.createElement('ct-carousel');
      imageCarousel.items = this.images.map((image) => {
        const imgWr = document.createElement('div');
        imgWr.innerHTML = `<img src="${image.url}" alt="${image.label || this.name}" style=" width: 100%; object-fit: contain; height: 100%;" />`;
        return imgWr;
      });

      const modal = document.createElement('ct-gallery-modal');
      modal.title = this.name;
      modal.content = imageCarousel;
      document.body.appendChild(modal);

      // Build main product image carousel.
      const modalSelector = modal.getSelector();
      const carousel = document.createElement('ct-carousel');
      carousel.items = this.images.map((image, k) => {
        const button = document.createElement('button');
        button.className = 'btn btn-link';
        button.setAttribute('data-bs-toggle', 'modal');
        button.setAttribute('data-bs-target', `#${modalSelector}`);
        button.innerHTML = `<img src="${image.url}" alt="${image.label || this.name}" style="max-height: 24rem; width: 100%; object-fit: contain; height: 100%;"/>`;
        // Open a full-screen pop-up with a carousel of product images.
        button.addEventListener('click', (e) => {
          e.preventDefault();
          imageCarousel.setActiveSlider(k);
        });
        return button;
      });
      this.querySelector('.card-img-wrapper').append(carousel);
    }

    if (this.product.isLoading !== true) {
      const addToCartForm = document.createElement('ct-add-to-cart-form');
      addToCartForm.product = this.product;
      addToCartForm.handleSkuChange = this.handleSkuChange;
      this.querySelector('.ct-add-to-cart-form').appendChild(addToCartForm);
    }
  }

  async handleSkuChange() {
    this.renderComponent();
  }
}

customElements.define('ct-product-details', ProductDetails);

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

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