UNPKG

@ecomplus/storefront-components

Version:
488 lines (458 loc) 15.3 kB
<section class="product" :data-product-id="body._id" :data-sku="body.sku" :data-selected-variation="selectedVariationId" > <a-alert :can-show="hasLoadError" variant="danger" > {{ i19loadProductErrorMsg }} <a href="#" class="alert-link" @click.prevent="fetchProduct" > {{ i19retry }} </a> </a-alert> <transition enter-active-class="animated fadeIn slower"> <div v-if="body._id" class="row" > <slot name="gallery-col"> <div :class="galleryColClassName"> <component :is="isSSR ? 'portal' : 'div'" selector="#product-gallery" > <slot name="stamps"/> <product-gallery :product="body" :can-add-to-cart="canAddToCart && body.available && isInStock" :current-slide.sync="currentGalleyImg" :is-s-s-r="isSSR" > <slot name="first-picture"/> </product-gallery> <slot name="gallery-footer"/> </component> </div> </slot> <div class="col" ref="actions" > <slot v-if="!isSSR" name="heading" > <component :is="headingTag" class="product__name" > {{ name }} </component> <p class="product__sku"> COD: {{ body.sku }} </p> </slot> <component :is="isSSR ? 'portal' : 'div'" selector="#product-actions" > <slot name="rating"> <div v-once class="product__rating" :data-sku="body.sku" ></div> </slot> <div v-if="!body.available" class="product__unavailable" > <slot name="unavailable"> {{ i19unavailable }} </slot> </div> <div v-else-if="!isInStock" class="product__out-of-stock" > <slot name="out-of-stock"> {{ i19outOfStock }} </slot> </div> <div v-else-if="isWithoutPrice" class="product__without-price" > <slot name="without-price"> <a v-if="quoteLink" target="_blank" rel="noopener" :href="quoteLink" > {{ i19quoteProduct }} </a> </slot> </div> <template v-else> <slot name="prices"> <p class="product__prices"> <a-prices :product="ghostProductForPrices" :is-literal="true" :is-big="true" @fix-price="price => fixedPrice = price" /> <slot name="discount-tag" v-bind="{ discount }" > <span v-if="discount > 0" class="product__discount" > {{ i19discountOf }} <strong>{{ discount }}%</strong> </span> </slot> </p> </slot> <slot name="variations" v-if="hasVariations" > <product-variations :product="body" :selected-id.sync="selectedVariationId" :max-options-btns="maxVariationOptionsBtns" @select-option="handleGridOption" /> <a-alert :can-show="hasClickedBuy && !selectedVariationId"> {{ i19selectVariationMsg }} </a-alert> <slot name="variations-info"/> </slot> <slot name="customizations" v-if="body.customizations" > <div v-for="custom in body.customizations" v-if="custom.custom_value" :key="custom._id" class="product__customization form-group" :class="custom.grid_id ? `product__customization--${custom.grid_id}` : null" > <label :for="`c-${custom._id}`"> {{ custom.label }} <span v-if="custom.add_to_price" class="badge badge-secondary" > {{ formatAdditionalPrice(custom.add_to_price) }} </span> </label> <input type="text" class="form-control" :id="`c-${custom._id}`" @keyup="ev => setCustomizationOption(custom, ev.target.value)" > </div> </slot> <div v-if="isKit" class="product__kit" > <slot name="kit" v-bind="{ kitItems }" > <transition enter-active-class="animated fadeInUp"> <quantity-selector v-if="kitItems.length && !isKitWithVariations" :items="kitItems" :min="body.min_quantity" :max="body.quantity" :slug="body.slug" :kit-product-id="body._id" :kit-name="name" :kit-price="fixedPrice" @buy="d => $emit('buy', d)" > <template #buy-button-content> <slot name="buy-button-content"/> </template> </quantity-selector> <kit-product-variations v-if="kitItems.length && isKitWithVariations" :items="kitItems" :min="body.min_quantity" :max="body.quantity" :slug="body.slug" :kit-product-id="body._id" :kit-name="name" :kit-price="fixedPrice" :max-options-btns="maxVariationOptionsBtns" > <template #buy-button-content> <slot name="buy-button-content"/> </template> </kit-product-variations> </transition> <span v-if="!kitItems.length" class="product__kit-loading spinner-border" role="status" > <span class="sr-only">Loading...</span> </span> </slot> </div> <template v-else> <div v-if="!isVariationInStock" class="product__out-of-stock" > <slot name="out-of-stock"> {{ i19outOfStock }} </slot> </div> <div v-else-if="hasBuyButton" class="product__buy" ref="buy" > <component :is="hasQuantitySelector ? 'quantity-selector' : 'div'" :items="hasQuantitySelector ? [{ _id: body._id, quantity: body.min_quantity || 1 }] : null" :min="body.min_quantity" :max="body.quantity" :has-buy-button="false" @set-quantity="({ quantity }) => qntToBuy = quantity" > <span @click="buy"> <slot name="buy" v-bind="{ hasClickedBuy, isOnCart }" > <button type="button" class="btn btn-lg btn-primary" :disabled="hasClickedBuy && !isOnCart" > <slot name="buy-button-content"> <i class="i-shopping-bag mr-1"></i> {{ strBuy }} </slot> </button> </slot> </span> </component> </div> <p class="product__short-stock" v-if="isLowQuantity" > <i class="i-forward mr-1"></i> {{ i19only }} <strong>{{ productQuantity }}</strong> {{ i19unitsInStock }} </p> </template> <slot name="sale-timer"> <div v-if="isOnSale" class="product__sale-timer mb-3" > <div> {{ i19offer }} <br><small>{{ i19endsIn }}</small> </div> <div class="h1 ml-3 mb-0" ref="timer" > 00:00:00 </div> </div> </slot> <slot name="favorite"> <div> <a class="btn btn-sm product__favorite" @click="toggleFavorite" :href="isLogged ? null : accountUrl" > <i class="i-heart mr-1" :class="isFavorite ? 'active' : null" > </i> <span> {{ isFavorite ? i19removeFromFavorites : i19addToFavorites }} </span> </a> </div> </slot> <slot name="share"> <a-share v-if="body.slug" class="mb-3" :url="`/${body.slug}`" :title="body.name" :description="body.short_description" /> </slot> <transition enter-active-class="animated fadeInUp"> <slot name="payment-gateways" v-bind="{ paymentOptions }" v-if="!isQuickview && paymentOptions.length" > <article> <div class="product__payment card mb-3"> <a id="product-payment-header" class="card-header" role="button" href="#product-payment" data-toggle="collapse" aria-expanded="false" aria-controls="product-payment" > <span>{{ i19paymentOptions }}</span> <i class="i-chevron-down"></i> </a> <div id="product-payment" class="collapse" aria-labelledby="product-payment-header" > <div class="card-body pb-0"> <div v-for="paymentOption in paymentOptions" :key="paymentOption.app_id" :id="`product-payment-${paymentOption.app_id}`" class="mb-3" > <slot :name="`payment-${paymentOption.app_id}`"> <payment-option v-for="(gateway, i) in paymentOption.payment_gateways" :key="`${paymentOption.app_id}-${i}`" :payment-gateway="gateway" :installments-option="paymentOption.installments_option" :price="fixedPrice" /> </slot> </div> </div> </div> </div> </article> </slot> </transition> <p v-if="body.production_time && body.production_time.days" class="product__production" > <i class="i-info-circle mr-1"></i> {{ i19productionDeadline }}: <strong> {{ body.production_time.days }} {{ body.production_time.working_days ? i19workingDays : i19days }} <template v-if="body.production_time.cumulative"> {{ i19perUnit }} </template> </strong> </p> <slot v-if="!isQuickview && (!isKit || kitItems.length)" name="shipping" > <shipping-calculator :shippedItems="isKit ? kitItems : [{ ...body, ...selectedVariation, product_id: body._id, quantity: qntToBuy || body.min_quantity || 1 }]" > <template v-slot:free-from-value="{ amountSubtotal, freeFromValue }"> <div class="product__free-shipping-from"> {{ i19freeShippingFrom }} <strong> {{ Math.ceil(freeFromValue / amountSubtotal) }} {{ i19units }} </strong> </div> </template> </shipping-calculator> </slot> <slot name="track-price"> <div v-once class="product__track-price" :data-sku="body.sku" ></div> </slot> </template> </component> <slot v-if="!isSSR && body.short_description" name="short-description" > <p class="product__info lead"> {{ body.short_description }} </p> </slot> </div> </div> </transition> <template v-if="!isQuickview && hasStickyBuyButton && body.available && isInStock"> <transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut fast" > <div v-show="isStickyBuyVisible" ref="sticky" class="product__sticky" > <div class="product__sticky-container container"> <div class="product__sticky-info"> <a-picture :can-calc-height="false" :src="thumbnail" class="product__sticky-picture" /> <h5>{{ name }}</h5> </div> <div class="product__sticky-buy"> <a-prices :product="ghostProductForPrices" :is-literal="false" :can-show-price-options="true" /> <a class="btn btn-lg btn-primary" href="#" @click.prevent="buyOrScroll" > <i class="i-shopping-bag mr-1"></i> {{ strBuy }} </a> </div> </div> </div> </transition> </template> <slot v-if="!body._id"/> </section>