@salla.sa/twilight-components
Version:
Salla Web Component
257 lines (256 loc) • 11.2 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { Host, h } from "@stencil/core";
import BellRingIcon from "../../assets/svg/bell-ring.svg";
import Helper from "../../Helpers/Helper";
export class SallaProductAvailability {
constructor() {
this.isUser = salla.config.isUser();
this.translationLoaded = false;
/**
* Listen to product options availability.
*/
this.notifyOptionsAvailability = false;
/**
* is current user already subscribed
*/
this.isSubscribed = false;
this.handleSubmitOptions = async () => {
let payload = { id: this.productId };
if (!this.notifyOptionsAvailability) {
return payload;
}
let optionsElement = document.querySelector(`salla-product-options[product-id="${this.productId}"]`);
let options = Object.values(await optionsElement?.getSelectedOptionsData() || {});
//if all options not selected, show message && throw exception
if (options.length && !await optionsElement?.reportValidity()) {
let errorMessage = salla.lang.get('common.messages.required_fields');
salla.error(errorMessage);
throw errorMessage;
}
payload.options = [];
options.forEach(option => {
//inject numbers only, without zeros
if (option && !isNaN(option)) {
payload.options.push(Number(option));
}
});
return payload;
};
// helpers
this.typing = (e) => {
const error = e.target.nextElementSibling;
e.target.classList.remove('s-has-error');
error?.classList.contains('s-product-availability-error-msg') && (error.innerText = '');
e.keyCode === 13 && this.submit();
};
salla.lang.onLoaded(() => {
this.translationLoaded = true;
this.title_ = this.host.title || salla.lang.get('pages.products.notify_availability_title');
this.modal?.setTitle(this.title_);
});
if (!this.productId) {
this.productId = salla.config.get('page.id');
}
if (this.isUser)
return;
this.channelsWatcher(this.channels);
this.title_ = this.host.title || salla.lang.get('pages.products.notify_availability_title');
this.host.removeAttribute('title');
//todo:: fix this to cover options too
this.isVisitorSubscribed = !this.notifyOptionsAvailability ? salla.storage.get(`product-${this.productId}-subscribed`) : '';
}
channelsWatcher(newValue) {
this.channels_ = !!newValue ? newValue.split(',') : [];
}
openModel() {
this.handleSubmitOptions().then(isSuccess => isSuccess ? this.modal.open() : null);
}
async submit() {
let payload = await this.handleSubmitOptions();
if (this.isUser) {
return salla.api.product.availabilitySubscribe(payload)
.then(() => this.isSubscribed = true);
}
if (this.channels_.includes('sms')) {
let { phone, countryCode } = await this.mobileInput.getValues();
payload['country_code'] = countryCode;
payload['phone'] = phone;
}
if (this.channels_.includes('email')) {
this.email.value !== '' && (payload['email'] = this.email.value);
}
await this.validateform();
return this.btn.load()
.then(() => this.btn.disable())
.then(() => salla.api.product.availabilitySubscribe(payload))
.then(() => {
if (!this.notifyOptionsAvailability) {
salla.storage.set(`product-${this.productId}-subscribed`, true);
this.isSubscribed = true;
return;
}
if (payload.options.length) {
let options = salla.storage.get(`product-${this.productId}-subscribed-options`) || [];
let selectedOptionsString = payload.options.join(',');
if (!options.includes(selectedOptionsString)) {
options.push(selectedOptionsString);
salla.storage.set(`product-${this.productId}-subscribed-options`, options);
this.isSubscribed = true;
}
else {
salla.log('already subscribed to this options');
}
}
})
.then(() => this.btn.stop())
.then(() => this.modal.close())
.catch(() => this.btn.stop() && this.btn.enable());
}
async validateform() {
try {
if (this.channels_.includes('email')) {
const isEmailValid = Helper.isValidEmail(this.email.value);
if (isEmailValid)
return;
!isEmailValid && this.validateField(this.email, salla.lang.get('common.elements.email_is_valid'));
}
if (this.channels_.includes('sms')) {
const isPhoneValid = await this.mobileInput.isValid();
if (isPhoneValid)
return;
}
}
catch (error) {
throw ('Please insert required fields');
}
}
validateField(field, errorMsg) {
field.classList.add('s-has-error');
field.nextElementSibling['innerText'] = '* ' + errorMsg;
}
render() {
return (h(Host, { key: 'aa627ba618b159913ad91efba99e57c14dd27832', class: "s-product-availability-wrap" }, this.isSubscribed || this.isVisitorSubscribed
? h("div", { class: "s-product-availability-subscribed" }, h("span", { innerHTML: BellRingIcon, class: "s-product-availability-subs-icon" }), salla.lang.get('pages.products.notify_availability_success'))
:
h("salla-button", { width: "wide", onClick: () => this.isUser ? this.submit() : this.openModel() }, salla.lang.get('pages.products.notify_availability')), this.isUser || this.isSubscribed || this.isVisitorSubscribed ? '' : this.renderModal()));
}
renderModal() {
return (h("salla-modal", { ref: modal => this.modal = modal, "modal-title": this.title_, subTitle: salla.lang.get('pages.products.notify_availability_subtitle'), width: "sm" }, h("span", { slot: 'icon', class: "s-product-availability-header-icon", innerHTML: BellRingIcon }), h("div", { class: "s-product-availability-body" }, this.channels_.includes('email') ? [
h("label", { class: "s-product-availability-label" }, salla.lang.get('common.elements.email')),
h("input", { class: "s-product-availability-input", onKeyDown: e => this.typing(e), placeholder: salla.lang.get('common.elements.email_placeholder') || 'your@email.com', ref: el => this.email = el, type: "email" }),
h("span", { class: "s-product-availability-error-msg" })
] : '', this.channels_.includes('sms') ? [
h("label", { class: "s-product-availability-label" }, salla.lang.get('common.elements.mobile')),
h("salla-tel-input", { ref: el => this.mobileInput = el, onKeyDown: e => this.typing(e) })
] : ''), h("div", { slot: "footer", class: "s-product-availability-footer" }, h("salla-button", { class: "modal-cancel-btn", width: "wide", color: "light", fill: "outline", onClick: () => this.modal.close() }, salla.lang.get('common.elements.cancel')), h("salla-button", { class: "submit-btn", "loader-position": 'center', width: "wide", ref: btn => this.btn = btn, onClick: () => this.submit() }, salla.lang.get('common.elements.submit')))));
}
static get is() { return "salla-product-availability"; }
static get originalStyleUrls() {
return {
"$": ["salla-product-availability.scss"]
};
}
static get styleUrls() {
return {
"$": ["salla-product-availability.css"]
};
}
static get properties() {
return {
"channels": {
"type": "string",
"attribute": "channels",
"mutable": false,
"complexType": {
"original": "'sms' | 'email' | 'sms,email'",
"resolved": "\"email\" | \"sms\" | \"sms,email\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Notification channels"
},
"getter": false,
"setter": false,
"reflect": false
},
"notifyOptionsAvailability": {
"type": "boolean",
"attribute": "notify-options-availability",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Listen to product options availability."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"productId": {
"type": "number",
"attribute": "product-id",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "product id that can visitor subscribe to its availability notification"
},
"getter": false,
"setter": false,
"reflect": false
},
"isSubscribed": {
"type": "boolean",
"attribute": "is-subscribed",
"mutable": true,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "is current user already subscribed"
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
}
};
}
static get states() {
return {
"translationLoaded": {},
"title_": {},
"isVisitorSubscribed": {}
};
}
static get elementRef() { return "host"; }
static get watchers() {
return [{
"propName": "channels",
"methodName": "channelsWatcher"
}];
}
}