shopper
Version:
plug shopify into any website
111 lines (100 loc) • 3.58 kB
text/typescript
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) {
({type: Object}) cartItem: CartItem
({type: String, reflect: true}) ["gid"]: string
({type: String, reflect: true}) ["uid"]: string
({type: String, reflect: true}) ["link"]: string
({type: String, reflect: true}) ["href"]: string
({type: String, reflect: true}) ["sale"]: string
({type: String, reflect: true}) ["image-size"]: string
({type: Boolean, reflect: true}) ["in-cart"]: boolean = false
({type: Boolean, reflect: true}) ["show-image"]: boolean = false
({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>
`
}
}