UNPKG

shopper

Version:
111 lines (100 loc) 3.58 kB
import {property} from "lit/decorators.js" import {html, css, TemplateResult} from "lit" import {LightDom} from "../framework/light-dom.js" import {isDefined} from "../toolbox/is-defined.js" import {ShopperState, CartItem, ShopperModel} from "../interfaces.js" import {calculatePercentOff} from "../toolbox/calculate-percent-off.js" import {chooseShopifyId} from "../toolbox/shopify-ids/choose-shopify-id.js" import {LoadableState, LoadableComponent} from "../framework/loadable-component.js" import {parseImageSize, sizeShopifyImage} from "./shopify-utils/size-shopify-image.js" export class ShopperProduct extends LightDom(LoadableComponent) { @property({type: Object}) cartItem: CartItem @property({type: String, reflect: true}) ["gid"]: string @property({type: String, reflect: true}) ["uid"]: string @property({type: String, reflect: true}) ["link"]: string @property({type: String, reflect: true}) ["href"]: string @property({type: String, reflect: true}) ["sale"]: string @property({type: String, reflect: true}) ["image-size"]: string @property({type: Boolean, reflect: true}) ["in-cart"]: boolean = false @property({type: Boolean, reflect: true}) ["show-image"]: boolean = false @property({type: Boolean, reflect: true}) ["out-of-stock"]: boolean = false static get styles() {return [...super.styles, css``]} get shopifyId() { const {gid, uid, link} = this return chooseShopifyId({gid, uid, link}) } shopperUpdate(state: ShopperState, {getters}: ShopperModel) { this.cartItem = state.catalog.find(item => item.product.id === this.shopifyId) this.loadableState = this.cartItem ? LoadableState.Ready : state.error ? LoadableState.Error : LoadableState.Loading this["in-cart"] = getters.itemsInCart.includes(this.cartItem) this["out-of-stock"] = this.cartItem ? !this.cartItem.product.available : false this["sale"] = this.cartItem ? isDefined(this.cartItem.product.comparedValue) ? calculatePercentOff({ currentValue: this.cartItem.product.value, comparisonValue: this.cartItem.product.comparedValue, }).toString() : undefined : undefined } private _handleAddToCart = () => { this.model.actions.addToCart(this.cartItem) } renderReady() { const {cartItem, _handleAddToCart} = this const href = this["href"] const inCart = this["in-cart"] const showImage = this["show-image"] const outOfStock = this["out-of-stock"] const imageSize = this["image-size"] const value = this.model.getters.getUnitValue(cartItem) const {product} = cartItem const linkify = (content: TemplateResult) => href ? html`<a href=${href}>${content}</a>` : content return !cartItem ? null : html` ${(showImage && product.image) ? html` <div class=product-image> ${linkify(html` <img src=${sizeShopifyImage( product.image.src, parseImageSize(imageSize), )} alt=${product.image.alt} /> `)} </div> ` : null} <div class=product-content> <h3 class=title> ${linkify(html`${product.title}`)} </h3> ${outOfStock ? html`<p class=out-of-stock>Out of stock</p>` : null} <div class=box> <crnc-price value="${value}" comparison="${product.comparedValue}" ></crnc-price> <button class=add-to-cart-button title=${inCart ? undefined : "Add to Cart"} @click=${_handleAddToCart} ?disabled=${outOfStock || inCart}> ${outOfStock ? "Sold out" : inCart ? "In Cart" : "Add to Cart"} </button> </div> </div> ` } }