diff --git a/common/config/main.php b/common/config/main.php index 1003a10..4b8d4b5 100755 --- a/common/config/main.php +++ b/common/config/main.php @@ -157,6 +157,9 @@ return [ ], ] ], + 'basket' => [ + 'class' => 'common\models\Basket', + ], ], 'modules' => [ diff --git a/common/models/Basket.php b/common/models/Basket.php new file mode 100644 index 0000000..20848c1 --- /dev/null +++ b/common/models/Basket.php @@ -0,0 +1,129 @@ +session = \Yii::$app->session; + if(!$this->session->has('basket')) { + $this->session->set('basket', [ ]); + } + parent::__construct($config); + } + + public function add(int $product_variant_id, int $count) + { + $data = $this->getData(); + if(array_key_exists($product_variant_id, $data)) { + $data[ $product_variant_id ][ 'count' ] += $count; + if($data[$product_variant_id]['count'] <= 0) { + unset($data[$product_variant_id]); + } + } else { + $model = $this->findModel($product_variant_id); + $data[ $product_variant_id ] = [ + 'price' => $model->price, + 'count' => $count, + ]; + } + $this->setData($data); + } + + public function set(int $product_variant_id, int $count) + { + $data = $this->getData(); + if(array_key_exists($product_variant_id, $data)) { + $data[ $product_variant_id ][ 'count' ] = $count; + if($data[$product_variant_id]['count'] <= 0) { + unset($data[$product_variant_id]); + } + } else { + $model = $this->findModel($product_variant_id); + $data[ $product_variant_id ] = [ + 'price' => $model->price, + 'count' => $count, + ]; + } + $this->setData($data); + } + + public function getData(): array + { + return $this->session->get('basket'); + } + + public function getItem(int $product_variant_id) { + $data = $this->getData(); + if(!empty($data[$product_variant_id])) { + return $data[$product_variant_id]; + } else { + return false; + } + } + + public function setData(array $data) + { + $this->session->set('basket', $data); + } + + public function getSum(): float + { + $data = $this->getData(); + $sum = 0; + foreach($data as $item) { + $sum += $item[ 'price' ] * $item[ 'count' ]; + } + return $sum; + } + + public function getCount(): int { + $data = $this->getData(); + return count($data); + } + + public function findModel(int $product_variant_id): ProductVariant + { + $model = ProductVariant::find() + ->where([ 'product_variant_id' => $product_variant_id ]) + ->one(); + if(empty( $model )) { + throw new NotFoundHttpException('Product not found'); + } else { + return $model; + } + } + + public function findModels(array $product_variant_ids) + { + return ProductVariant::find() + ->where([ 'product_variant_id' => $product_variant_ids ]) + ->with([ + 'product', + 'image', + ]) + ->all(); + } + + public function getModal(): string + { + $output = ''; + $data = $this->getData(); + $models = $this->findModels(array_keys($this->getData())); + if(!empty( $models )) { + $output = \Yii::$app->view->renderFile('@frontend/views/basket/modal_items.php', [ + 'models' => $models, + 'basket' => $this, + ]); + } + return $output; + } + } \ No newline at end of file diff --git a/common/modules/product/controllers/ManageController.php b/common/modules/product/controllers/ManageController.php index 1c04be5..a799a6b 100755 --- a/common/modules/product/controllers/ManageController.php +++ b/common/modules/product/controllers/ManageController.php @@ -80,7 +80,7 @@ class ManageController extends Controller public function actionCreate() { $model = new Product(); - + if ($model->load(Yii::$app->request->post())) { $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); diff --git a/frontend/assets/AppAsset.php b/frontend/assets/AppAsset.php index b9f42f4..a02356f 100755 --- a/frontend/assets/AppAsset.php +++ b/frontend/assets/AppAsset.php @@ -23,7 +23,9 @@ class AppAsset extends AssetBundle ]; public $js = [ 'js/js_head.js', - 'js/js_footer.js' + //'js/js_footer.js', + '/js/artbox_basket.js', + 'js/script.js', ]; public $depends = [ 'yii\web\JqueryAsset', diff --git a/frontend/controllers/BasketController.php b/frontend/controllers/BasketController.php new file mode 100755 index 0000000..fa79a46 --- /dev/null +++ b/frontend/controllers/BasketController.php @@ -0,0 +1,59 @@ +response; + $response->format = Response::FORMAT_JSON; + /** + * @var Basket $basket + */ + $basket = \Yii::$app->basket; + $result = [ + 'basket' => $basket->getData(), + ]; + return $result; + } + public function actionAdd(int $product_variant_id, int $count) { + $response = \Yii::$app->response; + $response->format = Response::FORMAT_JSON; + /** + * @var Basket $basket + */ + $basket = \Yii::$app->basket; + $basket->add($product_variant_id, $count); + $result = [ + 'basket' => $basket->getData(), + 'modal' => $basket->getModal(), + ]; + return $result; + } + public function actionSet(int $product_variant_id, int $count) { + $response = \Yii::$app->response; + $response->format = Response::FORMAT_JSON; + /** + * @var Basket $basket + */ + $basket = \Yii::$app->basket; + $basket->set($product_variant_id, $count); + $result = [ + 'basket' => $basket->getData(), + 'modal' => $basket->getModal(), + ]; + return $result; + } + public function actionTest() { + /** + * @var Basket $basket + */ + $basket = \Yii::$app->basket; + $modal = $basket->getModal(); + return $modal; + } +} diff --git a/frontend/controllers/CatalogController.php b/frontend/controllers/CatalogController.php index f80b514..afe354c 100755 --- a/frontend/controllers/CatalogController.php +++ b/frontend/controllers/CatalogController.php @@ -125,6 +125,7 @@ class CatalogController extends \yii\web\Controller */ $query = $productProvider->query; $query->with([ + 'variant', 'comments', 'averageRating', ]); diff --git a/frontend/views/basket/modal_items.php b/frontend/views/basket/modal_items.php new file mode 100644 index 0000000..a32e3dc --- /dev/null +++ b/frontend/views/basket/modal_items.php @@ -0,0 +1,96 @@ + + \ No newline at end of file diff --git a/frontend/views/catalog/_product_item.php b/frontend/views/catalog/_product_item.php index f0fa443..55cb209 100755 --- a/frontend/views/catalog/_product_item.php +++ b/frontend/views/catalog/_product_item.php @@ -1,10 +1,9 @@
@@ -25,7 +24,7 @@ use yii\helpers\Url; ]) ?>
- Купить светильник + Купить светильник
- есть на складе
Особенности
    - -
  • Тип: подвесной светильник
  • - -
  • Бренд: Massive
  • -
  • Модель: 41782/53/10
  • - -
  • кол-во ламп: 1
  • цоколь: E27
  • мощность: max. 60W
  • высота: 1250
  • ширина: 275
  • выступающая часть: 275
  • - -
-
@@ -85,18 +71,13 @@ use yii\helpers\Url;
Цена: - - 932.40 + 932.40 грн -
- - -
\ No newline at end of file diff --git a/frontend/views/catalog/product.php b/frontend/views/catalog/product.php index 9ea6ec5..0b20a7f 100755 --- a/frontend/views/catalog/product.php +++ b/frontend/views/catalog/product.php @@ -292,7 +292,7 @@ - + Купить светильник @@ -413,7 +413,7 @@
- Купить светильник + Купить светильник
Оплатить @@ -1319,7 +1319,7 @@ люстра FE/LEILA3
- Купить светильник + Купить светильник
  • К сравнению @@ -1361,7 +1361,7 @@  FE/LEILA1C
    - Купить светильник + Купить светильник
    • К сравнению @@ -1403,7 +1403,7 @@ настенный светильник FE/LEILA2
      - Купить светильник + Купить светильник
      • К сравнению diff --git a/frontend/views/catalog/products.php b/frontend/views/catalog/products.php index 42065c0..e2defb3 100755 --- a/frontend/views/catalog/products.php +++ b/frontend/views/catalog/products.php @@ -1,10 +1,11 @@
        diff --git a/frontend/views/layouts/main.php b/frontend/views/layouts/main.php index 57c556d..77010a3 100755 --- a/frontend/views/layouts/main.php +++ b/frontend/views/layouts/main.php @@ -157,7 +157,6 @@ AppAsset::register($this);

        Корзина пуста

        -
      diff --git a/frontend/web/js/artbox_basket.js b/frontend/web/js/artbox_basket.js new file mode 100644 index 0000000..acabe59 --- /dev/null +++ b/frontend/web/js/artbox_basket.js @@ -0,0 +1,70 @@ +var ArtboxBasket = (function () { + function ArtboxBasket() { + $.get('/basket', function (data) { + this._items = data.basket; + }.bind(this), 'json').fail(function () { + console.error('Basket cannot be init'); + }); + } + Object.defineProperty(ArtboxBasket.prototype, "items", { + get: function () { + return this._items; + }, + enumerable: true, + configurable: true + }); + ArtboxBasket.prototype.add = function (product_variant_id, count) { + $.post('/basket/add?product_variant_id=' + product_variant_id + '&count=' + count, function (data) { + this._items = data.basket; + this.updateModal(data.modal, true); + }.bind(this), 'json').fail(function (xhr, status, error) { + console.error(error); + }); + }; + ArtboxBasket.prototype.set = function (product_variant_id, count) { + $.post('/basket/set?product_variant_id=' + product_variant_id + '&count=' + count, function (data) { + this._items = data.basket; + this.updateModal(data.modal); + }.bind(this), 'json').fail(function (xhr, status, error) { + console.error(error); + }); + }; + ArtboxBasket.prototype.updateModal = function (modal, show) { + if (show === void 0) { show = false; } + var modalBox = $('#buyForm'); + modalBox.html(modal); + if (show) { + modalBox.modal('show'); + } + this.updateCart(); + }; + ArtboxBasket.prototype.updateCart = function () { + var cart = $('#top-cart-content'); + var count = this.count; + if (count > 0) { + $(cart).html('В корзине' + count + ' товар' + ((count > 4) ? 'ов' : ((count > 1) ? 'а' : '')) + '
      на ' + this.sum + '
      '); + } + else { + } + }; + Object.defineProperty(ArtboxBasket.prototype, "count", { + get: function () { + return Object.keys(this._items).length; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ArtboxBasket.prototype, "sum", { + get: function () { + var sum = 0; + $.each(this._items, function (index, value) { + sum += value.price * value.count; + }); + return sum; + }, + enumerable: true, + configurable: true + }); + return ArtboxBasket; +}()); +//# sourceMappingURL=artbox_basket.js.map \ No newline at end of file diff --git a/frontend/web/js/artbox_basket.js.map b/frontend/web/js/artbox_basket.js.map new file mode 100644 index 0000000..fd0ed16 --- /dev/null +++ b/frontend/web/js/artbox_basket.js.map @@ -0,0 +1 @@ +{"version":3,"file":"artbox_basket.js","sourceRoot":"","sources":["artbox_basket.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/frontend/web/js/artbox_basket.ts b/frontend/web/js/artbox_basket.ts new file mode 100644 index 0000000..f9e72fe --- /dev/null +++ b/frontend/web/js/artbox_basket.ts @@ -0,0 +1,57 @@ +class ArtboxBasket { + private _items; + get items() { + return this._items; + } + constructor() { + $.get('/basket', function (data) { + this._items = data.basket; + }.bind(this), 'json').fail(function() { + console.error('Basket cannot be init'); + }); + } + public add(product_variant_id, count) { + $.post('/basket/add?product_variant_id='+product_variant_id+'&count='+count, function (data) { + this._items = data.basket; + this.updateModal(data.modal, true); + }.bind(this), 'json').fail(function (xhr, status, error) { + console.error(error); + }); + } + public set(product_variant_id, count) { + $.post('/basket/set?product_variant_id='+product_variant_id+'&count='+count, function (data) { + this._items = data.basket; + this.updateModal(data.modal); + }.bind(this), 'json').fail(function (xhr, status, error) { + console.error(error); + }); + } + public updateModal(modal, show = false) + { + var modalBox = $('#buyForm'); + modalBox.html(modal); + if(show) { + modalBox.modal('show'); + } + this.updateCart(); + } + public updateCart() { + var cart = $('#top-cart-content'); + var count = this.count; + if(count > 0) { + $(cart).html('В корзине' + count + ' товар' + ((count > 4) ? 'ов' : ((count > 1) ? 'а' : '')) + '
      на ' + this.sum + '
      '); + } else { + + } + } + get count(): number { + return Object.keys(this._items).length; + } + get sum(): number { + var sum = 0; + $.each(this._items, function(index, value) { + sum += value.price * value.count; + }); + return sum; + } +} \ No newline at end of file diff --git a/frontend/web/js/js_head.js b/frontend/web/js/js_head.js index d9bb184..1b354e4 100755 --- a/frontend/web/js/js_head.js +++ b/frontend/web/js/js_head.js @@ -3516,48 +3516,48 @@ $(document).ready(function() { }, 'slow'); return false; }); - $(document).on("click", '.plus', function() { - var input = $(this).parent().find('input'); - var sp = parseFloat($(input).val()); - if (sp > 100) { - $(this).parent().find('.minus').attr('class', '').addClass('plus-disabled'); - $(input).val(sp + 1); - } else if (sp >= 0 && sp < 100) { - $(this).parent().find('.minus-disabled').attr('class', '').addClass('minus'); - $(input).val(sp + 1); - } - if (typeof save_cart == 'function') { - if (!$(input).hasClass('qtyInput')) { - save_cart($("#buyForm #prod_id").val(), $("#buyForm input.prod_count").val()); - } else { - save_cart($(input).prop('lang'), $(input).val(), $(this).closest("table.order_details")); - } - } - }); - $(document).on("click", '.minus', function() { - var input = $(this).parent().find('input'); - var sp = parseFloat($(input).val()); - if (sp > 2 && sp < 100) { - $(input).val(sp - 1); - } else if (sp = 2) { - $(this).parent().find('.minus').attr('class', '').addClass('minus-disabled'); - $(input).val(sp - 1); - } - if (typeof save_cart == 'function') - if (!$(input).hasClass('qtyInput')) { - save_cart($("#buyForm #prod_id").val(), $("#buyForm input.prod_count").val()); - } else { - save_cart($(input).prop('lang'), $(input).val(), $(this).closest("table.order_details")); - } - }); - $(".count_choise input").keydown(function(e) { - if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 190]) !== -1 || (e.keyCode == 65 && e.ctrlKey === true) || (e.keyCode >= 35 && e.keyCode <= 39)) { - return; - } - if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) { - e.preventDefault(); - } - }); +// $(document).on("click", '.plus', function() { +// var input = $(this).parent().find('input'); +// var sp = parseFloat($(input).val()); +// if (sp > 100) { +// $(this).parent().find('.minus').attr('class', '').addClass('plus-disabled'); +// $(input).val(sp + 1); +// } else if (sp >= 0 && sp < 100) { +// $(this).parent().find('.minus-disabled').attr('class', '').addClass('minus'); +// $(input).val(sp + 1); +// } +// if (typeof save_cart == 'function') { +// if (!$(input).hasClass('qtyInput')) { +// save_cart($("#buyForm #prod_id").val(), $("#buyForm input.prod_count").val()); +// } else { +// save_cart($(input).prop('lang'), $(input).val(), $(this).closest("table.order_details")); +// } +// } +// }); +// $(document).on("click", '.minus', function() { +// var input = $(this).parent().find('input'); +// var sp = parseFloat($(input).val()); +// if (sp > 2 && sp < 100) { +// $(input).val(sp - 1); +// } else if (sp = 2) { +// $(this).parent().find('.minus').attr('class', '').addClass('minus-disabled'); +// $(input).val(sp - 1); +// } +// if (typeof save_cart == 'function') +// if (!$(input).hasClass('qtyInput')) { +// save_cart($("#buyForm #prod_id").val(), $("#buyForm input.prod_count").val()); +// } else { +// save_cart($(input).prop('lang'), $(input).val(), $(this).closest("table.order_details")); +// } +// }); +// $(".count_choise input").keydown(function(e) { +// if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 190]) !== -1 || (e.keyCode == 65 && e.ctrlKey === true) || (e.keyCode >= 35 && e.keyCode <= 39)) { +// return; +// } +// if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) { +// e.preventDefault(); +// } +// }); $('.properties_block .block_title').on('click', function() { properties_block = $(this).parent(); if (properties_block.hasClass('closed')) { diff --git a/frontend/web/js/script.js b/frontend/web/js/script.js new file mode 100644 index 0000000..9018f21 --- /dev/null +++ b/frontend/web/js/script.js @@ -0,0 +1,34 @@ +var artbox_basket = new ArtboxBasket(); +$(document).on('click', '.buy_button', function(e) { + e.preventDefault(); + var product_variant_id = $(this).data('id'); + var count = 1; + artbox_basket.add(product_variant_id, count); +}); +$(document).on('change', '#buyForm .prod_count', function(e) { + e.preventDefault(); + var product_variant_id = $(this).parents('tr').data('id'); + var value = $(this).val(); + if(value < 0) { + value = 0; + } + artbox_basket.set(product_variant_id, value); +}); +$(document).on('click', '#buyForm .count_choise .minus', function(e) { + e.preventDefault(); + var container = $(this).parents('tr'); + var input = $(container).find('.prod_count'); + var value = $(input).val(); + var new_value = parseInt(value) - 1; + $(input).val(new_value); + $(input).trigger('change'); +}); +$(document).on('click', '#buyForm .count_choise .plus', function(e) { + e.preventDefault(); + var container = $(this).parents('tr'); + var input = $(container).find('.prod_count'); + var value = $(input).val(); + var new_value = parseInt(value) + 1; + $(input).val(new_value); + $(input).trigger('change'); +}); \ No newline at end of file -- libgit2 0.21.4