Configurable options added
This commit is contained in:
parent
4fb084557d
commit
5202729391
|
|
@ -1,10 +1,26 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[
|
'flatrate' => [
|
||||||
'code' => 'flatrate',
|
'code' => 'flatrate',
|
||||||
'name' => 'Flat Rate',
|
'name' => 'Flat Rate',
|
||||||
'class' => 'Webkul\Shipping\Calculators\FlatRate'
|
'description' => '',
|
||||||
|
'default_type' => 'per_order',
|
||||||
|
'types' => [
|
||||||
|
'per_unit' => 'Per Unit',
|
||||||
|
'per_order' => 'Per Order',
|
||||||
|
],
|
||||||
|
'price' => 10,
|
||||||
|
'class' => 'Webkul\Shipping\Calculators\FlatRate',
|
||||||
|
'status' => 1
|
||||||
|
],
|
||||||
|
|
||||||
|
'fedex' => [
|
||||||
|
'code' => 'fedex',
|
||||||
|
'name' => 'Fedex',
|
||||||
|
'description' => '',
|
||||||
|
'class' => 'Webkul\Shipping\Calculators\FedexRate',
|
||||||
|
'status' => 1
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,13 @@ class EventServiceProvider extends ServiceProvider
|
||||||
Event::listen('admin.acl.build', function ($acl) {
|
Event::listen('admin.acl.build', function ($acl) {
|
||||||
$acl->add('dashboard', 'Dashboard', 'admin.dashboard.index', 1);
|
$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('configuration', 'Configure', 'admin.account.edit', 5);
|
||||||
|
|
||||||
$acl->add('settings', 'Settings', 'admin.users.index', 6);
|
$acl->add('settings', 'Settings', 'admin.users.index', 6);
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,10 @@ class ConfigurableOption extends AbstractProduct
|
||||||
$config = [
|
$config = [
|
||||||
'attributes' => $this->getAttributesData($product, $options),
|
'attributes' => $this->getAttributesData($product, $options),
|
||||||
'index' => isset($options['index']) ? $options['index'] : [],
|
'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_prices' => $this->getVariantPrices($product),
|
||||||
'variant_images' => $this->getVariantImages($product),
|
'variant_images' => $this->getVariantImages($product),
|
||||||
'chooseText' => trans('shop::app.products.choose-option')
|
'chooseText' => trans('shop::app.products.choose-option')
|
||||||
|
|
@ -201,8 +205,14 @@ class ConfigurableOption extends AbstractProduct
|
||||||
|
|
||||||
foreach ($this->getAllowProducts($product) as $variant) {
|
foreach ($this->getAllowProducts($product) as $variant) {
|
||||||
$prices[$variant->id] = [
|
$prices[$variant->id] = [
|
||||||
'regular_price' => $variant->price,
|
'regular_price' => [
|
||||||
'final_price' => $this->price->getMinimalPrice($variant),
|
'formated_price' => core()->currency($variant->price),
|
||||||
|
'price' => $variant->price
|
||||||
|
],
|
||||||
|
'final_price' => [
|
||||||
|
'formated_price' => core()->currency($this->price->getMinimalPrice($variant)),
|
||||||
|
'price' => $this->price->getMinimalPrice($variant)
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Webkul\Shipping\Contracts\Carrier;
|
||||||
|
|
||||||
|
class FlatRate extends Carrier
|
||||||
|
{
|
||||||
|
public function calculateRates()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'code' => 'flatrate',
|
||||||
|
'title' => 'Flatrate',
|
||||||
|
'rates' => [
|
||||||
|
[
|
||||||
|
'title' => 'Flat Rate',
|
||||||
|
'rate' => 10
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Webkul\Shipping\Contracts\Carrier;
|
||||||
|
|
||||||
|
class PerProduct extends Carrier
|
||||||
|
{
|
||||||
|
public function calculeRates()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'code' => 'perproduct',
|
||||||
|
'title' => 'Per Product',
|
||||||
|
'rates' => [
|
||||||
|
[
|
||||||
|
'title' => 'Per Product',
|
||||||
|
'rate' => 10
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class Carrier {
|
||||||
|
|
||||||
|
abstract public function calculateRates();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
|
||||||
|
class Rates {
|
||||||
|
|
||||||
|
public function collectRates()
|
||||||
|
{
|
||||||
|
$rates = [];
|
||||||
|
|
||||||
|
foreach(Config::get('carriers') as $shippingMethod) {
|
||||||
|
if(isset($shippingMethod['class'])) {
|
||||||
|
$object = new $shippingMethod['class'];
|
||||||
|
|
||||||
|
if($rate = $object->calculeRates()) {
|
||||||
|
array_push($rates, $rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rates;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<span class="price-label">{{ __('shop::app.products.price-label') }}</span>
|
<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
|
@else
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
<input type="hidden" name="product">
|
<input type="hidden" name="product">
|
||||||
|
|
||||||
<input type="hidden" name="selected_configurable_option">
|
|
||||||
|
|
||||||
@include ('shop::products.view.gallery')
|
@include ('shop::products.view.gallery')
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
@inject ('configurableOptionHelper', 'Webkul\Product\Product\ConfigurableOption')
|
@inject ('configurableOptionHelper', 'Webkul\Product\Product\ConfigurableOption')
|
||||||
|
|
||||||
|
|
||||||
<product-options></product-options>
|
<product-options></product-options>
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
|
|
@ -10,39 +9,52 @@
|
||||||
<script type="text/x-template" id="product-options-template">
|
<script type="text/x-template" id="product-options-template">
|
||||||
<div class="attributes">
|
<div class="attributes">
|
||||||
|
|
||||||
|
<input type="hidden" name="selected_configurable_option" :value="selectedProductId">
|
||||||
|
|
||||||
<div v-for='(attribute, index) in childAttributes' class="attribute control-group" :class="[errors.has('super_attribute[' + attribute.id + ']') ? 'has-error' : '']">
|
<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>
|
<label class="reqiured">@{{ attribute.label }}</label>
|
||||||
|
|
||||||
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)">
|
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)" :id="['attribute_' + attribute.id]">
|
||||||
|
|
||||||
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
|
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<span class="control-error" v-if="errors.has('super_attribute[' + attribute.id + ']')">@{{ errors.first('super_attribute[' + attribute.id + ']') }}</span>
|
<span class="control-error" v-if="errors.has('super_attribute[' + attribute.id + ']')">
|
||||||
|
@{{ errors.first('super_attribute[' + attribute.id + ']') }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<?php $config = $configurableOptionHelper->getConfigurationConfig($product) ?>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
Vue.component('product-options', {
|
Vue.component('product-options', {
|
||||||
|
|
||||||
template: '#product-options-template',
|
template: '#product-options-template',
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
config: @json($configurableOptionHelper->getConfigurationConfig($product)),
|
config: @json($config),
|
||||||
childAttributes: []
|
|
||||||
|
childAttributes: [],
|
||||||
|
|
||||||
|
selectedProductId: '',
|
||||||
|
|
||||||
|
simpleProduct: null
|
||||||
}),
|
}),
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
|
var config = @json($config);
|
||||||
|
|
||||||
var childAttributes = this.childAttributes,
|
var childAttributes = this.childAttributes,
|
||||||
attributes = this.config.attributes,
|
attributes = config.attributes.slice(),
|
||||||
index = attributes.length,
|
index = attributes.length,
|
||||||
attribute;
|
attribute;
|
||||||
|
|
||||||
while (index--) {
|
while (index--) {
|
||||||
// attribute = Object.assign({}, attributes[index]);
|
|
||||||
attribute = attributes[index];
|
attribute = attributes[index];
|
||||||
|
|
||||||
attribute.options = [];
|
attribute.options = [];
|
||||||
|
|
@ -65,32 +77,68 @@
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
configure (attribute, value) {
|
configure (attribute, value) {
|
||||||
// this.simpleProduct = this._getSimpleProductId(attribute);
|
this.simpleProduct = this.getSelectedProductId(attribute, value);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
attribute.selectedIndex = this.getSelectedIndex(attribute, value);
|
||||||
|
|
||||||
if (attribute.nextAttribute) {
|
if (attribute.nextAttribute) {
|
||||||
attribute.nextAttribute.disabled = false;
|
attribute.nextAttribute.disabled = false;
|
||||||
|
|
||||||
this.fillSelect(attribute.nextAttribute);
|
this.fillSelect(attribute.nextAttribute);
|
||||||
this.resetChildren(attribute.nextAttribute);
|
this.resetChildren(attribute.nextAttribute);
|
||||||
} else {
|
} else {
|
||||||
//Set product id hidden value
|
this.selectedProductId = attribute.options[attribute.selectedIndex].allowedProducts[0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
attribute.selectedIndex = 0;
|
||||||
|
|
||||||
this.resetChildren(attribute);
|
this.resetChildren(attribute);
|
||||||
|
|
||||||
|
this.clearSelect(attribute.nextAttribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.reloadPrice();
|
this.reloadPrice();
|
||||||
// this.changeProductImage();
|
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) {
|
fillSelect (attribute) {
|
||||||
var options = this.getAttributeOptions(attribute.id),
|
var options = this.getAttributeOptions(attribute.id),
|
||||||
prevOption,
|
prevOption,
|
||||||
index = 1,
|
index = 1,
|
||||||
products,
|
allowedProducts,
|
||||||
i,
|
i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
|
this.clearSelect(attribute)
|
||||||
|
|
||||||
attribute.options = [];
|
attribute.options = [];
|
||||||
attribute.options[0] = {'id': '', 'label': this.config.chooseText, 'products': []};
|
attribute.options[0] = {'id': '', 'label': this.config.chooseText, 'products': []};
|
||||||
|
|
||||||
|
|
@ -98,25 +146,23 @@
|
||||||
prevOption = attribute.prevAttribute.options[attribute.prevAttribute.selectedIndex];
|
prevOption = attribute.prevAttribute.options[attribute.prevAttribute.selectedIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(attribute)
|
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
for (i = 0; i < options.length; i++) {
|
for (i = 0; i < options.length; i++) {
|
||||||
products = [];
|
allowedProducts = [];
|
||||||
|
|
||||||
if (prevOption) {
|
if (prevOption) {
|
||||||
for (j = 0; j < options[i].products.length; j++) {
|
for (j = 0; j < options[i].products.length; j++) {
|
||||||
if (prevOption.products &&
|
if (prevOption.products && prevOption.products.indexOf(options[i].products[j]) > -1) {
|
||||||
prevOption.products.indexOf(options[i].products[j]) > -1) {
|
allowedProducts.push(options[i].products[j]);
|
||||||
products.push(options[i].products[j]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
products = options[i].products.slice(0);
|
allowedProducts = options[i].products.slice(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (products.length > 0) {
|
if (allowedProducts.length > 0) {
|
||||||
options[i].products = products;
|
options[i].allowedProducts = allowedProducts;
|
||||||
|
|
||||||
attribute.options[index] = options[i];
|
attribute.options[index] = options[i];
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
|
@ -134,11 +180,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearSelect: function (attribute) {
|
||||||
|
if(!attribute)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var element = document.getElementById("attribute_" + attribute.id);
|
||||||
|
|
||||||
|
if(element) {
|
||||||
|
element.selectedIndex = "0";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getAttributeOptions (attributeId) {
|
getAttributeOptions (attributeId) {
|
||||||
var this_this = this,
|
var this_this = this,
|
||||||
options;
|
options;
|
||||||
|
|
||||||
|
|
||||||
this.config.attributes.forEach(function(attribute, index) {
|
this.config.attributes.forEach(function(attribute, index) {
|
||||||
if (attribute.id == attributeId) {
|
if (attribute.id == attributeId) {
|
||||||
options = attribute.options;
|
options = attribute.options;
|
||||||
|
|
@ -149,11 +205,30 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
reloadPrice () {
|
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;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
changeProductImage () {
|
changeProductImages () {
|
||||||
|
console.log(this.config.variant_images[this.simpleProduct])
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
Vue.component('product-gallery', {
|
||||||
|
props: ['images']
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endpush
|
||||||
Loading…
Reference in New Issue