Оформление заказа в корзине: адаптация тем дизайна

Дмитрий Елшин

В Shop-Script 8 появился ещё один способ оформления заказа — на одной странице с корзиной. Расскажем, как адаптировать темы дизайна для поддержки нового режима, а также о возможностях для работы с корзиной и оформлением заказа.

Пример оформления заказа в корзине. Тема дизайна "Default".

Подключение оформления заказа в корзине

Создайте файл order.html в теме дизайна для приложения Shop-Script и объявите его в theme.xml. Пример файла можно посмотрить в исходном коде темы дизайна «Дефолт».

В настройках витрины для настройки «Вид оформления заказа» выберите «Оформление заказа в корзине».


Витрина должна уметь поддерживать и пошаговое оформление заказа. Для формирования актуальных ссылок на корзину или страницу оформления используйте методы шаблонов Webasyst:

{$wa->shop->checkout()->cartUrl( $absolute = false )} {* ссылка на корзину *} 
{$wa->shop->checkout()->url( $absolute = false )} {* ссылка на страницу оформления заказа *}

Оформление

Файл order.html решает две задачи:

  1. Отображение пустой корзины, когда покупатель ещё не выбрал товары для покупки.
  2. Отображение корзины и формы оформления заказа с помощью методов шаблонов:
    • Блок корзины
      <div id="js-order-cart">
          {$wa->shop->checkout()->cart([
             "wrapper" => "#js-order-cart"
          ])}
      </div>
      
    • Блок оформления заказа
      <div id="js-order-form">
          {$wa->shop->checkout()->form([
             "wrapper" => "#js-order-form"
          ])}
      </div>
      

Допустимые параметры для этих методов:

  • wrapper string Обязательный параметр, содержащий селектор контейнера блока. На этот элемент будут ссылаться события и ему будут присваиваться data-атрибуты, необходимые для оформления заказа.
  • DEBUG bool Выводит в консоли браузера информацию о ходе работы. Значение по умолчанию — false.
  • adaptive bool Включает применение внутренних адаптивных стилей к элементам блока. По умолчанию — true.

При успешном оформлении заказа пользователь автоматически перенаправляется на страницу с адресом checkout/success/.

Доступные события JavaScript

Корзина

  • wa_order_cart_ready: корзина загрузилась, контроллер инициировался. В параметрах передается ссылка на контроллер.
  • wa_order_cart_changed: содержимое корзины было изменено на сервере. В параметрах передаются обновлённые данные с сервера.
  • wa_order_cart_rendered: корзина визуально обновлена на основе данных с сервера. В параметрах передаются обновлённые данные с сервера.
  • wa_order_cart_cleared: корзина очищена. В параметрах передаются обновлённые данные с сервера.
  • wa_order_cart_reloaded: DOM корзины перезаписан. В параметрах передается ссылка на новый контроллер.

Форма оформления заказа

  • wa_order_form_ready: форма загрузилась, контроллер инициировался. В параметрах передается ссылка на контроллер.
  • wa_order_form_changed: DOM некоторых блоков формы перезаписан. В параметрах передаются обновлённые данные с сервера.
  • wa_order_form_(auth | region | shipping | details | payment | confirm)_changed: DOM соответствующего блока формы перезаписан. В параметрах передаются обновлённые данные с сервера.
  • wa_order_form_reloaded: DOM формы перезаписан. В параметрах передается ссылка на новый контроллер.
  • wa_order_form_created: в параметрах передаются обновлённые данные с сервера.

Если вам требуются дополнительные события, напишите о них в комментариях.

Особенности и рекомендации

Версии браузеров

Страница оформления заказа в корзине работает в большинстве последних версий браузеров Chrome, Firefox, Safari и Edge и Internet Explorer не ниже 11-й версии.

Рекомендации по оформлению

  • В файле order.html реализуйте вёрстку контейнеров для корзины и формы заказа. Важно предусмотреть их адаптивность для мобильных устройств и других устройств с малой шириной экрана.
  • Ширина каждого блока не менее 375px.
  • При ширине экрана свыше 900px блоки выравниваются по горизонтали.
  • Каждый блок содержит стандартные адаптивные стили. Если разработчику требуется написание собственных стилей адаптации, передайте параметр "adaptive" => false при формировании HTML-кода блока.
  • Рекомендуется не делать серьёзных структурных изменений в стилях CSS в оформлении элементов. Некоторые JavaScript-скрипты зависят от свойств элементов (пример: слайдер с фото).
  • Рекомендуется не изменять JavaScript-логику внутренних контроллеров и взаимодействовать посредством событий, которые выполняются на "wrapper", указанный при формировании HTML-кода блока.

График работы магазина

В Shop-Script 8 график работы магазина настраивается более гибко, чем раньше, поэтому тема дизайна теперь должна уметь обработать массив данных о днях и часах работы магазина и показать результат посетителям сайта. Информацию о графике работы возвращает метод

{$wa->shop->schedule()}

В возвращаемом массиве элемент с ключом current_week содержит подмассив элементов, которые соответствуют дням недели. Каждый день недели здесь — массив со следующими ключами:

  • name string: название дня недели
  • work bool: флаг, обозначающий рабочий день
  • start_work string: время начала работы
  • end_work string: время окончания работы
  • end_processing string: время окончания обработки заказов

В этом массиве учитываются настройки для дней недели и дополнительных рабочих и выходных дней.

Массив, возвращаемый методом {$wa->shop->schedule()}, содержит, кроме current_week, также следующие элементы:

  • mode string: значение 'default' (используется общий график работы магазина) или 'custom' (используется собственный график работы в настройках оформления заказа в корзине для этой витрины)
  • timezone string: Идентификатор временной зоны, выбранной в настройках графика работы
  • week array: массив настроек для каждого из дней недели без учёта дополнительных рабочих и выходных дней
  • extra_workdays array: массив информации о дополнительных рабочих днях — каждый в виде массива с ключами
    • date: дата в формате DATE SQL
    • start_work
    • end_work
    • end_processing
  • extra_weekends array: массив дат дополнительных выходных дней в формате DATE SQL

Пример использования данных графика работы есть в исходном коде темы дизайна «Дефолт».

Формы авторизации, регистрации и восстановления пароля

Расширены возможности системных методов, которые формируют HTML-код форм авторизации, регистрации и восстановления пароля. Например, чтобы показать рядом с формой авторизации или регистрации иконки настроенных адаптеров соцсетей, достаточно передать в метод параметр show_oauth_adapters.

{* Авторизация *}
{$wa->loginForm($error, [
    'show_oauth_adapters' => true
])}

{* Регистрация *}
{$wa->signupForm($errors, [
    'show_oauth_adapters' => true
])}

Обмен данными между формами и сервером происходит в формате JSON. Благодаря этому удобно встраивать формы во всплывающие диалоги.

При взаимодействии пользователя с формой обрабатываются следующие события JavaScript:

  • wa_auth_form_loaded: форма авторизации загрузилась.
  • wa_auth_form_change_view: DOM формы изменился (например, показались сообщения об ошибках, появилось поле для ввода кода и т. п.).
  • wa_auth_contact_logged: контакт авторизован. В качестве параметра передаётся объект contact с единственным полем id.
  • wa_auth_set_password: событие, сообщающее о возможности перехода на форму setpassword. В параметрах передаётся строка hash — у этого значения ограниченное время жизни, оно необходимо для установки нового пароля. Без валидного хеша форма setpassword вернёт ошибку 404.
  • wa_auth_reset_password: новый пароль установлен.
  • wa_auth_resent_password: пароль отправлен пользователю.
  • wa_auth_contact_signed: контакт зарегистрировался. В качестве параметров передаются флаг password_sent — был ли отправлен пароль пользователю в режиме генерации пароля, и объект contact с единственным полем id. При возникновении ошибки параметр contact может иметь тип undefined.
7 ноября 2018
  • km 7 ноября 2018 15:34

    wa_order_form_changed и wa_order_form_(auth | region | shipping | details | payment | confirm)_changed получается будут вызываться одновременно?

  • golubevmark Webasyst 7 ноября 2018 16:06

    @km - Сначала будет событие конкретного блока (например "wa_order_form_auth_changed"), после общее событие для формы "wa_order_form_changed". Если было обновлено несколько блоков, то они будут вызваны в очереди в их логическом порядке, а в конце общее событие.

  • km 7 ноября 2018 16:20

    Логический порядок это какой?

  • Дмитрий Елшин Webasyst 7 ноября 2018 16:21

    Как они расположены в блоке формы относительно друг друга.

  • kadurinho 7 ноября 2018 19:58

    Дмитрий, если не ошибаюсь, на конференции было сказано, что изменять состав корзины можно будет полностью, что изменилось? Удалять товары, менять услуги и раньше можно было, в чем новинка? Я надеялся, что в корзине к примеру будет возможна смена цвета, характеристик... Планируется?

  • Дмитрий Елшин Webasyst 7 ноября 2018 21:12

    Планируется.

    В частности, смена артикула ожидается в версии 8.0.1.

  • kadurinho 7 ноября 2018 23:11

    Спасибо, это радует

  • Добрый день. В default 3.0 есть конструкция для определения ссылки корзины:

    {if $wa->shop}
        {$_cart_url = $wa->getUrl('shop/frontend/cart')}
        {if $wa->param('checkout_version') == 2}
            {$_cart_url = $wa->getUrl('shop/frontend/order')}
        {/if}
    {/if}

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

    Нам делать дополнительную настройку в теме дизайна или это будет пофикшено?

  • golubevmark Webasyst 9 ноября 2018 10:53

    @Алексей Александрович это был промежуточный вариант. Для получения пути к корзине используйте следующий helper:

    {$_cart_url = $wa->shop->checkout()->cartUrl()}

    Он смотрит на настройки магазина, и выдаст либо */cart/ либо */order/, в случае, если приложение магазин существует.

  • Алексей Webasyst 9 ноября 2018 11:20

    Хелпер

    {$wa->shop->checkout()->cartUrl()}

    будет только в 8-й версии, поэтому тут еще вопрос обратной совместимости.

  • golubevmark Webasyst 9 ноября 2018 11:34

    Для обратной совместимости подойдёт такое решение:

    {if $wa->shop}
        {if method_exists($wa->shop, 'checkout')}
            {$_cart_url = $wa->shop->checkout()->cartUrl()}
        {else}
            {$_cart_url = $wa->getUrl('shop/frontend/cart')}
        {/if}
    {/if}
  • Вот про адаптивные стили - там часть лежит в cart.css, попробовал добавить adaptive, но этот файл всёравно подгружается, что реально мешает свои стили добавлять. Так и должно быть?

    {$wa->shop->checkout()->cart([
      "DEBUG" => true,
      "wrapper" => "#js-order-cart",
      "adaptive" => false,
      "some_other_options" => "whatever"
    ])}
  • golubevmark Webasyst 9 ноября 2018 13:16

    Параметр "adaptive" влияет только на @media-queries стили. Полностью отключить наши стили нельзя, можно дополнить/переопределить некоторое стилевое оформление через CSS от темы.

  • Об этом и речь, в общем... Даже с параметром все @media-queries есть в файле, и применяются они сразу к .wa-order-cart-wrapper, а было бы логично к .wa-order-cart-wrapper.is-adaptive или типа того.

  • golubevmark Webasyst 9 ноября 2018 14:32

    Именно так и будет. Сейчас это есть только в актуальной неопубликованной версии. В ближайшее время выкатим, наверное :)

  • Ок, с этим разобрались. 

    Теперь вопрос, когда всё это отправлять на модерацию, учитывая что у меня в настройках темы используются Javascript табы и их хотелось бы оставить для всех пользователей старых версий.

    Можно сейчас добавить requirement, но это ведь не сработает... Как быть в итоге?

    <requirement property="app.installer" value=">=1.10" strict="true">

  • Дмитрий Елшин Webasyst 9 ноября 2018 15:08

    Обновление Фреймворка бесплатное.

    Темы дизайна, использующие свой кастомный js в theme.xml не смогут пройти модерацию.

    Примерно через два месяца Фреймворк начнёт силой вырезать весь кастомный код из разметки настроек.

  • Это я понял. Но если кто-то не будет обновлять фреймворк?)

  • Дмитрий Елшин Webasyst 9 ноября 2018 15:20

    В старой версии Фреймворка, при обновлении темы дизайна не обновлялся файл theme.xml (не спрашивайте почему). Соответственно все ваши кастомные поделки с табами и прочими прелестями останутся.

    Если же пользователь обновит Фреймворк и как-то поставит на него устаревшую версию темы дизайна — у него что-то пойдёт не поплану. Он обратится к вам или к нам и мы посоветуем ему обновиться до последней версии. :-)

  • Koin 9 ноября 2018 15:27

    На данный момент у вас не принимает на проверку темы с новыми настройками в theme.xml, пришлось лепить старые и отправлять на проверку.

    Плюс почему не сделали нормальные табы, а не эти ракрывахи, сугубо мое личное мнение, посмотрели бы в примерах у людей как сделали, видел в темах, очень удобно, но дело ваше.

  • Хм. Получается сейчас я переделанные тему не могу отправить на проверку? Нужно ждать выхода SS8?

  • Дмитрий Елшин Webasyst 9 ноября 2018 15:30

    Темы дизайна, которые используют новые возможности настроек будут опубликованы не раньше публичного релиза Фреймворка и Shop-Script — 21 ноября.

    Отправлять на модерацию можно уже сейчас. И даже нужно. Это повысит вероятность, что тема выйдет день в день с Фреймворком и Магазином (но это не точно).

  • Koin 9 ноября 2018 15:40

    Подскажите тогда как отправить то, если я отправляю и мне пишет что валидацию не прошла, я уже модератору написал два дня назад, молчат, выбора нет что новый двиг шоп 8, тока 7, забил и сделал по старому
    Вопрос остается как?

  • Уважаемые разработчики,

    Если вы переживаете насчет того, что тема будет промодерирована и опубликована ДО выхода SS8, то, пожалуйста, отправляйте вашу обновленную тему на модерацию начиная с 17:00 16 ноября - тогда ваша тема точно не будет опубликована раньше 21 ноября.

  • upd. всем разработчикам тем дизайна - публикации тем дизайна с изменениями под SS8 не будет до релиза самого SS8, НО уже на этой неделе вы можете (и лучше это сделать) отправлять ваши обновленные темы на модерацию - они будут проверены и если будут какие-либо замечания, то вы об этом узнаете до релиза SS8 с тем, чтобы у вас было время для внесение поправок.

    чуть позже возможность отправки на модерацию тем для SS8 будет доступна, так что у вас еще есть время все самостоятельно проверить на чистых установках (подпапки, https и т.д.)

  • Евгений Леман 16 ноября 2018 12:21

    Представим ситуацию:

    Человек не стал по каким-то причинам обновляться до 8 версии магазина. У него используется версия темы 1.5.0. Но в последний день SS7 была выпущена версия 1.5.1. А для 8-ки уже 1.6.0, которая требует и встает только на 8 версию.

    Вопрос: Он сможет обновиться до 1.5.1? Или инсталлер будет предлагать ему только 1.6.0, которую он поставить на 7-ке не сможет?

  • Алексей Webasyst 16 ноября 2018 12:31

    Как и с плагинами не сохраняются промежуточные версии для установки и инсталлер предлагает последнюю опубликованную.

    у клиента стоит 1.0
    давно уже выпущена 1.5 которую он может по требованиям использовать
    выпускается 2.0 и 1.5 больше клиенту не предлагается


  • Евгений 25 ноября 2018 14:33

    Добавьте возможность отключения сокращенного написания валют, многим не нравиться Р, нужен именно руб.

  • BNP (Дмитрий) 3 февраля 2019 01:44

    wa_order_form_ready

    вот сюда бы хотелось вторым параметром приехавшие параметры (как вот здесь wa_order_form_changed )  Это нужно, когда все параметры (доставка и оплата например) выбраны, а потом по какой-то причине корзина была перезагружена (тыкнули f5 или вообще пошли гулять по сайту и потом опять вернулись в корзину).

    На данный момент при таком раскладе нет возможности получить текущие выбранные параметры. Ну или я что-то не понимаю =)

  • golubevmark Webasyst 4 февраля 2019 12:28
    @BNP (Дмитрий)

    Событие "wa_order_form_ready" говорит о DOM-готовности блока, т.е. все необходимые JS/CSS загрузились и инициировались, блок готов к работе.

    wa_order_form_ready

    Контроллер формы не хранит в себе выбранные данные. Их можно получить, вызвав метод controller.getFormData(). Он будет в себе содержать массив с ключами вида:

    [{
        name: "shipping[type_id]",
        value: "pickup"
    }]

    Надеюсь, это решит вашу потребность.

    Начиная отвечать на ваш вопрос, я изучил данное событие детальнее и нашёл оплошность. Это событие возникало в момент готовности самого блока (обёртки), но внутренние секции инициировались позднее, что блокирует сбор данных, из-за отсутствия секций. Данный момент будет исправлен, и событие будет происходит после всех внутренних инициаций. Поэтому пока предложу вам вариант решения такой:

    var controller = $("#js-order-form").data("controller");
    
    controller.$wrapper.data("ready").promise().then( function(controller) {
        var data = controller.getFormData();
        console.log(data);
    });


    А в будущем вы сможете пользоваться событием так:

    $(document).on("wa_order_form_ready", function(event, controller) {
        var data = controller.getFormData();
        console.log(data);
    });



Чтобы добавить комментарий, зарегистрируйтесь или войдите