Commit 6c8e3423c3e98a9c21fa11c1f719c227645e5784

Authored by Yarik
1 parent fb14ea2a

Fast buy

frontend/controllers/CheckoutController.php
@@ -174,6 +174,33 @@ @@ -174,6 +174,33 @@
174 ] 174 ]
175 ); 175 );
176 } 176 }
  177 +
  178 + public function actionFast()
  179 + {
  180 + $this->enableCsrfValidation = false;
  181 + $response = \Yii::$app->response;
  182 + $response->format = $response::FORMAT_JSON;
  183 + $model = new Order(
  184 + [
  185 + 'scenario' => Order::SCENARIO_FAST,
  186 + ]
  187 + );
  188 + if ($model->load(\Yii::$app->request->post())) {
  189 + $model->label_id = 1;
  190 + $model->delivery_id = 5;
  191 + $model->payment_id = 3;
  192 + if ($model->save()) {
  193 + return [
  194 + 'success' => true,
  195 + 'msg' => \Yii::t(
  196 + 'app',
  197 + 'Заказ успешно оформлен. Вашему заказу присвоен номер ' . $model->id . '.'
  198 + ),
  199 + ];
  200 + }
  201 + }
  202 + return $model->getErrors();
  203 + }
177 204
178 public function beforeAction($action) 205 public function beforeAction($action)
179 { 206 {
@@ -181,7 +208,7 @@ @@ -181,7 +208,7 @@
181 * @var \artbox\order\models\Basket $basket 208 * @var \artbox\order\models\Basket $basket
182 */ 209 */
183 $basket = \Yii::$app->get('basket'); 210 $basket = \Yii::$app->get('basket');
184 - if ($action->id !== 'index' && empty($basket->getData())) { 211 + if ($action->id !== 'index' && $action->id !== 'fast' && empty($basket->getData())) {
185 return $this->redirect([ 'site/index' ]); 212 return $this->redirect([ 'site/index' ]);
186 } 213 }
187 return parent::beforeAction($action); 214 return parent::beforeAction($action);
frontend/models/Order.php
1 <?php 1 <?php
2 2
3 namespace frontend\models; 3 namespace frontend\models;
4 - 4 +
  5 + use artbox\catalog\models\Variant;
5 use artbox\order\models\Delivery; 6 use artbox\order\models\Delivery;
6 use artbox\order\models\Payment; 7 use artbox\order\models\Payment;
7 - 8 +
8 class Order extends \artbox\order\models\Order 9 class Order extends \artbox\order\models\Order
9 { 10 {
  11 + public $variantId;
  12 +
10 const SCENARIO_INFO = 'info'; 13 const SCENARIO_INFO = 'info';
11 const SCENARIO_DELIVERY = 'delivery'; 14 const SCENARIO_DELIVERY = 'delivery';
12 const SCENARIO_PAYMENT = 'payment'; 15 const SCENARIO_PAYMENT = 'payment';
13 const SCENARIO_CONFIRM = 'confirm'; 16 const SCENARIO_CONFIRM = 'confirm';
14 - 17 + const SCENARIO_FAST = 'fast';
  18 +
15 /** 19 /**
16 * @inheritdoc 20 * @inheritdoc
17 */ 21 */
@@ -34,10 +38,15 @@ @@ -34,10 +38,15 @@
34 self::SCENARIO_PAYMENT => [ 38 self::SCENARIO_PAYMENT => [
35 'payment_id', 39 'payment_id',
36 ], 40 ],
  41 + self::SCENARIO_FAST => [
  42 + 'name',
  43 + 'phone',
  44 + 'variantId',
  45 + ],
37 ] 46 ]
38 ); 47 );
39 } 48 }
40 - 49 +
41 /** 50 /**
42 * @inheritdoc 51 * @inheritdoc
43 */ 52 */
@@ -51,6 +60,7 @@ @@ -51,6 +60,7 @@
51 'email', 60 'email',
52 'delivery_id', 61 'delivery_id',
53 'payment_id', 62 'payment_id',
  63 + 'variantId',
54 ], 64 ],
55 'required', 65 'required',
56 ], 66 ],
@@ -94,9 +104,37 @@ @@ -94,9 +104,37 @@
94 'targetClass' => Payment::className(), 104 'targetClass' => Payment::className(),
95 'targetAttribute' => 'id', 105 'targetAttribute' => 'id',
96 ], 106 ],
  107 + [
  108 + [
  109 + 'variant_id',
  110 + ],
  111 + 'exist',
  112 + 'targetClass' => Variant::className(),
  113 + 'targetAttribute' => 'id',
  114 + 'filter' => function ($query) {
  115 + /**
  116 + * @var \yii\db\Query $query
  117 + */
  118 + $query->andWhere(
  119 + [
  120 + '>',
  121 + 'price',
  122 + 0,
  123 + ]
  124 + )
  125 + ->andWhere([ 'status' => true ])
  126 + ->andWhere(
  127 + [
  128 + '>',
  129 + 'stock',
  130 + 0,
  131 + ]
  132 + );
  133 + },
  134 + ],
97 ]; 135 ];
98 } 136 }
99 - 137 +
100 /** 138 /**
101 * Save active attributes to session variable 'order' 139 * Save active attributes to session variable 'order'
102 */ 140 */
@@ -108,7 +146,7 @@ @@ -108,7 +146,7 @@
108 } 146 }
109 \Yii::$app->session[ 'order' ] = $order; 147 \Yii::$app->session[ 'order' ] = $order;
110 } 148 }
111 - 149 +
112 /** 150 /**
113 * Load active attributes from session variable 'order' 151 * Load active attributes from session variable 'order'
114 */ 152 */
frontend/views/product/view.php
@@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
4 use artbox\catalog\models\Variant; 4 use artbox\catalog\models\Variant;
5 use artbox\core\components\SeoComponent; 5 use artbox\core\components\SeoComponent;
6 use artbox\core\helpers\ImageHelper; 6 use artbox\core\helpers\ImageHelper;
  7 + use frontend\models\Order;
  8 + use yii\bootstrap\ActiveForm;
7 use yii\bootstrap\Html; 9 use yii\bootstrap\Html;
8 use yii\helpers\ArrayHelper; 10 use yii\helpers\ArrayHelper;
9 use yii\web\View; 11 use yii\web\View;
@@ -209,14 +211,28 @@ @@ -209,14 +211,28 @@
209 </p> 211 </p>
210 <hr> 212 <hr>
211 <?php 213 <?php
  214 + echo Html::a(
  215 + Html::icon(
  216 + 'phone',
  217 + [
  218 + 'prefix' => 'fa fa-',
  219 + ]
  220 + ) . \Yii::t('app', 'Купить в один клик'),
  221 + '#',
  222 + [
  223 + 'data' => [
  224 + 'toggle' => 'modal',
  225 + 'target' => '#oneclick-modal',
  226 + ],
  227 + 'class' => 'btn btn-template-main',
  228 + ]
  229 + )
  230 + ?>
  231 + <?php
212 /* 232 /*
213 - ?>  
214 - <button class="btn btn-template-main">  
215 - <i class="fa fa-phone"></i> Купить в один клик  
216 - </button>  
217 - &emsp;<button class="btn btn-template-main">  
218 - <i class="fa fa-tags"></i> Купить в кредит  
219 - </button> 233 + &emsp;<button class="btn btn-template-main">
  234 + <i class="fa fa-tags"></i> Купить в кредит
  235 + </button>
220 */ 236 */
221 ?> 237 ?>
222 </div> 238 </div>
@@ -311,3 +327,65 @@ @@ -311,3 +327,65 @@
311 <!-- /.container --> 327 <!-- /.container -->
312 </div> 328 </div>
313 <!-- /#content --> 329 <!-- /#content -->
  330 +<div class="modal fade" id="oneclick-modal" tabindex="-1" role="dialog">
  331 + <div class="modal-dialog modal-sm">
  332 +
  333 + <div class="modal-content">
  334 + <div class="modal-header">
  335 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  336 + <h4 class="modal-title callback"><?php echo \Yii::t('app', 'Купить в один клик'); ?></h4>
  337 + </div>
  338 + <div class="modal-body">
  339 + <?php
  340 + $order = new Order(
  341 + [
  342 + 'scenario' => Order::SCENARIO_FAST,
  343 + 'variantId' => $variant->id,
  344 + ]
  345 + );
  346 + $form = ActiveForm::begin(
  347 + [
  348 + 'action' => [ 'checkout/fast' ],
  349 + 'id' => 'fast-buy-form',
  350 + ]
  351 + );
  352 + echo $form->field($order, 'variantId')
  353 + ->label(false)
  354 + ->hiddenInput();
  355 + echo $form->field($order, 'name')
  356 + ->label(false)
  357 + ->textInput(
  358 + [
  359 + 'placeholder' => $order->getAttributeLabel('name'),
  360 + ]
  361 + );
  362 + echo $form->field($order, 'phone')
  363 + ->label(false)
  364 + ->textInput(
  365 + [
  366 + 'placeholder' => $order->getAttributeLabel('phone'),
  367 + ]
  368 + );
  369 + echo Html::tag(
  370 + 'p',
  371 + Html::submitButton(
  372 + Html::icon(
  373 + 'shopping-cart',
  374 + [
  375 + 'prefix' => 'fa fa-',
  376 + ]
  377 + ) . \Yii::t('app', ' Отправить'),
  378 + [
  379 + 'class' => 'btn btn-template-main',
  380 + ]
  381 + ),
  382 + [
  383 + 'class' => 'text-center',
  384 + ]
  385 + );
  386 + $form::end();
  387 + ?>
  388 + </div>
  389 + </div>
  390 + </div>
  391 +</div>
frontend/web/js/script.js
1 -$(  
2 - function() {  
3 - var basket = new ArtboxBasket({  
4 - 'cartSelector': '#cart'  
5 - });  
6 - /**  
7 - * Modal form submit code  
8 - */  
9 - $(document)  
10 - .on(  
11 - 'beforeSubmit', '#feedback-form', function(e) {  
12 - var f = this;  
13 - var form = $(this);  
14 - var formData = form.serialize();  
15 - $.ajax(  
16 - {  
17 - url: form.attr("action"),  
18 - type: form.attr("method"),  
19 - data: formData,  
20 - success: function(data) {  
21 - f.reset();  
22 - $('#feedback-modal')  
23 - .modal('hide');  
24 - $('#success-modal')  
25 - .modal('show');  
26 - },  
27 - error: function() {  
28 - $('#feedback-modal')  
29 - .modal('hide');  
30 - }  
31 - }  
32 - );  
33 - }  
34 - )  
35 - .on(  
36 - 'submit', '#feedback-form', function(e) {  
37 - e.preventDefault(); 1 +$(function() {
  2 + var basket = new ArtboxBasket({
  3 + 'cartSelector': '#cart'
  4 + });
  5 + /**
  6 + * Modal form submit code
  7 + */
  8 + $(document)
  9 + .on('beforeSubmit', '#feedback-form', function(e) {
  10 + var f = this;
  11 + var form = $(this);
  12 + var formData = form.serialize();
  13 + $.ajax({
  14 + url: form.attr("action"),
  15 + type: form.attr("method"),
  16 + data: formData,
  17 + success: function(data) {
  18 + f.reset();
  19 + $('#feedback-modal')
  20 + .modal('hide');
  21 + $('#success-modal')
  22 + .modal('show');
  23 + },
  24 + error: function() {
  25 + $('#feedback-modal')
  26 + .modal('hide');
38 } 27 }
39 - ); 28 + });
  29 + })
  30 + .on('submit', '#feedback-form', function(e) {
  31 + e.preventDefault();
  32 + });
40 33
41 - /**  
42 - * Contact form submitting  
43 - */  
44 - $(document)  
45 - .on(  
46 - 'beforeSubmit', '#contact-form', function(e) {  
47 - var f = this;  
48 - var form = $(this);  
49 - var formData = form.serialize();  
50 - $.ajax(  
51 - {  
52 - url: form.attr("action"),  
53 - type: form.attr("method"),  
54 - data: formData,  
55 - success: function(data) {  
56 - f.reset();  
57 - form.replaceWith(data.alert);  
58 - },  
59 - error: function() { 34 + /**
  35 + * Contact form submitting
  36 + */
  37 + $(document)
  38 + .on('beforeSubmit', '#contact-form', function(e) {
  39 + var f = this;
  40 + var form = $(this);
  41 + var formData = form.serialize();
  42 + $.ajax({
  43 + url: form.attr("action"),
  44 + type: form.attr("method"),
  45 + data: formData,
  46 + success: function(data) {
  47 + f.reset();
  48 + form.replaceWith(data.alert);
  49 + },
  50 + error: function() {
60 51
61 - }  
62 - }  
63 - );  
64 } 52 }
65 - )  
66 - .on(  
67 - 'submit', '#contact-form', function(e) {  
68 - e.preventDefault();  
69 - }  
70 - );  
71 -  
72 - /**  
73 - * Button UP code  
74 - */  
75 - if ($('#back-to-top').length) {  
76 - var scrollTrigger = 100, // px  
77 - backToTop = function() {  
78 - var scrollTop = $(window)  
79 - .scrollTop();  
80 - if (scrollTop > scrollTrigger) {  
81 - $('#back-to-top')  
82 - .addClass('show');  
83 - } else {  
84 - $('#back-to-top')  
85 - .removeClass('show');  
86 - }  
87 - };  
88 - backToTop();  
89 - $(window)  
90 - .on(  
91 - 'scroll', function() {  
92 - backToTop();  
93 - }  
94 - );  
95 - $('#back-to-top')  
96 - .on(  
97 - 'click', function(e) {  
98 - e.preventDefault();  
99 - $('html,body')  
100 - .animate(  
101 - {  
102 - scrollTop: 0  
103 - }, 700  
104 - );  
105 - }  
106 - );  
107 - } 53 + });
  54 + })
  55 + .on('submit', '#contact-form', function(e) {
  56 + e.preventDefault();
  57 + });
108 58
109 - $(document)  
110 - .on('click', '.add-to-basket', function(e) {  
111 - e.preventDefault();  
112 - var id = $(this)  
113 - .data('id');  
114 - basket.add(id, 1);  
115 - if ($('.alert-cart').length > 0) { 59 + /**
  60 + * Button UP code
  61 + */
  62 + if ($('#back-to-top').length) {
  63 + var scrollTrigger = 100, // px
  64 + backToTop = function() {
  65 + var scrollTop = $(window)
  66 + .scrollTop();
  67 + if (scrollTop > scrollTrigger) {
  68 + $('#back-to-top')
  69 + .addClass('show');
116 } else { 70 } else {
117 - $('body').prepend($("<div class='alert-cart alert alert-success alert-dismissible'>Товар добавлен в корзину.</div>"));  
118 - setTimeout(function(){$(".alert-cart").addClass("active");},100);  
119 - setTimeout(function(){$(".alert-cart").removeClass("active");},3500);  
120 - setTimeout(function(){$(".alert-cart").remove();},3600); 71 + $('#back-to-top')
  72 + .removeClass('show');
121 } 73 }
  74 + };
  75 + backToTop();
  76 + $(window)
  77 + .on('scroll', function() {
  78 + backToTop();
122 }); 79 });
123 -  
124 - $(document)  
125 - .on('click', '.remove-product-cart', function(e) { 80 + $('#back-to-top')
  81 + .on('click', function(e) {
126 e.preventDefault(); 82 e.preventDefault();
127 - var id = $(this)  
128 - .parents('.product-row-basket')  
129 - .data('id');  
130 - showLoader('#basket');  
131 - var xhr = basket.remove(id);  
132 - xhr.done(function() {  
133 - $.pjax.reload({  
134 - container: '#basket',  
135 - fragment: '#basket',  
136 - timeout: 5000  
137 - });  
138 - }) 83 + $('html,body')
  84 + .animate({
  85 + scrollTop: 0
  86 + }, 700);
139 }); 87 });
  88 + }
  89 +
  90 + $(document)
  91 + .on('click', '.add-to-basket', function(e) {
  92 + e.preventDefault();
  93 + var id = $(this)
  94 + .data('id');
  95 + basket.add(id, 1);
  96 + if ($('.alert-cart').length > 0) {
  97 + } else {
  98 + $('body')
  99 + .prepend($("<div class='alert-cart alert alert-success alert-dismissible'>Товар добавлен в корзину.</div>"));
  100 + setTimeout(function() {
  101 + $(".alert-cart")
  102 + .addClass("active");
  103 + }, 100);
  104 + setTimeout(function() {
  105 + $(".alert-cart")
  106 + .removeClass("active");
  107 + }, 3500);
  108 + setTimeout(function() {
  109 + $(".alert-cart")
  110 + .remove();
  111 + }, 3600);
  112 + }
  113 + });
140 114
141 - $(document)  
142 - .on('change', '.increase-product-basket', function(e) {  
143 - var id = $(this)  
144 - .parents('.product-row-basket')  
145 - .data('id');  
146 - showLoader('#basket');  
147 - var xhr = basket.set(id, $(this)  
148 - .val());  
149 - xhr.done(function() {  
150 - $.pjax.reload({  
151 - container: '#basket',  
152 - fragment: '#basket',  
153 - timeout: 5000  
154 - }); 115 + $(document)
  116 + .on('click', '.remove-product-cart', function(e) {
  117 + e.preventDefault();
  118 + var id = $(this)
  119 + .parents('.product-row-basket')
  120 + .data('id');
  121 + showLoader('#basket');
  122 + var xhr = basket.remove(id);
  123 + xhr.done(function() {
  124 + $.pjax.reload({
  125 + container: '#basket',
  126 + fragment: '#basket',
  127 + timeout: 5000
155 }); 128 });
156 - }); 129 + })
  130 + });
157 131
158 - $(document)  
159 - .on('click', 'li.disabled a', function(e) {  
160 - e.preventDefault(); 132 + $(document)
  133 + .on('change', '.increase-product-basket', function(e) {
  134 + var id = $(this)
  135 + .parents('.product-row-basket')
  136 + .data('id');
  137 + showLoader('#basket');
  138 + var xhr = basket.set(id, $(this)
  139 + .val());
  140 + xhr.done(function() {
  141 + $.pjax.reload({
  142 + container: '#basket',
  143 + fragment: '#basket',
  144 + timeout: 5000
  145 + });
161 }); 146 });
162 - }  
163 -); 147 + });
  148 +
  149 + $(document)
  150 + .on('click', 'li.disabled a', function(e) {
  151 + e.preventDefault();
  152 + });
  153 +
  154 + $(document)
  155 + .on('submit', '#fast-buy-form', function(e) {
  156 + e.preventDefault();
  157 + });
  158 +
  159 + $(document)
  160 + .on('afterValidate', '#fast-buy-form', function(e, m, errors) {
  161 + if (!errors.length) {
  162 + var form = $(e.target);
  163 + var action = form.attr('action');
  164 + $.post(action, form.serialize(), function(data) {
  165 + if (data.success) {
  166 + $('#oneclick-modal')
  167 + .find('.modal-body')
  168 + .text(data.msg);
  169 + }
  170 + });
  171 + }
  172 + }.bind(this));
  173 +
  174 +});
164 function showLoader(container) { 175 function showLoader(container) {
165 $(container) 176 $(container)
166 .prepend('<div class="loader-wrapper"><div class="loader"></div></div>'); 177 .prepend('<div class="loader-wrapper"><div class="loader"></div></div>');