Merged with master
This commit is contained in:
commit
4e7b1f157b
|
|
@ -96,6 +96,12 @@ class EventServiceProvider extends ServiceProvider
|
|||
Event::listen('admin.acl.build', function ($acl) {
|
||||
$acl->add('dashboard', 'Dashboard', 'admin.dashboard.index', 1);
|
||||
|
||||
$acl->add('catalog', 'Catalog', 'admin.catalog.index', 2);
|
||||
|
||||
$acl->add('catalog.products', 'Products', 'admin.catalog.products.index', 1);
|
||||
|
||||
$acl->add('catalog.categories', 'Categories', 'admin.catalog.categories.index', 1);
|
||||
|
||||
$acl->add('configuration', 'Configure', 'admin.account.edit', 5);
|
||||
|
||||
$acl->add('settings', 'Settings', 'admin.users.index', 6);
|
||||
|
|
|
|||
|
|
@ -134,6 +134,22 @@ class Product extends Model
|
|||
return $this->attribute_family->custom_attributes->pluck('code')->contains($attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSaleable()
|
||||
{
|
||||
if($this->status) {
|
||||
if($this->inventories->sum('qty')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an attribute from the model.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Product;
|
||||
|
||||
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
|
||||
use Webkul\Product\Product\Gallery;
|
||||
use Webkul\Product\Product\Price;
|
||||
|
||||
class ConfigurableOption extends AbstractProduct
|
||||
{
|
||||
/**
|
||||
* AttributeOptionRepository object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributeOption;
|
||||
|
||||
/**
|
||||
* Gallery object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $gallery;
|
||||
|
||||
/**
|
||||
* Price object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $price;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param Webkul\Attribute\Repositories\AttributeOptionRepository $attributeOption
|
||||
* @param Webkul\Product\Product\Gallery $gallery
|
||||
* @param Webkul\Product\Product\Price $price
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
AttributeOption $attributeOption,
|
||||
Gallery $gallery,
|
||||
Price $price
|
||||
)
|
||||
{
|
||||
$this->attributeOption = $attributeOption;
|
||||
|
||||
$this->gallery = $gallery;
|
||||
|
||||
$this->price = $price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the allowed variants
|
||||
*
|
||||
* @param Product $product
|
||||
* @return float
|
||||
*/
|
||||
public function getAllowProducts($product)
|
||||
{
|
||||
$variants = [];
|
||||
|
||||
foreach ($product->variants as $variant) {
|
||||
if ($variant->isSaleable()) {
|
||||
$variants[] = $variant;
|
||||
}
|
||||
}
|
||||
|
||||
return $variants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the allowed variants JSON
|
||||
*
|
||||
* @param Product $product
|
||||
* @return float
|
||||
*/
|
||||
public function getConfigurationConfig($product)
|
||||
{
|
||||
$options = $this->getOptions($product, $this->getAllowProducts($product));
|
||||
|
||||
$config = [
|
||||
'attributes' => $this->getAttributesData($product, $options),
|
||||
'index' => isset($options['index']) ? $options['index'] : [],
|
||||
'regular_price' => [
|
||||
'formated_price' => core()->currency($this->price->getMinimalPrice($product)),
|
||||
'price' => $this->price->getMinimalPrice($product)
|
||||
],
|
||||
'variant_prices' => $this->getVariantPrices($product),
|
||||
'variant_images' => $this->getVariantImages($product),
|
||||
'chooseText' => trans('shop::app.products.choose-option')
|
||||
];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowed attributes
|
||||
*
|
||||
* @param Product $product
|
||||
* @return array
|
||||
*/
|
||||
public function getAllowAttributes($product)
|
||||
{
|
||||
return $product->super_attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Configurable Product Options
|
||||
*
|
||||
* @param Product $currentProduct
|
||||
* @param array $allowedProducts
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions($currentProduct, $allowedProducts)
|
||||
{
|
||||
$options = [];
|
||||
|
||||
$allowAttributes = $this->getAllowAttributes($currentProduct);
|
||||
|
||||
foreach ($allowedProducts as $product) {
|
||||
|
||||
$productId = $product->id;
|
||||
|
||||
foreach ($allowAttributes as $productAttribute) {
|
||||
$productAttributeId = $productAttribute->id;
|
||||
|
||||
$attributeValue = $product->{$productAttribute->code};
|
||||
|
||||
$options[$productAttributeId][$attributeValue][] = $productId;
|
||||
|
||||
$options['index'][$productId][$productAttributeId] = $attributeValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product attributes
|
||||
*
|
||||
* @param Product $product
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributesData($product, array $options = [])
|
||||
{
|
||||
$defaultValues = [];
|
||||
|
||||
$attributes = [];
|
||||
|
||||
foreach ($product->super_attributes as $attribute) {
|
||||
|
||||
$attributeOptionsData = $this->getAttributeOptionsData($attribute, $options);
|
||||
|
||||
if ($attributeOptionsData) {
|
||||
$attributeId = $attribute->id;
|
||||
|
||||
$attributes[] = [
|
||||
'id' => $attributeId,
|
||||
'code' => $attribute->code,
|
||||
'label' => $attribute->name,
|
||||
'options' => $attributeOptionsData
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attribute $attribute
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function getAttributeOptionsData($attribute, $options)
|
||||
{
|
||||
$attributeOptionsData = [];
|
||||
|
||||
foreach ($attribute->options as $attributeOption) {
|
||||
|
||||
$optionId = $attributeOption->id;
|
||||
|
||||
if(isset($options[$attribute->id][$optionId])) {
|
||||
$attributeOptionsData[] = [
|
||||
'id' => $optionId,
|
||||
'label' => $attributeOption->label,
|
||||
'products' => $options[$attribute->id][$optionId]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $attributeOptionsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product prices for configurable variations
|
||||
*
|
||||
* @param Product $product
|
||||
* @return array
|
||||
*/
|
||||
protected function getVariantPrices($product)
|
||||
{
|
||||
$prices = [];
|
||||
|
||||
foreach ($this->getAllowProducts($product) as $variant) {
|
||||
$prices[$variant->id] = [
|
||||
'regular_price' => [
|
||||
'formated_price' => core()->currency($variant->price),
|
||||
'price' => $variant->price
|
||||
],
|
||||
'final_price' => [
|
||||
'formated_price' => core()->currency($this->price->getMinimalPrice($variant)),
|
||||
'price' => $this->price->getMinimalPrice($variant)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $prices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product images for configurable variations
|
||||
*
|
||||
* @param Product $product
|
||||
* @return array
|
||||
*/
|
||||
protected function getVariantImages($product)
|
||||
{
|
||||
$images = [];
|
||||
|
||||
foreach ($this->getAllowProducts($product) as $variant) {
|
||||
$images[$variant->id] = $this->gallery->getImages($variant);
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Product;
|
||||
|
||||
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
|
||||
|
||||
class Gallery extends AbstractProduct
|
||||
{
|
||||
/**
|
||||
* Retrieve collection of gallery images
|
||||
*
|
||||
* @param Product $product
|
||||
* @return array
|
||||
*/
|
||||
public function getImages($product)
|
||||
{
|
||||
$images[] = [
|
||||
'small_image_url' => '',
|
||||
'medium_image_url' => '',
|
||||
'large_image_url' => '',
|
||||
];
|
||||
|
||||
return $images;
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +78,7 @@ class Price extends AbstractProduct
|
|||
public function getSpecialPrice($product)
|
||||
{
|
||||
if($this->haveSpecialPrice($product)) {
|
||||
return $product->special_price;
|
||||
return $product->special_price;
|
||||
} else {
|
||||
return $product->price;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,17 @@ namespace Webkul\Product\Product;
|
|||
|
||||
class Review extends AbstractProduct
|
||||
{
|
||||
/**
|
||||
* Returns the product's avg rating
|
||||
*
|
||||
* @param Product $product
|
||||
* @return float
|
||||
*/
|
||||
public function getReviews($product)
|
||||
{
|
||||
return $product->reviews()->where('status', 'approved');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product's avg rating
|
||||
*
|
||||
|
|
@ -12,7 +23,7 @@ class Review extends AbstractProduct
|
|||
*/
|
||||
public function getAverageRating($product)
|
||||
{
|
||||
return round($product->reviews->average('rating'));
|
||||
return number_format(round($product->reviews()->where('status', 'approved')->average('rating'), 2), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -23,7 +34,7 @@ class Review extends AbstractProduct
|
|||
*/
|
||||
public function getTotalReviews($product)
|
||||
{
|
||||
return $product->reviews()->count();
|
||||
return $product->reviews()->where('status', 'approved')->count();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -49,6 +49,9 @@ return [
|
|||
'specification' => 'Specification',
|
||||
'total-reviews' => ':total Reviews',
|
||||
'by' => 'By :name',
|
||||
'up-sell-title' => 'We found other products you might like!'
|
||||
'up-sell-title' => 'We found other products you might like!',
|
||||
'reviews-title' => 'Ratings & Reviews',
|
||||
'write-review-btn' => 'Write Review',
|
||||
'choose-option' => 'Choose an option'
|
||||
]
|
||||
];
|
||||
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
<div id="app">
|
||||
|
||||
@include('shop::layouts.header.index')
|
||||
|
||||
@yield('slider')
|
||||
|
||||
<div class="main-container-wrapper">
|
||||
|
||||
@include('shop::layouts.header.index')
|
||||
|
||||
@yield('slider')
|
||||
|
||||
<div class="content-container">
|
||||
|
||||
@yield('content-wrapper')
|
||||
|
|
|
|||
|
|
@ -22,11 +22,7 @@
|
|||
|
||||
@include ('shop::products.price', ['product' => $product])
|
||||
|
||||
@if ($product->reviews->count())
|
||||
|
||||
@include ('shop::products.review', ['product' => $product])
|
||||
|
||||
@endif
|
||||
@include ('shop::products.review', ['product' => $product])
|
||||
|
||||
@include ('shop::products.add-to', ['product' => $product])
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<span class="price-label">{{ __('shop::app.products.price-label') }}</span>
|
||||
|
||||
<span>{{ core()->currency($priceHelper->getMinimalPrice($product)) }}</span>
|
||||
<span class="final-price">{{ core()->currency($priceHelper->getMinimalPrice($product)) }}</span>
|
||||
|
||||
@else
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
<div class="product-ratings">
|
||||
@inject ('reviewHelper', 'Webkul\Product\Product\Review')
|
||||
@if ($total = $reviewHelper->getTotalReviews($product))
|
||||
|
||||
@inject ('reviewHelper', 'Webkul\Product\Product\Review')
|
||||
<div class="product-ratings">
|
||||
|
||||
@for ($i = 1; $i <= $reviewHelper->getAverageRating($product); $i++)
|
||||
<span class="stars">
|
||||
@for ($i = 1; $i <= round($reviewHelper->getAverageRating($product)); $i++)
|
||||
|
||||
<span class="icon star-icon"></span>
|
||||
|
||||
@endfor
|
||||
|
||||
</div>
|
||||
<span class="icon star-icon"></span>
|
||||
|
||||
@endfor
|
||||
</span>
|
||||
|
||||
<div class="total-reviews">
|
||||
{{ __('shop::app.products.total-reviews', ['total' => $total]) }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -9,129 +9,57 @@
|
|||
</div>
|
||||
<div class="layouter">
|
||||
|
||||
@include ('shop::products.view.gallery')
|
||||
<form method="POST" @auth('customer') action="{{ route('cart.customer.add', $product->id) }}" @endauth @guest action="{{ route('cart.guest.add', $product->id) }}" @endguest>
|
||||
@csrf()
|
||||
|
||||
<div class="product-details" id="dealit">
|
||||
<input type="hidden" name="product">
|
||||
|
||||
<div class="product-heading">
|
||||
<span>{{ $product->name }}</span>
|
||||
</div>
|
||||
@include ('shop::products.view.gallery')
|
||||
|
||||
<div class="rating">
|
||||
<img src="{{ bagisto_asset('images/5star.svg') }}" />
|
||||
75 Ratings & 11 Reviews
|
||||
</div>
|
||||
<div class="details">
|
||||
|
||||
@include ('shop::products.price', ['product' => $product])
|
||||
<div class="product-heading">
|
||||
<span>{{ $product->name }}</span>
|
||||
</div>
|
||||
|
||||
@include ('shop::products.view.stock')
|
||||
@include ('shop::products.review', ['product' => $product])
|
||||
|
||||
<br/>
|
||||
@include ('shop::products.price', ['product' => $product])
|
||||
|
||||
<div class="description">
|
||||
{{ $product->short_description }}
|
||||
</div>
|
||||
@include ('shop::products.view.stock')
|
||||
|
||||
@if ($product->type == 'configurable')
|
||||
|
||||
<div class="description">
|
||||
{{ $product->short_description }}
|
||||
</div>
|
||||
|
||||
@include ('shop::products.view.configurable-options')
|
||||
|
||||
@endif
|
||||
|
||||
<accordian :title="{{ __('shop::app.products.description') }}" :active="true">
|
||||
<div slot="header">
|
||||
{{ __('shop::app.products.description') }}
|
||||
<i class="icon expand-icon right"></i>
|
||||
</div>
|
||||
|
||||
<div slot="body">
|
||||
<div class="full-description">
|
||||
{{ $product->description }}
|
||||
<accordian :title="'{{ __('shop::app.products.description') }}'" :active="true">
|
||||
<div slot="header">
|
||||
{{ __('shop::app.products.description') }}
|
||||
<i class="icon expand-icon right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
@include ('shop::products.view.attributes')
|
||||
<div slot="body">
|
||||
<div class="full-description">
|
||||
{{ $product->description }}
|
||||
</div>
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
@include ('shop::products.view.reviews')
|
||||
@include ('shop::products.view.attributes')
|
||||
|
||||
@include ('shop::products.view.reviews')
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include ('shop::products.view.up-sells')
|
||||
|
||||
</section>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
var topBoundOfProductGallery = 0;
|
||||
function getTopBound() {
|
||||
var rect = document.getElementById("getbound").getBoundingClientRect();
|
||||
topBoundOfProductGallery = rect.top;
|
||||
console.log('From Top = ', rect.top);
|
||||
}
|
||||
|
||||
window.onload = getTopBound;
|
||||
|
||||
// window.onscroll = function() {
|
||||
// myFunction()
|
||||
// };
|
||||
|
||||
// $(document).ready(function () {
|
||||
// $(document).scroll(function (event) {
|
||||
// var scroll = $(document).scrollTop();
|
||||
// if(scroll > 182) {
|
||||
// $('#dealit').css('width', '50%');
|
||||
|
||||
// $('#dealit').css('margin-left', '59.7%');
|
||||
|
||||
// $('#getbound').css('position', 'fixed');
|
||||
|
||||
// $('#getbound').css('top', '0');
|
||||
// } else if(scroll < 182) {
|
||||
// $('#dealit').css('width', '100%');
|
||||
|
||||
// $('#dealit').css('margin-left', '');
|
||||
|
||||
// $('#getbound').css('position', '');
|
||||
|
||||
// $('#getbound').css('top', '');
|
||||
|
||||
// }
|
||||
|
||||
// });
|
||||
// });
|
||||
|
||||
// function myFunction() {
|
||||
|
||||
// if(document.body.scrollTop > 182 || document.documentElement.scrollTop > 182) {
|
||||
|
||||
// // document.getElementById('dealit').style.style = 'none';
|
||||
|
||||
// document.getElementById('dealit').classList.remove("product-details");
|
||||
|
||||
// document.getElementById('dealit').width = '50%';
|
||||
|
||||
// document.getElementById('dealit').marginLeft = '60%';
|
||||
|
||||
// document.getElementById('getbound').style.position = 'fixed';
|
||||
|
||||
// document.getElementById('getbound').style.top = '0';
|
||||
|
||||
// }
|
||||
// else if(document.body.scrollTop < 182 || document.documentElement.scrollTop < 182) {
|
||||
|
||||
// document.getElementById('dealit').classList.add("product-details");
|
||||
|
||||
// document.getElementById('dealit').width = '100%';
|
||||
|
||||
// document.getElementById('dealit').marginLeft = '0';
|
||||
|
||||
// document.getElementById('getbound').style.position = '';
|
||||
|
||||
// document.getElementById('getbound').style.top = '';
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
@endpush
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@inject ('productViewHelper', 'Webkul\Product\Product\View')
|
||||
|
||||
<accordian :title="{{ __('shop::app.products.specification') }}" :active="false">
|
||||
<accordian :title="'{{ __('shop::app.products.specification') }}'" :active="false">
|
||||
<div slot="header">
|
||||
{{ __('shop::app.products.specification') }}
|
||||
<i class="icon expand-icon right"></i>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,240 @@
|
|||
<div class="attributes">
|
||||
@if ($product->type == 'configurable')
|
||||
|
||||
<div class="attribute color">
|
||||
<div class="title">Color</div>
|
||||
@inject ('configurableOptionHelper', 'Webkul\Product\Product\ConfigurableOption')
|
||||
|
||||
<div class="values">
|
||||
<div class="colors red"></div>
|
||||
<div class="colors blue"></div>
|
||||
<div class="colors green"></div>
|
||||
</div>
|
||||
</div>
|
||||
<product-options></product-options>
|
||||
|
||||
<div class="attribute size">
|
||||
<div class="title">Size</div>
|
||||
@push('scripts')
|
||||
|
||||
<div class="values">
|
||||
<div class="size xl">XL</div>
|
||||
<div class="size xxl">XXL</div>
|
||||
<div class="size xxxl">XXXL</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/x-template" id="product-options-template">
|
||||
<div class="attributes">
|
||||
|
||||
<div class="attribute quantity">
|
||||
<div class="title">Quantity</div>
|
||||
<input type="hidden" name="selected_configurable_option" :value="selectedProductId">
|
||||
|
||||
<div class="values">
|
||||
<div class="size">1</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for='(attribute, index) in childAttributes' class="attribute control-group" :class="[errors.has('super_attribute[' + attribute.id + ']') ? 'has-error' : '']">
|
||||
<label class="reqiured">@{{ attribute.label }}</label>
|
||||
|
||||
</div>
|
||||
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)" :id="['attribute_' + attribute.id]">
|
||||
|
||||
<hr/>
|
||||
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
|
||||
|
||||
</select>
|
||||
|
||||
<span class="control-error" v-if="errors.has('super_attribute[' + attribute.id + ']')">
|
||||
@{{ errors.first('super_attribute[' + attribute.id + ']') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<?php $config = $configurableOptionHelper->getConfigurationConfig($product) ?>
|
||||
|
||||
<script>
|
||||
|
||||
Vue.component('product-options', {
|
||||
|
||||
template: '#product-options-template',
|
||||
|
||||
data: () => ({
|
||||
config: @json($config),
|
||||
|
||||
childAttributes: [],
|
||||
|
||||
selectedProductId: '',
|
||||
|
||||
simpleProduct: null
|
||||
}),
|
||||
|
||||
created () {
|
||||
var config = @json($config);
|
||||
|
||||
var childAttributes = this.childAttributes,
|
||||
attributes = config.attributes.slice(),
|
||||
index = attributes.length,
|
||||
attribute;
|
||||
|
||||
while (index--) {
|
||||
attribute = attributes[index];
|
||||
|
||||
attribute.options = [];
|
||||
|
||||
if (index) {
|
||||
attribute.disabled = true;
|
||||
} else {
|
||||
this.fillSelect(attribute);
|
||||
}
|
||||
|
||||
attribute = Object.assign(attribute, {
|
||||
childAttributes: childAttributes.slice(),
|
||||
prevAttribute: attributes[index - 1],
|
||||
nextAttribute: attributes[index + 1]
|
||||
});
|
||||
|
||||
childAttributes.unshift(attribute);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
configure (attribute, value) {
|
||||
this.simpleProduct = this.getSelectedProductId(attribute, value);
|
||||
|
||||
if (value) {
|
||||
attribute.selectedIndex = this.getSelectedIndex(attribute, value);
|
||||
|
||||
if (attribute.nextAttribute) {
|
||||
attribute.nextAttribute.disabled = false;
|
||||
|
||||
this.fillSelect(attribute.nextAttribute);
|
||||
this.resetChildren(attribute.nextAttribute);
|
||||
} else {
|
||||
this.selectedProductId = attribute.options[attribute.selectedIndex].allowedProducts[0];
|
||||
}
|
||||
} else {
|
||||
attribute.selectedIndex = 0;
|
||||
|
||||
this.resetChildren(attribute);
|
||||
|
||||
this.clearSelect(attribute.nextAttribute)
|
||||
}
|
||||
|
||||
this.reloadPrice();
|
||||
this.changeProductImages();
|
||||
},
|
||||
|
||||
getSelectedIndex (attribute, value) {
|
||||
var selectedIndex = 0;
|
||||
|
||||
attribute.options.forEach(function(option, index) {
|
||||
if(option.id == value) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
})
|
||||
|
||||
return selectedIndex;
|
||||
},
|
||||
|
||||
getSelectedProductId (attribute, value) {
|
||||
var options = attribute.options,
|
||||
matchedOptions;
|
||||
|
||||
matchedOptions = options.filter(function (option) {
|
||||
return option.id == value;
|
||||
});
|
||||
|
||||
if(matchedOptions[0] != undefined && matchedOptions[0].allowedProducts != undefined) {
|
||||
return matchedOptions[0].allowedProducts[0];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
fillSelect (attribute) {
|
||||
var options = this.getAttributeOptions(attribute.id),
|
||||
prevOption,
|
||||
index = 1,
|
||||
allowedProducts,
|
||||
i,
|
||||
j;
|
||||
|
||||
this.clearSelect(attribute)
|
||||
|
||||
attribute.options = [];
|
||||
attribute.options[0] = {'id': '', 'label': this.config.chooseText, 'products': []};
|
||||
|
||||
if (attribute.prevAttribute) {
|
||||
prevOption = attribute.prevAttribute.options[attribute.prevAttribute.selectedIndex];
|
||||
}
|
||||
|
||||
if (options) {
|
||||
for (i = 0; i < options.length; i++) {
|
||||
allowedProducts = [];
|
||||
|
||||
if (prevOption) {
|
||||
for (j = 0; j < options[i].products.length; j++) {
|
||||
if (prevOption.products && prevOption.products.indexOf(options[i].products[j]) > -1) {
|
||||
allowedProducts.push(options[i].products[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allowedProducts = options[i].products.slice(0);
|
||||
}
|
||||
|
||||
if (allowedProducts.length > 0) {
|
||||
options[i].allowedProducts = allowedProducts;
|
||||
|
||||
attribute.options[index] = options[i];
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resetChildren (attribute) {
|
||||
if (attribute.childAttributes) {
|
||||
attribute.childAttributes.forEach(function (set) {
|
||||
set.selectedIndex = 0;
|
||||
set.disabled = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
clearSelect: function (attribute) {
|
||||
if(!attribute)
|
||||
return;
|
||||
|
||||
var element = document.getElementById("attribute_" + attribute.id);
|
||||
|
||||
if(element) {
|
||||
element.selectedIndex = "0";
|
||||
}
|
||||
},
|
||||
|
||||
getAttributeOptions (attributeId) {
|
||||
var this_this = this,
|
||||
options;
|
||||
|
||||
this.config.attributes.forEach(function(attribute, index) {
|
||||
if (attribute.id == attributeId) {
|
||||
options = attribute.options;
|
||||
}
|
||||
})
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
reloadPrice () {
|
||||
var selectedOptionCount = 0;
|
||||
|
||||
this.childAttributes.forEach(function(attribute) {
|
||||
if(attribute.selectedIndex) {
|
||||
selectedOptionCount++;
|
||||
}
|
||||
});
|
||||
|
||||
var priceLabelElement = document.querySelector('.price-label');
|
||||
var priceElement = document.querySelector('.final-price');
|
||||
|
||||
if(this.childAttributes.length == selectedOptionCount) {
|
||||
priceLabelElement.style.display = 'none';
|
||||
|
||||
priceElement.innerHTML = this.config.variant_prices[this.simpleProduct].final_price.formated_price;
|
||||
} else {
|
||||
priceLabelElement.style.display = 'inline-block';
|
||||
|
||||
priceElement.innerHTML = this.config.regular_price.formated_price;
|
||||
}
|
||||
},
|
||||
|
||||
changeProductImages () {
|
||||
console.log(this.config.variant_images[this.simpleProduct])
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@endif
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="product-gallery-group" id="getbound">
|
||||
<div class="product-gallery-group">
|
||||
<div class="product-image-group">
|
||||
|
||||
<div class="side-group">
|
||||
|
|
@ -8,24 +8,19 @@
|
|||
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
|
||||
</div>
|
||||
|
||||
<div class="product-hero-image">
|
||||
<img src="{{ bagisto_asset('images/jeans_big.jpg') }}" />
|
||||
<div class="product-hero-image" id="product-hero-image">
|
||||
<img class="hero-image" src="{{ bagisto_asset('images/jeans_big.jpg') }}" />
|
||||
<img class="wishlist" src="{{ bagisto_asset('images/wish.svg') }}" />
|
||||
<img class="share" src="{{ bagisto_asset('images/icon-share.svg') }}" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="product-button-group">
|
||||
<form method="POST" @auth('customer') action="{{ route('cart.customer.add', $product->id) }}" @endauth @guest action="{{ route('cart.guest.add', $product->id) }}" @endguest>
|
||||
{{ csrf_field() }}
|
||||
|
||||
<input type="hidden" name="product_id" value="{{ $product->id }}">
|
||||
<input type="hidden" name="product_id" value="{{ $product->id }}">
|
||||
|
||||
<input type="hidden" name="qty" value="1">
|
||||
<input type="hidden" name="qty" value="1">
|
||||
|
||||
<input type="submit" class="btn btn-lg add-to-cart" value="Add to Cart">
|
||||
</form>
|
||||
<input type="submit" class="btn btn-lg add-to-cart" value="Add to Cart">
|
||||
{{-- <form>
|
||||
<input type="hidden" name="product_id" value="">
|
||||
<input type="hidden" name="qty" value="1">
|
||||
|
|
@ -34,3 +29,14 @@
|
|||
{{-- {{ dd(unserialize(Cookie::get('session_c'))) }} --}}
|
||||
</div>
|
||||
</div>
|
||||
@push('scripts')
|
||||
|
||||
<script>
|
||||
|
||||
Vue.component('product-gallery', {
|
||||
props: ['images']
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
@if ($total = $reviewHelper->getTotalReviews($product))
|
||||
<div class="rating-reviews">
|
||||
<div class="title">
|
||||
Ratings & Reviews
|
||||
<div class="rating-header">
|
||||
{{ __('shop::app.products.reviews-title') }}
|
||||
</div>
|
||||
|
||||
<div class="overall">
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</span>
|
||||
|
||||
<span class="stars">
|
||||
@for ($i = 1; $i <= $reviewHelper->getAverageRating($product); $i++)
|
||||
@for ($i = 1; $i <= round($reviewHelper->getAverageRating($product)); $i++)
|
||||
|
||||
<span class="icon star-icon"></span>
|
||||
|
||||
|
|
@ -27,13 +27,15 @@
|
|||
|
||||
</div>
|
||||
|
||||
<a href="{{ route('shop.reviews.create', $product->url_key) }}" class="btn btn-lg btn-primary">Write Review</a>
|
||||
<a href="{{ route('shop.reviews.create', $product->url_key) }}" class="btn btn-lg btn-primary">
|
||||
{{ __('shop::app.products.write-review-btn') }}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="reviews">
|
||||
|
||||
@foreach ($product->reviews()->paginate(5) as $review)
|
||||
@foreach ($reviewHelper->getReviews($product)->paginate(5) as $review)
|
||||
<div class="review">
|
||||
<div class="title">
|
||||
{{ $review->title }}
|
||||
|
|
@ -65,7 +67,6 @@
|
|||
|
||||
<a href="{{ route('shop.reviews.index', $product->url_key) }}" class="view-all">View All</a>
|
||||
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,4 +4,4 @@
|
|||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
||||
Loading…
Reference in New Issue