diff --git a/common/config/main.php b/common/config/main.php
index 07b6b0d..03dcf3b 100755
--- a/common/config/main.php
+++ b/common/config/main.php
@@ -39,6 +39,10 @@
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@artbox/weblog/messages',
],
+ 'order' => [
+ 'class' => 'yii\i18n\PhpMessageSource',
+ 'basePath' => '@artbox/order/messages',
+ ],
],
],
'filedb' => [
diff --git a/common/models/PasswordResetRequestForm.php b/common/models/PasswordResetRequestForm.php
new file mode 100644
index 0000000..f621b3e
--- /dev/null
+++ b/common/models/PasswordResetRequestForm.php
@@ -0,0 +1,78 @@
+ '\artbox\order\models\Customer',
+ 'filter' => [ 'status' => Customer::STATUS_ACTIVE ],
+ 'message' => 'There is no user with this email address.',
+ ],
+ ];
+ }
+ /**
+ * Sends an email with a link, for resetting the password.
+ *
+ * @return bool whether the email was send
+ */
+ public function sendEmail()
+ {
+ /* @var $user Customer */
+ $user = Customer::findOne(
+ [
+ 'status' => Customer::STATUS_ACTIVE,
+ 'email' => $this->email,
+ ]
+ );
+ if (!$user) {
+ return false;
+ }
+
+ if (!Customer::isPasswordResetTokenValid($user->password_reset_token)) {
+ $user->generatePasswordResetToken();
+ if (!$user->save()) {
+ return false;
+ }
+ }
+ return Yii::$app->mailer->compose(
+ [
+ 'html' => 'passwordResetToken-html',
+ 'text' => 'passwordResetToken-text',
+ ],
+ [ 'user' => $user ]
+ )
+ ->setFrom([ Yii::$app->params[ 'supportEmail' ] => Yii::$app->name . ' robot' ])
+ ->setTo($this->email)
+ ->setSubject('Password reset for ' . Yii::$app->name)
+ ->send();
+ }
+ }
\ No newline at end of file
diff --git a/common/models/ResetPasswordForm.php b/common/models/ResetPasswordForm.php
new file mode 100644
index 0000000..358d36e
--- /dev/null
+++ b/common/models/ResetPasswordForm.php
@@ -0,0 +1,72 @@
+_user = Customer::findByPasswordResetToken($token);
+ if (!$this->_user) {
+ throw new InvalidParamException('Wrong password reset token.');
+ }
+ parent::__construct($config);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function rules()
+ {
+ return [
+ [
+ 'password',
+ 'required',
+ ],
+ [
+ 'password',
+ 'string',
+ 'min' => 6,
+ ],
+ ];
+ }
+
+ /**
+ * Resets password.
+ *
+ * @return bool if password was reset.
+ */
+ public function resetPassword()
+ {
+ $user = $this->_user;
+ $user->setPassword($this->password);
+ $user->removePasswordResetToken();
+
+ return $user->save(false);
+ }
+ }
\ No newline at end of file
diff --git a/common/models/SignupForm.php b/common/models/SignupForm.php
new file mode 100644
index 0000000..867fe3d
--- /dev/null
+++ b/common/models/SignupForm.php
@@ -0,0 +1,99 @@
+ '\artbox\order\models\Customer',
+ 'message' => 'This username has already been taken.',
+ ],
+ [
+ 'username',
+ 'string',
+ 'min' => 2,
+ 'max' => 255,
+ ],
+
+ [
+ 'email',
+ 'trim',
+ ],
+ [
+ 'email',
+ 'required',
+ ],
+ [
+ 'email',
+ 'email',
+ ],
+ [
+ 'email',
+ 'string',
+ 'max' => 255,
+ ],
+ [
+ 'email',
+ 'unique',
+ 'targetClass' => '\artbox\order\models\Customer',
+ 'message' => 'This email address has already been taken.',
+ ],
+
+ [
+ 'password',
+ 'required',
+ ],
+ [
+ 'password',
+ 'string',
+ 'min' => 6,
+ ],
+ ];
+ }
+
+ /**
+ * Signs user up.
+ *
+ * @return \artbox\order\models\Customer|null the saved model or null if saving fails
+ */
+ public function signup()
+ {
+ if (!$this->validate()) {
+ return null;
+ }
+
+ $user = new Customer();
+ $user->username = $this->username;
+ $user->email = $this->email;
+ $user->setPassword($this->password);
+ $user->generateAuthKey();
+
+ return $user->save() ? $user : null;
+ }
+ }
\ No newline at end of file
diff --git a/frontend/assets/AppAsset.php b/frontend/assets/AppAsset.php
index 697ef92..f7e2144 100755
--- a/frontend/assets/AppAsset.php
+++ b/frontend/assets/AppAsset.php
@@ -33,6 +33,7 @@
'yii\web\YiiAsset',
'rmrevin\yii\fontawesome\AssetBundle',
'yii\bootstrap\BootstrapPluginAsset',
+ 'yii\widgets\PjaxAsset',
'artbox\order\assets\BasketAsset',
];
}
diff --git a/frontend/config/main.php b/frontend/config/main.php
index 67f489e..1d60719 100755
--- a/frontend/config/main.php
+++ b/frontend/config/main.php
@@ -1,6 +1,7 @@
dirname(__DIR__),
'bootstrap' => [ 'log' ],
'controllerNamespace' => 'frontend\controllers',
+ 'controllerMap' => [
+ 'basket' => 'artbox\order\controllers\BasketController',
+ ],
'components' => [
'request' => [
'class' => LanguageRequest::className(),
@@ -22,7 +26,7 @@
'baseUrl' => '/',
],
'user' => [
- 'identityClass' => 'common\models\User',
+ 'identityClass' => 'artbox\order\models\Customer',
'enableAutoLogin' => true,
'identityCookie' => [
'name' => '_identity-frontend',
@@ -69,6 +73,9 @@
'robots.txt' => 'site/robots',
],
],
+ 'basket' => [
+ 'class' => Basket::className(),
+ ],
],
'params' => $params,
];
diff --git a/frontend/config/params.php b/frontend/config/params.php
index fa597b5..90de023 100755
--- a/frontend/config/params.php
+++ b/frontend/config/params.php
@@ -2,3 +2,4 @@
return [
'adminEmail' => 'admin@example.com',
];
+
\ No newline at end of file
diff --git a/frontend/controllers/CheckoutController.php b/frontend/controllers/CheckoutController.php
new file mode 100755
index 0000000..84bed77
--- /dev/null
+++ b/frontend/controllers/CheckoutController.php
@@ -0,0 +1,190 @@
+get('basket');
+ $data = $basket->getData();
+ $variants = [];
+ if (!empty($data)) {
+ $variants = $basket->findModels(array_keys($data));
+ }
+ return $this->render(
+ 'index',
+ [
+ 'basket' => $basket,
+ 'variants' => $variants,
+ ]
+ );
+ }
+
+ public function actionInfo()
+ {
+ $model = new Order(
+ [
+ 'scenario' => Order::SCENARIO_INFO,
+ ]
+ );
+ if (!\Yii::$app->user->isGuest) {
+ /**
+ * @var \artbox\order\models\Customer $user
+ */
+ $user = \Yii::$app->user->identity;
+ $model->name = $user->name;
+ $model->email = $user->email;
+ $model->phone = $user->phone;
+ $model->city = $user->city;
+ $model->address = $user->address;
+ }
+ $model->loadActive();
+ if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
+ $model->saveActive();
+ return $this->redirect([ 'delivery' ]);
+ }
+ return $this->render(
+ 'info',
+ [
+ 'model' => $model,
+ ]
+ );
+ }
+
+ public function actionDelivery()
+ {
+ $model = new Order(
+ [
+ 'scenario' => Order::SCENARIO_INFO,
+ ]
+ );
+ if (!empty($order = \Yii::$app->session->get('order')) && $model->load($order, '') && $model->validate()) {
+ $model->scenario = Order::SCENARIO_DELIVERY;
+ $model->loadActive();
+ if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
+ $model->saveActive();
+ return $this->redirect([ 'payment' ]);
+ }
+ } else {
+ return $this->redirect([ 'info' ]);
+ }
+ $deliveries = Delivery::find()
+ ->with('lang')
+ ->where([ 'status' => true ])
+ ->orderBy([ 'sort' => SORT_ASC ])
+ ->all();
+ return $this->render(
+ 'delivery',
+ [
+ 'model' => $model,
+ 'deliveries' => $deliveries,
+ ]
+ );
+ }
+
+ public function actionPayment()
+ {
+ $model = new Order(
+ [
+ 'scenario' => Order::SCENARIO_INFO,
+ ]
+ );
+ $order = \Yii::$app->session->get('order');
+ if (!empty($model)) {
+ if ($model->load($order, '') && $model->validate()) {
+ $model->scenario = Order::SCENARIO_DELIVERY;
+ if ($model->load($order, '') && $model->validate()) {
+ $model->scenario = Order::SCENARIO_PAYMENT;
+ $model->loadActive();
+ if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
+ $model->saveActive();
+ return $this->redirect('confirm');
+ } else {
+ $payments = Payment::find()
+ ->with('lang')
+ ->where([ 'status' => true ])
+ ->orderBy([ 'sort' => SORT_ASC ])
+ ->all();
+ return $this->render(
+ 'payment',
+ [
+ 'model' => $model,
+ 'payments' => $payments,
+ ]
+ );
+ }
+ }
+ }
+ }
+ return $this->redirect(
+ 'delivery'
+ );
+ }
+
+ public function actionConfirm()
+ {
+ $model = new Order();
+ $order = \Yii::$app->session->get('order');
+ $model->load($order, '');
+ if (!$model->validate()) {
+ return $this->redirect([ 'payment' ]);
+ }
+ if (\Yii::$app->request->isPost) {
+ $model->label_id = 1;
+ $model->save(false);
+ /**
+ * @var \artbox\order\models\Basket $basket
+ */
+ $basket = \Yii::$app->get('basket');
+ foreach ($basket->findModels(array_keys($basket->getData())) as $variant) {
+ $orderProduct = new OrderProduct(
+ [
+ 'order_id' => $model->id,
+ 'variant_id' => $variant->id,
+ 'sku' => $variant->sku,
+ 'price' => $variant->price,
+ 'count' => $basket->getItem($variant->id)[ 'count' ],
+ ]
+ );
+ $orderProduct->save();
+ }
+ \Yii::$app->session->remove('order');
+ $basket->clear();
+ return $this->redirect([ 'site/index' ]);
+ }
+ return $this->render(
+ 'confirm',
+ [
+ 'model' => $model,
+ ]
+ );
+ }
+
+ public function beforeAction($action)
+ {
+ /**
+ * @var \artbox\order\models\Basket $basket
+ */
+ $basket = \Yii::$app->get('basket');
+ if ($action->id !== 'index' && empty($basket->getData())) {
+ return $this->redirect([ 'site/index' ]);
+ }
+ return parent::beforeAction($action);
+ }
+ }
+
\ No newline at end of file
diff --git a/frontend/controllers/PageController.php b/frontend/controllers/PageController.php
index 2c4f8fb..8cd4b40 100755
--- a/frontend/controllers/PageController.php
+++ b/frontend/controllers/PageController.php
@@ -3,9 +3,6 @@
use artbox\core\components\SeoComponent;
use artbox\core\models\Page;
- use yii\helpers\Json;
- use yii\helpers\Url;
- use yii\helpers\VarDumper;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use Yii;
diff --git a/frontend/controllers/SiteController.php b/frontend/controllers/SiteController.php
index 8803b2c..a38fc76 100755
--- a/frontend/controllers/SiteController.php
+++ b/frontend/controllers/SiteController.php
@@ -1,12 +1,18 @@
response->format = Response::FORMAT_JSON;
- if (empty( Yii::$app->request->post() )) {
+ if (empty(Yii::$app->request->post())) {
throw new BadRequestHttpException();
} else {
$model = new Feedback();
@@ -173,4 +179,103 @@
}
}
}
+
+ public function actionLogin()
+ {
+ if (!\Yii::$app->user->isGuest) {
+ return $this->redirect([ 'index' ]);
+ }
+
+ $loginForm = new LoginForm();
+ $signupForm = new SignupForm();
+ if ($loginForm->load(\Yii::$app->request->post()) && $loginForm->login()) {
+ if (!empty($loginForm->returnUrl)) {
+ return $this->redirect($loginForm->returnUrl);
+ } else {
+ return $this->redirect([ 'index' ]);
+ }
+ }
+ if ($signupForm->load(\Yii::$app->request->post())) {
+ if ($user = $signupForm->signup()) {
+ if (\Yii::$app->getUser()
+ ->login($user)
+ ) {
+ return $this->redirect([ 'index' ]);
+ }
+ }
+ }
+ return $this->render(
+ 'login',
+ [
+ 'loginForm' => $loginForm,
+ 'signupForm' => $signupForm,
+ ]
+ );
+ }
+
+ public function actionLogout()
+ {
+ \Yii::$app->user->logout();
+
+ return $this->redirect([ 'index' ]);
+ }
+
+ /**
+ * Requests password reset.
+ *
+ * @return mixed
+ */
+ public function actionRequestPasswordReset()
+ {
+ $model = new PasswordResetRequestForm();
+ if ($model->load(Yii::$app->request->post()) && $model->validate()) {
+ if ($model->sendEmail()) {
+ Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
+
+ return $this->redirect([ 'index' ]);
+ } else {
+ Yii::$app->session->setFlash(
+ 'error',
+ 'Sorry, we are unable to reset password for the provided email address.'
+ );
+ }
+ }
+
+ return $this->render(
+ 'requestPasswordResetToken',
+ [
+ 'model' => $model,
+ ]
+ );
+ }
+
+ /**
+ * Resets password.
+ *
+ * @param string $token
+ *
+ * @return mixed
+ * @throws BadRequestHttpException
+ */
+ public function actionResetPassword($token)
+ {
+ try {
+ $model = new ResetPasswordForm($token);
+ } catch (InvalidParamException $e) {
+ throw new BadRequestHttpException($e->getMessage());
+ }
+
+ if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
+ Yii::$app->session->setFlash('success', 'New password saved.');
+
+ return $this->redirect([ 'index' ]);
+ }
+
+ return $this->render(
+ 'resetPassword',
+ [
+ 'model' => $model,
+ ]
+ );
+ }
}
diff --git a/frontend/models/Order.php b/frontend/models/Order.php
new file mode 100644
index 0000000..0cb2f66
--- /dev/null
+++ b/frontend/models/Order.php
@@ -0,0 +1,126 @@
+ [
+ 'name',
+ 'phone',
+ 'email',
+ 'city',
+ 'address',
+ 'comment',
+ ],
+ self::SCENARIO_DELIVERY => [
+ 'delivery_id',
+ ],
+ self::SCENARIO_PAYMENT => [
+ 'payment_id',
+ ],
+ ]
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function rules()
+ {
+ return [
+ [
+ [
+ 'name',
+ 'phone',
+ 'email',
+ 'delivery_id',
+ 'payment_id',
+ ],
+ 'required',
+ ],
+ [
+ [
+ 'name',
+ 'phone',
+ 'email',
+ 'city',
+ 'address',
+ ],
+ 'string',
+ 'max' => 255,
+ ],
+ [
+ [
+ 'comment',
+ ],
+ 'string',
+ ],
+ [
+ [
+ 'delivery_id',
+ 'payment_id',
+ ],
+ 'integer',
+ ],
+ [
+ [
+ 'delivery_id',
+ ],
+ 'exist',
+ 'targetClass' => Delivery::className(),
+ 'targetAttribute' => 'id',
+ ],
+ [
+ [
+ 'payment_id',
+ ],
+ 'exist',
+ 'targetClass' => Payment::className(),
+ 'targetAttribute' => 'id',
+ ],
+ ];
+ }
+
+ /**
+ * Save active attributes to session variable 'order'
+ */
+ public function saveActive()
+ {
+ $order = \Yii::$app->session->get('order', []);
+ foreach ($this->activeAttributes() as $attribute) {
+ $order[ $attribute ] = $this->getAttribute($attribute);
+ }
+ \Yii::$app->session[ 'order' ] = $order;
+ }
+
+ /**
+ * Load active attributes from session variable 'order'
+ */
+ public function loadActive()
+ {
+ $order = \Yii::$app->session->get('order');
+ if (!empty($order)) {
+ foreach ($this->activeAttributes() as $attribute) {
+ if (!empty($order[ $attribute ])) {
+ $this->setAttribute($attribute, $order[ $attribute ]);
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/frontend/views/basket/cart.php b/frontend/views/basket/cart.php
new file mode 100755
index 0000000..d706fc5
--- /dev/null
+++ b/frontend/views/basket/cart.php
@@ -0,0 +1,27 @@
+
+= $count; ?>
+ 'sub-title',
+ ]
+ ),
+ [
+ '/checkout/index',
+ ],
+ [
+ 'class' => 'cart-item-link',
+ ]
+ );
+?>
diff --git a/frontend/views/basket/modal_items.php b/frontend/views/basket/modal_items.php
new file mode 100755
index 0000000..0df3838
--- /dev/null
+++ b/frontend/views/basket/modal_items.php
@@ -0,0 +1,10 @@
+
variants[ 0 ]->stock && $product->variants[ 0 ]->price) {
+ echo Html::a(
+ Html::tag(
+ 'i',
+ '',
+ [
+ 'class' => 'fa fa-shopping-cart',
+ ]
+ ) . \Yii::t('app', 'В корзину'),
+ '#',
[
- 'class' => 'fa fa-shopping-cart',
+ 'class' => 'btn btn-template-main add-to-basket',
+ 'data-id' => $product->variants[ 0 ]->id,
]
- ) . \Yii::t('app', 'В корзину'),
- '#',
- [ 'class' => 'btn btn-template-main' ]
- );
+ );
+ } else {
+ echo Html::a(
+ \Yii::t('app', 'Нет в наличии'),
+ '#',
+ [
+ 'class' => 'btn btn-info disabled',
+ 'data-id' => $product->variants[ 0 ]->id,
+ ]
+ );
+ }
?>
diff --git a/frontend/views/checkout/confirm.php b/frontend/views/checkout/confirm.php
new file mode 100644
index 0000000..fc801df
--- /dev/null
+++ b/frontend/views/checkout/confirm.php
@@ -0,0 +1,248 @@
+formatter;
+ $basket = \Yii::$app->get('basket');
+ $sum = 0;
+ $sumDiscount = 0;
+ $variants = $basket->findModels(array_keys($basket->getData()));
+ foreach ($variants as $variant) {
+ $count = $basket->getItem($variant->id)[ 'count' ];
+ $sum += $variant->price * $count;
+ if (!empty($variant->price_old)) {
+ $sumDiscount += ( $variant->price_old - $variant->price ) * $count;
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+ 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Адрес'),
+ [ 'checkout/info' ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'truck',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ доставки'),
+ [ 'checkout/delivery' ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'money',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ оплаты'),
+ [
+ 'checkout/payment',
+ ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'eye',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Просмотр заказа'),
+ '#'
+ ),
+ [
+ 'class' => 'active',
+ ]
+ );
+ ?>
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+ product->image->getPath())
+ ->fillResize(50, 50)
+ ->renderImage(
+ [
+ 'alt' => $variant->product->lang->title,
+ 'title' => $variant->product->lang->title,
+ ]
+ ),
+ [
+ 'product/view',
+ 'id' => $variant->product->id,
+ ],
+ [ 'target' => '_blank' ]
+ )
+ ?>
+ |
+
+ product->lang->title,
+ [
+ 'product/view',
+ 'id' => $variant->product->id,
+ ],
+ [ 'target' => '_blank' ]
+ )
+ ?>
+ |
+ getItem($variant->id))) {
+ echo $item[ 'count' ];
+ }
+ ?> |
+ price ? : 0 ) . ' грн.'; ?> |
+ price_old - $variant->price ) ? : 0 ) . ' грн.'; ?> |
+ price * $item[ 'count' ] . ' грн.'; ?> |
+
+
+
+
+
+ |
+ грн. |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ грн. |
+
+
+ |
+ грн. |
+
+
+ |
+ delivery->value; ?> грн. |
+
+
+ |
+ delivery->value; ?> грн. |
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/views/checkout/delivery.php b/frontend/views/checkout/delivery.php
new file mode 100644
index 0000000..8071e3b
--- /dev/null
+++ b/frontend/views/checkout/delivery.php
@@ -0,0 +1,238 @@
+formatter;
+ $basket = \Yii::$app->get('basket');
+ $sum = 0;
+ $sumDiscount = 0;
+ foreach ($basket->findModels(array_keys($basket->getData())) as $variant) {
+ $count = $basket->getItem($variant->id)[ 'count' ];
+ $sum += $variant->price * $count;
+ if (!empty($variant->price_old)) {
+ $sumDiscount += ( $variant->price_old - $variant->price ) * $count;
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+ 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Адрес'),
+ [ 'checkout/info' ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'truck',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ доставки'),
+ '#'
+ ),
+ [
+ 'class' => 'active',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'money',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ оплаты'),
+ [
+ 'checkout/payment',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'eye',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Просмотр заказа'),
+ [
+ 'checkout/confirm',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ ?>
+
+
+
+
+
+ hasErrors()) {
+ echo Html::tag(
+ 'p',
+ \Yii::t('app', 'Please choose delivery method.'),
+ [
+ 'class' => 'text-danger',
+ ]
+ );
+ }
+ foreach ($deliveries as $index => $delivery) {
+ ?>
+
+
+
+
+
+
lang->description; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+ |
+ asDecimal($sumDiscount, 2); ?> |
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/views/checkout/index.php b/frontend/views/checkout/index.php
new file mode 100644
index 0000000..a8fd618
--- /dev/null
+++ b/frontend/views/checkout/index.php
@@ -0,0 +1,456 @@
+formatter;
+ $sum = 0;
+ $sumDiscount = 0;
+ foreach ($variants as $variant) {
+ $count = $basket->getItem($variant->id)[ 'count' ];
+ $sum += $variant->price * $count;
+ if (!empty($variant->price_old)) {
+ $sumDiscount += ( $variant->price_old - $variant->price ) * $count;
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+ getItem($variant->id)[ 'count' ];
+ ?>
+
+
+ product->image->getPath())
+ ->fillResize(50, 50)
+ ->renderImage(
+ [
+ 'alt' => $variant->product->lang->title,
+ 'title' => $variant->product->lang->title,
+ ]
+ ),
+ [
+ '/product/view',
+ 'id' => $variant->product->id,
+ ],
+ [
+ 'target' => '_blank',
+ ]
+ );
+ ?>
+ |
+
+ product->lang->title,
+ [
+ '/product/view',
+ 'id' => $variant->product->id,
+ ],
+ [
+ 'target' => '_blank',
+ ]
+ );
+ ?>
+ |
+
+ 'form-control increase-product-basket',
+ ]
+ );
+ ?>
+ |
+
+ asDecimal($variant->price ? : 0, 2);
+ ?>
+ |
+
+ price_old)) {
+ echo $formatter->asDecimal($variant->price_old - $variant->price, 2);
+ } else {
+ echo $formatter->asDecimal(0, 2);
+ }
+ ?>
+ |
+
+ asDecimal(
+ ( $variant->price ? : 0 ) * $count,
+ 2
+ );
+ ?>
+ |
+
+ |
+
+
+
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+ |
+ asDecimal($sumDiscount, 2); ?> |
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+
+
+
+
+
+
+
+
+
+
Смотрите также
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 280
+ 143.00
+
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
143.00
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
143.00
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 280
+ 143.00
+
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
143.00
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
143.00
+
+ В корзину
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/views/checkout/info.php b/frontend/views/checkout/info.php
new file mode 100644
index 0000000..1ebc0a0
--- /dev/null
+++ b/frontend/views/checkout/info.php
@@ -0,0 +1,258 @@
+formatter;
+ $basket = \Yii::$app->get('basket');
+ $sum = 0;
+ $sumDiscount = 0;
+ foreach ($basket->findModels(array_keys($basket->getData())) as $variant) {
+ $count = $basket->getItem($variant->id)[ 'count' ];
+ $sum += $variant->price * $count;
+ if (!empty($variant->price_old)) {
+ $sumDiscount += ( $variant->price_old - $variant->price ) * $count;
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+
+ 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Адрес'),
+ '#'
+ ),
+ [
+ 'class' => 'active',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'truck',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ доставки'),
+ [
+ 'checkout/delivery',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'money',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ оплаты'),
+ [
+ 'checkout/payment',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'eye',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Просмотр заказа'),
+ [
+ 'checkout/confirm',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ ?>
+
+
+
+ user->isGuest) {
+ ?>
+
+
+
+
+ field($model, 'name')
+ ->textInput();
+ ?>
+
+
+
+
+
+
+
+ field($model, 'city')
+ ->textInput();
+ ?>
+
+
+ field($model, 'address')
+ ->textInput();
+ ?>
+
+
+
+
+
+
+ field($model, 'phone')
+ ->textInput();
+ ?>
+
+
+ field($model, 'email')
+ ->textInput();
+ ?>
+
+
+
+
+
+ field($model, 'comment')
+ ->textarea(
+ [
+ 'rows' => 4,
+ ]
+ );
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+ |
+ asDecimal($sumDiscount, 2); ?> |
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/views/checkout/payment.php b/frontend/views/checkout/payment.php
new file mode 100644
index 0000000..a3aa112
--- /dev/null
+++ b/frontend/views/checkout/payment.php
@@ -0,0 +1,235 @@
+formatter;
+ $basket = \Yii::$app->get('basket');
+ $sum = 0;
+ $sumDiscount = 0;
+ foreach ($basket->findModels(array_keys($basket->getData())) as $variant) {
+ $count = $basket->getItem($variant->id)[ 'count' ];
+ $sum += $variant->price * $count;
+ if (!empty($variant->price_old)) {
+ $sumDiscount += ( $variant->price_old - $variant->price ) * $count;
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+ 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Адрес'),
+ [ 'checkout/info' ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'truck',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ доставки'),
+ [ 'checkout/delivery' ]
+ )
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'money',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Способ оплаты'),
+ [
+ '#',
+ ]
+ ),
+ [
+ 'class' => 'active',
+ ]
+ );
+ echo Html::tag(
+ 'li',
+ Html::a(
+ Html::icon(
+ 'eye',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . Html::tag('br') . \Yii::t('app', 'Просмотр заказа'),
+ [
+ 'checkout/confirm',
+ ]
+ ),
+ [
+ 'class' => 'disabled',
+ ]
+ );
+ ?>
+
+
+
+
+
+ hasErrors()) {
+ echo Html::tag(
+ 'p',
+ \Yii::t('app', 'Please choose payment method.'),
+ [
+ 'class' => 'text-danger',
+ ]
+ );
+ }
+ foreach ($payments as $index => $payment) {
+ ?>
+
+
+
+
+
+
lang->description; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+ |
+ asDecimal($sumDiscount, 2); ?> |
+
+
+ |
+ asDecimal($sum, 2); ?> |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/views/layouts/main.php b/frontend/views/layouts/main.php
index 0d7b7f4..fdec370 100755
--- a/frontend/views/layouts/main.php
+++ b/frontend/views/layouts/main.php
@@ -23,6 +23,9 @@
use yii\widgets\Breadcrumbs;
AppAsset::register($this);
+ /**
+ * @var \artbox\order\models\Customer $user
+ */
$user = \Yii::$app->user->identity;
$seo = Yii::$app->get('seo');
$feedback = new Feedback();
@@ -140,8 +143,16 @@ _________________________________________________________ -->
-
- Вход
+ user->isGuest) {
+ ?>
+
+ Вход
+ username, [ 'account/index' ]);
+ }
+ ?>
@@ -240,7 +251,7 @@ _________________________________________________________ -->
-
0
+
0
]
),
[
- '/basket/index',
+ '/checkout/index',
],
[
'class' => 'cart-item-link',
@@ -332,64 +343,75 @@ _________________________________________________________ -->
-
-
-
-
-
-
-
- [ '/site/login' ],
- ]
- );
- echo $login->field($loginForm, 'returnUrl')
- ->label(false)
- ->hiddenInput();
- echo $login->field($loginForm, 'username')
- ->label(false)
- ->textInput(
- [
- 'placeholder' => $loginForm->getAttributeLabel('username'),
- ]
- );
- echo $login->field($loginForm, 'username')
- ->label(false)
- ->passwordInput(
- [
- 'placeholder' => $loginForm->getAttributeLabel('password'),
- ]
- );
- $login::end();
+ user->isGuest) {
?>
-
-
-
-
-
+
-
-
+
+
+
+ [ '/site/login' ],
+ ]
+ );
+ echo $login->field($loginForm, 'returnUrl')
+ ->label(false)
+ ->hiddenInput();
+ echo $login->field($loginForm, 'username')
+ ->label(false)
+ ->textInput(
+ [
+ 'placeholder' => $loginForm->getAttributeLabel('username'),
+ ]
+ );
+ echo $login->field($loginForm, 'password')
+ ->label(false)
+ ->passwordInput(
+ [
+ 'placeholder' => $loginForm->getAttributeLabel('password'),
+ ]
+ );
+ echo Html::submitButton(
+ \Yii::t('app', 'Login'),
+ [
+ 'class' => 'btn btn-success',
+ ]
+ );
+ $login::end();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/views/product/view.php b/frontend/views/product/view.php
index 139106c..6cd0de6 100755
--- a/frontend/views/product/view.php
+++ b/frontend/views/product/view.php
@@ -171,21 +171,54 @@
sku; ?>
Цена:price ? : 0; ?> грн
-
-
+ stock && $variant->price) {
+ echo Html::a(
+ Html::tag(
+ 'i',
+ '',
+ [
+ 'class' => 'fa fa-shopping-cart',
+ ]
+ ) . \Yii::t('app', 'Добавить в корзину'),
+ '#',
+ [
+ 'class' => 'btn btn-success add-to-basket',
+ 'data-id' => $variant->id,
+ ]
+ );
+ } else {
+ echo Html::a(
+ \Yii::t('app', 'Нет в наличии'),
+ '#',
+ [
+ 'class' => 'btn btn-info disabled',
+ 'data-id' => $variant->id,
+ ]
+ );
+ }
+ ?>
+
+
+ */
+ ?>
-
-
-
+
+
+
+ */
+ ?>
diff --git a/frontend/views/site/_slider_product.php b/frontend/views/site/_slider_product.php
index 3a193b0..0080230 100755
--- a/frontend/views/site/_slider_product.php
+++ b/frontend/views/site/_slider_product.php
@@ -5,89 +5,103 @@
use yii\web\View;
/**
- * @var View $this
- * @var Product $product
+ * @var View $this
+ * @var Product $product
*/
?>
-
-
- image ? $product->image->getPath() : '@frontend/web/img/no-image.png'
- )
- ->fillResize(260, 260)
- ->render(),
- [
- 'class' => 'img-responsive-image1',
- ]
- ),
+
+
+ image ? $product->image->getPath() : '@frontend/web/img/no-image.png'
+ )
+ ->fillResize(260, 260)
+ ->render(),
[
- 'product/view',
- 'id' => $product->id,
+ 'class' => 'img-responsive-image1',
]
- );
- ?>
-
-
-
-
- lang->title,
- [
- 'product/view',
- 'id' => $product->id,
- ]
- );
- ?>
-
-
- variants[ 0 ]->price_old) {
- echo Html::tag('del', $product->variants[ 0 ]->price_old . ' грн.');
- }
- echo $product->variants[ 0 ]->price ? : 0 . ' грн.';
- ?>
-
- 'fa fa-shopping-cart',
- ]
- ) . \Yii::t('app', 'В корзину'),
- '#',
- [ 'class' => 'btn btn-template-main' ]
- );
- ?>
-
-
-
- is('new')) {
- ?>
-
- is('akcia')) {
- ?>
-
- $product->id,
+ ]
+ );
?>
-
-
-
+
+
+
+ lang->title,
+ [
+ 'product/view',
+ 'id' => $product->id,
+ ]
+ );
+ ?>
+
+
+ variants[ 0 ]->price_old) {
+ echo Html::tag('del', $product->variants[ 0 ]->price_old . ' грн.');
+ }
+ echo ( $product->variants[ 0 ]->price ? : 0 ) . ' грн.';
+ ?>
+
+ variants[ 0 ]->stock && $product->variants[ 0 ]->price) {
+ echo Html::a(
+ Html::tag(
+ 'i',
+ '',
+ [
+ 'class' => 'fa fa-shopping-cart',
+ ]
+ ) . \Yii::t('app', 'В корзину'),
+ '#',
+ [
+ 'class' => 'btn btn-template-main add-to-basket',
+ 'data-id' => $product->variants[ 0 ]->id,
+ ]
+ );
+ } else {
+ echo Html::a(
+ \Yii::t('app', 'Нет в наличии'),
+ '#',
+ [
+ 'class' => 'btn btn-info disabled',
+ 'data-id' => $product->variants[ 0 ]->id,
+ ]
+ );
+ }
+ ?>
+
+
+
+ is('new')) {
+ ?>
+
+ is('akcia')) {
+ ?>
+
+
+
+
+
+
diff --git a/frontend/views/site/login.php b/frontend/views/site/login.php
new file mode 100644
index 0000000..26201e5
--- /dev/null
+++ b/frontend/views/site/login.php
@@ -0,0 +1,112 @@
+title = \Yii::t('app', 'Новый аккаунт / Регистрация');
+ $this->params[ 'breadcrumbs' ][] = $this->title;
+?>
+
+
+
+
+
+
+
+
+
+
Html::a(
+ \Yii::t('app', 'напишите нам'),
+ [
+ 'page/view',
+ 'id' => 17,
+ ]
+ ),
+ ]
+ ); ?>
+
+
+
+ field($signupForm, 'username')
+ ->textInput();
+ echo $formSignup->field($signupForm, 'email')
+ ->textInput();
+ echo $formSignup->field($signupForm, 'password')
+ ->passwordInput();
+ echo Html::tag(
+ 'div',
+ Html::submitButton(
+ Html::icon(
+ 'user-md',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . \Yii::t('app', 'Register'),
+ [
+ 'class' => 'btn btn-template-main',
+ ]
+ ),
+ [
+ 'class' => 'text-center',
+ ]
+ );
+ $formSignup::end();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+ field($loginForm, 'username')
+ ->textInput();
+ echo $formLogin->field($loginForm, 'password')
+ ->passwordInput();
+ echo $formLogin->field($loginForm, 'rememberMe')
+ ->checkbox();
+ echo Html::tag(
+ 'div',
+ Html::submitButton(
+ Html::icon(
+ 'sign-in',
+ [
+ 'prefix' => 'fa fa-',
+ ]
+ ) . \Yii::t('app', 'Login'),
+ [
+ 'class' => 'btn btn-template-main',
+ ]
+ ),
+ [
+ 'class' => 'text-center',
+ ]
+ );
+ $formSignup::end();
+ ?>
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/views/site/requestPasswordResetToken.php b/frontend/views/site/requestPasswordResetToken.php
new file mode 100644
index 0000000..371742e
--- /dev/null
+++ b/frontend/views/site/requestPasswordResetToken.php
@@ -0,0 +1,33 @@
+title = 'Request password reset';
+ $this->params[ 'breadcrumbs' ][] = $this->title;
+?>
+
+
= Html::encode($this->title) ?>
+
+
Please fill out your email. A link to reset password will be sent there.
+
+
+
+ 'request-password-reset-form' ]); ?>
+
+ = $form->field($model, 'email')
+ ->textInput([ 'autofocus' => true ]) ?>
+
+
+ = Html::submitButton('Send', [ 'class' => 'btn btn-primary' ]) ?>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/views/site/resetPassword.php b/frontend/views/site/resetPassword.php
new file mode 100644
index 0000000..56acace
--- /dev/null
+++ b/frontend/views/site/resetPassword.php
@@ -0,0 +1,33 @@
+title = 'Reset password';
+ $this->params[ 'breadcrumbs' ][] = $this->title;
+?>
+
+
= Html::encode($this->title) ?>
+
+
Please choose your new password:
+
+
+
+ 'reset-password-form' ]); ?>
+
+ = $form->field($model, 'password')
+ ->passwordInput([ 'autofocus' => true ]) ?>
+
+
+ = Html::submitButton('Save', [ 'class' => 'btn btn-primary' ]) ?>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/web/css/style.css b/frontend/web/css/style.css
index 7bdea96..15053ed 100755
--- a/frontend/web/css/style.css
+++ b/frontend/web/css/style.css
@@ -4495,25 +4495,28 @@ a.list-group-item.active > .badge,
right: 15px;
}
-.radio-but{
+.radio-but {
padding: 5px 0 5px 38px;
position: relative;
margin: 5px 0;
}
-.radio-but a:before{
- content:'';
- position:absolute;
- left:0;
- top:0;
+
+.radio-but a:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
width: 28px;
- height:28px;
+ height: 28px;
background: rgb(215, 220, 222);
border-radius: 5px;
}
-.radio-but.checked a:before{
+
+.radio-but.checked a:before {
background: rgb(26, 188, 156);
}
-.radio-but.checked a:after{
+
+.radio-but.checked a:after {
content: '';
position: absolute;
left: 0;
@@ -4530,7 +4533,8 @@ a.list-group-item.active > .badge,
font-size: 18px;
padding-right: 20px;
}
-.reset-filters{
+
+.reset-filters {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
@@ -4539,8 +4543,100 @@ a.list-group-item.active > .badge,
outline: none;
margin-bottom: 20px;
}
-#cart .badge{
+
+#cart .badge {
position: absolute;
top: 2px;
right: 4px;
+}
+
+.basket-container {
+ position: relative;
+}
+
+.order-radio {
+ height: 10px;
+}
+
+.loader-wrapper {
+ background: rgba(255, 255, 255, 0.7);
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 2000;
+}
+
+.loader {
+ display: block;
+ position: relative;
+ left: 50%;
+ top: 50%;
+ width: 150px;
+ height: 150px;
+ margin: -75px 0 0 -75px;
+ border-radius: 50%;
+ border: 3px solid transparent;
+ border-top-color: #1980b3;
+ z-index: 2001;
+
+ -webkit-animation: spin 2s linear infinite;
+ animation: spin 2s linear infinite;
+}
+
+.loader:before {
+ content: "";
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ right: 5px;
+ bottom: 5px;
+ border-radius: 50%;
+ border: 3px solid transparent;
+ border-top-color: #3399cc;
+
+ -webkit-animation: spin 3s linear infinite;
+ animation: spin 3s linear infinite;
+}
+
+.loader:after {
+ content: "";
+ position: absolute;
+ top: 15px;
+ left: 15px;
+ right: 15px;
+ bottom: 15px;
+ border-radius: 50%;
+ border: 3px solid transparent;
+ border-top-color: #70b7da;
+
+ -webkit-animation: spin 1.5s linear infinite;
+ animation: spin 1.5s linear infinite;
+}
+
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
}
\ No newline at end of file
diff --git a/frontend/web/js/script.js b/frontend/web/js/script.js
index ed766d7..01842c6 100755
--- a/frontend/web/js/script.js
+++ b/frontend/web/js/script.js
@@ -1,6 +1,8 @@
$(
function() {
-
+ var basket = new ArtboxBasket({
+ 'cartSelector': '#cart'
+ });
/**
* Modal form submit code
*/
@@ -52,7 +54,7 @@ $(
data: formData,
success: function(data) {
f.reset();
- form.replaceWith(data.alert)
+ form.replaceWith(data.alert);
},
error: function() {
@@ -103,5 +105,56 @@ $(
}
);
}
+
+ $(document)
+ .on('click', '.add-to-basket', function(e) {
+ e.preventDefault();
+ var id = $(this)
+ .data('id');
+ basket.add(id, 1);
+ });
+
+ $(document)
+ .on('click', '.remove-product-cart', function(e) {
+ e.preventDefault();
+ var id = $(this)
+ .parents('.product-row-basket')
+ .data('id');
+ showLoader('#basket');
+ var xhr = basket.remove(id);
+ xhr.done(function() {
+ $.pjax.reload({
+ container: '#basket',
+ fragment: '#basket',
+ timeout: 5000
+ });
+ })
+ });
+
+ $(document)
+ .on('change', '.increase-product-basket', function(e) {
+ var id = $(this)
+ .parents('.product-row-basket')
+ .data('id');
+ showLoader('#basket');
+ var xhr = basket.set(id, $(this)
+ .val());
+ xhr.done(function() {
+ $.pjax.reload({
+ container: '#basket',
+ fragment: '#basket',
+ timeout: 5000
+ });
+ });
+ });
+
+ $(document)
+ .on('click', 'li.disabled a', function(e) {
+ e.preventDefault();
+ });
}
-);
\ No newline at end of file
+);
+function showLoader(container) {
+ $(container)
+ .prepend('
');
+}
\ No newline at end of file
--
libgit2 0.21.4