Новый дизайн сайта Gosso.ru и как я его делала

Сайты на InSales /
Всем привет! С августа-месяца и до сегодняшнего дня я очень часто отказывалась от новых проектов, ссылаясь на текущую загруженность, и наверняка многие мои клиенты хотели бы узнать чем таким срочным и долгим я занималась.

Сегодня я готова ответить на этот вопрос и представить вниманию широкой общественности новый дизайн сайта Gosso.ru.

Должна сразу предупредить, что данная статья будет с уклоном в техническую сторону дела. Она будет полезна для разработчиков шаблонов под InSales и немного полезна для пользователей в плане того что будет содержать реализуемые «фичи» для магазина на InSales.

Поехали!

Оптимизация и быстродействие

Магазин принимает около 500 заказов в день, имеет около 90 000 товаров и несколько тысяч товарных категорий.

Это делает невозможным использование полного списка категорий, т.к. он будет формироваться по 30+ секунд.

Также ввиду особенностей InSales при использовании в каком-либо виде иерархии категорий (например, при выводе подкатегорий, при выводе цепочки текущих категорий и т.д.) платформа разворачивает вообще всю структуру категорий, что не может не сказываться на быстродействии. Поэтому мне сразу же пришлось кешировать всю работу с иерархией категорий с помощью liquid-тега cache (по-моему его даже в документации ни insales, ни shopify нет).

Далее, по макету у меня был в мобильной версии полностью раскрываемый без перезагрузки каталог. Как я уже говорила, использование полного списка категорий – отпадает. Поэтому мне пришлось пойти на хитрость и с помощью liquid (и, соответственно, с кешированием) сформировать json, в котором бы присутствовали подкатегории текущей категории. Проблема в том что insales не будет просто так формировать страницу по какому попало урлу. Для такой задачи подойдет только шаблон collection, но он у нас будет использоваться для товарных категорий. Так что же делать? В целом insales может сформировать отдельную страницу по своим сортировкам. Наиболее простым решением здесь было использовать какой-то непопулярный тип сортировки, коим была объявлена сортировка по возрастанию скидки.

В результате страница такой сортировки превратилась в нечто такое, зато стала пригодна для таскания оттуда списка подкатегорий. Написала ajax-запрос по клику на каждый уровень в мобильном каталоге – и дело в шляпе!

В старом дизайне сайта был «быстрый просмотр» товара при наведении, с изображениями, от которого клиент не хотел отказываться в новом дизайне. Этот просмотр в старом дизайне жутко «тормозил» из-за того что загружался (благо, через отдельный запрос к json’ам товаров, а не прямо в html) сразу при открытии страницы, что мне показалось пустой тратой ресурсов несчастных клиентских браузеров, и в своем исполнении эту загрузку я сделала при наведении курсора на товар. Задержка при появлении элемента, конечно, видна, но она не превышает пол-секунды, клиента это устроило.

Фичи и их реализация

Избранное
Нужно отметить, что делался сайт на каркасе тем InSales, очень с моей точки зрения удобном и функциональном, на нем же сделаны их бесплатные темы «Фортуна», «Карбон» и некоторые другие.

В каркасе по умолчанию есть работа с избранным, но хранится оно в cookie (вообще технология прошлого века, давно пора отходить от их использования по поводу и без, давно же уже есть localStorage), но клиент хотел чтобы избранное хранилось в личном кабинете покупателя, для чего мне пришлось создать дополнительное поле покупателя, спрятать его из интерфейса (обычными стилями и jquery hide) и отправлять ajax-запросы на его обновление.

Все оказалось не так просто как на словах! Insales для каждого доп. поля покупателя еще и формирует свой id значения, уникальный для каждого покупателя.

Соответственно, при первой записи доп. поля нужно как-то получить этот id значения и сохранить его (например, в тот же localStorage). Пример моего кода (для вышеназванного каркаса тем InSales):

self.saveFavoritesToField = function(favorites, callback){
  showPreloader();
  var fieldId = localStorage['fieldId'];
    /* нам надо определить id значения поля перед тем как его записывать */
      if (typeof fieldId == 'undefined' || fieldId == '') {
      		$('.js-client-field-id').load('/client_account/contacts form#contacts', function(){
            	fieldId = $('.js-client-field-id input[name="client[fields_values_attributes][3681475][id]"]').val();
              	self.postClientField(fieldId, favorites, callback);
              	localStorage['fieldId'] = fieldId;
            });
      } else {
      	self.postClientField(fieldId, favorites, callback);
      }
  };
self.postClientField = function(fieldId, favorites, callback){
  				$.ajax({
      				url: '/client_account/contacts',
        			method: 'post',
        			data: '_method=put&client[fields_values_attributes][3681475][hack]=&client[fields_values_attributes][3681475][id]=' + fieldId + '&client[fields_values_attributes][3681475][value]=' + JSON.stringify(favorites),
        			success: callback,
                  	error: function(){
                    	localStorage['fieldId'] = ''; //если пост завершился ошибкой, значит юзер у нас скорее всего перелогинился в другой ЛК, нужно снова получить id поля (проверка что юзер залогинен – вообще в другом месте)
                      	self.saveFavoritesToField(favorites, callback);
                    }
      	});
  };


Число 3681475 в коде, само собой, нужно заменить на id поля в реальном проекте.

Все, теперь метод saveFavoritesToField можно использовать для сохранения избранных товаров в доп. поле покупателя. Done!

Выбор готового дизайна
У клиента существует каталог готовых дизайнов (более 2000 штук), отдельно взятые товары можно заказать с дизайнами из этого каталога. Каждый дизайн представляет собой товар в магазине.

Одновременно на страницу такое количество товаров грузить – не вариант. Благо, они поделены на категории, и в макете для десктопа и планшета у нас всплывающее окно. Ок, делаем отдельный шаблон для категории с каталогами (без шапки и подвала), грузим его через jquery load. Готово.

Но в мобильной версии у нас всплывающего окна нет. Здесь я использовала API плагина owl carousel, который создает карусель дизайнов и ajax-запросы к json категории дизайнов.

Другой вопрос – привязка дизайна к товару. Она осуществляется путем записи все в тот же localStorage javascript-объекта с соответствием товар-дизайн. Уже позже я подумала о том что было бы логичнее и правильнее записывать это в комментарий к позиции заказа. Но на момент разработки эта сущность вообще вылетела у меня из головы :(

Загрузка своего дизайна
Загрузка своего дизайна осуществляется с помощью доп. поля заказа с типом «файл». Такой тип поля есть только в доп. полях заказа, его нет ни в полях покупателя, ни в полях адреса. С помощью довольно древнего плагина ajaxForm происходит ajax-загрузка изображения на сервер к корзине покупателя.

Далее перетаскивание изображения в контейнере осуществляется с помощью jquery ui draggable, масштабирование изображения колесом мыши – самописное (не буду его здесь приводить, т.к. данный кусок кода еще нуждается в оптимизации). Полученные размеры и смещение изображения записываются в доп. поле заказа в виде текста.

Таких изображений можно загрузить до 3х штук, под каждое из них существует свое доп. поле заказа, номер доп. поля хранится в localStorage и меняется при добавлении очередного товара со своим дизайном в корзину.

Отдельная тема – очистка поля с типом файл при удалении товара с дизайном (для простоты было принято что количество товаров в с дизайнами в корзине менять будет нельзя, но удаляться товар-дизайн должен при удалении товара, к которому он принадлежит). Методом проб и ошибок (а также разговоров с одним из разработчиков платформы) был найден ajax-запрос для очистки поля с файлом. Вот код такого запроса:

var fieldId = designItem.design.fieldId;   //id поля текущего дизайна
var fieldsValuesAttributes = {};
fieldsValuesAttributes[fieldId] = {
    hack: fieldId,
    field_id: fieldId,
    _destroy: 1
};
$.ajax({
    url: '/cart_items.json',
    method: 'post',
    dataType: 'JSON',
    data: {
        order: {
      		fields_values_attributes: fieldsValuesAttributes
    		}
  	},
  	success: function(){}
});

В целом взаимодействие с дизайнами в корзине можно сделать темой отдельной статьи.

Показ условий доставки для региона РФ
Как известно, у инсейлс есть свой собственный геотаргетинг. С его помощью можно определить регион покупателя, и сделать что-то если это какой-то определенный регион.

Все в тот же localStorage я записываю автоматически определенный регион и даю покупателю возможность его изменить.

Благо, gosso – клиент трудолюбивый, он согласился сам создавать свой блок для условий самовывоза и доставки под каждый регион, а я вывожу контент всех таких блоков на отдельной странице и делаю к ней ajax-запрос для получения этого контента. Вот и весь секрет :)

Заключение

Это описание минимальной части всех фич, используемых на сайте, и их реализации. У клиента еще масса идей для новых фич, да и со старыми еще есть куда стремиться и что оптимизировать.

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

Пишите на e-mail: iam@insalesguru.ru, а также в скайп: anastasya.kachalova и телеграм: @Kachalova
Всем спасибо за прочтение и до новых встреч!

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.