commercetools-8.x-1.2-alpha1/modules/commercetools_decoupled/js/molecules/ProductListItem.js
modules/commercetools_decoupled/js/molecules/ProductListItem.js
class ProductListItem extends HTMLElement {
connectedCallback() {
const placeholderProduct = {
name: 'Placeholder for title',
slug: 'placeholder-path',
masterVariant: {
images: [{ url: '' }],
price: { localizedPrice: '$1000' },
},
isLoading: true,
};
const product = this.isLoading !== true ? this.product : placeholderProduct;
this.name = product.name;
if (!product.slug) {
new Drupal.Message().add(
'The product slug value is missing for a product.',
{ type: 'error' },
);
}
this.path = Drupal.url(
`${drupalSettings.commercetoolsDecoupled.catalogPath.substring(1)}/${product.slug}`,
);
this.image = product?.masterVariant?.images?.[0]?.url ?? '';
if (this.image) {
this.image = window.commercetools.applyImageStyle(this.image);
}
this.price = product?.masterVariant?.price ?? {};
this.isLoading = product.isLoading;
const priceHtml = this.price?.discounted?.localizedPrice
? `${this.price?.localizedPrice ? `<del>${this.price.localizedPrice}</del>` : ''} <span class="discount text-danger">${this.price.discounted.localizedPrice}</span>`
: this.price?.localizedPrice || '';
this.innerHTML = /* html */ `
<figure class="card flex-row h-100${this.isLoading ? ' placeholderify' : ''}">
<div class="container">
<div class="row">
<div class="col-4">
<a class="h-100" href="${this.path}">
<div class="h-100 d-flex flex-wrap align-items-center">
<img src="${this.image}" class="p-2 m-auto max-width" alt="${this.name}" style="max-height: 16rem; width: auto; max-width: 100%">
</div>
</a>
</div>
<div class="col-8 card-body d-flex flex-column">
<h2 class="card-title fs-5 text-truncate text-primary"><a class="text-decoration-none" href="${this.path}">${this.name}</a></h2>
<div class="border-top py-3 mb-3">
${
this.isLoading || !product?.masterVariant?.attributes
? ''
: Object.values(product.masterVariant.attributes)
.map((attr) => {
attr.key = attr.name;
document.dispatchEvent(
new CustomEvent(
'commercetools:productAttributeLabel',
{ detail: attr },
),
);
return `
<div class="fw-medium">
<span>${attr.label}: </span>
<span ${attr.name === 'color' || attr.name === 'finish' ? '' : `style="white-space: pre-wrap;"`}>${attr.labelValue}</span>
</div>
`;
})
.join('')
}
</div>
<div class="border-top pt-3">
<a href="${this.path}" class="card-btn btn btn-primary btn-sm float-end">${Drupal.t('Details')}</a>
${priceHtml ? `<span class="price">${priceHtml}</span>` : ''}
</div>
</div>
</div>
</div>
</figure>
`;
}
setLoadingState(state = null) {
const stateClasses = {
load: 'placeholderify',
reload: 'reloadify',
};
this.querySelectorAll('figure.card').forEach((card) => {
card.classList.remove(...Object.values(stateClasses));
const stateClass = stateClasses[state];
if (state !== null && stateClass) {
card.classList.add(stateClass);
}
});
}
}
customElements.define('ct-product-list-item', ProductListItem);
