msPaidOptions. Платные опции к товару

Компонент позволяет создавать дополнительные опции к товару, которые могут повлиять на его итоговую стоимость.




Шаг 1.Создаем опции.


Заходим в настройки минишопа и переходим на вкладку опции (стандартные опции товара).
Компонент добавляет два типа опций: Группа переключателей и Группа флажков.

Группа переключателей

Создаем опцию дополнительная гарантия к товару и отмечаем к какой категории товаров эта опция будет применяться.



Группа флажков

Добавки к пицце.



Шаг 2.Выводим опции на странице продукта.


Используем стандартный сниппет минишопа msProductOptions. В параметрах указываем какие опции выводить и чанк оформления.
{'!msProductOptions' | snippet : [
    'onlyOptions' => 'guarantee,pizza',
    'tpl' => 'tpl.msPaidOptions',
]}

Если нужно вывести еще и стандартные опции, то нужно исключить опции, которые уже вывели:
{'!msProductOptions' | snippet: [
    'ignoreOptions' => 'guarantee,pizza'
]}

Результат (кликабельно):




Поле с ценой должно иметь класс ms2_price.

Шаг 3. Выводим опции товара в корзине


По умолчанию, опции выводяться так (чанки: tpl.msCart, tpl.msEmail, tpl.msGetOrder):
{if $product.options?}
    <div class="small">
        {$product.options | join : '; '}
    </div>
{/if}
Заменяем этот кусок кода на вот этот:
{if $product.options}
    <div class="small">
        {foreach $product.options as $option => $value}
            {if $option in ['guarantee', 'pizza']}
                <b>{$product[($option ~ '.caption')]}</b>: {$value | join: ','};
            {else}
                {$value};
            {/if}
        {/foreach}
    </div>
{/if}
Результат:


Уникальные опции


Таким образом добавленные опции будут одинаковыми для всех товаров категорий, которые мы отметили. Но, можно установить и уникальные опции для товара.

Переходим к товару на вкладку опции и редактируем необходимые опции. Мы можем менять местами, удалять, изменять и добавлять новые опции.


Опции в модалке




Реализация:

Я буду использовать модалку из Bootstrap 5, но можно использовать любую другую. Главное понять логику.

Шаг 1. В чанк tpl.msProducts.row дописываем поля, чтобы потом использовать их в модалке:
<input type="hidden" name="price" value="{$price}">
<input type="hidden" name="title" value="{$pagetitle}">

Шаг 2. В этом же чанке меняем кнопку отправки формы на кнопку вызова модалки
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#modal-product">
    <i class="fas fa-shopping-cart"></i>
</button>

Шаг 3. Создаем модалку
<div class="modal fade" id="modal-product" tabindex="-1" aria-labelledby="modal-product" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered modal-fullscreen-lg-down">
        <div class="modal-content">
            <div class="modal-header">
                {*Название товара*}
                <h5 class="modal-title"></h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <form method="post" class="ms2_form d-flex flex-wrap justify-content-between align-items-center text-start px-0">
                    <input type="hidden" name="id" value="{$id}">
                    <input type="hidden" name="count" value="1">
                    <input type="hidden" name="options" value="[]">
                    {*Цена товара*}
                    <div class="col-12">
                        <span class="price fw-bold fs-5"><span class="ms2_price">{$price}</span> {'ms2_frontend_currency' | lexicon}</span>
                    </div>
                    {*Опции товара*}
                    <div class="col-12" id="ajax-options"></div>
                    <div class="col-12">
                        <button type="submit" name="ms2_action" value="cart/add" class="btn btn-outline-primary" aria-label="{'ms2_frontend_add_to_cart' | lexicon}">
                            <i class="fas fa-shopping-cart"></i>
                            <span class="d-none d-xl-inline-block">{'ms2_frontend_add_to_cart' | lexicon}</span>
                        </button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

Шаг 4.Добавляем скрипт
$(document).on('show.bs.modal', (event) => {
    // Работаем только с нашей формой
    if(event.target.id != 'modal-product') return;
    // Получаем текущую форму 
    let $form = $(event.relatedTarget).closest('.ms2_form');
    // Получаем данные с формы
    let data = $form.serializeArray();
    // Получаем модалку
    let $modal = $(event.target);
    // id товара
    let productID;
    // Заполняем форму в модалке
    for(let idx in data) {
        let name = data[idx].name;
        let value = data[idx].value;
        // Получаем id продукта
        if(name == 'id') {
            productID = value;
        }
        if(name == 'title') {
            $modal.find('.modal-title').text(value);
        } else if(name == 'price') {
            $modal.find('.ms2_price').text(value);
        } else {
            $modal.find('input[name="'+name+'"]').val(value);
        }
    }
    // Получаем опции и вставляем в модаку
    msPaidOptions.request({
        action: 'options',
        product: productID,
        onlyOptions: 'guarantee,pizza',
    }, (res) => {
        if(res.success) {
            $modal.find('#ajax-options').html(res.data);
        }
    });
});
// Закрываем модалку после добавления товара в корзину
miniShop2.Callbacks.add('Cart.add.response.success', 'cart_add_ok', (response) => {
    $('.modal.show').modal('hide');
});

Совместимость с msPromoСode2


1. Открываем файл
core/components/mspromocode2/plugins/mspc2msongetproductprice.class.php
2. Добавляем код:
$mspaidoptions = $this->modx->getService('mspaidoptions', 'msPaidOptions', MODX_CORE_PATH . 'components/mspaidoptions/model/');
if ($mspaidoptions) {
    $this->sp['price'] = $mspaidoptions->getPrice($this->sp['product'], $_REQUEST['options']);
}
после строчки:
$product = $this->sp['product'];

Ссылка на компонент
Aleksandr Huz
06 мая 2021, 10:13
modx.pro
8
1 917
+18
Поблагодарить автора Отправить деньги

Комментарии: 16

Константин Ильин
06 мая 2021, 22:38
+1
Супер!

Я делал подобный функционал через MIGX, проблема вставала когда использовал msPromocode2 там пересчет цены он сбивал все надбавки к цене, (не утверждаю, но видимо берет цену у продукта, а не из корзины), хотелось бы узнать совместимость с подобными компонентами которые пересчитывают цену
    Aleksandr Huz
    06 мая 2021, 22:46
    +1
    В планах msOptionsPrice2. но теперь и msPromocode2.
      Aleksandr Huz
      02 марта 2022, 19:38
      +1
      Чтобы работало с msPromoСode2 нужно в файл
      core/components/mspromocode2/plugins/mspc2msongetproductprice.class.php
      добавить код:
      $mspaidoptions = $this->modx->getService('mspaidoptions', 'msPaidOptions', MODX_CORE_PATH . 'components/mspaidoptions/model/');
      if ($mspaidoptions) {
          $this->sp['price'] = $mspaidoptions->getPrice($this->sp['product'], $_REQUEST['options']);
      }
      после строчки:
      $product = $this->sp['product'];
        nekto
        12 июля 2022, 18:47
        0
        Кривое решение непроверенное,
        $_REQUEST['options']
        всегда пустой, и цены сбиваются
      Виталий Батушев
      07 мая 2021, 15:36
      0
      Чо-т долго модерируют.
      Геннадий
      15 июля 2021, 10:48
      +1
      Из пожеланий:
      1. пофиксить
      \core\components\mspaidoptions\processors\mgr\option\getlist.class.php 26 
      PHP warning: Invalid argument supplied for foreach()
      2. при удалении пунктов у опций, не сохранять в базу
      {"values":[],"prices":[]}
      Не то чтобы важно, но если соберетесь обновлять, прошу учесть.
        Диман
        18 сентября 2021, 19:16
        0
        Поставил на тестовый сайтик, создал опции



        при редактирование товара



        и ошибки…

        [2021-09-18 20:44:59] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/getlist.class.php : 26) PHP warning: Invalid argument supplied for foreach()
        [2021-09-18 20:45:50] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/create.class.php : 21) PHP warning: json_decode() expects parameter 1 to be string, array given
        [2021-09-18 20:45:50] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/create.class.php : 37) PHP warning: in_array() expects parameter 2 to be array, null given
        [2021-09-18 20:46:46] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/create.class.php : 21) PHP warning: json_decode() expects parameter 1 to be string, array given
        [2021-09-18 20:46:46] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/create.class.php : 37) PHP warning: in_array() expects parameter 2 to be array, null given
        [2021-09-18 20:55:30] (ERROR @ /core/components/mspaidoptions/processors/mgr/option/getlist.class.php : 26) PHP warning: Invalid argument supplied for foreach()
          Aleksandr Huz
          18 сентября 2021, 19:39
          +1
          Спасибо. Исправил. Обновляйтесь
          Диман
          19 сентября 2021, 09:55
          0
          Добавления класса .ms2_price, не меняет значение в корзине. Может не так подключаю? ))
            Aleksandr Huz
            19 сентября 2021, 11:31
            0
            В корзине пока нет такой возможности. только на странице товара или в модалке до добавление товара в корзину
            Александр
            30 января 2023, 13:03
            0
            с msOptionsPrice2 так и нет совемстимости? очень требуется такой функционал на modx опции + допы. Заказчик готов платить, но компоента такого нет(
              Aleksandr Huz
              30 января 2023, 13:17
              0
              К сожалению, пока нет.
                Александр
                30 января 2023, 13:54
                0
                очень печально, непонятно как такое реализовывать.
                спасибо
              Сергей
              14 февраля 2024, 17:38
              0
              так а где пакет-то купить можно?
                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                16