@salla.sa/twilight-components
Version:
Salla Web Component
166 lines (160 loc) • 9.81 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
import { d as defineCustomElement$2 } from './salla-skeleton2.js';
var DiscountType;
(function (DiscountType) {
DiscountType["PERCENTAGE"] = "percentage";
DiscountType["FIXED"] = "fixed";
DiscountType["FREE_PRODUCT"] = "free_product";
})(DiscountType || (DiscountType = {}));
var OfferType;
(function (OfferType) {
OfferType["PRODUCT_COUNT"] = "products_count";
OfferType["PRODUCT_PURCHASE"] = "order_amount";
})(OfferType || (OfferType = {}));
const sallaConditionalOfferCss = ":host{display:block}";
const SallaConditionalOffer$1 = /*@__PURE__*/ proxyCustomElement(class SallaConditionalOffer extends HTMLElement {
constructor() {
super();
this.__registerHost();
this.offer = null;
this.products = {};
this.isLoading = true;
this.canRender = true;
}
componentWillLoad() {
salla.onReady().then(() => {
var _a, _b, _c;
if (!((_a = salla.config.get('store.features')) === null || _a === void 0 ? void 0 : _a.includes('conditional-offer')) || (salla.storage.get("cart") !== '' && !((_c = (_b = salla.storage.get("cart")) === null || _b === void 0 ? void 0 : _b.summary) === null || _c === void 0 ? void 0 : _c.count))) {
throw new Error('feature or cart object does not existed');
}
})
.then(() => salla.api.cart.offers())
.then(({ data }) => {
//it's okay if there is an exception here, all thens will be skipped, and will catch the error,
this.offer = data.find(offer => offer.type === "conditional");
if (!this.offer) {
throw new Error('No conditional offer has been activated in the merchant dashboard');
}
this.offer.details.discounts.unshift(({ value: 0, min_spend: 0 }));
return this.updateInitialOfferValue();
}).then(() => this.getProducts()).then(() => salla.event.on("cart::updated", (updatedCart) => this.updateOfferValues(updatedCart)))
.catch(error => {
this.canRender = false;
salla.logger.warn('salla-conditional-offer:: ', error);
}).finally(() => {
this.isLoading = false;
});
}
getProducts() {
const freeProductIDs = this.offer.details.discounts.filter(({ type }) => type === DiscountType.FREE_PRODUCT).map(({ value }) => value);
if (freeProductIDs.length > 0) {
return salla.product.fetch({ source: 'selected', source_value: freeProductIDs }).then(({ data }) => {
data.forEach(({ id, url, image }) => {
this.products[id] = { url, image };
});
});
}
}
updateInitialOfferValue() {
return salla.api.cart.details().then(({ data: { cart } }) => this.updateOfferValues(cart));
}
updateOfferValues({ items, total }) {
var _a;
const current_value = this.offer.details.based_on === OfferType.PRODUCT_COUNT ? items.reduce((count, { quantity }) => count + quantity, 0) : total;
//we need to assign the offer object a new reference to trigger re-rendering
this.offer = Object.assign(Object.assign({}, this.offer), { details: Object.assign(Object.assign({}, (_a = this.offer) === null || _a === void 0 ? void 0 : _a.details), { current_value }) });
return this.offer;
}
getCheckpointContent(discount) {
var _a, _b;
if (discount.type === DiscountType.PERCENTAGE)
return `${discount.value}%`;
if (discount.type === DiscountType.FIXED)
return salla.money(discount.value);
if (discount.type !== DiscountType.FREE_PRODUCT) {
salla.logger.error(`salla-conditional-offer:: unexpected type (${discount.type})!`);
return "";
}
const productItem = this.products[discount.value];
if (!productItem) {
salla.logger.error(`salla-conditional-offer:: there is no product with id (${discount.value})!`);
return "";
}
return h("a", { class: "s-conditional-offer-product-link", href: productItem.url }, h("img", { class: "s-conditional-offer-checkpoint-image-content", loading: "lazy", decoding: "async", alt: ((_a = productItem === null || productItem === void 0 ? void 0 : productItem.image) === null || _a === void 0 ? void 0 : _a.alt) || "", src: (_b = productItem === null || productItem === void 0 ? void 0 : productItem.image) === null || _b === void 0 ? void 0 : _b.url }));
}
getOfferType(discount) {
var _a;
const basedOn = (_a = this.offer.details) === null || _a === void 0 ? void 0 : _a.based_on;
if (basedOn === OfferType.PRODUCT_COUNT)
return salla.lang.choice("blocks.header.products_count", discount.min_spend);
if (basedOn === OfferType.PRODUCT_PURCHASE)
return salla.money(discount.min_spend);
salla.logger.warn(`salla-conditional-offer:: Unexpected offer detail's based_on value: ${basedOn}`);
return `${discount.min_spend}`;
}
clamp(value, min, max) {
return Math.max(min, Math.min(value, max));
}
mapValueRanges(value, initialMinRange, initialMaxRange, newMinRange, newMaxRange) {
const newRange = ((value - initialMinRange) * (newMaxRange - newMinRange)) / (initialMaxRange - initialMinRange) + newMinRange;
if (newRange === Number.POSITIVE_INFINITY)
return 100;
if (newRange === Number.NEGATIVE_INFINITY)
return 0;
return this.clamp(newRange, 0, 100);
}
getCheckPointView(discount, index) {
var _a, _b;
const checkpointIndex = this.offer.details.discounts.findIndex(({ min_spend }) => min_spend === discount.min_spend);
const previousCheckpointValue = (_b = (_a = this.offer.details.discounts[checkpointIndex - 1]) === null || _a === void 0 ? void 0 : _a.min_spend) !== null && _b !== void 0 ? _b : 0;
const progressPercentage = this.mapValueRanges(this.offer.details.current_value, previousCheckpointValue, discount.min_spend, 0, 100);
const isActive = discount.min_spend <= this.offer.details.current_value;
return (h("div", { class: "s-conditional-offer-checkpoint-container" }, index > 0 ? [
h("div", { key: "progress-line", class: "s-conditional-offer-progress-line-container" }, h("div", { class: "s-conditional-offer-progress-line-inactive" }), h("div", { class: "s-conditional-offer-progress-line-active", style: { width: `${progressPercentage}%` } })),
h("div", { key: "checkpoint", class: `s-conditional-offer-checkpoint ${isActive ? "s-conditional-offer-active-checkpoint" : ""}` }, h("div", { class: `s-conditional-offer-item-avatar-content ${isActive ? "active" : ""}`, innerHTML: this.products && this.getCheckpointContent(discount) }), h("div", { class: `s-conditional-offer-checkpoint-label ${isActive ? "active" : ""}`, innerHTML: this.getOfferType(discount) }))
] :
h("div", { key: "label", class: { "s-conditional-offer-checkpoint-label": true, "first-checkpoint": index === 0, active: isActive }, innerHTML: this.getOfferType(discount) })));
}
getLoadingSkeletonView() {
return h(Host, { class: "s-conditional-offer-container" }, h("div", { class: "s-conditional-offer-skeleton-inner-container" }, h("div", { class: "s-conditional-offer-skeleton-subtitle" }, h("salla-skeleton", { height: "16px", width: "30%" })), h("div", { class: "s-conditional-offer-skeleton-subtitle" }, h("salla-skeleton", { height: "16px", width: "35%" })), h("div", { class: "s-conditional-offer-skeleton-checkpoints-wrapper" }, Array(3).fill(null).map(() => ([h("salla-skeleton", { key: "checkpoint-line", height: "8px" }), h("div", { key: "checkpoint" }, h("salla-skeleton", { height: "60px", width: "60px", type: "circle" }))])))));
}
render() {
if (!this.canRender)
return null;
if (this.isLoading)
return this.getLoadingSkeletonView();
return h(Host, { class: "s-conditional-offer-container" }, h("div", { class: "s-conditional-offer-title-wrapper" }, h("div", { class: "s-conditional-offer-title" }, this.offer.title), this.offer.description ? h("div", { class: "s-conditional-offer-subtitle" }, this.offer.description, " ", h("i", { class: "sicon-information" })) : null), h("div", { class: "s-conditional-offer-progress-container" }, this.offer.details.discounts.map((discount, index) => (h("div", { class: { "flex-1": index > 0 }, key: discount.min_spend }, this.getCheckPointView(discount, index))))));
}
static get style() { return sallaConditionalOfferCss; }
}, [0, "salla-conditional-offer", {
"offer": [32],
"products": [32],
"isLoading": [32],
"canRender": [32]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["salla-conditional-offer", "salla-skeleton"];
components.forEach(tagName => { switch (tagName) {
case "salla-conditional-offer":
if (!customElements.get(tagName)) {
customElements.define(tagName, SallaConditionalOffer$1);
}
break;
case "salla-skeleton":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
} });
}
const SallaConditionalOffer = SallaConditionalOffer$1;
const defineCustomElement = defineCustomElement$1;
export { SallaConditionalOffer, defineCustomElement };
//# sourceMappingURL=salla-conditional-offer.js.map
//# sourceMappingURL=salla-conditional-offer.js.map