@salla.sa/twilight-components
Version:
Salla Web Component
283 lines (274 loc) • 15.2 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
import { A as ArrowDown } from './keyboard_arrow_down.js';
import { B as BellRing } from './bell-ring.js';
import { P as PendingOrdersIcon } from './cart.js';
import { W as WishListIcon } from './star.js';
import { C as Cancel } from './cancel.js';
import { R as Rate } from './star2.js';
var OrderIcon = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>box-bankers</title>
<path d="M28 1.333h-24c-2.205 0-4 1.795-4 4v5.333c0 0.736 0.597 1.333 1.333 1.333v14.667c0 2.205 1.795 4 4 4h21.333c2.205 0 4-1.795 4-4v-14.667c0.736 0 1.333-0.597 1.333-1.333v-5.333c0-2.205-1.795-4-4-4zM28 26.667c0 0.735-0.599 1.333-1.333 1.333h-21.333c-0.735 0-1.333-0.599-1.333-1.333v-14.667h5.333v2.667c0 1.471 1.196 2.667 2.667 2.667h8c1.471 0 2.667-1.196 2.667-2.667v-2.667h5.333zM12 14.667v-2.667h8v2.667zM29.333 9.333h-26.667v-4c0-0.735 0.599-1.333 1.333-1.333h24c0.735 0 1.333 0.599 1.333 1.333z"></path>
</svg>
`;
var UserCircle = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>user-circle</title>
<path d="M16 22.964c-4.525 0-8.447 1.713-9.993 4.365-0.371 0.636-0.156 1.452 0.48 1.823s1.453 0.156 1.823-0.48c0.855-1.465 3.624-3.041 7.689-3.041s6.835 1.576 7.689 3.041c0.249 0.424 0.696 0.661 1.155 0.661 0.228 0 0.459-0.059 0.669-0.181 0.637-0.371 0.852-1.187 0.48-1.823-1.545-2.652-5.467-4.365-9.992-4.365zM22.667 13.631c0-3.676-2.991-6.667-6.667-6.667s-6.667 2.991-6.667 6.667 2.991 6.667 6.667 6.667 6.667-2.992 6.667-6.667zM12 13.631c0-2.205 1.795-4 4-4s4 1.795 4 4-1.795 4-4 4-4-1.795-4-4zM16 0.297c-8.823 0-16 7.177-16 16 0 2.941 0.821 5.831 2.373 8.357 0.252 0.411 0.689 0.636 1.137 0.636 0.239 0 0.479-0.064 0.696-0.197 0.628-0.385 0.824-1.207 0.439-1.833-1.295-2.108-1.979-4.516-1.979-6.963 0-7.352 5.981-13.333 13.333-13.333s13.333 5.981 13.333 13.333c0 2.448-0.684 4.856-1.979 6.961-0.385 0.628-0.189 1.448 0.437 1.835 0.627 0.384 1.448 0.189 1.835-0.437 1.553-2.527 2.373-5.416 2.373-8.359 0-8.823-7.177-16-16-16z"></path>
</svg>
`;
var LogoutIcon = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>send-out</title>
<path d="M16 26.667h-9.333c-0.736 0-1.333-0.597-1.333-1.333v-18.667c0-0.736 0.597-1.333 1.333-1.333h9.333c0.737 0 1.333-0.596 1.333-1.333s-0.596-1.333-1.333-1.333h-9.333c-2.205 0-4 1.795-4 4v18.667c0 2.205 1.795 4 4 4h9.333c0.737 0 1.333-0.596 1.333-1.333s-0.596-1.333-1.333-1.333zM29.231 15.491c-0.068-0.164-0.167-0.312-0.289-0.436l-5.332-5.332c-0.521-0.521-1.364-0.521-1.885 0s-0.521 1.364 0 1.885l3.057 3.059h-12.781c-0.737 0-1.333 0.596-1.333 1.333s0.596 1.333 1.333 1.333h12.781l-3.057 3.057c-0.521 0.521-0.521 1.364 0 1.885 0.26 0.26 0.601 0.391 0.943 0.391s0.683-0.131 0.943-0.391l5.332-5.332c0.124-0.123 0.221-0.271 0.289-0.435 0.135-0.325 0.135-0.693 0-1.019z"></path>
</svg>
`;
var WalletIcon = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>wallet</title>
<path d="M28 6.667h-24c-0.736 0-1.333-0.597-1.333-1.333s0.597-1.333 1.333-1.333h24c0.737 0 1.333-0.596 1.333-1.333s-0.596-1.333-1.333-1.333h-24c-2.204 0-3.999 1.793-4 3.997v18.669c0 3.676 2.991 6.667 6.667 6.667h21.333c2.205 0 4-1.795 4-4v-16c0-2.205-1.795-4-4-4zM29.333 26.667c0 0.736-0.597 1.333-1.333 1.333h-21.333c-2.205 0-4-1.795-4-4v-14.895c0.416 0.147 0.865 0.228 1.333 0.228h24c0.736 0 1.333 0.597 1.333 1.333zM22.667 14.667c-2.205 0-4 1.795-4 4s1.795 4 4 4 4-1.795 4-4-1.795-4-4-4zM22.667 20c-0.736 0-1.333-0.597-1.333-1.333s0.597-1.333 1.333-1.333 1.333 0.597 1.333 1.333-0.597 1.333-1.333 1.333z"></path>
</svg>
`;
const sallaUserMenuCss = "";
const SallaUserMenu$1 = /*@__PURE__*/ proxyCustomElement(class SallaUserMenu extends HTMLElement {
constructor() {
super();
this.__registerHost();
this.items = {
notifications: BellRing,
orders: OrderIcon,
pending_orders: PendingOrdersIcon,
wishlist: WishListIcon,
profile: UserCircle,
wallet: WalletIcon,
};
this.accountLoading = false;
this.opened = false;
this.notifications = salla.lang.get('common.titles.notifications');
this.orders = salla.lang.get('common.titles.orders');
this.pending_orders = salla.lang.get('common.titles.pending_orders');
this.wishlist = salla.lang.get('common.titles.wishlist');
this.profile = salla.lang.get('common.titles.profile');
this.rating = salla.lang.get('common.titles.rating');
this.wallet = salla.lang.get('common.titles.wallet');
this.logout = salla.lang.get('blocks.header.logout');
this.hello = salla.lang.get('pages.checkout.hello');
this.first_name = salla.storage.get('user.first_name') || '';
this.last_name = salla.storage.get('user.last_name') || '';
this.avatar = salla.storage.get('user.avatar') || salla.url.cdn('images/avatar.png', 40, 40);
this.badges = {
notifications: salla.helpers.number(salla.storage.get('user.notifications') || 0),
pending_orders: salla.helpers.number(salla.storage.get('user.pending_orders') || 0),
};
this.hasBadges = Number(salla.storage.get('user.pending_orders')) > 0 ||
Number(salla.storage.get('user.notifications')) > 0;
/**
* To display only the list without the dropdown functionality
*/
this.inline = false;
/**
* To display the trigger as an avatar only
*/
this.avatarOnly = false;
/**
* To display the dropdown header in mobile sheet
*/
this.showHeader = false;
/**
* To Make the dropdown menu relative to parent element or not
*/
this.relativeDropdown = false;
this.onClickOutside = () => {
this.opened = false;
};
this.OrderUpdate = 0;
// salla.auth.event.onLoggedIn(() => {
// this.is_loggedIn = true
// })
salla.lang.onLoaded(() => {
this.notifications = salla.lang.get('common.titles.notifications');
this.orders = salla.lang.get('common.titles.orders');
this.pending_orders = salla.lang.get('common.titles.pending_orders');
this.wishlist = salla.lang.get('common.titles.wishlist');
this.profile = salla.lang.get('common.titles.profile');
this.hello = salla.lang.get('pages.checkout.hello');
this.rating = salla.lang.get('common.titles.rating');
this.wallet = salla.lang.get('common.titles.wallet');
this.logout = salla.lang.get('blocks.header.logout');
});
//we need it only in theme-y
if (this.host.hasAttribute('with-rating')) {
this.items.rating = Rate;
}
//we need it to be the last item
this.items.logout = LogoutIcon;
salla.onReady(() => {
if (salla.config.isGuest()) {
return;
}
this.is_loggedIn = true;
/**
* Get Fresh Notifications In These Cases:
* - is notification page, if user already changed the status of his orders (to reset notification badge)
* - is pending orders page, if user already changed the status of his orders (to reset orders badge)
* - is profile page, in case user changed his name or avatar, we need to update it
* - half hour is passed from the last user data fetched
*
* //todo:: update the data in the storage in customer pages
* //todo:: cover two requests in customer pages
* //todo:: make sure to run this only after token is set
*/
const shouldFetchProfile = !this.inline &&
(salla.url.is_page('customer.notifications') ||
salla.url.is_page('customer.orders.index.pending') ||
salla.url.is_page('customer.profile') ||
(Date.now() - (salla.storage.get('user.fetched_at') || 0)) / 1000 / 60 > 30);
if (shouldFetchProfile) {
this.fetchFreshProfile();
}
else {
salla.event.on('profile::info.fetched', res => {
this.updateProfileState(res);
});
}
});
}
componentWillLoad() {
return new Promise(resolve => salla.onReady(resolve)).then(() => {
let trigger = this.host.querySelector('[slot="trigger"]');
this.triggerSlot =
'<div class="s-user-menu-trigger"><div class="s-user-menu-avatar-wrap"><img class="s-user-menu-trigger-avatar" src="{avatar}" alt="{first_name}{last_name}" /></div><div class="s-user-menu-trigger-content"><span class="s-user-menu-trigger-hello">{hello}</span><p class="s-user-menu-trigger-name">{first_name} {last_name}</p></div> <i class="s-user-menu-trigger-icon">{icon}</i></div>';
if (!trigger) {
return;
}
this.triggerSlot = trigger.innerHTML;
trigger.innerHTML = this.replaceParams(trigger.innerHTML);
});
}
fetchFreshProfile() {
//don't request fetchFreshProfile unless token is injected into the api
if (!salla.api.token) {
salla.log('trying to fetchFreshProfile before injected the token!!');
return;
}
salla.profile.api.info().then(res => {
this.updateProfileState(res);
});
}
updateProfileState(res) {
this.badges = {
notifications: salla.helpers.number(res.data.notifications || 0),
pending_orders: salla.helpers.number(res.data.pending_orders || 0),
};
this.hasBadges = Number(res.data.pending_orders) > 0 || Number(res.data.notifications) > 0;
this.first_name = res.data.first_name;
this.last_name = res.data.last_name;
this.avatar = res.data.avatar || salla.url.cdn('images/avatar.png', 40, 40);
}
async open(e) {
this.opened = !this.opened;
e.stopPropagation();
if (this.opened) {
window.addEventListener('click', this.onClickOutside);
}
}
menuItemClicked(event, item) {
if (item[0] !== 'logout') {
return;
}
event.preventDefault();
salla.auth.logout('sall-user-menu');
}
replaceParams(body) {
return body
.replace(/\{hello\}/g, this.hello)
.replace(/\{first_name\}/g, this.first_name)
.replace(/\{last_name\}/g, this.last_name)
.replace(/\{avatar\}/g, this.avatar)
.replace(/\{icon\}/g, ArrowDown);
}
getTheHeader() {
return (h("div", { class: {
's-user-menu-trigger-slot': true,
's-user-menu-red-dot': this.hasBadges,
's-user-menu-trigger-avatar-only': this.avatarOnly,
}, id: "trigger-slot", onClick: e => this.open(e), innerHTML: this.replaceParams(this.triggerSlot) }));
}
getMenuItem(item, i) {
//todo:: enhancement support slot here
if (item[0] === 'wallet' && !window.can_access_wallet)
return;
return (h("li", { class: {
's-user-menu-dropdown-item': true,
's-user-menu-dropdown-item-logout': i + 1 == Object.entries(this.items).length,
} }, h("a", { href: salla.url.get(item[0]), onClick: event => this.menuItemClicked(event, item) }, h("i", { innerHTML: item[1] }, " "), h("span", { class: "s-user-menu-dropdown-item-title" }, this[item[0]]), !['٠', '0', undefined].includes(this.badges[item[0]]) ? (h("span", { class: "s-user-menu-dropdown-item-badge" }, this.badges[item[0]])) : (''))));
}
componentShouldUpdate() {
if (!this.opened) {
window.removeEventListener('click', this.onClickOutside);
}
}
render() {
if (!this.is_loggedIn) {
return (h(Host, null, h("slot", { name: "login-btn" }, h("button", { class: "s-user-menu-login-btn", onClick: () => salla.event.dispatch('login::open'), innerHTML: UserCircle }))));
}
if (this.inline) {
return (h(Host, null, h("ul", { class: "s-user-menu-inline" }, Object.entries(this.items).map((item, i) => this.getMenuItem(item, i)))));
}
return (h(Host, null, h("div", { class: {
's-user-menu-wrapper': true,
's-user-menu-relative-dropdown': this.relativeDropdown,
} }, this.getTheHeader(), h("div", { class: { 's-user-menu-toggler': true, opened: this.opened } }, h("div", { class: "s-user-menu-dropdown", onClick: e => e.stopPropagation() }, this.showHeader ? (h("div", { class: "s-user-menu-dropdown-header" }, h("img", { src: this.avatar, alt: `${this.first_name} ${this.last_name}` }), h("div", { class: "s-user-menu-dropdown-header-content" }, h("span", null, this.hello), h("p", null, this.first_name, " ", this.last_name)), h("button", { class: "s-user-menu-dropdown-header-close", innerHTML: Cancel, onClick: () => (this.opened = false) }))) : (''), h("ul", { class: "s-user-menu-dropdown-list" }, Object.entries(this.items).map((item, i) => this.getMenuItem(item, i))))))));
}
componentDidLoad() {
var _a;
//make sure to load the avatar if it's lazy, we use it in Y
(_a = document.lazyLoadInstance) === null || _a === void 0 ? void 0 : _a.update(this.host.querySelectorAll('.lazy'));
}
get host() { return this; }
static get style() { return sallaUserMenuCss; }
}, [4, "salla-user-menu", {
"inline": [516],
"avatarOnly": [516, "avatar-only"],
"showHeader": [516, "show-header"],
"relativeDropdown": [516, "relative-dropdown"],
"accountLoading": [32],
"opened": [32],
"notifications": [32],
"orders": [32],
"pending_orders": [32],
"wishlist": [32],
"profile": [32],
"rating": [32],
"wallet": [32],
"logout": [32],
"hello": [32],
"first_name": [32],
"last_name": [32],
"avatar": [32],
"is_loggedIn": [32],
"badges": [32],
"hasBadges": [32],
"OrderUpdate": [32]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["salla-user-menu"];
components.forEach(tagName => { switch (tagName) {
case "salla-user-menu":
if (!customElements.get(tagName)) {
customElements.define(tagName, SallaUserMenu$1);
}
break;
} });
}
const SallaUserMenu = SallaUserMenu$1;
const defineCustomElement = defineCustomElement$1;
export { SallaUserMenu, defineCustomElement };
//# sourceMappingURL=salla-user-menu.js.map
//# sourceMappingURL=salla-user-menu.js.map