One Page Shop - cały sklep na jednej stronie

Jak wyeksportować i zaimportować swój szablon w e-Sklepie?

Comarch e-Sklep daje możliwość dostosowania wyglądu do preferencji sprzedawcy oraz potrzeb Klientów. Jeśli utworzyłeś już swój autorski projekt, to masz możliwość jego zapisania. Plik będzie potrzebny przy chęci modyfikacji wyglądu. Zapisana wersja szablonu może również stanowić kopię bezpieczeństwa. Warto jest więc wyeksportować szablon do pliku.

Jak wyeksportować swój szablon z Comarch e-Sklep?

Krok 1. W panelu administracyjnym przejdź do sekcji Wygląd Sklepu/ Ustawienia/ Edytuj ustawienia zaawansowane/ zakładka Eksport szablonu.

Krok 2. W tym miejscu możesz opcjonalnie (przed eksportem) określić autora szablonu, podać adres e-mail, telefon oraz adres WWW swojego e-Sklepu.

Krok 3. Jeżeli chcesz wyeksportować szablon do pliku użyj przycisku Eksportuj szablon.

Gotowe! Szablon został wyeksportowany do pliku na Twoim urządzeniu.

Wskazówka
Z tego miejsca możesz także wyeksportować posiadane w e-Sklepie bannery, korzystając z przycisku Eksportuj bannery.

Jak wgrać własny szablon do Comarch e-Sklep?

Własny szablon. Jak go wgrać?

Po skomponowaniu swojego własnego szablonu możesz wgrać go do e-Sklepu. Postępuj zgodnie z poniższymi krokami.

Krok 1. W panelu administracyjnym przejdź do sekcji Wygląd Sklepu/ Ustawienia/ Edytuj ustawienia zaawansowane/ zakładka Import szablonu.

Krok 2. Określ, czy wgrywany szablon ma podmienić istniejące bannery. Gdy parametr zostanie zaznaczony, wówczas wszystkie bannery zapisane na danym slocie zostaną usunięte i zastąpione bannerami z importowanego szablonu.

Krok 3. Wybierz plik XML swojego szablonu i naciśnij Importuj szablon.

Uwaga
Import szablonu jest operacją nieodwracalną i spowoduje nadpisanie dotychczasowego szablonu. W przypadku, gdy szablon był modyfikowany (dokonywano zmian w kodzie HTML) jego aktualizacja spowoduje, iż zmiany nie zostaną przeniesione. Warto wykonać eksport posiadanego szablonu do pliku w celu zapisania oraz posiadania wglądu to wprowadzanych modyfikacji. Jeżeli istnieje taka konieczność należy ponownie dokonać samodzielnej edycji szablonu

Wskazówka
W zakładce Szablony możesz określić, czy wgrywany szablon ma być domyślny i aktywny w e-Sklepie.

Krok 4. Teraz możesz podejrzeć zmiany, jakie zaszły w wyglądzie Twojego e-Sklepu. W tym celu możesz podejrzeć zmiany w czasie rzeczywistym lub przejść w tryb incognito. Pamiętaj, że wszelkie zmiany zostaną opublikowane po pełnej synchronizacji, która wciągu 10 minut zgodnie z wyświetlanym komunikatem.

Gotowe! Twój szablon został zaimportowany do e-Sklepu.

Jak dodać wideo w sekcji z filmami?

Filmy produktowe na rynku e-commerce są dziś powszechną formą prezentowania towarów w sklepach internetowych. Producenci czy właściciele sklepów chcą wyróżniać swój asortyment. Niejednokrotnie pomaga to także w ukazaniu zastosowania produktu. Każdy film wyróżnia się sposobem prezentacji. W szablonie One Page Shop i Topaz dostępna jest sekcja, gdzie możesz publikować filmy, które pomogą Ci wypromować oferowany przez Ciebie towar.

Konfiguracja sekcji z filmami

Z poziomu panelu administracyjnego możesz w łatwy i szybki sposób dodać wideo. Postępuj zgodnie z poniższą instrukcją. Krok 1. Zaloguj się do panelu administracyjnego. Krok 2. Przejdź do zakładki Wygląd sklepu/ Ustawienia/ Strona główna. Na dole strony znajdź Ustawienia sekcji z filmami. Krok 3. Uzupełnij informacje o filmie: Etykietę PL oraz wstaw Link do filmu. W sekcji możesz zaprezentować filmy:
  • udostępnione w sekcji Ustawienia/ Pliki użytkownika – przykładowy link: usr/nazwafilmu.mp4
  • opublikowane w portalu YouTube – przykładowy link: https://www.youtube.com/embed/jq3B5jp8QwI
  • dodane na zewnętrznym hostingu – przykładowy link: https://twojhosting.pl/filmy/nazwafilmu.mp4
Krok 4. Uzupełnij tłumaczenia dla nazwy filmów prezentowanych w szablonie. Naciśnij link videoElement1, a zostaniesz przekierowany do edycji tłumaczenia. W polu tekst wpisz odpowiednią nazwę filmu i zapisz zmiany. Krok 5. Zapisz i opublikuj zmiany. Gotowe! Od teraz Klienci zobaczą w szablonie skonfigurowaną sekcję z opublikowanymi filmami. Przejdź do naszego sklepu demonstracyjnego i zobacz, jak wygląda skonfigurowana sekcja.

Jak zmienić kolejność wyświetlanych elementów na stronie głównej w One Page Shop?

W szablonie One Page Shop możesz zmieniać dowolnie kolejność wyświetlanych na głównej stronie elementów. Możesz dzięki temu spersonalizować swój e-Sklep tak, by był bardziej unikalny.

Konfiguracja strony głównej

Aby dokonać zmian w kolejności wyświetlanych elementów na stronie głównej wystarczy, że zalogujesz się do panelu administracyjnego, a następnie przejdziesz do sekcji Wygląd sklepu/ Ustawienia/ Strona Główna. Wyświetli się wówczas panel, który zawiera w sobie ustawienia nagłówka strony, treści strony oraz sekcji z filmami.

Ustawienia nagłówka strony

W nagłówku znajdują się następujące elementy:
  • Logotyp,
  • Produkty,
  • Blog,
  • Lookbook,
  • O firmie,
  • Kontakt,
  • Koszyk,
  • Informacje o języku i walucie, możliwość wyboru. 

Lista elementów w nagłówku strony

W tym miejscu możesz nie tylko dodać link do nagłówka, ale także ustalić, czy odnośniki do stron mają być widoczne. Możliwa jest też zmiana kolejności wyświetlania poszczególnych elementów. Wystarczy, że przesuniesz wybrany element za pomocą strzałki w kolumnie Kolejność. Możesz także określić, który odnośnik powinien być wyróżniony, a dokładniej, który link w nagłówku będzie posiadała inny kolor. Zmiany koloru czcionki możesz dokonać w sekcji Wygląd sklepu/ Ustawienia/ Ogólne. Odpowiadają za to sekcje:
   

Ustawienia treści strony

Pozostając w obszarze Wygląd sklepu/ Ustawienia/ Strona główna możesz zmienić ustawienia treści strony. W tym miejscu również istnieje możliwość zmiany kolejności wyświetlania poszczególnych elementów na stronie głównej sklepu oraz ukrycia elementu. Wystarczy, że odznaczysz checkbox w kolumnie Dostępne.

Ustawienia sekcji z filmami

W szablonie One Page Shop dostępna jest sekcja, w której możesz publikować filmy, które pomogą Ci wypromować oferowany przez Ciebie towar. Film możesz dodać w prosty i szybki sposób z poziomu panelu administracyjnego. Szczegóły konfiguracji znajdują się w artykule: Jak dodać wideo w sekcji z filmami w szablonie One Page Shop?

Jak wykonać kopię bezpieczeństwa mojego szablonu?

Jak wykonać kopię bezpieczeństwa mojego szablonu?

Oprawa wizualna sklepu jest bardzo ważnym elementem podczas prowadzenia sprzedaży w sieci. Narzędzie Kreator Wyglądu Comarch e-Sklep umożliwia stworzenie własnych, niepowtarzalnych szablonów wedle preferencji i potrzeb użytkowników. W intuicyjnym narzędziu jakim jest Kreator, będziesz w stanie zaprojektować wszelkie niezbędne funkcje, takie jak stronę główną, listę towarów, szczegóły towaru oraz koszyk. Jeśli Twój projekt szablonu został zaimportowany do e-Sklepu oraz skonfigurowany wedle Twoich preferencji (dodanie grafik do bannerów, modyfikacje kolorystyczne) masz możliwość jego zapisania, co będzie stanowić kopię bezpieczeństwa. Kopia bezpieczeństwa to dane, które w każdej chwili można odtworzyć w przypadku ich utracenia (np. poprzez przypadkowe usunięcie) lub częstego wprowadzania zmian. Dane, jakie może zawierać kopia bezpieczeństwa to szablon, który wcześniej został przez nas wygenerowany wraz z bannerami. Zaleca się wykonywanie kopii zapasowych oraz zabezpieczenie ich hasłem. Każda wykonana kopia zapasowa powinna zostać zapisana w bezpiecznym i dogodnym dla Użytkownika miejscu.

Jak wykonać kopię bezpieczeństwa?

W Panelu Administracyjnym przejdź do sekcji Wygląd sklepu/ Ustawienia/ Edytuj ustawienia zaawansowane, a następnie przejdź do zakładki Eksport szablonu. W pustych polach znajdujących się w zakładce Eksport szablonu, opcjonalnie przed eksportem możesz uzupełnić powyższe dane, tj. Autora szablonu, e-mail, telefon i stronę WWW sklepu. Aby wyeksportować szablon, kliknij Eksportuj szablon. Wyeksportowany plik jest w formacie XML, a jego nazwa zawiera szablon oraz wersję, co znacznie ułatwia zarządzanie kopiami bezpieczeństwa w przypadku wykonywania ich regularnie.

Jak wyeksportować bannery?

Bannery, które znajdują się w Twoim sklepie możesz również wyeksportować tworząc kopię bezpieczeństwa. W tym celu także musisz przejść do Wygląd sklepu/ Ustawienia/ Edytuj ustawienia zaawansowane, a następnie do zakładki Eksport szablonu. Obok przycisku Eksportuj szablon, znajduje się przycisk Eksportuj bannery, który musisz kliknąć aby bannery, które posiadasz w e-Sklepie zostały weksportowane. Kopia bezpieczeństwa jest również zapisywana w formacie XML, a nazwa pliku wskazuje na szablon, wersję i zawartość bannerów.

Jak zabezpieczyć hasłem swój szablon?

Jeśli chcesz, aby Twój szablon został zabezpieczony hasłem, a znajomość hasła była niezbędna podczas zaimportowania tego szablonu do e-Sklepu, musisz w tym celu przejść w Panelu Administracyjnym do sekcji Wygląd sklepu/ Ustawienia/ Ustawienia zaawansowane, następnie do zakładki Szablon. W tym miejscu nadasz hasło dla swojego szablonu. Zgodnie z Polityką bezpieczeństwa haseł, hasło powinno:
  • Składać się z minimum 8 znaków,
  • Zawierać dużą literę,
  • Zawierać małą literę,
  • Zawierać cyfrę 0-9,
  • Zawierać znak specjalny – ‘!.+?;^]=-(&_)#=
Gotowe! Teraz Twój szablon został zabezpieczony hasłem. Jeśli wyeksportujesz szablon, który zabezpieczyłeś hasłem – podczas importu tego szablonu, będziesz musiał podać nadane wcześniej hasło. Jego brak uniemożliwi import szablonu, a podanie błędnego hasła spowoduje nieprawidłowe działanie szablonu po imporcie. Więcej informacji znajdziesz:

One Page Shop - podstawowe informacje

Wstęp

One Page Shop to szablon zaprojektowany z myślą o użytkownikach, którzy w swojej ofercie posiadają jedynie kilka towarów. Dzięki niemu zaprezentujesz na głównej stronie wyjątkowe produkty, które posiadasz w swojej ofercie. Struktura szablonu skupiona jest na zaprezentowaniu asortymentu tak, aby decyzje zakupowe Twoich Klientów zapadały szybciej. Potencjalny klient może odnaleźć najważniejsze informacje na temat Twojej oferty przeglądając jedną stronę witryny. Szablon One Page Shop:
  • dostępny jest we wszystkich wariantach Comarch e-Sklep,
  • pozwala na prezentację 20 towarów prostych,
  • dostępny jest w dwóch motywach kolorystycznych,
  • jest prosty w konfiguracji bezpośrednio w panelu.
Przejdź do naszego sklepu demonstracyjnego i zobacz, jak wygląda One Page Shop w Comarch e-Sklep.   W tym artykule zawarliśmy podstawowe informacje na temat funkcji dostępnych w szablonie. Dzięki udogodnieniom i możliwości edycji niektórych elementów możesz łatwo spersonalizować swój e-Sklep.

Konfiguracja One Page Shop w panelu administracyjnym

Z poziomu panelu administracyjnego możesz dokonywać edycji każdego elementu znajdującego się na stronie. Możesz także ustalać sposoby dostaw oraz płatności. Po przejściu do sekcji Wygląd sklepu/ Ustawienia dostępne są ustawienia dla trzech zakładek: Ogólne, Strona główna, Dodatkowe.
  • W zakładce Ogólne możesz dokonać zmian w motywie kolorystycznym Twojego e-Sklepu. Z tego poziomu również możesz dokonać m.in takich zmian, jak: prezentacja punktów osobistego, edycji terminu dostaw czy umożliwienie prezentacji informacji o najniższej cenie towaru lub usługi jaka obowiązywała w okresie 30 dni przed wprowadzeniem obniżki.
  • W zakładce Strona główna znajdują się ustawienia, które pomagają „układać” poszczególne elementy na stronie głównej. W tym miejscu możesz zdecydować, gdzie powinny wyświetlać się produkty, lookbook i bannery. Część wyświetlanych elementów możesz ukryć.
  • W zakładce Dodatkowe widnieją ustawienia, dzięki którym możesz decydować o możliwości udostępniania towarów w poszczególnych mediach społecznościowych, czy udostępniania przycisku obliczającego ratę lub leasing. Dodatkowo możesz włączyć prezentację tabeli rozmiarów na stronie towaru.

Ustawienia Strony Głównej

Ustawienia zawarte w tym miejscu odpowiadają za elementy, które wyświetlane są na stronie głównej. Możesz zmieniać ich kolejność, nazwę, ukryć lub wyróżnić. W tym miejscu wyróżnia się następujące sekcje:

Ustawienia nagłówka strony

W nagłówku znajdują się następujące elementy:
  • Logotyp,
  • Odnośnik do listy z produktami (nasze produkty),
  • Blog,
  • Lookbook,
  • Informacje o firmie,
  • Kontakt,
  • Koszyk,
  • Możliwość wyboru języka i waluty w e-Sklepie.
W tym miejscu możesz nie tylko dodać link do nagłówka, ale także ustalić, czy i jakie odnośniki do stron mają być widoczne. Możliwa jest też zmiana kolejności wyświetlania poszczególnych elementów.

Ustawienia treści strony

Pozostając w obszarze Wygląd sklepu/ Ustawienia/ Strona główna możesz zmienić ustawienia treści strony. W tym miejscu również istnieje możliwość zmiany kolejności wyświetlania poszczególnych elementów na stronie głównej sklepu oraz ukrycia elementu. Szczegółowe informacje na temat konfiguracji znajdują się w artykule: Jak zmienić kolejność wyświetlanych elementów na stronie głównej w One Page Shop?

Elementy w szablonie

1. Sekcja z filmami

W One Page Shop masz możliwość dodania filmów promujących nie tylko produkty, ale także Twoją firmę, dostępne marki czy producentów. Film możesz dodać w prosty i szybki sposób z poziomu panelu administracyjnego. W sekcji możesz zaprezentować filmy:
  • udostępnione w sekcji Ustawienia/ Pliki użytkownika,
  • opublikowane w portalu YouTube,
  • dodane na zewnętrznym hostingu.
Szczegóły konfiguracji znajdują się w artykule: Jak dodać wideo w sekcji z filmami w szablonie One Page Shop?

2. Banner

Aby dodać zdjęcia do banneru przejdź do zakładki Wygląd sklepu/ Ustawienia/ Bannery, a następnie klikając na kafelek o nazwie mainBanner wybierz odpowiednie zdjęcie. 
Wskazówka
Rekomendowany rozmiar grafik dla banneru to 1920 x 540 px.
Szczegóły na temat dodawania i edycji bannerów znajdują się w artykule: Bannery.

3. Lookbook

Widok charakteryzuje się prezentacją zdjęć w formie listy i precyzyjnym oznaczeniem towarów na zdjęciu. Dzięki znacznikom umieszczonym na grafice Twoi klienci będą mogli podejrzeć towar i dodać go bezpośrednio do koszyka. Po kliknięciu na przycisk z plusem wyświetli się popup ze szczegółami towaru oraz opcją zakupu.
Wskazówka
Rekomendowany rozmiar grafik do lookbooka to 560 x 500 px.
Aby poprawnie skonfigurować lookbook, skorzystaj z naszej instrukcji zawartej w artykule: Jak skonfigurować Lookbook w Comarch e-Sklep?

4. Lista towarów

Szablon One Page Shop został stworzony z myślą o użytkownikach, którzy w swojej ofercie nie posiadają wielu produktów. Z tego powodu, na stronie głównej wyświetlanych jest 20 towarów prostych, które zostały przypisane do pierwszej kategorii w systemie Comarch ERP. Z tego powodu zalecamy utworzenie jednej kategorii, która ma być przesyłana do One Page Shop'a.
Przyklad
W systemie ERP posiadasz kategorię A, B oraz C. W kategorii A i B znajduje się po 5 produktów, zaś w kategorii C, która liczy 10 produktów. Po wykonaniu synchronizacji zostanie wyświetlonych 5 produktów z kategorii A, ponieważ jest ona pierwsza w systemie Comarch ERP.
Lista produktów wyświetlana jest w formie kafli.
Sekcja z listą towarów w One Page Shop Comarch

5. Szczegóły towaru – jakie informacje widnieją na pop-upie?

W szablonie One Page Shop Klient będzie mógł zobaczyć szczegóły danego towaru nie musząc przechodzić na osobną stronę. Wystarczy, że kliknie na kafelek z interesującym go artykułem lub naciśnie Kup teraz. Wyświetli się wówczas pop up, który zawiera w sobie szereg informacji na temat towaru, między innymi:
  • Cenę wraz z formą dostawy, kalkulatorami ratalnymi oraz leasingowymi,
  • Dostępność produktu,
  • Cechy towaru,
  • Opis towaru,
  • Tabelę rozmiarów,
  • Liczbę opinii oraz zakładkę z wystawionymi już komentarzami,
  • Informację o ilości osób, która kupiła dany towar,
  • Możliwość udostępnienia towaru w social mediach lub za pomocą linku,
  • Opcję „Zapytaj o towar”,
  • Zestawy promocyjne.
Pop-up ze szczegółami towaru w One Page Shop Comarch
Jeśli posiadasz produkt, który nie posiada wariantów istnieje możliwość zakupu tego towaru z pominięciem pop-up podczas kliknięcia w przycisk "Kup teraz". Klikając w inne miejsce na towarze, pop-up ze szczegółami wyświetli się. Jeśli chcesz wyłączyć pop-up, możesz to zrobić z poziomu Panelu Administracyjnego przechodząc do sekcji Wygląd sklepu/ Ustawienia:

6. Koszyk

W szablonie One Page Shop składanie zamówienia jest szybkie i wygodne dla użytkownika. Koszyk został zaprojektowany tak, aby użytkownik mógł w jednym kroku wypełnić niezbędne dane: 
  • Formularz z danymi zamawiającego oraz danymi do faktury,
  • Sposób dostawy,
  • Sposób płatności,
  • Miejsce na wpisanie kodu rabatowego.
Po uzupełnieniu powyższych informacji można przejść do podsumowania, w którym prezentowane są wcześniej wprowadzone dane klienta. Oprócz tego w koszyku One Page Shop jest możliwość wyświetlania ceny za sztukę. Pojawi się ona po dodaniu do koszyka kilku sztuk produktu. Przy jednej sztuce towaru wyświetlana będzie tylko cena. Od wersji 2024.1.1 w szablonie One Page Shop dodano możliwość wyświetlania w koszyku informacji jakiej kwoty brakuje do darmowej dostawy.  Funkcja ta możliwa jest do uruchomienia z poziomu Panelu Administracyjnego w sekcji Wygląd sklepu/ Ustawienia/ Ustawienia szablonu/ Ogólne: Ustawienia te można zmienić według własnego uznania, a następnie należy użyć opcji Zapisz i Publikuj.

7. Blog

Prowadzenie bloga jest istotnym elementem sklepu internetowego. Dzięki niemu sprzedawca może dzielić się swoją wiedzą i spostrzeżeniami na temat reklamowanych produktów. W ten sposób sprzedawca może podpowiedzieć klientom w jaki sposób mogą oni wykorzystać oferowane przez niego artykuły. Prowadzenie bloga ma również dobry wpływ na pozycjonowanie, ze względu na unikalne treści. Dzięki temu Twój e-Sklep może częściej pojawiać się w wynikach wyszukiwania. W szablonie One Page Shop masz możliwość tworzenia dowolnej ilości wpisów. Na stronie głównej wyświetlone zostaną trzy najnowsze. Użytkownik ma możliwość podglądu całej listy artykułów. Wystarczy, że kliknie w etykietę Najnowsze wpisy. Szczegółowe informacje na temat konfiguracji bloga w e-Sklepie znajdują się w artykule: Jak skonfigurować blog?

8. Info-banner

Banner informacyjny pozwala na zaprezentowanie w przejrzysty sposób korzyści z zakupach w Twoim e-Sklepie. Modyfikacji tego obszaru dokonasz z poziomu panelu administracyjnego, przechodząc do sekcji Wygląd sklepu/ Ustawienia/ Bannery. Następnie przechodząc do szczegółów banneru o nazwie info-banner dostosujesz element do swoich preferencji. Możesz skorzystać z domyślnych grafik lub dodać własne.

9. Element tekstowy ze zdjęciem

Element tekstowy ze zdjęciem charakteryzuje się możliwością wprowadzenia statycznego opisu na stronie głównej w twoim e-Sklepie. Możesz zawrzeć w nim np. podstawowe informacje na temat Twojej firmy, asortymentu sklepu lub inne wartościowe dla Ciebie treści. Element tekstowy możesz odpowiednio skonfigurować przechodząc do sekcji Wygląd sklepu/ Ustawienia/ Edytuj ustawienia zaawansowane, a następnie do zakładki Obiekty, gdzie skonfigurujesz zawartość elementu.
Wskazówka
Za wyświetlanie elementu tekstowego w szablonie One Page Shop odpowiada obiekt o nazwie text-el-photo-mp-1.
Więcej informacji na temat konfiguracji znajduje się w artykule: Element tekstowy w szablonie.

10. Stopka

Dzięki modyfikacji obszaru możesz jeszcze bardziej spersonalizować swój sklep poprzez uzupełnienie stopki w szereg przydatnych informacji. Elementem tym możesz zarządzać z poziomu sekcji Wygląd Sklepu/ Ustawienia/ Nagłówek i Stopka. Szczegółowe informacje na temat konfiguracji stopki znajdują się w artykule: Rozbudowana stopka w szablonach – jak ją skonfigurować?

11. Strefa Klienta

Do Strefy Klienta w szablonie One Page Shop masz możliwość zalogowania się poprzez Facebooka oraz przez Google. Więcej na temat konfiguracji logowania przez Facebooka i Google znajdziesz tutaj. Masz także możliwość całkowitego ukrycia Strefy Klienta na stronie sklepu internetowego. Zdecydujesz o tym zaznaczając właściwą opcję w zakładce Wygląd sklepu/ Ustawienia/ Ustawienia szablonu/ Ogólne: Wprowadzone zmiany standardowo należy zapisać i opublikować.

Jak zaktualizować szablon do najnowszej wersji?

Jak zaktualizować szablon do najnowszej wersji?

Wskazówka
Od 1 czerwca 2025 roku zakończyliśmy aktualizację oraz wydawanie nowych wersji szablonów Bursztyn, Agat i Opal, a tym samym ich wsparcie, aby skupić się na nowoczesnych rozwiązaniach, które jeszcze lepiej odpowiadają na potrzeby dynamicznie rozwijającego się rynku e-commerce. Zachęcamy Was do przejścia na nasze nowe, udoskonalone szablony. Dla sklepów B2C polecamy szablony Topaz, One Page Shop oraz Dla Gastronomii, natomiast dla platform B2B idealnym wyborem będą Rubin i Szafir.

Wstęp

W e-Sklepie możesz dowolnie zmieniać szablony. Możesz je także modyfikować oraz aktualizować. Wiąże się to z wgraniem zupełnie nowego szablonu na miejsce starego. Aktualizacja wyglądu powoduje zmianę dotychczasowych ustawień. Przed każdą aktualizacją polecamy utworzyć odpowiednią dla siebie instrukcję, która będzie zawierała Twoje ustawienia kolorów czy modyfikacje w kodzie szablonu. Możesz także wyeksportować dotychczasowy szablon, aby stanowił on kopię bezpieczeństwa.

Jak zaktualizować szablon?

Instrukcja aktualizacji szablonów: Rubin, Szafir, Topaz i One Page Shop (dostępnych w Kreatorze Wyglądu)

Aby zaktualizować szablon Rubin, Szafir, Topaz lub One Page Shop należy skorzystać z aktualnej wersji Kreatora Wyglądu, do którego odnośnik znajduje się w panelu administracyjnym e-Sklepu w sekcji Wygląd sklepu/ Kreator wyglądu. Istnieją dwie możliwości aktualizacji tych szablonów:

  • wygenerowanie nowego szablonu w Kreatorze Wyglądu oraz wgranie go do e-Sklepu,
  • import posiadanego szablonu do Kreatora Wyglądu oraz ponowne wygenerowanie go w najnowszej wersji.

Wyeksportowany z Kreatora Wyglądu szablon należy wgrać do e-Sklepu. W panelu administracyjnym e-Sklepu, w sekcji Wygląd sklepu znajduje się bezpośredni odnośnik do importu szablonu z Kreatora wyglądu. Szczegółowa instrukcja dostępna jest w artykule Jak wyeksportować i zaimportować swój szablon w e-Sklepie?

Podczas dokonywania modyfikacji w szablonach zachęcamy do skorzystania z naszego Centrum Pomocy.

Wskazówka
Pamiętaj o zapisaniu szablonu oraz opublikowaniu go w e-Sklepie. Zmiany wprowadzone w ustawieniach zostaną zsynchronizowane do sklepu po 10 minutach.

Instrukcja aktualizacji szablonów: Bursztyn, Agat i Opal.

Aby zaktualizować szablon Bursztyn, Agat lub Opal należy w panelu administracyjnym e-Sklepu przejść do sekcji Wygląd Sklepu/ Gotowe szablony Comarch, w której znajdują się najnowsze wersje szablonów dostępne do zainstalowania. Z wyświetlonej listy należy wybrać szablon, który ma zostać wgrany do e-Sklepu. W tym celu wybierz przycisk Chcę pobrać i zainstalować szablon:

Następnie wyświetli się nowe okno, w którym należy:

  • wybrać tzw. slot, który zostanie nadpisany nowym (aktualnym) szablonem. W każdym e-Sklepie dostępne są 4 miejsca na wgranie szablonu, spośród których jeden szablon oznacza się jako aktywny i domyślny,
  • określić, czy wgrywany szablon ma podmienić istniejące bannery. Gdy parametr zostanie zaznaczony, wówczas wszystkie bannery zapisane na danym slocie zostaną usunięte i zastąpione bannerami z importowanego szablonu. Jeżeli w nadpisywanym szablonie znajdują się bannery oraz lookbooki, które mają nadal wyświetlać się w e-Sklepie, należy wskazany parametr zostawić odznaczony. Gdy parametr nie zostanie zaznaczony, wówczas dotychczasowe bannery i lookbooki nie zostaną usunięte.
  • Zaimportować szablon do e-Sklepu.
    Wskazówka
    Import szablonu jest operacją nieodwracalną i spowoduje nadpisanie dotychczasowego szablonu. W przypadku, gdy szablon był modyfikowany (dokonywano zmian w kodzie HTML) jego aktualizacja spowoduje, iż zmiany nie zostaną przeniesione. Warto wykonać eksport posiadanego szablonu do pliku w celu zapisania oraz posiadania wglądu to wprowadzanych modyfikacji. Jeżeli istnieje taka konieczność należy ponownie dokonać samodzielnej edycji szablonu.

Aby nowy szablon pojawił się w e-Sklepie należy upewnić się, czy jest on aktywny oraz ustawiony jako domyślny. W sekcji Wygląd sklepu/Ustawienia/Edytuj ustawienia zaawansowane w zakładce Szablon znajdują się odpowiedzialne za to parametry, które powinny być zaznaczone.

Wszelkie zmiany należy zapisać, a następnie opublikować.

Uwaga
Jeżeli szablon nie zostanie opublikowany, wówczas nie pojawi się on w e-Sklepie.

Instrukcja aktualizacji innych szablonów (niż szablonów Comarch) oraz aktualizacji szablonów z własnymi modyfikacjami

Jeżeli w swoim Comarch e-Sklepie korzystasz z własnego szablonu, czyli innego niż gotowe szablony Comarch, to powinieneś jego aktualizację przeprowadzić we własnym zakresie lub zlecić ją firmie/ osobie, która dla Ciebie przygotowała ten szablon. W przypadku, gdy korzystasz z gotowego szablonu Comarch, ale wprowadziłeś do niego indywidualne zmiany (poza Kreatorem Wyglądu), to również we własnym zakresie (lub ze wsparciem autora zmian) musisz zadbać o aktualizację swojej wersji szablonu.

Banner promocyjny w szablonie Topaz i One Page Shop

Banner promocyjny - jak to działa?

Banner promocyjny wyświetli się na stronie głównej Twojego e-Sklepu i będzie prezentował typ towaru, który wskażesz. Taki rodzaj banneru pomoże Ci w zwróceniu uwagi Klientów na towary, które zostały objęte na przykład ofertą specjalną.

Dodanie banneru

Banner możesz dodać z poziomu Kreatora Wyglądu B2C  (zamiennie: panel administracyjny e-Sklepu: Wygląd sklepu/ Kreator wyglądu). Aby dodać banner promocyjny do swojego szablonu, przejdź na stronę "Strona główna", po czym wybierz Banner promocyjny i przeciągnij go w wybrane przez Ciebie miejsce. W podglądzie układu szablonu, po najechaniu kursorem na obszar z bannerem promocyjnym, zobaczysz możliwość jego edycji. Wybierz ikonę "zębatki", aby móc edytować i określić liczbę wyświetlanych towarów oraz typ promowanych towarów. Zapisz wprowadzone zmiany. Jeśli pozostałe strony szablonu są gotowe i skonfigurowane, to możesz wygenerować szablon. Więcej informacji na temat Kreatora Wyglądu oraz poszczególnych sekcji znajdziesz w artykule: Kreator wyglądu Topaz (B2C) Po zaimportowaniu szablonu do panelu administracyjnego możesz przejść do edycji banneru. Postępuj zgodnie z poniższą instrukcją.

Edycja banneru

Modyfikacja wszystkich bannerów dostępnych w szablonach Comarch możliwa jest w panelu administracyjnym w obszarze Wygląd sklepu> Ustawienia> Bannery. Informacje odnośnie domyślnej, tradycyjnej modyfikacji bannerów znajdują się w artykule: Bannery

Odnajdź banner na liście nazwany "promotionalBanner", a następnie wybierz go, aby edytować i dodać zdjęcie

Po dokonaniu modyfikacji należy zapisać i opublikować zmiany. Gotowe! Teraz Twój banner promocyjny wyświetli się na stronie głównej.
Banner promocyjny w szablonie Topaz
Banner promocyjny w szablonie Topaz.

Kreator Wyglądu One Page Shop (B2C)

Wstęp

Jednym z kluczowych elementów, który przyczynia się do sukcesu w branży e-commerce jest oprawa wizualna sklepu. W dużym stopniu to właśnie ona wpływa na całościowe wrażenia użytkowników i ich proces zakupowy. Dzięki narzędziu - Kreator Wyglądu Comarch e-Sklep, właściciele sklepów mają możliwość stworzyć swój własny, niepowtarzalny szablon, który będzie dostosowany do ich preferencji oraz do potrzeb użytkowników.

Kreator jest dostępny pod linkiem: Kreator szablonu Comarch e-Sklep. Odnośnik znajduje się w panelu administracyjnym e-Sklepu Wygląd sklepu > Kreator wyglądu.

Zastosowanie

Kreator jest intuicyjnym narzędziem służącym do tworzenia szablonów. Jego obsługa nie wymaga umiejętności technicznych ani programowania. Wszystko odbywa się na poziomie strony internetowej, gdzie z gotowych elementów za pomocą metody "przeciągnij i upuść" możesz zaprojektować wygląd swojego sklepu. Dodatkowo, stworzony szablon jest dostosowany do wyświetlania na różnych urządzeniach (RWD).

W ramach kreatora zaprojektujesz wszystkie niezbędne obszary sklepu. Po utworzeniu szkieletu e-Sklepu, przychodzi czas na modyfikację oprawy wizualnej szablonu. Możesz dowolnie zmieniać kolory elementów znajdujących się na stronie, ikony, a także czcionkę.

Kto może używać tej opcji?

Aby móc używać tego narzędzia należy posiadać:

  • Comarch e-Sklep obsługujący procesy B2C,
  • szerokość ekranu powyżej 1280 px, a zalecana to 1920 px,
  • oraz jedną z przeglądarek internetowych w aktualnej wersji.

Wskazówka
Kreator wyglądu Comarch e-Sklep dostępny jedynie w wersji przeglądarkowej.

Tworzymy!

Jak zaprojektować układ szablonu?

Aby rozpocząć tworzenie szablonu należy przejść na stronę Kreatora Wyglądu. Wyświetlony zostanie powitalny komunikat. Na początku należy określić, dla jakiego modelu sprzedaży projektujesz szablon dla swojego e-Sklepu. Do wyboru masz sprzedaż detaliczną lub hurtową. Sprzedaż detaliczna przeznaczona jest dla użytkowników, którzy chcą sprzedawać swoje produkty głównie klientom indywidualnym. Wybierz odpowiedni model, a następnie naciśnij przycisk Rozpocznij pracę. Po jego kliknięciu będzie można stworzyć nowy szablon lub edytować jeden z kilku gotowych.

W sytuacji gdy wcześniej tworzony był już projekt, widoczny będzie przycisk umożliwiający dokończenie szablonu lub rozpoczęcie nowego projektu. Opcja Nowy szablon umożliwia zbudowanie od początku nowego szablonu Topazu według Twojego indywidualnego pomysłu.
Wskazówka
Szablon One Page Shop - Demo jest gotowym szablonem, który możesz zainstalować bezpośrednio z obszaru Wygląd sklepu > Gotowe szablony Comarch.
W trzech krótkich krokach zapoznasz się z podstawowymi funkcjami kreatora. Następnie możesz już przystąpić do dalszych modyfikacji szablonu lub od razu wygenerować przygotowaną wersję szablonu One Page Shop.

Od czego zacząć?

Wybierz wersję językową Kreatora i rozpocznij pracę nad swoim szablonem. Wersje do wyboru to: język polski, angielski, niemiecki oraz francuski. Język wybieramy klikając strzałkę obok flagi i nazwy języka w lewym dolnym rogu. Przy podglądzie prac na pełnym ekranie, wybrany język zostaje zachowany i szablon będzie wyświetlał się w wybranej wersji językowej.

Gdy już wybierzesz wersję językową dla swojego Kreatora warto zacząć od nazwania swojego przyszłego szablonu. Można to zrobić klikając Zmień i wpisując nazwę w lewym górnym rogu, zastępując nazwę "One Page Shop (2023.1)". Nazwa ta będzie widoczna po zaimportowaniu szablonu do panelu administracyjnego oraz po wyeksportowaniu szablonu do pliku XML wraz z datą i godziną jego wygenerowania.

Krok 1 - Sekcja Szablon

W tej sekcji należy zaprojektować wygląd strony głównej naszego Comarch e-Sklepu. Strona główna może składać się z następujących elementów:

  • Nagłówek,
  • Baner,
  • Widget,
  • Siatka towarów
  • Newsletter,
  • Sekcja z filmami
  • Blog,
  • Element tekstowy,
  • Banner informacyjny,
  • Lookbook
  • Stopka.

Po rozwinięciu każdej z sekcji ukażą się dostępne elementy:

Metodą "Przeciągnij i upuść" przenosimy wybrane elementy na obszar po prawej stronie:

Postępuj analogicznie z pozostałymi elementami.

Nagłówek

Sekcja „Nagłówek” prezentuje dwa widoki.

Banner

Sekcja "Banner" pozwala wybrać jedną z sześciu możliwości prezentacji banerów. Informacje dotyczące rekomendowanych rozmiarów obrazków w bannerach opisaliśmy w tym artykule. Jest on widoczna tylko dla strony głównej i listy towarowej.

Banner promocyjny

Sekcja "Banner promocyjny" dodać banner prezentujący promocje.

Widget

Sekcja "Widget" pozwala dodać jeden z dwóch dostępnych wariantów, które pozwolą zaprezentować następujące funkcje:
  • Widget-banner-1
    • Dodanie zdjęcia,
    • Dodanie tekstu nagłówka (tekst pionowy),
    • Dodanie tekstu przycisku (tooltip).
    • Dodanie linku do przycisku,
    • Dodanie tekstu..
  • Widget-banner-1
    • Dodanie zdjęcia,
    • Dodanie tekstu nagłówka (tekst pod zdjęciem),
    • Dodanie tekstu,
    • Dodanie linku do tekstu.

Siatka towarów

Na szczegółach wybranego obiektu (Siatka towarów) określamy jakie dokładnie towary zostaną zaprezentowane w sekcji „Nasze produkty".

Dodatkowo po najechaniu kursorem na tę sekcję, wybierając Opcje, możemy ustawić następujące opcje:
  • wybierz sposób wyświetlania produktów na liście,
  • prezentowanie drugiego zdjęcia towaru na kiście,
  • dodatkowe informacje na liście towarów,
  • graficzna prezentacja wariantów towaru,
  • po dodaniu do koszyka,
  • pozwalaj na udostępnianie towarów,,
  • pomijaj popup ze szczegółami przy kupowaniu towarów prostych.
 

Newsletter

Sekcja "Newsletter" pozwala dodać jeden z czterech dostępnych wariantów zapisu klientów do subskrypcji. Dwie sekcje pokazują się w formie wyskakującego okienka (pop-up), które prezentowane są wyłącznie na stronie głównej e-Sklepu (newsletter-3, newsletter-4). Wszystkie teksty dostępne w nowym newsletterze są edytowalne w ustawieniach szablonu w menu Wygląd sklepu > Ustawienia > Bannery > Newsletter banner. 

Sekcja z filmami

Sekcja z filmami prezentuje jeden widok. Film wprowadza się w ustawieniach szablonu w sekcji Strona główna > Ustawienia sekcji z filmami.

Blog

Sekcja "Blog" pozwala wybrać spośród dwóch dostępnych wariantów. Blog -1 prezentuje tylko zdjęcia, natomiast Blog-2 oraz Blog-3 zawiera również krótkie opisy wprowadzające do pozostałej treści wpisu.

Element tekstowy

Element tekstowy pozwala na zamieszczenie dłuższego opisu, który będzie wyświetlany na stronie głównej Comarch e-Sklep. W kreatorze wyglądu Comarch są do wyboru dwa warianty:
  • element tekstowy z samym tekstem,
  • element tekstowy z możliwością dodania zdjęcia.
Tekst wprowadza się edytując obiekt tekstowy w ustawieniach szablonu: Wygląd sklepu > Ustawienia > Edytuj ustawienia zaawansowane > Obiekty:
  • text-el-no-photo-mp-1 – element bez obrazka,
  • text-el-photo-mp-2 – element z obrazkiem.

Po wybraniu wszystkich niezbędnych sekcji nasza strona główna powinna być gotowa. Efekt naszej pracy możemy podejrzeć klikając Podgląd w prawym górnym rogu. Dostępny jest podgląd w wersji mobilnej i desktopowej.

Strona główna wymaga dwóch podstawowych elementów: nagłówka oraz stopki. Pozostałe elementy nie są obowiązkowe.

Banner informacyjny

Banner informacyjny pozwala na zaprezentowanie w przejrzysty sposób korzyści z zakupach w Twoim sklepie. Dotyczą one obszarów: dostawy, jakości i kontaktu z klientem. Banner możesz dodać tylko do strony głównej lub do wszystkich stron. Sekcja Odkryj Comarch e-Sklep różni się prezentacją oraz elementami między bannerami i zawiera:
  • info-banner-1 – element z ikonkami i podpisem
    • Szybka dostawa,
    • Gwarancja jakości,
    • Odbiór osobisty,
    • Reklamacje,
    • Zwroty towarów,
  • info-banner-3 – element z ikonkami i krótką informacją
    • Ekspresowa wysyłka,
    • Darmowa dostawa,
    • Obsługa klienta,
  • info-banner-3 – element z ikonkami i krótkim opisem
    • Ekspresowa dostawa,
    • Darmowa dostawa,
    • Strefa kontaktu.
  • info-banner- 4 – Poznaj produkt
    • Wyróżnij główny towar – zdjęcie główne,
    • Pozostałe towary – zdjęcia na zewnątrz,

Lookbook

Sekcja "Lookbook" prezentuje jeden widok, który pozwoli na promowanie wielu towarów w bardzo atrakcyjnej formie.

Koszyk

Sekcja "Koszyk" pozwala dodać jeden z trzech dostępnych wariantów, gdzie każdy z nich posiada inną ilość kroków.

Stopka

Sekcja "Stopka" zawiera jeden widok do wyboru. W każdym widoku widnieją strony statyczne, którymi można zarządzać w sekcji Wygląd Sklepu > Ustawienia > Nagłówek i Stopka. Dla każdej z sekcji wyświetla się jej utworzona w panelu nazwa. W stopce znajdują się także informacje na temat rodzaju prezentowanych cen w e-Sklepie (brutto czy netto) oraz komunikat @Comarch SA 2023. All rights reserved Powered by Comarch e-Sklep. Dodatkowo istnieje możliwość umieszczenia w stopce odnośników do mediów społecznościowych oraz ich ikony. W stopce trzeciej możemy dodać ikony naszych dostawców oraz form płatności wykorzystywanych w sklepie.

Następnie możemy przejść do modyfikacji wyglądu naszego szablonu. W tym celu należy przejść do zakładki Style.

Style

Jak zmienić kolory, czcionki oraz ikony?

Po dodaniu elementów strony możemy dodatkowo podejrzeć, jak będzie wyglądał nasz przyszły szablon. W tym celu należy przejść do zakładki Style.

Dodatkowo w zakładce Style możemy zmodyfikować wygląd naszego szablonu. Zmianie podlegają:

  • motyw kolorystyczny,
  • czcionka,
  • ikony,
  • styl okien i przycisków.

Motyw kolorystyczny

Aby zmienić kolor naszego szablonu należy przejść do sekcji Motyw kolorystyczny, gdzie do wyboru przygotowaliśmy 7 gotowych motywów.

Wskazówka
W aktualnej wersji Kreatora dodaliśmy nowy, ciemny motyw kolorystyczny.

Każdy z motywów możemy edytować według indywidualnych preferencji. Możemy zmodyfikować kolor poszczególnych elementów (m.in.: tło strony, tło nagłówka, nazwę towaru, czy nawet drugorzędny kolor tekstu w newsletterze). Zmiany należy zapisać klikając Zapisz. Jeśli wykonane zmiany nie są zadowalające, możemy przywrócić ustawienia domyśle dla danego motywu kolorystycznego, klikając przycisk Przywróć.

Możliwe jest również wprowadzenie szesnastkowego zapisu kolorów. Heksadecymalny zapis kolorów dla poszczególnych sekcji w szablonie dostępny jest podczas edycji wybranego motywu kolorystycznego.

Czcionki

W zależności od potrzeb istnieje możliwość wybrania czcionki. Dla naszych klientów udostępniliśmy jej 13 różnych typów. Pod nazwą każdej z nich znajduje się przykładowy wygląd w różnych formatach.

Ikony

Mamy do wyboru 3 różne warianty wyglądu ikon. Dodatkowo istnieje możliwość wyboru w jakiej postaci wyświetla się ikona koszyka (torba, wózek lub koszyk) oraz loader.

Wskazówka
Od teraz możesz zmienić rodzaj loadera, wybierając jedną z 5 propozycji widocznych powyżej.

Styl okien i przycisków

Ostatnim elementem, który możemy modyfikować z poziomu zakładki Style jest styl okien i przycisków. Mamy do wyboru 3 różne warianty zaokrągleń.

Generowanie i wgrywanie szablonu

Po zaprojektowaniu wyglądu szablonu możemy go wygenerować i pobrać na dysk korzystając z przycisku Generuj widocznego w prawym górnym rogu:

Obok przycisku Generuj dostępna jest również opcja Importuj szablon, umożliwiająca wgranie wcześniej zapisanego szablonu z dysku i ponowną jego edycję.

W przypadku prawidłowego wygenerowania szablonu wyświetlony zostanie komunikat informujący o tym fakcie i pobrany plik.

Pobrany szablon należy zaimportować w Comarch e-Sklep w zakładce Wygląd sklepu > Zaimportuj szablon z Kreatora Wyglądu.

W szablonie Topaz znajduje się informacja na temat godziny wygenerowania szablonu w Kreatorze. Taka informacja znajduje się w panelu administracyjnym w menu: Wygląd sklepu > Ustawienia > Więcej (trzy kropki), gdzie należy wybrać opcję Edytuj ustawienia zaawansowane, a potem ponownie Więcej > Edytuj HTML. Następnie z listy plików należy wybrać _layout.html. Informacje na temat modyfikacji, w tym godzina ostatniej modyfikacji, znajdują się nad oknem edycji pliku. Jeżeli plik nie był modyfikowany, wówczas godzina odpowiada godzinie wygenerowania szablonu w kreatorze.

W przypadku braku obowiązkowych elementów szablonu nie będzie możliwe jego wygenerowanie. przycisk Generuj będzie wyszarzały, a w prawym dolnym rogu pojawi się komunikat „Uzupełnij elementy wymagane w szablonie”. Sekcje, gdzie element nie został wybrany będą się wyświetlać z odpowiednią ikoną.

  Kreatorze wyglądu istnieje również możliwość cofania się podczas tworzenia szablonu, w ramach której obsługujemy do 30 kroków w wstecz. Dodatkowo możemy także wykonywać krok do przodu. Zapisywane są wszystkie zmiany na elementach, informacje odnośnie styli, czcionek, ikonach oraz nazwie szablonu.

Aktualizacja szablonu

W Kreatorze Wyglądu znajduje się opcja aktualizacji poprzednich wersji szablonu. W celu zaktualizowania całego szablonu należy wgrać plik z poprzednim szablonem do Kreatora Wyglądu, według tej instrukcji:
  • po uruchomieniu strony kreatora wybierz opcję: Stwórz nowy projekt,
  • wybierz Nowy szablon,
  • w prawym górnym rogu wybierz opcję Importuj szablon,
  • następnie zaimportuj plik z szablonem, który ma być zaktualizowany. Po poprawnym zaimportowaniu szablonu otrzymasz informację zwrotną:
  • po wgraniu szablonu do aktualizacji użyj opcji Generuj. 
Dzięki temu w prosty sposób można starsze szablony Topaz podnieść do wersji aktualnej.

Więcej informacji

Więcej informacji można znaleźć w artykułach o wyglądzie sklepu oraz o dostosowaniu wyglądu.

Posiadam gotowy szablon Comarch. Jak mogę go dostosować do kryteriów WCAG 2.1/2.2?

Wstęp

Z dniem 28 czerwca 2025 roku w życie wejdą przepisy związane z implementacją ustawy z dnia 26 kwietnia 2024 r. o zapewnianiu spełniania wymagań dostępności niektórych produktów i usług. Wdraża ona do polskiego prawa tzw. Europejski Akt o Dostępności (EAA) – unijną dyrektywę 2019/882. Celem ustawy jest zapewnienie, że kluczowe produkty i usługi będą dostępne dla wszystkich użytkowników, w tym osób z niepełnosprawnościami. Przedsiębiorcy mają czas do 28 czerwca 2025 roku, aby dostosować swoje produkty i usługi do nowych wymogów.
Wskazówka
Chcesz dowiedzieć się więcej o tych przepisach? Sprawdź artykuł w naszym Centrum Pomocy: Europejski Akt o Dostępności (EAA) i zapoznaj się ze szczegółami
W niniejszym artykule wskazujemy, jakie czynności należy wykonać, jeśli posiadasz jeden ze standardowych szablonów Comarch, czyli: Rubin, Szafir, Topaz, One Page Shop lub Dla Gastronomii.   

Sprawdź, jaki szablon posiadasz

Nie wiesz, który szablon posiadasz? Możesz to sprawdzić w panelu administracyjnym Comarch e-Sklep. Aby to zrobić, z poziomu panelu administracyjnego przejdź do zakładki Wygląd sklepu/ Ustawienia a następnie, pod przyciskiem "Więcej" wybierz Edytuj ustawienia zaawansowane. W obszarze, który został wyświetlony, pojawi się kilka zakładek, a wśród nich zakładka "Szablon". Wybierz ją, po czym sprawdź szablon:   Jeśli Twój szablon to Rubin, Szafir, Topaz, One Page Shop lub Dla Gastronomii, to możesz przejść do kolejnej części artykułu. Jeśli posiadasz własny szablon z indywidualnymi modyfikacjami, to przejdź do artykułu: Posiadam własny szablon, jak mogę go dostosować do kryteriów WCAG 2.1/2.2?  Jeśli posiadasz szablon Bursztyn, Agat lub Opal, to przejdź do artykułu: Posiadam szablon Bursztyn, Opal lub Agat, jak mogę go dostosować do kryteriów WCAG 2.1/2.2?  

Co zrobić jako właściciel e-Sklepu lub Partner, jeśli używam gotowych szablonów Comarch?

Jako właściciel e-Sklepu lub Partner Comarch zadbaj, aby zadbać o dostosowanie swojej witryny do obowiązujących przepisów. Nowe wymogi to wspólna odpowiedzialność:
  • Comarch e-Sklep – zajmiemy się kwestiami technicznymi w przypadku Gotowych Szablonów Comarch, do których należą m.in. zmiany w kodzie,
  • Właściciel, administrator lub Partner sklepu – musisz zadbać o treści i elementy, które dodajesz samodzielnie. Chodzi tu głównie opis produktów, zdjęcia i grafiki czy identyfikację wizualną. 
 

Jak zacząć?

Jeśli korzystasz z gotowych szablonów, takich jak Rubin, Szafir, Topaz, One Page Shop lub Dla Gastronomii, nie musisz przejmować się samodzielnym edytowaniem ich kodu. Wszystkie usprawnienia zostaną udostępnione wraz z aktualizacją, która pojawi się w czerwcu 2025 roku.

Aktualizacja szablonu

Wskazówka
Aktualizację szablonu wykonaj wtedy, kiedy będzie ona dostępna. Realizacja wersji 2025.4 przewidywana jest przed 28 czerwca 2025 roku, poinformujemy o niej w aktualnościach. Będzie ona zawierała zmiany związane z omawianymi tutaj przepisami.

Jak zaktualizować szablon?

Aby zaktualizować szablon i przejść na Topaz, One Page Shop, Dla Gastronomii, Rubin lub Szafir, należy skorzystać z aktualnej wersji Kreatora Wyglądu. Pamiętaj, że szablony Rubin i Szafir przeznaczone są tylko dla sklepów Enterprise i B2B. Odnośnik znajduje się również w panelu administracyjnym e-Sklepu w sekcji Wygląd sklepu > Kreator wyglądu.  Istnieją trzy możliwości aktualizacji tych szablonów:
  • Wygenerowanie zupełnie nowego szablonu w Kreatorze Wyglądu oraz wgranie go do e-Sklepu,
  • Wybór i edycja jednego z gotowych układów i jego modyfikacja,
  • Import posiadanego szablonu do Kreatora Wyglądu oraz ponowne wygenerowanie go w najnowszej wersji.
Wygenerowany z Kreatora Wyglądu szablon należy wgrać do e-Sklepu. W panelu administracyjnym e-Sklepu, w sekcji Wygląd sklepu znajduje się bezpośredni odnośnik do importu szablonu z Kreatora wyglądu. Szczegółowa instrukcja dostępna jest w artykule Jak wyeksportować i zaimportować swój szablon w e-Sklepie?
Pamiętaj o zapisaniu szablonu oraz opublikowaniu go w e-Sklepie. Zmiany wprowadzone w ustawieniach zostaną zsynchronizowane do sklepu po 10 minutach.
Wskazówka
Informacje na temat aktualizacji znajdują się w Centrum Pomocy: Jak zaktualizować szablon do najnowszej wersji?  
Więcej informacji na temat Kreatora Wyglądu B2C oraz B2B znajduje się w Centrum Pomocy:

Odpowiedni kontrast kolorów w e-Sklepie – wymóg WCAG na poziomie AA

Jednym z głównych wymogów WCAG jest stosowanie odpowiednich kontrastów na stronach internetowych. Jeśli w wybranym szablonie graficznym wykorzystujesz któryś ze standardowych motywów kolorystycznych dostępnych w kreatorach, to zostaną one dostosowane do wymagań wynikających z przepisów. Jeśli natomiast masz przygotowany własny motyw kolorystyczny lub chcesz zmienić część kolorów zastosowanych w szablonie, to pamiętaj, że muszą one posiadać odpowiednie kontrasty. Wszelkich zmian kolorystycznych możesz dokonać w Kreatorze Wyglądu.  Odpowiedni kontrast między tekstem a tłem jest kluczowy dla osób z dysfunkcjami wzroku. WCAG 2.1 określa minimalny współczynnik kontrastu (4.5:1 dla tekstu zwykłego i 3:1 dla tekstu dużego). Ważne jest również unikanie łączenia kolorów, które mogą być trudne do rozróżnienia, takich jak czerwony i zielony. Kontrasty po modyfikacji kolorów możesz sprawdzić np. narzędziem WAVE. WAVE to popularny, dostępny dla wszystkich zestaw narzędzi do oceny dostępności stron internetowych. Rozszerzenia WAVE dla Chrome, Firefox i Edge, umożliwiają testowanie bezpośrednio w tych przeglądarkach, bez przesyłania danych na serwer WAVE. WAVE znajdziesz pod linkiem: WAVE Web Accessibility Evaluation Tools.  

Jak sprawdzić kontrast?

Przejdź na stronę swojego e-Sklepu. Włącz wtyczkę WAVE. Po prawej stronie ekranu wyświetli się panel boczny, na pierwszej zakładce widać podsumowanie całej strony: Już na tym etapie możesz przejść do szczegółów, klikając "View details". Możesz w tym miejscu przejść także do zakładki "Contrast".   Czerwone kwadraty oznaczają obszar do poprawy. Przejdź przez stronę, aby zobaczyć szczegóły każdego z nich. Po kliknięciu na jeden z kwadratów pokaże się komunikat dotyczący kontrastu: W panelu bocznym pojawi się dokładna informacja na temat koloru. W tym miejscu, korzystając z suwaków możesz od razu dostosować kolor tak, aby był odpowiedni i sprawdzić, czy spełnia wymagania WCAG.  

Gdzie dostosować kolory?

Kolory w szablonie możesz zmienić korzystając z Kreatora Wyglądu. Po imporcie szablonu, edycji lub stworzeniu nowego projektu, przejdź do zakładki "Style" i edytuj motyw kolorystyczny:   Następnie możesz zmieniać swobodnie kolor na wybranych elementach:   Zmian możesz dokonać także z poziomu panelu administracyjnego, przechodząc do zakładki Wygląd Sklepu > Ustawienia.

Pozostałe zmiany

Poza zmianami w szablonie graficznym sklepu należy uzupełnić szereg danych. Znaczącą część tych elementów możesz wykonać już teraz, nie czekając na aktualizację Comarch e-Sklep. Poniżej znajduje się lista zmian, które należy wdrożyć w swoim e-Sklepie.

Teksty alternatywne ("Alt", alty) w Comarch e-Sklep

Twój szablon musi obsługiwać parametr "alt" w obrazkach. Jeśli wykorzystasz aktualny szablon standardowy od Comarch to obsługę zapewnia Comarch e-Sklep, jeśli zdecydowałeś się na indywidualny szablon lub samodzielną aktualizację starszej wersji to upewnij się, że w szablonie są obsługiwane parametry "alt" we wskazanych elementach. Teksty alternatywne („alt”) to krótkie opisy obrazków, które pozwalają osobom korzystającym z czytników ekranu zrozumieć, co znajduje się na zdjęciu. Atrybut „alt” jest szczególnie ważny dla zdjęć produktów, ponieważ umożliwia przekazanie najważniejszych informacji o produktach.  Dlaczego tekst alternatywny jest taki ważny? 
  • Pomaga osobom korzystającym z czytników ekranu, które odczytują tekst alternatywny na głos,
  • Poprawia dostępność stron internetowych, czyniąc je bardziej przyjaznymi dla wszystkich użytkowników,
  • Wpływa na pozycjonowanie w wyszukiwarkach, ponieważ dobrze opisane obrazy są lepiej interpretowane przez algorytmy Google.   
Dobrze sformułowany opis powinien być zwięzły, ale wystarczająco informacyjny. Poniżej prezentujemy przykłady dobrego i złego zastosowania opisów alternatywnych:
Przyklad
Poprawne :
  • Czerwona sukienka maxi z rozcięciem, modelka na tle miejskiego pejzażu.
  • Białe sneakersy z grubą podeszwą, ustawione na drewnianej podłodze.
  • Nowoczesna sofa w kolorze szarym, z drewnianymi nogami, ustawiona w minimalistycznym salonie.
  • Słuchawki bezprzewodowe z aktywną redukcją szumów, na białym tle.
Niepoprawne:
  • Sukienka.
  • Buty sportowe.
  • Fajna kanapa.
  • Najlepszy sprzęt w dobrej cenie!

Gdzie należy uzupełnić teksty alternatywne (alt)?

1. Dla zdjęć towarów w systemach Comarch ERP

Korzystam z Comarch ERP Optima
Po uruchomieniu Comarch ERP Optima przejdź na pozycję cennika, a następnie edytuj wybrany towar. Następnie przejdź na zakładkę "Atrybuty", a następnie do sekcji "Zdjęcia i załączniki". W tym miejscu zobaczysz kolumnę "Atrybut Alt".
Po dwukrotnym kliknięciu możliwe jest uzupełnienie opisu alternatywnego: Po dokonaniu zmian należy je zapisać. Po wykonaniu wszystkich modyfikacji należy wykonać synchronizację.

Korzystam z Comarch ERP XL

Po uruchomieniu ERP XL przejdź do Sprzedaż > Towary , a następnie na zakładkę "Załączniki". Opis alternatywny dla towaru stanowi Kod:    
Korzystam z Comarch ERP XT
Przejdź na kartę produktu, a następnie do zakładki "Zdjęcia". Wśród pól do uzupełnienia znajdziesz "Opis alternatywny (Alt)".   W tym miejscu wpisz odpowiednią treść, a następnie zapisz wprowadzone zmiany.  

2. Dla zdjęć w bannerach – w panelu administracyjnym Comarch e-Sklep

Pamiętaj, alby alty (opisy alternatywne) były uzupełnione także w przypadku bannerów. Aby to zrobić, przejdź z poziomu panelu administracyjnego do Wygląd sklepu > Ustawienia > Bannery  do edycji swoich bannerów. Klikając na odpowiedni kafelek pojawią się opcje z uzupełnieniem Alt:

3. Dla zdjęć stosowanych na stronach z treściami formalnymi – w panelu administracyjnym Comarch e-Sklep

Obrazki możesz dodawać także do treści, które udostępniasz na specjalnych stronach, takich jak np. Regulamin sklepu, Polityka prywatności, Wysyłka itp. W obszarze do edycji, który jest dostępny z poziomu panelu administracyjnego w sekcji Ustawienia > Treści formalne edytuj interesującą Cię treść, a dodając obrazek uzupełnij alt:    

4. Dla zdjęć wprowadzonych w opisie towaru i opisie kategorii

Dodając opisy produktów i kategorii, warto upewnić się, że linkowane zdjęcia zawierają poprawnie uzupełniony atrybut "alt". To kluczowe dla osób korzystających z czytników ekranu. Dbałość o ten detal poprawia dostępność strony i zwiększa jej widoczność w sieci. Opis towaru i kategorii możesz dodać w systemach Comarch ERP.  Opis kategorii możesz ustawić również z poziomu panelu administracyjnego, bez konieczności korzystania z systemu ERP. Szczegółowe informacje znajdują się w artykule: Jak edytować kategorię w Comarch e-Sklep? 

5. Dla zdjęć w Blogu

Obrazki, które dodawane są dla wpisów blogowych od wersji 2025.4 będą posiadały atrybuty ALT oraz Title. Ich uzupełnienie będzie możliwe przy przejściu z poziomu panelu administracyjnego Comarch e-Sklep do sekcji Marketing > Blog przy dodawaniu wpisu:

6. Dla zdjęć w plikach użytkownika w sekcji "Twoje pliki"

Pliki użytkownika w e-Sklepie to dedykowana przestrzeń do przechowywania własnych materiałów, które mogą zostać wykorzystane w sklepie internetowym. Pliki można przesyłać za pośrednictwem panelu administracyjnego, w sekcji Ustawienia > Twoje pliki. Maksymalny rozmiar pojedynczego pliku: 3 MB. Pliki, które dodawane są we wspomnianym obszarze, od wersji 2025.4 będą posiadały atrybuty ALT oraz Title. Ich uzupełnienie będzie możliwe przy przejściu z poziomu panelu administracyjnego do sekcji Ustawienia > Twoje pliki przy edycji pliku lub jego dodaniu.
Wskazówka
Jeśli posiadasz sklep wielojęzyczny, to we wszystkich tych wymienionych powyżej obszarach, znajdują się również obrazki dla danego języka. Pamiętaj, alby atrybut ALT zdefiniować dla każdego z nich!
 

Atrybut title - obowiązkowy czy nie?

Atrybut title jest przydatny do przekazywania dodatkowych informacji o elementach HTML, widocznych jako podpowiedź po najechaniu kursorem. Może być używany w ikonach bez podpisu, formularzach czy linkach, aby dostarczyć kontekst. Nie jest jednak obowiązkowy według WCAG, ponieważ czytniki ekranu często go ignorują, a osoby nawigujące klawiaturą mogą nie mieć do niego dostępu.  

Zalecenia dla udostępnianych treści - ogranicz migające elementy

Jako właściciel sklepu musisz sam zadbać o to, jakie treści umieszczasz na swojej stronie. Migające elementy, takie jak animacje czy reklamy, mogą wywoływać problemy u osób z padaczką fotogenną. Według kryteriów WCAG 2.1 zalecane jest ograniczenie migających treści do maksymalnie trzech błysków na sekundę lub ich całkowite usunięcie. Jako właściciel sklepu musisz dbać o statyczne elementy lub spokojne animacje. Również treści zawarte w różnego typu prospektach, gazetkach czy folderach informacyjnych w formie dokumentów powinny być zgodne z wytycznymi WCAG.

1.Obrazki i bannery

W szablonach graficznych takie elementy mogą pojawić się na przykład w bannerach i elementach tekstowych ze zdjęciem. Upewnij się, że grafiki tam zamieszczone są odpowiednie, czyli bez intensywnych animacji i nieodpowiednich kolorów. Szczególną uwagę zwróć na pliki w formacie GIF. Sprawdź, w jaki sposób możesz skonfigurować bannery oraz elementy tekstowe ze zdjęciem.  

2.Materiały audio i viedo

Aby sklep internetowy był w pełni dostępny zgodnie z WCAG, właściciele muszą zadbać o dodanie audiodeskrypcji i transkrypcji do materiałów multimedialnych (filmy, nagrania dźwiękowe). Choć oba rozwiązania służą poprawie dostępności, mają różne funkcje.
  • Audiodeskrypcja to dodatkowy opis dźwiękowy, który przedstawia istotne elementy wizualne nagrania osobom niewidzącym,
  • Transkrypcja to zapis tekstowy całej treści audio, umożliwiający odbiór treści osobom niesłyszącym, może to być w formie napisów dla audiodeskrypcji.
Dodanie tych elementów leży po stronie właścicieli sklepów. Do filmów, które udostępniasz, dodaj zatem widoczne napisy, a także dobrej jakości opis dźwiękowy. Ich brak może wykluczyć część użytkowników i wpłynąć na komfort korzystania ze strony. Dobre praktyki dostępności to nie tylko wymóg, ale też inwestycja w lepsze doświadczenie klientów.

Dostosuj komunikację mailową - aktualizacja lub zmiana treści e-mail

Dostosowanie treści e-mail zgodnie z wytycznymi WCAG to kluczowy krok w budowaniu dostępnej i klarownej komunikacji. W tej części artykułu przedstawiamy rozwiązania zarówno dla domyślnych wiadomości, jak i tych modyfikowanych, aby zapewnić ich lepszą czytelność i dostępność dla wszystkich odbiorców.

1.Treści mailowe są domyślne, nie zostały sformatowane

Jeśli treści nie zostały przez Ciebie zmienione i stanowią domyślne treści, które są dostępne w Comarch e-Sklep, to wystarczy, że zaktualizujesz je. Aby to zrobić, należy przejść w panelu administracyjnym do zakładki Ustawienia > Treści formalne, a następnie wybrać „Wysyłka e-mail i SMS”. Zakładka ta zawiera treści wiadomości wysyłane do klientów po wykonaniu określonych akcji, np. po zakupie czy rejestracji. W Comarch e-Sklep istnieje możliwość przywrócenia standardowej treści pojedynczej wiadomości e-mail lub wszystkich jednocześnie. Opcja ta stanowi również aktualizację treści e-mail. "Przywróć domyślną treść" dostępna jest w panelu administracyjnym e-Sklepu w menu Ustawienia/ Treści formalne/ Wysyłka e-mail i SMS na szczegółach każdej wiadomości, po kliknięciu w przycisk Więcej:  

2.Treści mailowe są modyfikowane, zostały przeze mnie zmienione

Jeśli posiadasz własne, dostosowane do Twojej komunikacji marketingowej treści e-mail, to sprawdź, czy są one odpowiednio napisane i sformatowane. Zastosuj się do poniższych wskazówek. W jaki sposób poprawnie napisać i sformatować treści?
  • Struktura Stosuj nagłówki (<h1>, <h2> itd.) dla przejrzystości. Używaj krótkich akapitów i list punktowanych.
  • Tekst i formatowanie Zapewnij wysoki kontrast między tekstem a tłem. Wybieraj czytelne czcionki (sans-serif, min. 12-14 px). Nie używaj wyłącznie koloru do przekazywania informacji.
  • Obrazy i multimedia Dodawaj tekst alternatywny (alt text) do obrazów. Unikaj tekstu osadzonego w grafikach, jeśli można go przesłać jako tekst.
  • Linki i przyciski Stosuj opisowe teksty linków zamiast „Kliknij tutaj”. Upewnij się, że są łatwe do kliknięcia na ekranach dotykowych.
  • Język i czytelność Używaj prostego i zrozumiałego języka. Unikaj skrótów i branżowego żargonu, jeśli odbiorca może ich nie znać.
  • Testowanie Sprawdź wiadomość na różnych urządzeniach i czytnikach ekranu. Zweryfikuj zgodność ze standardami WCAG.
Szczegółowe informacje na temat edycji treści e-mail znajdują się a artykule: E-mail i SMS  

3.Załączniki (m.in. instrukcje, katalogi)

Należy zadbać o to, aby wszystkie udostępniane w sklepie załączniki, takie jak instrukcje czy katalogi, były zgodne z wytycznymi WCAG, zapewniając tym samym ich pełną dostępność dla wszystkich użytkowników.  

Dodatkowe narzędzia pomocne przy wdrażaniu WCAG

Przystosowanie e-Sklepu do wymogów nie musi wiązać się z dużymi wydatkami na zmiany w kodzie. Kluczowe aspekty dostępności można wdrożyć samodzielnie, wykorzystując opcje dostępne w systemach Comarch ERP, a także Kreatorze Wyglądu czy Panelu Administracyjnym. Warto pamiętać, że poprawa dostępności to nie tylko obowiązek wynikający z przepisów, ale także realna szansa na zwiększenie grona klientów oraz podniesienie komfortu ich zakupów. Istnieje kilka ogólnodostępnych narzędzi, które pomogą Ci dostosować sklep do wymogów. Obszerna lista narzędzi do oceny dostępności stron internetowych, zgodnych z WCAG znajduje się na stronie: Web Accessibility Evaluation Tools List .  

Podsumowanie

Dostępność cyfrowa to nie jednorazowe przedsięwzięcie, lecz ciągły rozwój i udoskonalanie. Regularne sprawdzanie funkcjonalności, optymalizacja elementów wizualnych i dostosowywanie sposobów interakcji pozwalają na stałe podnoszenie jakości doświadczeń użytkowników. Dążenie do pełnej zgodności ze standardami WCAG 2.1/2.2 oraz wymogami Europejskiego Aktu o Dostępności (EAA) nie tylko ułatwia nawigację wszystkim odwiedzającym, ale także buduje pozytywny wizerunek i wzmacnia pozycję na rynku. Wdrażanie kolejnych usprawnień to inwestycja w przyszłość, która przynosi korzyści zarówno właścicielom, jak i ich klientom.

Instrukcja: Jak dostosować samodzielnie szablon do szybkich zwrotów w e-Commerce?

Wskazówka
Wskazówka: W tym artykule trzeba będzie wprowadzać zmiany w plikach js oraz scss. Z tego artykułu dowiesz się jak je kompilować i minifikować.
W szablonach Rubin, Szafir oraz Topaz / One Page Shop wprowadziliśmy funkcjonalność szybkich zwrotów. Umożliwia ona klientom składanie wniosku o zwrot produktu zarówno z poziomu profilu klienta (zalogowani), jak i z dedykowanej strony zwrotów po podaniu numeru zamówienia oraz adresu e-mail (niezalogowani). Wraz z funkcjonalnością pojawił się m.in. rozbudowany ekran potwierdzenia zwrotu zawierający kolejne kroki i adres do wysyłki, banery informacyjne dotyczące terminu zwrotu oraz przyciski akcji w tabeli produktów wyświetlane bezpośrednio (zamiast w rozwijanym menu). Aby Twój szablon poprawnie obsługiwał te zmiany, wprowadź modyfikacje opisane poniżej w sekcji dotyczącej Twojego szablonu. Po zakończeniu edycji pamiętaj o kompilacji i minifikacji plików js oraz scss.
Wskazówka
Potrzebujesz pomocy lub masz pytania? Skontaktuj się z nami poprzez portal asysta.comarch.pl.
Wskazówka
Obecnie w Polsce trwają prace nad ostatecznym kształtem przepisów oraz nowelizacją Ustawy o prawach konsumenta, która wdroży unijną dyrektywę UE 2023/2673 i wprowadzi nowe wymagania techniczne dla platform e-commerce (m.in. ułatwienia w procedurze zwrotów). W momencie publikacji ostatecznej wersji polskich przepisów, wdrożone funkcjonalności mogą wymagać dostosowania do ostatecznych wytycznych ustawodawcy. Prezentowane informacje mają charakter poglądowy a instrukcja dotyczy zmian, jakie wprowadziliśmy w szablonach Comarch – w przypadku pytań dotyczących indywidualnej sytuacji prawnej Twojego sklepu, zalecamy konsultację z radcą prawnym lub adwokatem.

Szablon Rubin

1. Tłumaczenia

W panelu administracyjnym sklepu zaktualizuj dwa istniejące tłumaczenia oraz dodaj nowe klucze wymagane przez funkcjonalność szybkich zwrotów. Zaktualizuj poniższe istniejące tłumaczenia: ReturnSuccessTitle - PL: Gotowe! Przyjęliśmy Twoje zgłoszenie - EN: Done! We have received your request - DE: Fertig! Wir haben Ihre Anfrage erhalten - FR: C'est fait ! Nous avons reçu votre demande ReturnSuccessInfo - PL: Przygotuj paczkę i odeślij ją do nas – wszystkie szczegóły znajdziesz poniżej. - EN: Prepare the package and send it back to us – all the details are below. - DE: Bereiten Sie das Paket vor und senden Sie es an uns zurück – alle Details finden Sie unten. - FR: Préparez le colis et renvoyez-le nous – tous les détails sont ci-dessous. Dodaj nowe tłumaczenia: OrderReturnDeadlineInfo - PL: Zamówienie można zwrócić w ciągu {0} dni od daty dostawy. - EN: You can return the order within {0} days from the delivery date. - DE: Sie können die Bestellung innerhalb von {0} Tagen ab Lieferdatum zurückgeben. - FR: Vous pouvez retourner la commande dans les {0} jours suivant la date de livraison. RestrictedOrderViewInfo - PL: Wybrane dane zamówienia zostały ukryte ze względów bezpieczeństwa. Możesz zwrócić produkty bez logowania. - EN: Some order details are hidden for security reasons. You can return products without signing in. - DE: Einige Bestelldetails wurden aus Sicherheitsgründen ausgeblendet. Sie können Produkte ohne Anmeldung zurücksenden. - FR: Certaines informations de la commande ont été masquées pour des raisons de sécurité. Vous pouvez retourner des produits sans vous connecter. Com_RefundMethod - PL: Sposób zwrotu środków - EN: Refund method - DE: Rückerstattungsmethode - FR: Mode de remboursement Com_RefundAsPaid - PL: Tak jak zapłacono - EN: Same as paid - DE: Wie bezahlt - FR: Comme payé Com_RefundToBankAccount - PL: Na konto bankowe - EN: To bank account - DE: Auf Bankkonto - FR: Sur le compte bancaire Com_BankAccountNumber - PL: Nr konta bankowego - EN: Bank account number - DE: Bankkontonummer - FR: Numéro de compte bancaire Com_ConfirmationSentTo - PL: Potwierdzenie zwrotu zostało wysłane na adres: - EN: Return confirmation has been sent to: - DE: Bestätigung wurde gesendet an: - FR: La confirmation de retour a été envoyée à: Com_NextSteps - PL: Następne kroki - EN: Next Steps - DE: Nächste Schritte - FR: Prochaines étapes Com_PackProducts - PL: Bezpiecznie zapakuj swoje produkty - EN: Safely pack your products - DE: Verpacken Sie Ihre Produkte sicher - FR: Emballez vos produits en toute sécurité Com_SendPackageTo - PL: Wyślij paczkę na adres: - EN: Send the package to the address: - DE: Senden Sie das Paket an die Adresse: - FR: Envoyez le colis à l'adresse: Com_RefundAfterReceive - PL: Pieniądze zwrócimy niezwłocznie po otrzymaniu i sprawdzeniu Twojej paczki - EN: We will refund the money promptly upon receipt and inspection of your package - DE: Wir erstatten das Geld umgehend nach Erhalt und Überprüfung Ihres Pakets zurück - FR: Nous rembourserons l'argent rapidement après réception et inspection de votre colis ReturnInThreeSteps - PL: Zwróć towar w 3 krokach - EN: Return the product in 3 steps - DE: Geben Sie die Ware in 3 Schritten zurück - FR: Retournez la marchandise en 3 étapes ReturnWithoutReasonInfo - PL: Przysługuje Ci możliwość zwrotu bez podania przyczyny. - EN: You have the right to return the product without giving a reason. - DE: Sie haben das Recht, die Ware ohne Angabe von Gründen zurückzugeben. - FR: Vous avez le droit de retourner la marchandise sans donner de motif. OrEnterOrderNumber - PL: lub podaj numer zamówienia - EN: or enter the order number - DE: oder geben Sie die Bestellnummer ein - FR: ou saisissez le numéro de commande FillForm - PL: Wypełnij formularz - EN: Fill out the form - DE: Füllen Sie das Formular aus - FR: Remplissez le formulaire ReturnOnline - PL: zwrotu online - EN: online return - DE: Online-Rückgabe - FR: retour en ligne SendParcel - PL: Wyślij paczkę - EN: Send the parcel - DE: Paket senden - FR: Envoyer le colis SendParcelToOurAddress - PL: nadaj przesyłkę na nasz adres - EN: send the parcel to our address - DE: senden Sie das Paket an unsere Adresse - FR: envoyez le colis à notre adresse FastSimpleSecure - PL: Szybko, prosto i bezpiecznie. - EN: Fast, simple and secure. - DE: Schnell, einfach und sicher. - FR: Rapide, simple et sécurisé. ReadyForReturn - PL: Gotowy do zwrotu? - EN: Ready for return? - DE: Bereit zur Rückgabe? - FR: Prêt pour le retour ? ReadyForReturnInfo - PL: Kliknij poniżej, aby rozpocząć proces zwrotu. Przeprowadzimy Cię przez wszystkie kroki. - EN: Click below to start the return process. We will guide you through all the steps. - DE: Klicken Sie unten, um den Rückgabeprozess zu starten. Wir führen Sie durch alle Schritte. - FR: Cliquez ci-dessous pour lancer le processus de retour. Nous vous guiderons à travers toutes les étapes. StartReturn - PL: Rozpocznij zwrot - EN: Start return - DE: Rückgabe starten - FR: Commencer le retour ProductReturn - PL: Zwrot produktu - EN: Product return - DE: Produktrückgabe - FR: Retour du produit ProductReturnFormInfo - PL: Wprowadź dane zamówienia, aby zlokalizować zakup i rozpocząć proces zwrotu. Numer zamówienia znajdziesz w e-mailu z potwierdzeniem. - EN: Enter the order details to locate the purchase and start the return process. You will find the order number in the confirmation e-mail. - DE: Geben Sie die Bestelldaten ein, um den Kauf zu lokalisieren und den Rückgabeprozess zu starten. Die Bestellnummer finden Sie in der Bestätigungs-E-Mail. - FR: Saisissez les données de la commande pour localiser l'achat et démarrer le processus de retour. Vous trouverez le numéro de commande dans l'e-mail de confirmation. InvalidOrderNumber - PL: Błędny numer zamówienia. Spróbuj ponownie. - EN: Invalid order number. Please try again. - DE: Ungültige Bestellnummer. Bitte versuchen Sie es erneut. - FR: Numéro de commande incorrect. Veuillez réessayer. FindOrder - PL: Znajdź zamówienie - EN: Find order - DE: Bestellung finden - FR: Trouver la commande LoginToSeeOrdersAndReturn - PL: aby zobaczyć swoje zamówienia i dokonać zwrotu. - EN: to see your orders and make a return. - DE: um Ihre Bestellungen einzusehen und eine Rückgabe vorzunehmen. - FR: pour voir vos commandes et effectuer un retour. RefundLookupError - PL: Wystąpił błąd podczas wyszukiwania zamówienia. Spróbuj ponownie później. - EN: An error occurred while searching for the order. Please try again later. - DE: Bei der Suche nach der Bestellung ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut. - FR: Une erreur s'est produite lors de la recherche de la commande. Veuillez réessayer plus tard.

2. Nowa strona Szybkie zwroty

Funkcjonalność szybkich zwrotów wymaga utworzenia dodatkowej strony statycznej refunds. Wykonaj poniższe kroki.

Plik refunds.html w katalogu głównym szablonu

W katalogu głównym szablonu utwórz nowy plik refunds.html z następującą zawartością: {% extends '_layout.html' -%} {% block pageContent -%} {% include 'static-elements/refunds/refunds.html' -%} {% endblock -%}

Plik static-elements/refunds/refunds.html

W folderze static-elements utwórz nowy katalog refunds, a w nim plik refunds.html: <div class="page-padding"> <h1 class="refunds-page-title refunds-initial-view-js">{{ translations.Returns }}</h1> <section class="refunds-container refunds-initial-view-js"> <div class="refunds-info"> <h2 class="refunds-info__title">{{ translations.ReturnInThreeSteps }}</h2> <p class="refunds-info__intro">{{ translations.ReturnWithoutReasonInfo }}</p> <ol class="refunds-steps"> <li class="refunds-steps__item"> <span class="refunds-steps__number">1</span> <p class="refunds-steps__text"><strong>{{ translations.LogIn }}</strong> {{ translations.OrEnterOrderNumber }}</p> </li> <li class="refunds-steps__item"> <span class="refunds-steps__number">2</span> <p class="refunds-steps__text"><strong>{{ translations.FillForm }}</strong> {{ translations.ReturnOnline }}</p> </li> <li class="refunds-steps__item"> <span class="refunds-steps__number">3</span> <p class="refunds-steps__text"><strong>{{ translations.SendParcel }}</strong> - {{ translations.SendParcelToOurAddress }}</p> </li> </ol> <p class="refunds-info__hint">{{ translations.FastSimpleSecure }}</p> </div> <div class="refunds-cta"> <div class="refunds-cta__header"> <h3 class="refunds-cta__title">{{ translations.ReadyForReturn }}</h3> <p class="refunds-cta__description">{{ translations.ReadyForReturnInfo }}</p> </div> {% if usr.Authenticated -%} <a href="{{ config.DefinedPages.CustomerProfile.Url }}?tab=orders" class="primary-action-button refunds-cta__button" rel="nofollow" aria-label="{{ translations.StartReturn }}"> {{ translations.StartReturn }} </a> {% else -%} <button type="button" class="primary-action-button refunds-cta__button start-refund-js" aria-label="{{ translations.StartReturn }}"> {{ translations.StartReturn }} </button> {% endif -%} </div> </section> {% unless usr.Authenticated -%} <section class="refund-form-section refund-form-view-js hidden-js"> <div class="refund-form"> <div class="refund-form__header"> <h2 class="refund-form__title">{{ translations.ProductReturn }}</h2> <p class="refund-form__description">{{ translations.ProductReturnFormInfo }}</p> </div> <form class="refund-form__body refund-form-js" novalidate data-error="{{ translations.RefundLookupError }}"> <div class="form__input-wrapper"> <label for="refundOrderNumber" class="form__input-info input-info-js">{{ translations.NumberOfOrder }}</label> <input id="refundOrderNumber" type="text" name="orderNumber" class="form__input-value input-value-js" maxlength="50" required> <div class="form__invalid-input validation-info-js validation-required-js hidden-js">{{ translations.FieldRequired }}</div> </div> <div class="form__input-wrapper"> <label for="refundEmail" data-type="email" class="form__input-info input-info-js">{{ translations.EmailAddress }}</label> <input id="refundEmail" type="email" name="email" class="form__input-value input-value-js" maxlength="192" autocomplete="email" required> <div class="form__invalid-input validation-info-js validation-required-js hidden-js">{{ translations.FieldRequired }}</div> <div class="form__invalid-input validation-info-js email-valid-js hidden-js">{{ translations.FillProperEmail }}</div> </div> <button type="button" class="primary-action-button refund-form__submit refund-form-submit-js"> {{ translations.FindOrder }} </button> <p class="refund-form__login-info"> {{ translations.HaveAccount }} <a class="refund-form__login-link show-login-popup-js" rel="nofollow" tabindex="0" role="button">{{ translations.LogIn }},</a> {{ translations.LoginToSeeOrdersAndReturn }} </p> </form> </div> </section> {% endunless -%} </div>

Plik js/layout1.js – kod obsługi formularza zwrotu

Na końcu pliku js/layout1.js dodaj poniższy kod odpowiedzialny za walidację i wysłanie formularza wyszukiwania zamówienia (dla niezalogowanego klienta): $(document).ready(function() { refunds.init(); }); const refunds = { init: function() { this.events(); }, findRefundOrder: function(orderNumber, email) { return $.post('', { __action: 'Order/QuickReturnLookup', orderId: orderNumber, email: email, __csrf: __CSRF }); }, showForm: function() { $('.refunds-initial-view-js').addClass('hidden-js'); $('.refund-form-view-js').removeClass('hidden-js'); $('.refund-form-js input[name="orderNumber"]').trigger('focus'); }, clearFieldError: function(input) { const $input = $(input); $input.removeClass('validation-error-js'); $input.closest('.form__input-wrapper').find('.form__invalid-input').addClass('hidden-js'); }, submitForm: async function(button) { const $submit = $(button); const $form = $submit.closest('.refund-form-js'); const $orderInput = $form.find('input[name="orderNumber"]'); const $emailInput = $form.find('input[name="email"]'); const orderValue = $orderInput.val().trim(); const emailValue = $emailInput.val().trim(); const emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w{2,}$/; let hasError = false; $form.find('.form__invalid-input').addClass('hidden-js'); $form.find('.form__input-value').removeClass('validation-error-js'); if (orderValue.length === 0) { $orderInput.addClass('validation-error-js'); $orderInput.closest('.form__input-wrapper').find('.validation-required-js').removeClass('hidden-js'); hasError = true; } if (emailValue.length === 0) { $emailInput.addClass('validation-error-js'); $emailInput.closest('.form__input-wrapper').find('.validation-required-js').removeClass('hidden-js'); hasError = true; } else if (!emailRegex.test(emailValue)) { $emailInput.addClass('validation-error-js'); $emailInput.closest('.form__input-wrapper').find('.email-valid-js').removeClass('hidden-js'); hasError = true; } if (hasError) { return; } $submit.prop('disabled', true); try { const result = await refunds.findRefundOrder(orderValue, emailValue); const action = result.action; if (action.Redirect302) { globalThis.location.href = action.Redirect302; return; } app.temporaryPopupMessage(undefined, action.Message, action.Type); } catch (error) { console.error('Refund order lookup failed.', error); app.temporaryPopupMessage(undefined, $form.data('error'), 'err'); } finally { $submit.prop('disabled', false); } }, events: function() { $('body').on('click', '.start-refund-js', function() { refunds.showForm(); }); $('body').on('input', '.refund-form-js .form__input-value', function() { refunds.clearFieldError(this); }); $('body').on('click', '.refund-form-submit-js', function(e) { e.preventDefault(); refunds.submitForm(this); }); $('body').on('keydown', '.refund-form-js input', function(e) { if (e.key === 'Enter') { e.preventDefault(); $(this).closest('.refund-form-js').find('.refund-form-submit-js').trigger('click'); } }); } };

Pliki SCSS strony Szybkie zwroty

W folderze scss/static-elements utwórz nowy katalog refunds i umieść w nim trzy pliki: refunds-g.scss, refunds-m.scss i refunds-t.scss. scss/static-elements/refunds/refunds-g.scss: .refunds-page-title { margin: 0 0 24px; font-size: 24px; font-weight: 500; line-height: 32px; color: $primaryColorFont; } .refunds-container { display: flex; flex-direction: column; align-items: center; gap: 32px; margin-bottom: 32px; color: $primaryColorFont; } .refunds-info { align-self: flex-start; display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 800px; &__title { margin: 0; font-size: 20px; font-weight: 600; line-height: 28px; color: $primaryColorFont; } &__intro { margin: 0; font-size: 16px; font-weight: 500; line-height: 24px; color: $primaryColorFont; } &__hint { margin: 4px 0 0; font-size: 12px; font-weight: 400; line-height: 20px; color: $breadcrumbs; } } .refunds-steps { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; &__item { display: flex; align-items: center; gap: 12px; } &__number { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background-color: #f3f3f3; color: $primaryColor; font-size: 14px; font-weight: 600; line-height: 20px; } &__text { margin: 0; font-size: 14px; font-weight: 400; line-height: 22px; color: $primaryColorFont; strong { font-weight: 600; } } } .refunds-cta { box-sizing: border-box; width: 100%; max-width: 578px; padding: 40px; display: flex; flex-direction: column; align-items: center; gap: 24px; background-color: $bgColor; border: 1px solid $lightBorderColor; border-radius: 8px; &__header { display: flex; flex-direction: column; align-items: center; gap: 12px; width: 100%; } &__title { margin: 0; font-size: 24px; font-weight: 600; line-height: 32px; text-align: center; color: $primaryColorFont; } &__description { margin: 0; font-size: 16px; font-weight: 400; line-height: 24px; text-align: center; color: $breadcrumbs; } &__button { width: 100%; text-decoration: none; } } .refund-form-section { display: flex; justify-content: center; width: 100%; margin-bottom: 32px; } .refund-form { box-sizing: border-box; width: 100%; max-width: 578px; padding: 40px; background-color: $bgColor; border: 1px solid $lightBorderColor; border-radius: 8px; &__header { display: flex; flex-direction: column; gap: 12px; margin-bottom: 32px; } &__title { margin: 0; font-size: 24px; font-weight: 600; line-height: 32px; color: $primaryColorFont; } &__description { margin: 0; font-size: 14px; font-weight: 400; line-height: 20px; color: $breadcrumbs; } &__body { display: flex; flex-direction: column; } .form__input-wrapper { .form__input-value { &.validation-error-js { border-color: $dangerColor; color: $dangerColor; } } .form__invalid-input { position: static; display: block; margin: 4px 0 0; padding-left: 16px; text-align: left; color: $dangerColor; font-size: 12px; font-weight: 400; line-height: 16px; } } &__submit { width: 100%; margin-top: 4px; } &__login-info { margin: 16px 0 0; text-align: center; font-size: 14px; font-weight: 400; line-height: 20px; color: $primaryColorFont; } &__login-link { color: $primaryColor; font-weight: 600; cursor: pointer; text-decoration: none; &:hover { text-decoration: underline; } } } scss/static-elements/refunds/refunds-m.scss: @media screen and (max-width: 767px) { .refunds-page-title { font-size: 20px; line-height: 28px; margin-bottom: 16px; } .refunds-container { gap: 24px; margin-bottom: 24px; } .refunds-info { max-width: 100%; gap: 12px; &__title { font-size: 18px; line-height: 24px; } &__intro { font-size: 14px; line-height: 22px; } } .refunds-steps { &__item { align-items: flex-start; gap: 10px; } &__number { width: 28px; height: 28px; font-size: 13px; } &__text { font-size: 13px; line-height: 20px; padding-top: 3px; } } .refunds-cta { padding: 24px; &__title { font-size: 20px; line-height: 28px; } &__description { font-size: 14px; line-height: 22px; } } .refund-form { padding: 24px; &__header { margin-bottom: 24px; } &__title { font-size: 20px; line-height: 28px; } &__description { font-size: 13px; line-height: 18px; } &__login-info { font-size: 13px; } } } scss/static-elements/refunds/refunds-t.scss: @media screen and (min-width: 768px) and (max-width: 1439px) { .refunds-info { max-width: 100%; } }

3. Modyfikacje istniejących plików HTML

partials/cart/thx.html

W pliku partials/cart/thx.html znajdź fragment generujący etykietę zgody w sekcji zgód marketingowych: <label tabindex="0" role="checkbox" aria-checked="false" for="{{ consent.FieldValue }}" class="cart__tos-label tos-js"> Usuń z niego atrybut for="{{ consent.FieldValue }}". Po zmianie linia powinna wyglądać tak: <label tabindex="0" role="checkbox" aria-checked="false" class="cart__tos-label tos-js">

partials/common/login.html

1. W pliku partials/common/login.html w kontenerze opakowującym formularz dodaj klasę login-container-popup. Zamień linię: <div class="{% if page.PageId != config.DefinedPages.Login.Id and page.PageId != config.DefinedPages.CustomerProfile.Id and page.PageId != config.DefinedPages.Order.Id -%} login-popup-js{% else -%} login-container {% endif -%}"> na: <div class="{% if page.PageId != config.DefinedPages.Login.Id and page.PageId != config.DefinedPages.CustomerProfile.Id and page.PageId != config.DefinedPages.Order.Id -%} login-popup-js login-container-popup{% else -%} login-container {% endif -%}"> 2. W warunku otaczającym przycisk zamykający popup logowania usuń warunek and settings.signIn == "popup". Zamień linię: {% if page.PageId != config.DefinedPages.Login.Id and page.PageId != config.DefinedPages.CustomerProfile.Id and page.PageId != config.DefinedPages.Order.Id and settings.signIn == "popup" -%} na: {% if page.PageId != config.DefinedPages.Login.Id and page.PageId != config.DefinedPages.CustomerProfile.Id and page.PageId != config.DefinedPages.Order.Id -%}

partials/product/amount-stepper.html

W pliku partials/product/amount-stepper.html znajdź blok ustawiający zmienne dla typów complaint i return: {% if type == 'complaint' or type == 'return' -%} {% assign reloadClass = '' -%} {% assign complaintOrReturn = true -%} {% endif -%} i dodaj w jego wnętrzu nową linię ustawiającą maksymalną ilość produktu: {% if type == 'complaint' or type == 'return' -%} {% assign reloadClass = '' -%} {% assign complaintOrReturn = true -%} {% assign max = product.Quantity | Normalize -%} {% endif -%}

partials/order/products-partials/product-table-header.html

Na samym początku pliku partials/order/products-partials/product-table-header.html dodaj blok przypisujący flagę complaintsOrReturnsEnabled: {% if config.Complaints.ComplaintsEnabled or config.Complaints.ReturnsEnabled -%} {% assign complaintsOrReturnsEnabled = true -%} {% endif -%}

partials/product/products-table.html

Przyciski reklamacji i zwrotu są wyświetlane bezpośrednio w tabeli, zamiast w rozwijanym menu. W pliku partials/product/products-table.html znajdź komórkę z opcjami: <td class="options drop"> {% if order.Status == 3 and complaintsOrReturnsEnabled and product.CanComplain == true -%} <button aria-label="{{translations.Options}}" class="pure-button open-dropdown-js"> <svg width="24" height="24" style="transform: rotate(90deg);"> <use href="css/img/fontawesome-icons.svg?v={{lqTS}}#ellipsis-h-{{settings.iconStyle}}"></use> </svg> </button> <div class="dropdown dropdown-js hidden-js" {% if productsSize == 1 -%} style="bottom: auto !important;" {% endif -%}> {% if config.Complaints.ComplaintsEnabled == true and product.CanComplain == true -%} <button class="pure-button open-complaint-form-js" data-type="complaint" data-product="{{ product.Url }}"> {{ translations.Complain }} </button> {% endif -%} {% if config.Complaints.ReturnsEnabled == true and product.CanReturn == true and product.IsSetElement == false -%} <button class="pure-button open-complaint-form-js" data-type="return" data-product="{{ product.Url }}"> {{ translations.Return }} </button> {% endif -%} </div> {% endif -%} </td> i zastąp ją następującym fragmentem: <td class="options complaint-actions-inline"> {% if order.Status == 3 and complaintsOrReturnsEnabled -%} {% if config.Complaints.ComplaintsEnabled == true and product.CanComplain == true -%} <button class="pure-button open-complaint-form-js complaint-action-btn" data-type="complaint" data-product="{{ product.Url }}"> {{ translations.Complain }} </button> {% endif -%} {% if config.Complaints.ReturnsEnabled == true and product.CanReturn == true and product.IsSetElement == false -%} <button class="pure-button open-complaint-form-js complaint-action-btn" data-type="return" data-product="{{ product.Url }}"> {{ translations.Return }} </button> {% endif -%} {% endif -%} </td> Następnie w tym samym pliku znajdź zewnętrzny warunek otaczający kontenery formularzy reklamacji i zwrotu i poluzuj go (usuń warunek product.CanComplain == true). Zamień: {% if order.Status == 3 and complaintsOrReturnsEnabled and product.CanComplain == true -%} na: {% if order.Status == 3 and complaintsOrReturnsEnabled -%}

partials/customer-profile/orders/order-details.html

W pliku partials/customer-profile/orders/order-details.html wykonaj poniższe zmiany. a) Bloki Opcje (zawierające klasę options submenu z przyciskami akcji zamówienia) opakuj warunkiem {% unless order.Restricted -%} ... {% endunless -%}, aby ukryć je dla niezalogowanych klientów dokonujących szybkiego zwrotu. Wstaw {% unless order.Restricted -%} bezpośrednio przed otwierającym <div class="options submenu"> i zamykającym {% endunless -%} po jego zamykającym </div>: {% unless order.Restricted -%} <div class="options submenu"> ... </div> {% endunless -%} b) W kontenerze messages-container-js na początku (przed istniejącymi komunikatami typu OrderEditable) dodaj baner informujący o ukrytych danych zamówienia oraz, na końcu kontenera, baner informujący o terminie zwrotu: {% if order.Restricted -%} <div class="return-info-banner"> <svg width="20" height="20" class="icon" aria-hidden="true"> <use href="css/img/fontawesome-icons.svg?v={{lqTS}}#info-circle-{{settings.iconStyle}}"></use> </svg> <span>{{ translations.RestrictedOrderViewInfo }}</span> </div> {% endif -%} {% if order.Status == 3 and config.Complaints.ReturnsEnabled -%} <div class="return-info-banner"> <svg width="20" height="20" class="icon" aria-hidden="true"> <use href="css/img/fontawesome-icons.svg?v={{lqTS}}#info-circle-{{settings.iconStyle}}"></use> </svg> <span>{{ translations.OrderReturnDeadlineInfo | Format: config.Complaints.DaysToReturn }}</span> </div> {% endif -%} c) We wszystkich miejscach wyświetlających numer telefonu klienta zamień warunki sprawdzające jedynie pusty ciąg na warunki sprawdzające również wartość null. Zamień każde wystąpienie: {% if order.Customer.DeliveryAddress.PhoneNo != '' -%} na: {% if order.Customer.DeliveryAddress.PhoneNo != null and order.Customer.DeliveryAddress.PhoneNo != '' -%} d) Analogicznie zaktualizuj warunek wyświetlania NIP-u/TIN-u w sekcji danych do faktury. Zamień: {% elseif order.Customer.TIN != '' -%} na: {% elseif order.Customer.TIN != null and order.Customer.TIN != '' -%} e) W sekcji adresu dostawy zamień otwierający warunek alternatywny {% else -%} (bezpośrednio przed kontenerem z translations.DelivAddress) na bardziej restrykcyjny: {% elseif order.Customer.DeliveryAddress != null -%} f) Sekcję wybranego dokumentu (ChoosenDocument) opakuj warunkiem ukrywającym ją dla zamówień typu restricted. Wstaw {% unless order.Restricted -%} przed kontenerem order-details-item z tytułem translations.ChoosenDocument oraz {% endunless -%} za jego zamykającym </div>. g) W sekcji dokumentów zamówienia dodaj do warunku sprawdzenie order.Restricted == false. Zamień: {% if orderDocumentsSize > 0 -%} na: {% if orderDocumentsSize > 0 and order.Restricted == false -%} h) W sekcji załączników zamówienia dodaj analogiczne sprawdzenie. Zamień: {% if config.Orders.AttachmentsEnabled and orderAttachmentsSize > 0 -%} na: {% if config.Orders.AttachmentsEnabled and orderAttachmentsSize > 0 and order.Restricted == false -%} i) W sekcji zamówień powiązanych zamień: {% if order.RelatedOrders[0] -%} na: {% if order.RelatedOrders[0] and order.Restricted == false -%}

partials/customer-profile/complaints/complaint-form.html

W pliku partials/customer-profile/complaints/complaint-form.html wprowadź poniższe zmiany. a) W kontenerze amount-stepper-container (wewnątrz warunku {% if type != 'set-return' -%}) na samym początku dodaj nową etykietę: <span class="amount-stepper-container__label">{{ translations.Quantity }}:</span> b) Pod sekcją z komentarzem reklamacji/zwrotu (po zamykającym {% endif -%} z sekcji complaint-message-textarea) wewnątrz warunku {% if type != 'set-return' -%} dodaj sekcję wyboru sposobu zwrotu środków: <div class="refund-method-wrapper"> <div class="refund-method-wrapper__title">{{ translations.Com_RefundMethod }} <span class="required">*</span></div> <label class="refund-method-option"> <input type="radio" name="refundMethod" class="refund-method-option__radio refund-method-radio-js" value="asPaid" checked> <span class="refund-method-option__box" aria-hidden="true"></span> <span class="refund-method-option__label"> {{ translations.Com_RefundAsPaid }} {% if order.Payment.Name and order.Payment.Name != '' -%} ({{ order.Payment.Name }}){% endif -%} </span> </label> <label class="refund-method-option"> <input type="radio" name="refundMethod" class="refund-method-option__radio refund-method-radio-js" value="bankAccount"> <span class="refund-method-option__box" aria-hidden="true"></span> <span class="refund-method-option__label">{{ translations.Com_RefundToBankAccount }}</span> </label> </div> <div class="form__input-wrapper account-number-wrapper-js hidden-js"> <label for="accountNumber" class="form__input-info input-info-js">{{ translations.Com_BankAccountNumber }} <span class="required">*</span></label> <input id="accountNumber" class="form__input-value input-value-js" type="text" name="accountNumber" maxlength="50" disabled> <div class="form__invalid-input validation-info-js validation-required-js hidden-js">{{ translations.FieldRequired }}</div> </div> c) W sekcji załączników plików zamień prosty licznik file-{{forloop.index}} na prefiks zawierający identyfikator zamówienia, numer produktu i typ formularza. Tuż przed pętlą {% for i in (1..config.Complaints.AttachmentsMaxCount) -%} dodaj nową linię: {% capture filePrefix -%}file-{{ order.Id }}-{{ product.No }}-{{ type }}{% endcapture -%} Następnie wewnątrz pętli zamień: <label for="file-{{forloop.index}}" class="file"> <input id="file-{{forloop.index}}" class="add-attachement-in-complaint-js hidden-js" type="file" ... > na: <label for="{{ filePrefix }}-{{ forloop.index }}" class="file"> <input id="{{ filePrefix }}-{{ forloop.index }}" class="add-attachement-in-complaint-js hidden-js" type="file" ... > d) Komunikat sukcesu wyświetlany po wysłaniu formularza ma być inny dla reklamacji, a inny dla zwrotu. Znajdź kontener <div class="success-message-js hidden-js"> i jego dotychczasową zawartość: <div class="success-message-js hidden-js"> <span> {{ successInfo }} </span> </div> zastąp: <div class="success-message-js hidden-js"> {% if complaint -%} <span>{{ successInfo }}</span> {% else -%} <div class="data-form__header return-success__header"> <span></span> <button class="close-button hide-container-js closing-modal-js" aria-label="{{ translations.Close }}"> <svg aria-hidden="true" width="24" height="24" class="svgIcon"><use xlink:href="css/img/fontawesome-icons.svg?v={{lqTS}}#times-{{settings.iconStyle}}"></use></svg> </button> </div> <div class="return-success__icon"> <svg aria-hidden="true" width="48" height="48" class="svgIcon"><use xlink:href="css/img/fontawesome-icons.svg?v={{lqTS}}#check-circle-{{settings.iconStyle}}"></use></svg> </div> <div class="return-success__title">{{ successTitle }}</div> <div class="return-success__subtitle">{{ successInfo }}</div> {% if order.Customer.Email and order.Customer.Email != '' -%} <div class="return-success__email-box"> <svg aria-hidden="true" width="20" height="20" class="svgIcon"><use xlink:href="css/img/fontawesome-icons.svg?v={{lqTS}}#info-circle-{{settings.iconStyle}}"></use></svg> <div> <div>{{ translations.Com_ConfirmationSentTo }}</div> <strong>{{ order.Customer.Email }}</strong> </div> </div> {% endif -%} <div class="return-success__steps-title">{{ translations.Com_NextSteps }}</div> <ol class="return-success__steps"> <li>{{ translations.Com_PackProducts }}</li> <li> {{ translations.Com_SendPackageTo }} {% if config.Shop.Address.Street != '' -%} {{ config.Shop.Address.Street }}{% endif -%} {% if config.Shop.Address.StreetNo != '' -%} {{ config.Shop.Address.StreetNo }}{% endif -%} {% if config.Shop.Address.UnitNo != '' -%}/{{ config.Shop.Address.UnitNo }}{% endif -%} {% if config.Shop.Address.ZipCode != '' or config.Shop.Address.City != '' -%}, {{ config.Shop.Address.ZipCode }} {{ config.Shop.Address.City }}{% endif -%} </li> <li>{{ translations.Com_RefundAfterReceive }}</li> </ol> <div class="buttons-container short"> <button class="primary-action-button hide-container-js closing-modal-js"> {{ translations.Close }} </button> </div> {% endif -%} </div>

4. Modyfikacje pliku js/layout-customerprofile0.js

Poniższe zmiany dotyczą pliku js/layout-customerprofile0.js (jego nieskompresowanej wersji, którą po edycji należy ponownie zminifikować do layout-customerprofile0.min.js). a) W funkcji openComplaintForm wewnątrz warunku if (hiddenContainer) – tuż po linii hiddenContainer.querySelector('.success-message-js').classList.add('hidden-js'); – dodaj kod ujawniający nagłówek formularza oraz resetujący wybór sposobu zwrotu do opcji domyślnej: const mainHeader = hiddenContainer.querySelector(':scope > .data-form__header'); if (mainHeader) { mainHeader.classList.remove('hidden-js'); } hiddenContainer.classList.remove('hidden-js'); const asPaidRadio = hiddenContainer.querySelector('.refund-method-radio-js[value="asPaid"]'); if (asPaidRadio) { asPaidRadio.checked = true; $(asPaidRadio).trigger('change'); } (Linia hiddenContainer.classList.remove('hidden-js'); już istnieje – pokazana jest dla kontekstu. Nowe są bloki const mainHeader i const asPaidRadio.) b) W funkcji sendComplaint, w bloku przygotowującym dane formularza – po pętli for (const item of dataFromHTML) dokładającej pola do fd – dodaj fragment dołączający parametr qrHash z adresu URL przy wysyłaniu zwrotu: if (form.find('input[name="__action"]').val() === 'Order/ReturnAdd') { const qrHash = new URLSearchParams(globalThis.location.search).get('qrHash'); if (qrHash) { fd.append('qrHash', qrHash); } } c) W tej samej funkcji sendComplaint, w callbacku success po pomyślnym wysłaniu, zamień fragment: form.parents('.add-complaint-form-js').find('.success-message-js').removeClass('hidden-js'); na: const container = form.parents('.add-complaint-form-js'); container.find('.success-message-js').removeClass('hidden-js'); container.children('.data-form__header').addClass('hidden-js'); d) Na samym końcu pliku js/layout-customerprofile0.js dodaj nowy handler obsługujący przełączanie sposobu zwrotu środków. Pokazuje on / ukrywa pole na numer konta bankowego: $('body').on('change', '.refund-method-radio-js', function(e) { const radio = $(e.currentTarget); const form = radio.closest('.form-js'); const wrapper = form.find('.account-number-wrapper-js'); const input = wrapper.find('input[name="accountNumber"]'); if (radio.val() === 'bankAccount' && radio.prop('checked')) { wrapper.removeClass('hidden-js'); input.prop('disabled', false); input.prop('required', true); } else { wrapper.addClass('hidden-js'); wrapper.find('.validation-required-js').addClass('hidden-js'); wrapper.find('.form__input-info').removeClass('validation-error'); input.removeClass('validation-error-js'); input.prop('required', false); input.prop('disabled', true); input.val(''); } });

5. Modyfikacje plików SCSS profilu klienta

Poniższe style należy dodać do plików scss/static-elements/customer-profile/customer-profile-g.scss (wersja desktop) oraz scss/static-elements/customer-profile/customer-profile-m.scss (wersja mobile). Po zmianach pamiętaj o kompilacji – nie edytuj ręcznie wynikowych plików CSS.

Plik scss/static-elements/customer-profile/customer-profile-g.scss

a) Dla "przyklejonej" kolumny z akcjami reklamacji/zwrotu w tabeli produktów dodaj reguły wewnątrz selektora otaczającego tabelę zamówienia (tam, gdzie znajdują się style dla thead tr th): thead tr th.open-complaint-form-container-js { position: sticky; right: 0; background: transparent; z-index: 5; &::before { content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 200px; background: linear-gradient(to right, rgba(255, 255, 255, 0), #fff 50%); pointer-events: none; } } td.complaint-actions-inline { white-space: nowrap; text-align: right; padding-left: 16px; padding-right: 8px; position: sticky; right: 0; background: #fff; z-index: 2; &::before { content: ''; position: absolute; top: 0; bottom: 0; left: -32px; width: 32px; background: linear-gradient(to right, rgba(255, 255, 255, 0), #fff 100%); pointer-events: none; } .pure-button.complaint-action-btn { display: inline-flex; background: transparent; border: 0; border-radius: 4px; color: $primaryColor; padding: 4px 8px; cursor: pointer; font-size: 14px; font-weight: 600; line-height: 20px; transition: background-color 150ms ease; &:hover, &:focus-visible { color: $primaryColor; background: rgba(0, 0, 0, 0.06); } & + .complaint-action-btn { margin-left: 8px; } } } b) Style hovera dla wiersza tabeli z akcjami reklamacji/zwrotu (umieść w głównym zakresie pliku): .row { &:hover, &:focus-within, &.hovered-js { td.complaint-actions-inline { background: #F1DDDE; &::before { background: linear-gradient(to right, rgba(241, 221, 222, 0), #F1DDDE 100%); } } } &.set td.complaint-actions-inline { background: #ececec; &::before { background: linear-gradient(to right, rgba(236, 236, 236, 0), #ececec 100%); } } } c) Style banera informacyjnego (termin zwrotu / ukryte dane zamówienia): .return-info-banner { display: flex; align-items: center; gap: 12px; padding: 12px 16px; margin: 0 0 24px 0; background: #E8F1F8; border: 1px solid #C7DCEE; border-radius: 5px; font-size: 14px; line-height: 20px; color: #2C3E50; .icon { flex-shrink: 0; fill: #4A90BC; } strong { font-weight: 600; } } d) Style sekcji wyboru sposobu zwrotu środków oraz radio-buttonów: .refund-method-wrapper { text-align: left; display: flex; flex-direction: column; gap: 16px; margin-bottom: 24px; &__title { color: $primaryColorFont; font-size: 14px; font-weight: 500; line-height: 20px; } } .refund-method-option { display: flex; align-items: center; gap: 8px; cursor: pointer; &__radio { display: none; &:checked ~ .refund-method-option__box { border-color: $primaryColor; &::after { content: ""; display: block; width: 8px; height: 8px; border-radius: 50%; background: $primaryColor; } } } &__box { display: flex; justify-content: center; align-items: center; width: 16px; height: 16px; border: 1px solid #767676; border-radius: 50%; flex-shrink: 0; } &__label { font-size: 14px; line-height: 20px; } } e) Style ekranu sukcesu po wysłaniu zwrotu (m.in. ikona, tytuł, lista kolejnych kroków): .add-complaint-form-js .characters-length { margin-top: 0; bottom: 23px; } .add-complaint-form-js { .quantity__plus.disabled-js, .quantity__minus.disabled-js { opacity: 0.4; } } .add-complaint-form-js .data-form__header.return-success__header { margin-bottom: 8px; } .return-success { &__icon { display: flex; justify-content: center; margin-bottom: 16px; svg { fill: #2E7D32; } } &__title { text-align: center; font-size: 20px; font-weight: 600; line-height: 28px; color: $primaryColorFont; margin-bottom: 8px; } &__subtitle { text-align: center; font-size: 14px; line-height: 20px; color: $labelsColor; padding-bottom: 24px; border-bottom: 1px solid #E7E7E7; margin-bottom: 24px; } &__email-box { display: flex; align-items: flex-start; gap: 12px; padding: 12px 16px; background: #F0F6FC; border: 1px solid #D6E4F0; border-radius: 6px; margin-bottom: 24px; font-size: 14px; line-height: 20px; color: $primaryColorFont; svg { fill: #1976D2; flex-shrink: 0; margin-top: 2px; } } &__steps-title { font-size: 14px; font-weight: 600; line-height: 20px; color: $primaryColorFont; margin-bottom: 12px; } &__steps { margin: 0 0 24px; padding-left: 20px; font-size: 14px; line-height: 20px; color: $primaryColorFont; li { margin-bottom: 8px; &:last-child { margin-bottom: 0; } } } } f) Uzupełnij wnętrze selektora .file-attachements-wrapper o style dla kontenera pojedynczego załącznika: .file-container { .file { align-items: center; font-weight: 400; color: $primaryColorFont; justify-content: flex-start; } .icon-js svg { fill: $primaryColorFont; } .clear-file-input-js { flex-shrink: 0; display: flex; align-items: center; svg { width: 14px; height: 14px; fill: $primaryColor; } } }

Plik scss/static-elements/customer-profile/customer-profile-m.scss

Na końcu pliku customer-profile-m.scss dodaj reguły dopasowujące przyciski reklamacji/zwrotu do widoku mobilnego (układają się one wówczas jeden pod drugim): .eshop__table-container { thead tr th.open-complaint-form-container-js::before { width: 100px; } td.complaint-actions-inline { .pure-button.complaint-action-btn { display: block; width: max-content; margin-left: auto; text-align: right; & + .complaint-action-btn { margin-left: auto; margin-top: 4px; } } } } Po wprowadzeniu wszystkich powyższych zmian w szablonie Rubin pamiętaj o kompilacji oraz minifikacji plików js i scss, zgodnie z artykułem dostępnym pod linkiem https://pomoc.comarchesklep.pl/artykul/kompilacja-i-minifikacja-plikow/.

Szablon Szafir

1. Tłumaczenia

W panelu administracyjnym sklepu dodaj nowe klucze tłumaczeń wymagane przez funkcjonalność szybkich zwrotów w szablonie Szafir. OrderReturnDeadlineInfo - PL: Zamówienie można zwrócić w ciągu {0} dni od daty dostawy. - EN: You can return the order within {0} days from the delivery date. - DE: Sie können die Bestellung innerhalb von {0} Tagen ab Lieferdatum zurückgeben. - FR: Vous pouvez retourner la commande dans les {0} jours suivant la date de livraison. RestrictedOrderViewInfo - PL: Wybrane dane zamówienia zostały ukryte ze względów bezpieczeństwa. Możesz zwrócić produkty bez logowania. - EN: Some order details are hidden for security reasons. You can return products without signing in. - DE: Einige Bestelldetails wurden aus Sicherheitsgründen ausgeblendet. Sie können Produkte ohne Anmeldung zurücksenden. - FR: Certaines informations de la commande ont été masquées pour des raisons de sécurité. Vous pouvez retourner des produits sans vous connecter. RefundMethod - PL: Sposób zwrotu środków - EN: Refund method - DE: Rückerstattungsmethode - FR: Méthode de remboursement RefundAsPaid - PL: Tak jak zapłacono - EN: As paid - DE: Wie bezahlt - FR: Comme payé RefundToBankAccount - PL: Na konto bankowe - EN: To bank account - DE: Auf Bankkonto - FR: Sur le compte bancaire BankAccountNumber - PL: Nr konta bankowego - EN: Bank account number - DE: Bankkontonummer - FR: Numéro de compte bancaire ReturnConfirmationTitle - PL: Gotowe! Przyjęliśmy Twoje zgłoszenie - EN: Done! We have received your request - DE: Fertig! Wir haben Ihre Anfrage erhalten - FR: Terminé! Nous avons reçu votre demande ReturnConfirmationInfo - PL: Przygotuj paczkę i odeślij ją do nas – wszystkie szczegóły znajdziesz poniżej. - EN: Prepare the package and send it back to us – all details can be found below. - DE: Bereiten Sie das Paket vor und senden Sie es an uns zurück – alle Details finden Sie unten. - FR: Préparez le colis et renvoyez-le nous – tous les détails se trouvent ci-dessous. ReturnConfirmationEmailSent - PL: Potwierdzenie zwrotu zostało wysłane na adres: - EN: Return confirmation has been sent to: - DE: Die Rücksendebestätigung wurde gesendet an: - FR: La confirmation de retour a été envoyée à: NextSteps - PL: Następne kroki - EN: Next steps - DE: Nächste Schritte - FR: Prochaines étapes ReturnStep1 - PL: Bezpiecznie zapakuj swoje produkty - EN: Safely pack your products - DE: Verpacken Sie Ihre Produkte sicher - FR: Emballez vos produits en toute sécurité ReturnStep2Address - PL: Wyślij paczkę na adres - EN: Send the package to - DE: Senden Sie das Paket an - FR: Envoyez le colis à ReturnStep3 - PL: Pieniądze zwrócimy niezwłocznie po otrzymaniu i sprawdzeniu Twojej paczki. - EN: We will refund the money promptly after receiving and checking your package. - DE: Wir erstatten das Geld umgehend nach Erhalt und Überprüfung Ihres Pakets. - FR: Nous rembourserons l'argent rapidement après réception et vérification de votre colis. ReturnInThreeSteps - PL: Zwróć towar w 3 krokach - EN: Return the product in 3 steps - DE: Geben Sie die Ware in 3 Schritten zurück - FR: Retournez la marchandise en 3 étapes ReturnWithoutReasonInfo - PL: Przysługuje Ci możliwość zwrotu bez podania przyczyny. - EN: You have the right to return the product without giving a reason. - DE: Sie haben das Recht, die Ware ohne Angabe von Gründen zurückzugeben. - FR: Vous avez le droit de retourner la marchandise sans donner de motif. OrEnterOrderNumber - PL: lub podaj numer zamówienia - EN: or enter the order number - DE: oder geben Sie die Bestellnummer ein - FR: ou saisissez le numéro de commande FillForm - PL: Wypełnij formularz - EN: Fill out the form - DE: Füllen Sie das Formular aus - FR: Remplissez le formulaire ReturnOnline - PL: zwrotu online - EN: online return - DE: Online-Rückgabe - FR: retour en ligne SendParcel - PL: Wyślij paczkę - EN: Send the parcel - DE: Paket senden - FR: Envoyer le colis SendParcelToOurAddress - PL: nadaj przesyłkę na nasz adres - EN: send the parcel to our address - DE: senden Sie das Paket an unsere Adresse - FR: envoyez le colis à notre adresse FastSimpleSecure - PL: Szybko, prosto i bezpiecznie. - EN: Fast, simple and secure. - DE: Schnell, einfach und sicher. - FR: Rapide, simple et sécurisé. ReadyForReturn - PL: Gotowy do zwrotu? - EN: Ready for return? - DE: Bereit zur Rückgabe? - FR: Prêt pour le retour ? ReadyForReturnInfo - PL: Kliknij poniżej, aby rozpocząć proces zwrotu. Przeprowadzimy Cię przez wszystkie kroki. - EN: Click below to start the return process. We will guide you through all the steps. - DE: Klicken Sie unten, um den Rückgabeprozess zu starten. Wir führen Sie durch alle Schritte. - FR: Cliquez ci-dessous pour lancer le processus de retour. Nous vous guiderons à travers toutes les étapes. StartReturn - PL: Rozpocznij zwrot - EN: Start return - DE: Rückgabe starten - FR: Commencer le retour ProductReturn - PL: Zwrot produktu - EN: Product return - DE: Produktrückgabe - FR: Retour du produit ProductReturnFormInfo - PL: Wprowadź dane zamówienia, aby zlokalizować zakup i rozpocząć proces zwrotu. Numer zamówienia znajdziesz w e-mailu z potwierdzeniem. - EN: Enter the order details to locate the purchase and start the return process. You will find the order number in the confirmation e-mail. - DE: Geben Sie die Bestelldaten ein, um den Kauf zu lokalisieren und den Rückgabeprozess zu starten. Die Bestellnummer finden Sie in der Bestätigungs-E-Mail. - FR: Saisissez les données de la commande pour localiser l'achat et démarrer le processus de retour. Vous trouverez le numéro de commande dans l'e-mail de confirmation. InvalidOrderNumber - PL: Błędny numer zamówienia. Spróbuj ponownie. - EN: Invalid order number. Please try again. - DE: Ungültige Bestellnummer. Bitte versuchen Sie es erneut. - FR: Numéro de commande incorrect. Veuillez réessayer. FindOrder - PL: Znajdź zamówienie - EN: Find order - DE: Bestellung finden - FR: Trouver la commande LoginToSeeOrdersAndReturn - PL: aby zobaczyć swoje zamówienia i dokonać zwrotu. - EN: to see your orders and make a return. - DE: um Ihre Bestellungen einzusehen und eine Rückgabe vorzunehmen. - FR: pour voir vos commandes et effectuer un retour. RefundLookupError - PL: Wystąpił błąd podczas wyszukiwania zamówienia. Spróbuj ponownie później. - EN: An error occurred while searching for the order. Please try again later. - DE: Bei der Suche nach der Bestellung ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut. - FR: Une erreur s'est produite lors de la recherche de la commande. Veuillez réessayer plus tard.

2. Nowa strona Szybkie zwroty

Funkcjonalność szybkich zwrotów wymaga utworzenia dodatkowej strony statycznej refunds. Wykonaj poniższe kroki.

Plik refunds.html w katalogu głównym szablonu

W katalogu głównym szablonu utwórz nowy plik refunds.html z następującą zawartością: {% extends '_layout.html' %} {% block content %} {% include 'static-elements/refunds/refunds.html' %} {% endblock %}

Plik static-elements/refunds/refunds.html

W folderze static-elements utwórz nowy katalog refunds, a w nim plik refunds.html: <section class="refunds refunds-js form-js"> <p class="refunds-header refunds-initial-view-js">{{ translations.Returns }}</p> <div class="refunds-intro refunds-initial-view-js"> <div class="refunds-info"> <p class="refunds-info-title">{{ translations.ReturnInThreeSteps }}</p> <p class="refunds-info-desc">{{ translations.ReturnWithoutReasonInfo }}</p> <ol class="refunds-steps"> <li class="refunds-steps-item"> <span class="refunds-steps-number">1</span> <p class="refunds-steps-text"><strong>{{ translations.SignIn }}</strong> {{ translations.OrEnterOrderNumber }}</p> </li> <li class="refunds-steps-item"> <span class="refunds-steps-number">2</span> <p class="refunds-steps-text"><strong>{{ translations.FillForm }}</strong> {{ translations.ReturnOnline }}</p> </li> <li class="refunds-steps-item"> <span class="refunds-steps-number">3</span> <p class="refunds-steps-text"><strong>{{ translations.SendParcel }}</strong> - {{ translations.SendParcelToOurAddress }}</p> </li> </ol> <p class="refunds-info-hint">{{ translations.FastSimpleSecure }}</p> </div> <div class="refunds-cta"> <p class="refunds-cta-title">{{ translations.ReadyForReturn }}</p> <p class="refunds-cta-desc">{{ translations.ReadyForReturnInfo }}</p> {% if usr.Authenticated -%} <a aria-label="{{ translations.StartReturn }}" href="{{ config.DefinedPages.CustomerProfile.Url }}?tab=orders" class="refunds-cta-button" rel="nofollow"> {{ translations.StartReturn }} </a> {% else -%} <button aria-label="{{ translations.StartReturn }}" type="button" class="refunds-cta-button start-refund-js"> {{ translations.StartReturn }} </button> {% endif -%} </div> </div> {% unless usr.Authenticated -%} <div class="refunds-form-section refund-form-view-js hidden-js"> <div class="refunds-form"> <p class="refunds-form-title">{{ translations.ProductReturn }}</p> <p class="refunds-form-desc">{{ translations.ProductReturnFormInfo }}</p> <div class="refund-form-js" data-cp-url="{{ config.DefinedPages.CustomerProfile.Url }}"> <div class="message-bar-ui warning-bar-ui refund-lookup-error-js hidden-js">{{ translations.RefundLookupError }}</div> <div class="form__input-wrapper"> <label for="refundOrderNumber" data-type="text" class="form__input-info form__input-info-js">{{ translations.OrderNumber }} <span class="required-ui">*</span></label> <input id="refundOrderNumber" aria-label="{{ translations.OrderNumber }}" type="text" name="orderNumber" class="form__input-value form__input-value-js" maxlength="50" required /> <span class="error-ui validation-info-js validation-required-js hidden-js">{{ translations.RequiredField }}</span> </div> <div class="form__input-wrapper"> <label for="refundEmail" data-type="email" class="form__input-info form__input-info-js">{{ translations.EmailAddress }} <span class="required-ui">*</span></label> <input id="refundEmail" aria-label="{{ translations.EmailAddress }}" type="email" name="email" class="form__input-value form__input-value-js" maxlength="192" autocomplete="email" required /> <span class="error-ui validation-info-js validation-required-js hidden-js">{{ translations.RequiredField }}</span> <span class="error-ui validation-info-js email-valid-js hidden-js">{{ translations.FillProperEmail }}</span> </div> <div class="required-fields-info-ui form__required-fields-info"><span class="required-ui">* </span>{{ translations.RequiredFields }}</div> <button aria-label="{{ translations.FindOrder }}" type="button" class="refunds-form-submit refund-form-submit-js"> {{ translations.FindOrder }} </button> <p class="refunds-form-login-info"> {{ translations.HaveAccount }} <a href="{{ config.DefinedPages.Login.Url }}" class="refunds-form-login-link" rel="nofollow">{{ translations.SignIn }}</a>, {{ translations.LoginToSeeOrdersAndReturn }} </p> </div> </div> </div> {% endunless -%} </section>

Plik js/layout0.js – kod obsługi formularza zwrotu

Na końcu pliku js/layout0.js dodaj poniższy kod odpowiedzialny za walidację i wysłanie formularza wyszukiwania zamówienia (dla niezalogowanego klienta). Po zapisaniu pliku pamiętaj o zminifikowaniu go do layout0.min.js. const refunds = { findRefundOrder(orderNumber, email) { return $.post('', { __action: 'Order/QuickReturnLookup', orderId: orderNumber, email: email, __csrf: __CSRF }); }, showForm() { document.querySelectorAll('.refunds-initial-view-js').forEach((el) => el.classList.add('hidden-js')); document.querySelectorAll('.refund-form-view-js').forEach((el) => el.classList.remove('hidden-js')); document.querySelector('.refund-form-js input[name="orderNumber"]')?.focus(); }, clearFieldError(input) { input.classList.remove('validation-error-ui', 'validation-error-lq'); input.closest('.form__input-wrapper') ?.querySelectorAll('.error-ui') .forEach((el) => el.classList.add('hidden-js')); }, markFieldError(input, errorSelector) { input.classList.add('validation-error-ui', 'validation-error-lq'); input.closest('.form__input-wrapper')?.querySelector(errorSelector)?.classList.remove('hidden-js'); }, validateForm({ orderInput, emailInput }) { const orderValue = orderInput.value.trim(); const emailValue = emailInput.value.trim(); const emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w{2,}$/; let hasError = false; if (orderValue.length === 0) { refunds.markFieldError(orderInput, '.validation-required-js'); hasError = true; } if (emailValue.length === 0) { refunds.markFieldError(emailInput, '.validation-required-js'); hasError = true; } else if (!emailRegex.test(emailValue)) { refunds.markFieldError(emailInput, '.email-valid-js'); hasError = true; } return { hasError, orderValue }; }, async submitForm(button) { const form = button.closest('.refund-form-js'); if (!form) { return; } const orderInput = form.querySelector('input[name="orderNumber"]'); const emailInput = form.querySelector('input[name="email"]'); form.querySelectorAll('.error-ui').forEach((el) => el.classList.add('hidden-js')); form.querySelector('.refund-lookup-error-js')?.classList.add('hidden-js'); form.querySelectorAll('.form__input-value').forEach((el) => { el.classList.remove('validation-error-ui', 'validation-error-lq'); }); const { hasError, orderValue } = refunds.validateForm({ orderInput, emailInput }); if (hasError) { return; } button.disabled = true; const errorBar = form.querySelector('.refund-lookup-error-js'); try { const result = await refunds.findRefundOrder(orderValue, emailInput.value.trim()); const action = result.action; if (action.Redirect302) { globalThis.location.href = action.Redirect302; return; } if (errorBar) { errorBar.textContent = action.Message; errorBar.classList.remove('hidden-js'); } } catch (error) { console.error('Refund order lookup failed.', error); errorBar?.classList.remove('hidden-js'); } finally { button.disabled = false; } } }; js.delegate(document.body, 'click', '.start-refund-js', () => refunds.showForm()); js.delegate(document.body, 'input', '.refund-form-js .form__input-value', function () { refunds.clearFieldError(this); }); js.delegate(document.body, 'click', '.refund-form-submit-js', function (event) { event.preventDefault(); refunds.submitForm(this); }); js.delegate(document.body, 'keydown', '.refund-form-js input', function (event) { if (event.key !== 'Enter') { return; } event.preventDefault(); this.closest('.refund-form-js')?.querySelector('.refund-form-submit-js')?.click(); });

Pliki SCSS strony Szybkie zwroty

W folderze scss/static-elements utwórz nowy katalog refunds i umieść w nim dwa pliki: refunds-g.scss (style desktop) oraz refunds-m.scss (style mobilne). scss/static-elements/refunds/refunds-g.scss: .refunds { padding: 40px 110px; background-color: $bgColor; color: $primaryColorFont; .refunds-header { display: block; width: 100%; margin: 0 0 24px; color: $primaryColorFont; text-align: left; font-size: 32px; font-weight: 500; line-height: 42px; letter-spacing: 0.8px; } .refunds-intro { display: flex; flex-direction: column; align-items: center; gap: 32px; margin-bottom: 40px; } .refunds-info { align-self: flex-start; width: 100%; max-width: 800px; display: flex; flex-direction: column; gap: 16px; color: $primaryColorFont; @media screen and (min-width: 769px) and (max-width: 1279px) { max-width: 100%; } } .refunds-info-title { margin: 0; font-size: 20px; font-weight: 500; line-height: 28px; letter-spacing: 0.4px; } .refunds-info-desc { margin: 0; font-size: 16px; font-weight: 400; line-height: 24px; letter-spacing: 0.3px; } .refunds-info-hint { margin: 4px 0 0; color: $secondaryColorFont; font-size: 12px; font-weight: 400; line-height: 20px; letter-spacing: 0.2px; } .refunds-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; } .refunds-steps-item { display: flex; align-items: center; gap: 12px; } .refunds-steps-number { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background-color: $formsBgColor; color: $primaryColor; font-size: 14px; font-weight: 600; line-height: 20px; } .refunds-steps-text { margin: 0; font-size: 14px; font-weight: 400; line-height: 22px; letter-spacing: 0.3px; strong { font-weight: 600; } } .refunds-cta { box-sizing: border-box; width: 100%; max-width: 578px; padding: 32px 40px; display: flex; flex-direction: column; align-items: center; gap: 12px; background-color: $bgColor; border: 1px solid $lightBorderColor; } .refunds-cta-title { margin: 0; text-align: center; font-size: 22px; font-weight: 500; line-height: 30px; letter-spacing: 0.5px; color: $primaryColorFont; } .refunds-cta-desc { margin: 0; text-align: center; color: $secondaryColorFont; font-size: 14px; font-weight: 400; line-height: 22px; letter-spacing: 0.3px; } .refunds-cta-button, .refunds-form-submit { display: inline-block; width: 100%; margin-top: 8px; padding: 12px 16px; background: $btnSolidBgColor; color: $btnSolidTextColor; border: 1px solid $btnSolidBgColor; font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; text-decoration: none; cursor: pointer; transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; &:hover, &:focus { background: $btnSolidHoverBgColor; color: $btnSolidHoverTextColor; border-color: $btnSolidHoverBgColor; } &[disabled], &[disabled]:hover { background: $btnDisabledBg; border-color: $btnDisabledFont; color: $btnDisabledFont; cursor: default; } } .refunds-form-section { display: flex; justify-content: center; width: 100%; margin-top: 32px; margin-bottom: 40px; } .refunds-form { box-sizing: border-box; width: 100%; max-width: 578px; padding: 32px 40px; background-color: $bgColor; border: 1px solid $lightBorderColor; } .refunds-form-title { margin: 0 0 8px; font-size: 22px; font-weight: 500; line-height: 30px; letter-spacing: 0.5px; color: $primaryColorFont; } .refunds-form-desc { margin: 0 0 20px; color: $secondaryColorFont; font-size: 14px; font-weight: 400; line-height: 22px; letter-spacing: 0.3px; } .refund-form-js { display: flex; flex-direction: column; .form__input-wrapper { position: relative; margin-bottom: 16px; .form__input-info { display: block; margin: 0 0 4px; color: $primaryColorFont; font-size: 13px; font-weight: 400; line-height: 18px; } input { width: 100%; height: 36px; margin: 0; padding: 0 10px; box-sizing: border-box; border: 1px solid $lightBorderColor; font-size: 14px; &::placeholder { font-size: 14px; } &.validation-error-ui, &.validation-error-lq { border-color: $dangerColor; color: $dangerColor; } } .error-ui { position: static; display: block; margin: 4px 0 0; padding: 0; text-align: left; color: $dangerColor; font-size: 12px; font-weight: 400; line-height: 16px; } } .form__required-fields-info { margin: 4px 0 16px; color: $primaryColorFont; font-size: 12px; font-weight: 300; line-height: 18px; } } .refunds-form-login-info { margin: 12px 0 0; text-align: center; color: $primaryColorFont; font-size: 14px; font-weight: 400; line-height: 22px; } .refunds-form-login-link { color: $primaryColor; font-weight: 600; cursor: pointer; text-decoration: none; &:hover { text-decoration: underline; } } } scss/static-elements/refunds/refunds-m.scss: @media screen and (max-width: 768px) { .refunds { padding: 20px 16px; .refunds-header { font-size: 24px; line-height: 32px; margin-bottom: 16px; } .refunds-intro { gap: 24px; margin-bottom: 24px; } .refunds-info { max-width: 100%; gap: 12px; } .refunds-info-title { font-size: 18px; line-height: 24px; } .refunds-info-desc { font-size: 14px; line-height: 22px; } .refunds-steps-item { align-items: flex-start; gap: 10px; } .refunds-steps-number { width: 28px; height: 28px; font-size: 13px; } .refunds-steps-text { font-size: 13px; line-height: 20px; padding-top: 3px; } .refunds-cta { padding: 24px; } .refunds-cta-title { font-size: 20px; line-height: 28px; } .refunds-form-section { margin-top: 20px; margin-bottom: 24px; } .refunds-form { padding: 24px; border: none; } .refunds-form-title { font-size: 20px; line-height: 28px; } .refunds-form-desc { margin-bottom: 16px; } .refunds-form-login-info { font-size: 13px; } } }

3. Modyfikacje istniejących plików HTML

partials/customer-profile/orders/order-details.html

W pliku partials/customer-profile/orders/order-details.html wykonaj poniższe zmiany. a) Blok z przyciskami akcji nawigacji zamówienia (zawierający {% if order.EditingAllowed -%}, opcje anulowania, edycji, ponowienia, druku itp.) opakuj warunkiem ukrywającym go dla zamówień typu restricted. Bezpośrednio po linii z elementem <li class="active-ui only-text-ui ...">...</li> wstaw: {% unless order.Restricted -%} a tuż przed zamykającym znacznikiem </ul> tej samej nawigacji dodaj: {% endunless -%} b) Na początku kontenera messages-container-lq messages-container-ui (zaraz po jego otwarciu) dodaj baner informujący o ukrytych danych zamówienia: {% if order.Restricted -%} <div class="message-bar-ui no-margin-ui"> <i class="not-clickable-ui ti-info-alt"></i> {{ translations.RestrictedOrderViewInfo }} </div> {% endif -%} c) Na końcu tego samego kontenera (przed zamykającym </div>) dodaj baner informujący o terminie zwrotu wraz z przypisaniem flagi complaintsOrReturnsEnabled: {% if config.Complaints.ComplaintsEnabled or config.Complaints.ReturnsEnabled -%} {% assign complaintsOrReturnsEnabled = true -%} {% endif -%} {% if order.Status == 3 and complaintsOrReturnsEnabled -%} <div class="message-bar-ui no-margin-ui"> <i class="not-clickable-ui ti-info-alt"></i> {{translations.OrderReturnDeadlineInfo | Format: config.Complaints.DaysToReturn}} </div> {% endif -%} d) Blok z przyciskami akcji wewnątrz info-container-js (zawierający przyciski order.CanCancel, edycji, ponowienia zakupu itd.) opakuj warunkiem {% unless order.Restricted -%} ... {% endunless -%}. Wstaw {% unless order.Restricted -%} bezpośrednio przed pierwszym {% if order.CanCancel -%}, a {% endunless -%} po zamykającym warunku odpowiedzialnym za popup potwierdzenia ({% include 'partials/common/confirmation-popup.html' with 0 -%}). e) W sekcji wyświetlającej dokumenty zamówienia zamień: {% if order.Documents %} na: {% if order.Documents and order.Restricted == false %} f) We wszystkich miejscach wyświetlających numer telefonu klienta zamień warunki sprawdzające jedynie pusty ciąg na warunki sprawdzające również wartość null. Zamień każde wystąpienie: {% if order.Customer.DeliveryAddress.PhoneNo != '' -%} na: {% if order.Customer.DeliveryAddress.PhoneNo != null and order.Customer.DeliveryAddress.PhoneNo != '' -%} g) Każdą sekcję z tytułem translations.ChoosenDocument opakuj warunkiem ukrywającym ją dla zamówień restricted. Wstaw {% unless order.Restricted -%} bezpośrednio przed <div class="name-ui mt20-ui">{{ translations.ChoosenDocument }}</div> oraz {% endunless -%} po jej zamykającym </div>. h) W sekcji wyświetlającej alternatywny adres dostawy zamień warunek {% else -%} (bezpośrednio przed order-info-item-ui z translations.DelivAddress) na bardziej restrykcyjny: {% elseif order.Customer.DeliveryAddress != null -%} i) W sekcji danych do faktury zamień warunek wyświetlania NIP-u/TIN-u. Zamień: {% elseif order.Customer.TIN != '' -%} na: {% elseif order.Customer.TIN != null and order.Customer.TIN != '' -%} j) W sekcji załączników zamówienia (kontener attachements-ui remarks-ui) zamień warunek otaczający. Zamień: {% if config.Orders.AttachmentsEnabled -%} na: {% if config.Orders.AttachmentsEnabled and order.Restricted == false -%} k) W sekcji zamówień powiązanych (kontener remarks-ui eshop-order-ui) zamień: {% if order.RelatedOrders -%} na: {% if order.RelatedOrders and order.Restricted == false -%}

partials/customer-profile/complaints/complaint-form.html

W pliku partials/customer-profile/complaints/complaint-form.html wprowadź poniższe zmiany. a) W kontenerze amount-stepper-container-ui amount-stepper-container-lq (wewnątrz warunku {% if type != 'set-return' -%}) na samym początku dodaj etykietę widoczną tylko dla zwrotów: {% unless complaint -%} <span class="amount-stepper-label-ui">{{ translations.Quantity }}:</span> {% endunless -%} b) Bezpośrednio po zamknięciu kontenera amount-stepper-container-ui (po jego </div> i odpowiadającym {% endif -%}) dodaj sekcję wyboru sposobu zwrotu środków – widoczną tylko w formularzu zwrotu: {% unless complaint -%} <div class="refund-method-container-ui refund-method-container-js"> <label for="refundMethod" class="label-ui">{{ translations.RefundMethod }} <span class="required-ui">*</span></label> <div> <span class="select-background-ui"> <select id="refundMethod" aria-label="{{ translations.RefundMethod }}" name="refundMethod" class="refund-method-select-js"> <option value="original" selected="selected">{{ translations.RefundAsPaid }} {% if order.Payment.Name and order.Payment.Name != "" -%} ({{ order.Payment.Name }}){% endif -%}</option> <option value="bank">{{ translations.RefundToBankAccount }}</option> </select> </span> <i class="ti-angle-down select-arrow-ui"></i> </div> <div class="bank-account-container-ui bank-account-container-js hidden-js"> <label for="bankAccountNumber" class="label-ui">{{ translations.BankAccountNumber }} <span class="required-ui">*</span></label> <div> <input id="bankAccountNumber" aria-label="{{ translations.BankAccountNumber }}" type="text" name="bankAccountNumber" placeholder="{{ translations.BankAccountNumber }}" disabled /> <span class="error-ui validation-info-js validation-required-js hidden-js">{{ translations.RequiredField }}</span> </div> </div> </div> {% endunless -%} c) Komunikat sukcesu wyświetlany po wysłaniu formularza ma być inny dla reklamacji, a inny dla zwrotu. Znajdź kontener <div class="success-message-js hidden-js"> wraz z jego dotychczasową zawartością (komunikat ComplaintAdded + successInfo): <div class="success-message-js hidden-js"> <div class="complaint-added-ui"> <i class="va-mid-ui ti-check"></i> <span class="va-mid-ui line-height-1-ui"> {{ translations.ComplaintAdded }} </span> </div> <div class="info-ui"> {{ successInfo }} </div> </div> i zastąp go nową, rozszerzoną wersją z dwoma wariantami (reklamacja / zwrot): <div class="success-message-js hidden-js"> {% if complaint -%} <div class="complaint-added-ui"> <i class="va-mid-ui ti-check"></i> <span class="va-mid-ui line-height-1-ui"> {{ translations.ComplaintAdded }} </span> </div> <div class="info-ui"> {{ successInfo }} </div> {% else -%} <div class="return-success-popup-ui"> <div class="return-success-icon-ui"> <i class="ti-check"></i> </div> <div class="return-success-title-ui">{{ translations.ReturnConfirmationTitle }}</div> <div class="return-success-desc-ui">{{ translations.ReturnConfirmationInfo }}</div> {% if order.Customer.Email and order.Customer.Email != "" -%} <div class="return-success-email-info-ui"> <i class="ti-info-alt"></i> <span>{{ translations.ReturnConfirmationEmailSent }} <strong>{{ order.Customer.Email }}</strong></span> </div> {% endif -%} <div class="return-success-steps-title-ui">{{ translations.NextSteps }}</div> <ol class="return-success-steps-ui"> <li>{{ translations.ReturnStep1 }}</li> <li>{{ translations.ReturnStep2Address }}: {{ config.Shop.Address.Street }} {{ config.Shop.Address.StreetNo }}{% if config.Shop.Address.UnitNo and config.Shop.Address.UnitNo != "" -%}/{{ config.Shop.Address.UnitNo }}{% endif -%}, {{ config.Shop.Address.ZipCode }} {{ config.Shop.Address.City }}</li> <li>{{ translations.ReturnStep3 }}</li> </ol> <div class="return-success-actions-ui"> <button aria-label="{{ translations.Close }}" class="btn-ui return-success-close-ui hide-container-js closing-modal-js"> {{ translations.Close }} </button> </div> </div> {% endif -%} </div>

4. Modyfikacje pliku js/init-ui2.js

Poniższe zmiany dotyczą pliku js/init-ui2.js (po edycji pamiętaj o zminifikowaniu go do init-ui2.min.js). a) Tuż po linii rejestrującej handler openComplaintForm: js.delegate(document.body, 'click', '.open-complaint-form-js', openComplaintForm); dodaj poniższy handler obsługujący przełączanie sposobu zwrotu środków – pokazuje on / ukrywa pole na numer konta bankowego: js.delegate(document.body, 'change', '.refund-method-select-js', function() { const container = js.parents(this, 'refund-method-container-js'); if(!container) return; const bankWrapper = container.getElementsByClassName('bank-account-container-js')[0]; if(!bankWrapper) return; const bankInput = bankWrapper.querySelector('input[name="bankAccountNumber"]'); const validationMsg = bankWrapper.getElementsByClassName('validation-required-js')[0]; if(this.value === 'bank') { bankWrapper.classList.remove('hidden-js'); if(bankInput) { bankInput.disabled = false; bankInput.required = true; } } else { bankWrapper.classList.add('hidden-js'); if(bankInput) { bankInput.disabled = true; bankInput.required = false; bankInput.value = ''; bankInput.classList.remove('validation-error-lq', 'validation-error-ui'); } if(validationMsg) validationMsg.classList.add('hidden-js'); } }); b) W funkcji sendComplaint, bezpośrednio po pętli for (var i=0; i<dataFromHTML.length; i++) dokładającej pola do fd, dodaj fragment dołączający parametr qrHash z adresu URL przy wysyłaniu zwrotu: if (form.find('input[name="__action"]').val() === 'Order/ReturnAdd') { var qrHash = new URLSearchParams(globalThis.location.search).get('qrHash'); if (qrHash) { fd.append('qrHash', qrHash); } }

5. Modyfikacje pliku scss/globals/_globals2.scss

W pliku scss/globals/_globals2.scss wewnątrz selektora opakowującego (tego, który zawiera m.in. .note-ui) dodaj poniższe reguły. Po zmianach pamiętaj o kompilacji SCSS – nie edytuj ręcznie wynikowych plików CSS. a) Style etykiety ilości oraz kontenera wyboru sposobu zwrotu środków (wstaw w sąsiedztwie istniejących reguł sekcji formularza reklamacji/zwrotu): .amount-stepper-label-ui { margin-right: 10px; vertical-align: middle; } .refund-method-container-ui { margin-bottom: 20px; .bank-account-container-ui { margin-top: 10px; input { width: 100%; } } } b) Style ekranu sukcesu po wysłaniu zwrotu (ikona, tytuł, lista kolejnych kroków, sekcja z e-mailem i przyciskiem zamknięcia): .return-success-popup-ui { padding: 30px 20px 20px; .return-success-icon-ui { width: 60px; height: 60px; border-radius: 50%; border: 2px solid #68a204; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center; i { color: #68a204; font-size: 26px; } } .return-success-title-ui { font-size: 18px; font-weight: 500; text-align: center; margin-bottom: 10px; } .return-success-desc-ui { font-size: 14px; color: $primaryColorFont; text-align: center; margin-bottom: 20px; } .return-success-email-info-ui { background-color: $bgColor; border: 1px solid $lightBorderColor; padding: 12px; border-radius: 4px; font-size: 14px; margin-bottom: 20px; display: flex; align-items: flex-start; i { margin-right: 10px; color: $primaryColorFont; font-size: 16px; line-height: 1.4; } strong { display: block; } } .return-success-steps-title-ui { font-weight: 500; margin-bottom: 10px; } .return-success-steps-ui { padding-left: 20px; margin: 0 0 20px; font-size: 14px; li { margin-bottom: 8px; padding-left: 5px; } } .return-success-actions-ui { border-top: 1px solid $lightBorderColor; padding-top: 15px; text-align: right; .return-success-close-ui { padding: 10px 30px; } } } Po wprowadzeniu wszystkich powyższych zmian w szablonie Szafir pamiętaj o kompilacji oraz minifikacji plików js i scss, zgodnie z artykułem dostępnym pod linkiem https://pomoc.comarchesklep.pl/artykul/kompilacja-i-minifikacja-plikow/.

Szablon Topaz / One Page Shop

Zmiany opisane poniżej dotyczą szablonu Topaz. Szablon One Page Shop ma praktycznie identyczną strukturę – wszystkie modyfikacje dotyczą tych samych plików i mają tę samą zawartość. Wystarczy zastosować poniższą instrukcję w plikach szablonu OPS pod tymi samymi ścieżkami.

1. Tłumaczenia

W panelu administracyjnym sklepu dodaj nowe klucze tłumaczeń wymagane przez funkcjonalność szybkich zwrotów w szablonie Topaz / OPS. RestrictedOrderViewInfo - PL: Wybrane dane zamówienia zostały ukryte ze względów bezpieczeństwa. Możesz zwrócić produkty bez logowania. - EN: Some order details are hidden for security reasons. You can return products without signing in. - DE: Einige Bestelldetails wurden aus Sicherheitsgründen ausgeblendet. Sie können Produkte ohne Anmeldung zurücksenden. - FR: Certaines informations de la commande ont été masquées pour des raisons de sécurité. Vous pouvez retourner des produits sans vous connecter. Prf_ReturnPeriodInfo - PL: Zamówienie można zwrócić w ciągu {0} dni od daty dostawy. - EN: The order can be returned within {0} days from the delivery date. - DE: Die Bestellung kann innerhalb von {0} Tagen ab dem Lieferdatum zurückgegeben werden. - FR: La commande peut être retournée dans un délai de {0} jours à compter de la date de livraison. ComplaintSuccessTitle - PL: Gotowe! Przyjęliśmy Twoje zgłoszenie - EN: Done! We have received your request - DE: Fertig! Wir haben Ihre Meldung erhalten - FR: C'est fait ! Nous avons reçu votre demande ComplaintSuccessDescription - PL: Przygotuj paczkę i odeślij ją do nas – wszystkie szczegóły znajdziesz poniżej. - EN: Prepare the parcel and send it back to us – you will find all the details below. - DE: Bereiten Sie das Paket vor und senden Sie es an uns zurück – alle Details finden Sie unten. - FR: Préparez le colis et renvoyez-le-nous – vous trouverez tous les détails ci-dessous. ComplaintSuccessConfirmationSent - PL: Potwierdzenie zwrotu zostało wysłane na adres: - EN: The return confirmation has been sent to: - DE: Die Rückgabebestätigung wurde an folgende Adresse gesendet: - FR: La confirmation de retour a été envoyée à : ComplaintSuccessStepsTitle - PL: Następne kroki - EN: Next steps - DE: Nächste Schritte - FR: Étapes suivantes ComplaintSuccessStep1 - PL: Bezpiecznie zapakuj swoje produkty - EN: Pack your products securely - DE: Verpacken Sie Ihre Produkte sicher - FR: Emballez vos produits en toute sécurité ComplaintSuccessStep2 - PL: Wyślij paczkę na adres: - EN: Send the parcel to: - DE: Senden Sie das Paket an folgende Adresse: - FR: Envoyez le colis à l'adresse : ComplaintSuccessStep3 - PL: Pieniądze zwrócimy niezwłocznie po otrzymaniu i sprawdzeniu Twojej paczki. - EN: We will refund the money immediately after receiving and inspecting your parcel. - DE: Wir erstatten den Betrag unverzüglich nach Erhalt und Prüfung Ihres Pakets. - FR: Nous rembourserons l'argent immédiatement après réception et vérification de votre colis. ReturnInThreeSteps - PL: Zwróć towar w 3 krokach - EN: Return the product in 3 steps - DE: Geben Sie die Ware in 3 Schritten zurück - FR: Retournez la marchandise en 3 étapes ReturnWithoutReasonInfo - PL: Przysługuje Ci możliwość zwrotu bez podania przyczyny. - EN: You have the right to return the product without giving a reason. - DE: Sie haben das Recht, die Ware ohne Angabe von Gründen zurückzugeben. - FR: Vous avez le droit de retourner la marchandise sans donner de motif. OrEnterOrderNumber - PL: lub podaj numer zamówienia - EN: or enter the order number - DE: oder geben Sie die Bestellnummer ein - FR: ou entrez le numéro de commande FillForm - PL: Wypełnij formularz - EN: Fill out the form - DE: Füllen Sie das Formular aus - FR: Remplissez le formulaire ReturnOnline - PL: zwrotu online - EN: online return - DE: Online-Rückgabe - FR: retour en ligne SendParcel - PL: Wyślij paczkę - EN: Send the parcel - DE: Senden Sie das Paket - FR: Envoyez le colis SendParcelToOurAddress - PL: nadaj przesyłkę na nasz adres - EN: send the parcel to our address - DE: senden Sie das Paket an unsere Adresse - FR: envoyez le colis à notre adresse FastSimpleSecure - PL: Szybko, prosto i bezpiecznie. - EN: Fast, simple and secure. - DE: Schnell, einfach und sicher. - FR: Rapide, simple et sûr. ReadyForReturn - PL: Gotowy do zwrotu? - EN: Ready for return? - DE: Bereit zur Rückgabe? - FR: Prêt pour le retour ? ReadyForReturnInfo - PL: Kliknij poniżej, aby rozpocząć proces zwrotu. Przeprowadzimy Cię przez wszystkie kroki. - EN: Click below to start the return process. We will guide you through all the steps. - DE: Klicken Sie unten, um den Rückgabeprozess zu starten. Wir führen Sie durch alle Schritte. - FR: Cliquez ci-dessous pour commencer le processus de retour. Nous vous guiderons à chaque étape. StartReturn - PL: Rozpocznij zwrot - EN: Start return - DE: Rückgabe starten - FR: Commencer le retour ProductReturn - PL: Zwrot produktu - EN: Product return - DE: Produktrückgabe - FR: Retour du produit ProductReturnFormInfo - PL: Wprowadź dane zamówienia, aby zlokalizować zakup i rozpocząć proces zwrotu. Numer zamówienia znajdziesz w e-mailu z potwierdzeniem. - EN: Enter the order details to locate the purchase and start the return process. You will find the order number in the confirmation e-mail. - DE: Geben Sie die Bestelldaten ein, um den Kauf zu lokalisieren und den Rückgabeprozess zu starten. Die Bestellnummer finden Sie in der Bestätigungs-E-Mail. - FR: Saisissez les données de la commande pour localiser l'achat et démarrer le processus de retour. Vous trouverez le numéro de commande dans l'e-mail de confirmation. FindOrder - PL: Znajdź zamówienie - EN: Find order - DE: Bestellung finden - FR: Trouver la commande RefundLookupError - PL: Wystąpił błąd podczas wyszukiwania zamówienia. Spróbuj ponownie później. - EN: An error occurred while searching for the order. Please try again later. - DE: Fehler beim Suchen nach der Bestellung. Versuchen Sie es später erneut. - FR: Une erreur s'est produite lors de la recherche de la commande. Veuillez réessayer plus tard. LoginToSeeOrdersAndReturn - PL: aby zobaczyć swoje zamówienia i dokonać zwrotu. - EN: to see your orders and make a return. - DE: um Ihre Bestellungen zu sehen und eine Rückgabe zu machen. - FR: pour voir vos commandes et faire un retour. InvalidEmail - PL: Nieprawidłowy adres e-mail - EN: Invalid e-mail address - DE: Ungültige E-Mail-Adresse - FR: L'adresse e-mail est incorrecte. RefundMethod - PL: Sposób zwrotu środków - EN: Refund method - DE: Rückerstattungsmethode - FR: Mode de remboursement RefundAsPaid - PL: Zwrot na sposób płatności - EN: Refund to the original payment method - DE: Rückerstattung auf die ursprüngliche Zahlungsmethode - FR: Remboursement sur le mode de paiement initial RefundToBankAccount - PL: Zwrot na konto bankowe - EN: Refund to bank account - DE: Rückerstattung auf das Bankkonto - FR: Remboursement sur un compte bancaire

2. Nowa strona Szybkie zwroty

Funkcjonalność szybkich zwrotów wymaga utworzenia dodatkowej strony statycznej refunds. Wykonaj poniższe kroki.

Plik refunds.html w katalogu głównym szablonu

W katalogu głównym szablonu utwórz nowy plik refunds.html z następującą zawartością: {% extends '_layout.html' -%} {% block pageContent -%} {% include 'static-elements/refunds/refunds.html' -%} {% endblock -%}

Plik static-elements/refunds/refunds.html

W folderze static-elements utwórz nowy katalog refunds, a w nim plik refunds.html: {% include 'partials/common/breadcrumbs.html' -%} <section class="refunds-container refunds-container-js page-padding"> <div class="refunds-view refunds-view--intro refunds-initial-view-js"> <div class="refunds-intro"> <h2 class="refunds-intro__heading">{{ translations.ReturnInThreeSteps }}</h2> <p class="refunds-intro__lead">{{ translations.ReturnWithoutReasonInfo }}</p> <ol class="refunds-steps"> <li class="refunds-steps__item"> <span class="refunds-steps__text"> <strong>{{ translations.Log_Login }}</strong> {{ translations.OrEnterOrderNumber }} </span> </li> <li class="refunds-steps__item"> <span class="refunds-steps__text"> <strong>{{ translations.FillForm }}</strong> {{ translations.ReturnOnline }} </span> </li> <li class="refunds-steps__item"> <span class="refunds-steps__text"> <strong>{{ translations.SendParcel }}</strong> &ndash; {{ translations.SendParcelToOurAddress }} </span> </li> </ol> <p class="refunds-intro__hint">{{ translations.FastSimpleSecure }}</p> </div> <div class="refunds-card"> <h3 class="refunds-card__heading">{{ translations.ReadyForReturn }}</h3> <p class="refunds-card__text">{{ translations.ReadyForReturnInfo }}</p> {% if customer.Authenticated -%} <a class="primary-action-button refunds-card__btn" href="{{ config.DefinedPages.CustomerProfile.Url }}?tab=orders-active"> {{ translations.StartReturn }} </a> {% else -%} <button type="button" class="primary-action-button refunds-card__btn start-refund-js"> {{ translations.StartReturn }} </button> {% endif -%} </div> </div> <div class="refunds-view refunds-view--lookup refund-form-view-js hidden-js"> <div class="refunds-lookup"> <h2 class="refunds-lookup__heading">{{ translations.ProductReturn }}</h2> <p class="refunds-lookup__lead">{{ translations.ProductReturnFormInfo }}</p> <div class="form inputs-container-js refund-form-js" data-error="{{ translations.RefundLookupError }}"> <div class="form__input-wrapper"> <input id="refunds-orderNumber" class="form__input-value form__input-value-js" type="text" name="orderNumber" autocomplete="off" required /> <label for="refunds-orderNumber" class="form__input-info form__input-info-js">{{ translations.Com_OrderNumber }}</label> <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> </div> <div class="form__input-wrapper"> <input id="refunds-email" class="form__input-value form__input-value-js" type="email" name="email" autocomplete="email" required /> <label for="refunds-email" data-type="email" class="form__input-info form__input-info-js">{{ translations.EmailAddress }}</label> <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> <p class="form__invalid-input form__validation-info-js" style="display: none">{{ translations.InvalidEmail }}</p> </div> <button type="button" class="primary-action-button refund-form-submit-js"> {{ translations.FindOrder }} </button> {% if customer.Authenticated == false -%} <p class="refunds-lookup__loginPrompt"> {{ translations.Reg_HaveAcc }} <button type="button" class="refunds-lookup__loginLink refunds-login-trigger-js"> {{ translations.Log_Login }} </button> {{ translations.LoginToSeeOrdersAndReturn }} </p> {% endif -%} </div> </div> </div> </section> {% if customer.Authenticated == false -%} <div class="popup-dialog popup-dialog-js popup-dialog-js--loginRegister loginRegister loginRegister--login-only"> {% include 'partials/common/login-register-popup.html' -%} </div> {% endif -%} {% if settings.newsletterOnFunctionalPages == 'yes' -%} {% include 'partials/newsletter-global.html' -%} {% endif -%}

Plik js/layout1.js – kod obsługi formularza zwrotu

Na końcu pliku js/layout1.js dodaj poniższy kod odpowiedzialny za walidację i wysłanie formularza wyszukiwania zamówienia (dla niezalogowanego klienta). Po zapisaniu pamiętaj o zminifikowaniu pliku do layout1.min.js. $(document).ready(function() { refunds.init(); }); const refunds = { init: function() { this.events(); }, findRefundOrder: function(orderNumber, email) { return $.post('', { __action: 'Order/QuickReturnLookup', orderId: orderNumber, email: email, __csrf: __CSRF }); }, showForm: function() { $('.refunds-initial-view-js').addClass('hidden-js'); $('.refund-form-view-js').removeClass('hidden-js'); $('.refund-form-js input[name="orderNumber"]').trigger('focus'); }, clearFieldError: function(input) { const $input = $(input); const $wrapper = $input.closest('.form__input-wrapper'); $input.removeClass('form__validation-error-js'); $wrapper.removeClass('form__validation-error-js'); $wrapper.find('.form__invalid-input').hide(); }, submitForm: async function(button) { const $submit = $(button); const $form = $submit.closest('.refund-form-js'); const $orderInput = $form.find('input[name="orderNumber"]'); const $emailInput = $form.find('input[name="email"]'); const orderValue = $orderInput.val().trim(); const emailValue = $emailInput.val().trim(); const emailRegex = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w{2,}$/; let hasError = false; $form.find('.form__invalid-input').hide(); $form.find('.form__input-value').removeClass('form__validation-error-js'); $form.find('.form__input-wrapper').removeClass('form__validation-error-js'); if (orderValue.length === 0) { $orderInput.addClass('form__validation-error-js'); $orderInput.closest('.form__input-wrapper').find('.form__validation-required-js').show(); hasError = true; } if (emailValue.length === 0) { $emailInput.addClass('form__validation-error-js'); $emailInput.closest('.form__input-wrapper').find('.form__validation-required-js').show(); hasError = true; } else if (emailRegex.test(emailValue)) { $emailInput.removeClass('form__validation-error-js'); } else { $emailInput.addClass('form__validation-error-js'); $emailInput.closest('.form__input-wrapper').find('.form__validation-info-js').show(); hasError = true; } if (hasError) { return; } $submit.prop('disabled', true); try { const result = await refunds.findRefundOrder(orderValue, emailValue); const action = result.action; if (action.Redirect302) { globalThis.location.href = action.Redirect302; return; } app.showTemporaryPopup(action.Message, 'error', '', 8000); } catch (error) { console.error('Refund order lookup failed.', error); app.showTemporaryPopup($form.data('error'), 'error'); } finally { $submit.prop('disabled', false); } }, events: function() { $('body').on('click', '.start-refund-js', function() { refunds.showForm(); }); $('body').on('click', '.refunds-login-trigger-js', function(e) { const $popup = $('.popup-dialog-js--loginRegister'); if ($popup.find('.reminder-container:visible').length > 0) { $popup.find('.backButton-js').click(); } const loginTabText = $popup.find('.loginRegisterTab-js').first().text(); $popup.find('.loginRegisterHeader').text(loginTabText); globalThis.location.hash = '#login-redirect=' + __CustomerProfileUrl + '?tab=orders-active'; $('body').addClass('modal-opened'); $popup.show(); $popup.find('.login-register-close-button').removeClass('hidden'); if (typeof app !== 'undefined' && typeof app.activateFocusTrap === 'function') { app.activateFocusTrap('.popup-dialog-js--loginRegister', e.currentTarget); } if (typeof ui !== 'undefined' && typeof ui.formLabelAnimationOnCartLoginPage === 'function') { ui.formLabelAnimationOnCartLoginPage(); } }); $('body').on('click', '.login-register-close-button', function() { $('.popup-dialog-js--loginRegister').hide(); $('body').removeClass('modal-opened'); history.replaceState(null, '', globalThis.location.pathname + globalThis.location.search); }); $('body').on('input', '.refund-form-js .form__input-value', function() { refunds.clearFieldError(this); }); $('body').on('click', '.refund-form-submit-js', function(e) { e.preventDefault(); refunds.submitForm(this); }); $('body').on('keydown', '.refund-form-js input', function(e) { if (e.key === 'Enter') { e.preventDefault(); $(this).closest('.refund-form-js').find('.refund-form-submit-js').trigger('click'); } }); } };

Pliki SCSS strony Szybkie zwroty

W folderze scss/static-elements utwórz nowy katalog refunds, a w nim trzy pliki: refunds-g.scss (style ogólne), refunds-d.scss (desktop) oraz refunds-m.scss (mobile). scss/static-elements/refunds/refunds-g.scss: .refunds-container { box-sizing: border-box; margin: 0 auto; color: $primaryFontColor; background-color: $primaryPageBg; .refunds-view { display: flex; flex-direction: column; align-items: center; &.hidden-js { display: none; } } .refunds-intro { width: 100%; align-self: stretch; &__heading { margin: 0 0 16px; font-size: $mediumFontSize; font-weight: 600; line-height: 1.4; color: $primaryFontColor; } &__lead { margin: 0 0 16px; font-size: 16px; font-weight: 500; line-height: 1.5; color: $primaryFontColor; } &__hint { margin: 16px 0 0; font-size: $extraSmallFontSize; color: $secondaryFontColor; } } .refunds-steps { list-style: none; counter-reset: refund-step; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; &__item { counter-increment: refund-step; display: flex; align-items: center; gap: 12px; &::before { content: counter(refund-step); flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; background-color: $primaryBtnBg; color: $primaryBtnFontColor; font-weight: 600; font-size: $smallFontSize; line-height: 1; display: inline-flex; align-items: center; justify-content: center; } } &__text { font-size: $smallFontSize; line-height: 1.5; color: $primaryFontColor; strong { font-weight: 600; } } } .refunds-card, .refunds-lookup { box-sizing: border-box; width: 100%; background-color: $primaryPageBg; border: 1px solid $borderColor; border-radius: 8px; display: flex; flex-direction: column; margin-left: auto; margin-right: auto; } .refunds-card { align-items: center; text-align: center; gap: 12px; &__heading { margin: 0; font-size: $bigFontSize; font-weight: 600; line-height: 1.3; color: $primaryFontColor; } &__text { margin: 0; font-size: 16px; line-height: 1.5; color: $secondaryFontColor; } &__btn { width: 100%; margin-top: 12px; } } .refund-form-js { .form__invalid-input { margin: 4px 0 0; font-size: $extraSmallFontSize; line-height: 16px; color: $messageErrorColor; } } .refunds-lookup { gap: 16px; &__heading { margin: 0; font-size: $bigFontSize; font-weight: 600; line-height: 1.3; color: $primaryFontColor; } &__lead { margin: 0; font-size: $smallFontSize; line-height: 1.5; color: $secondaryFontColor; } &__loginPrompt { margin: 8px 0 0; font-size: $smallFontSize; color: $primaryFontColor; } &__loginLink { color: $linkFontColor; font-weight: 600; text-decoration: underline; &:hover, &:focus { text-decoration: none; } } &__error { margin: 0; font-size: $smallFontSize; color: $messageErrorColor; } } } .loginRegister--login-only { .loginRegisterTabsContainer { display: none; } .registrationForm-js { display: none; } } scss/static-elements/refunds/refunds-d.scss: @media screen and (min-width: 769px) { .refunds-container { max-width: 1400px; padding-top: 32px; padding-bottom: 64px; .refunds-view { gap: 32px; } .refunds-intro { &__heading { font-size: 20px; } &__lead { margin-bottom: 24px; } } .refunds-card, .refunds-lookup { max-width: 578px; } .refunds-card { padding: 40px; } .refunds-lookup { padding: 32px; } } } scss/static-elements/refunds/refunds-m.scss: @media screen and (max-width: 768px) { .refunds-container { padding: 16px 3% 40px; .refunds-view { gap: 24px; } .refunds-intro { &__heading { font-size: 18px; } &__lead { font-size: $smallFontSize; margin-bottom: 16px; } } .refunds-steps { &__item { &::before { width: 28px; height: 28px; } } } .refunds-card { padding: 24px 16px; &__heading { font-size: $mediumFontSize; } &__text { font-size: $smallFontSize; } } .refunds-lookup { padding: 20px 16px; &__heading { font-size: $mediumFontSize; } } } }

3. Modyfikacje istniejących plików HTML

partials/customer/order-content.html

W pliku partials/customer/order-content.html wykonaj poniższe zmiany. a) Bezpośrednio po otwarciu kontenera <div class="orderContent order-content-js"> dodaj dwa nowe bannery informacyjne (jeden o ukrytych danych zamówienia, drugi o terminie zwrotu, wraz z wyliczaniem flagi hasReturnableProduct): {% if order.Restricted -%} <div class="orderContent__returnInfo" role="note"> <svg height="20" width="20" class="svgIcon orderContent__returnInfo__icon"> <use xlink:href="css/img/icons-sprite.svg#circle-info-regular"></use> </svg> <span>{{ translations.RestrictedOrderViewInfo }}</span> </div> {% endif -%} {% assign hasReturnableProduct = false -%} {% if config.Complaints.ReturnsEnabled -%} {% for product in order.Products -%} {% if product.CanReturn -%} {% assign hasReturnableProduct = true -%} {% break -%} {% endif -%} {% endfor -%} {% endif -%} {% if hasReturnableProduct -%} <div class="orderContent__returnInfo" role="note"> <svg height="20" width="20" class="svgIcon orderContent__returnInfo__icon"> <use xlink:href="css/img/icons-sprite.svg#circle-info-regular"></use> </svg> <span>{{ translations.Prf_ReturnPeriodInfo | Format: config.Complaints.DaysToReturn }}</span> </div> {% endif -%} b) Kontener <div class="orderContent__docsToPrint">...</div> (z dokumentami do druku) opakuj warunkiem {% unless order.Restricted -%} ... {% endunless -%}, aby ukrywać go dla zamówień typu restricted. c) Cały dotychczasowy blok przycisków reklamacji/zwrotu (oparty na konstrukcji {% if ComplaintsEnabled and ReturnsEnabled %} ... {% elseif ComplaintsEnabled %} ... {% elseif ReturnsEnabled %} ... {% endif %} z jednym wspólnym przyciskiem) zamień na dwa niezależne warunki, dzięki czemu dla produktu uprawnionego zarówno do reklamacji, jak i do zwrotu, oba przyciski wyświetlają się obok siebie. Strukturę wewnątrz warunku {% if product.CanComplain or product.CanReturn -%} zastąp poniższym kodem: {% if config.Complaints.ComplaintsEnabled == true and product.CanComplain -%} <button class="orderContent__complainBtn orderContent__complainBtn--complaint showPopupBtn-js addDataToComplaintForm-js" data-popup-class="popupDialog" data-form-type="complaint" data-product-id="{{product.No}}" data-image-id="{{product.ImageId}}" data-imageext="{{product.Image.ExternalUrl}}" data-product-name="{{product.NameNoHtml | H}}" data-product-complain="{{product.CanComplain}}" data-product-count="{{ newProductQuantity }} {{ product.Unit }}" data-product-unit="{{ product.Unit }}" data-product-description="{{ productAttributes | Join: ' / ' | H }}" data-product-return="false" data-product-quantity="{{newProductQuantity}}" data-order-id="{{order.Id}}" data-order-date="{{order.Date | Date: 'yyyy-MM-dd'}}"> <svg height="16" width="16" class="svgIcon"> <use xlink:href="css/img/icons-sprite.svg#comment-alt-regular"></use> </svg> {{translations.Prf_SendComplaint }} </button> {% endif -%} {% if config.Complaints.ReturnsEnabled == true and product.CanReturn -%} <button class="orderContent__complainBtn orderContent__complainBtn--return showPopupBtn-js addDataToComplaintForm-js" data-popup-class="popupDialog" data-form-type="return" data-product-id="{{product.No}}" data-image-id="{{product.ImageId}}" data-imageext="{{product.Image.ExternalUrl}}" data-product-name="{{product.NameNoHtml | H}}" data-product-complain="false" data-product-count="{{ newProductQuantity }} {{ product.Unit }}" data-product-unit="{{ product.Unit }}" data-product-description="{{ productAttributes | Join: ' / ' | H }}" data-product-return="{{product.CanReturn}}" data-product-quantity="{{newProductQuantity}}" data-order-id="{{order.Id}}" data-order-date="{{order.Date | Date: 'yyyy-MM-dd'}}"> <svg height="16" width="16" class="svgIcon"> <use xlink:href="css/img/icons-sprite.svg#sync-regular"></use> </svg> {{ translations.Prf_OrderReturn }} </button> {% endif -%} Kluczowe różnice w stosunku do poprzedniej wersji: każdy przycisk renderowany jest niezależnie (oba mogą wystąpić równocześnie), przyciski mają modyfikatory orderContent__complainBtn--complaint i orderContent__complainBtn--return, atrybut data-form-type (odczytywany w JS), w przycisku reklamacji wymuszone data-product-return="false", w przycisku zwrotu wymuszone data-product-complain="false", ikony 16x16 (#comment-alt-regular dla reklamacji, #sync-regular dla zwrotu), a etykieta przycisku zawiera już tylko jedno tłumaczenie. d) W pozostałych miejscach z przyciskami reklamacji/zwrotu (sekcje, w których nie zmieniają się klasy i ikony) dodaj jedynie dwa nowe atrybuty: data-product-unit="{{ product.Unit }}" data-product-description="{{ productAttributes | Join: ' / ' | H }}" e) W sekcji załączników zamówienia zamień: {% if order.Attachments[0] -%} na: {% if order.Attachments[0] and order.Restricted == false -%} f) W kontenerze <div class="orderContent__recipient orderContent__infoBox"> zamień wyświetlanie adresu dostawy: <span class="orderContent__lightText">{{ order.Customer.DeliveryAddress.Street }} {{ order.Customer.DeliveryAddress.StreetNo }} / {{ order.Customer.DeliveryAddress.UnitNo }}</span> na: <span class="orderContent__lightText">{{ order.Customer.DeliveryAddress.Street }} {{ order.Customer.DeliveryAddress.StreetNo }}{% if order.Customer.DeliveryAddress.UnitNo != null and order.Customer.DeliveryAddress.UnitNo != '' -%} / {{ order.Customer.DeliveryAddress.UnitNo }}{% endif -%}</span> g) Sekcję z przyciskami akcji zamówienia (orderCancel-js, ponowienie płatności itd.) opakuj warunkiem {% unless order.Restricted -%} ... {% endunless -%}. Wstaw {% unless order.Restricted -%} bezpośrednio przed warunkiem {% if order.CanRestorePayment -%}, a {% endunless -%} po zamykającym {% endif -%} bloku z przyciskiem anulowania zamówienia.

partials/common/complaint-popup.html

Plik partials/common/complaint-popup.html wymaga gruntownej przebudowy. Usuwamy z niego radiowe przyciski wyboru "reklamacja/zwrot", a typ formularza jest teraz przekazywany z zewnątrz przez parametr __include. Sterowanie ilością zostało przeniesione do kafelka z produktem (z etykietą i obsługą wariantu statycznego, gdy zostaje tylko 1 sztuka). W formularzu zwrotu zamiast samego pola numeru konta pojawia się sekcja wyboru sposobu zwrotu środków (refundMethod-js) – z opcją „zwrot na sposób płatności" (domyślna) lub „zwrot na konto bankowe". Pole numeru konta jest domyślnie ukryte i disabled; pokazuje się dopiero po wybraniu opcji „konto bankowe" (obsługa w JS w metodzie changeRefundMethod). Tytuł, kafelek produktu i formularz oznaczone są dodatkową klasą complain-form-view-js, dzięki czemu po pomyślnym wysłaniu formularza można je ukryć i wyświetlić ekran sukcesu (complain-success-view-js). Zastąp całą zawartość pliku poniższym kodem: {% if hideContent -%} {% else -%} {% assign formType = include -%} {% assign isReturn = false -%} {% if formType == 'return' -%} {% assign isReturn = true -%} {% endif -%} <div class="popupDialog popupDialog__complain popupDialog-js"> {% assign order = customer-profile.Order -%} <div class="popupDialog__wrapper"> <button class="popupDialog__closeBtn closePopupBtn-js"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#times-light"></use> </svg> </button> <span class="popupDialog__title complain-form-view-js"> {% if isReturn -%} {{ translations.Prf_OrderReturn }} {% else -%} {{ translations.Prf_SendComplaint }} {% endif -%} </span> <div class="complain__product complain-form-view-js"> <figure> <img class="productImage-js" src="" alt="product_image"> <svg height="20" width="20" class="svgIcon svgIcon--emptyImage"> <use href="css/img/icons-sprite.svg#image-regular"></use> </svg> </figure> <div class="complain__productInfo"> <span class="complain__productTitle productName-js"></span> <span class="complain__productDescription productDescription-js"></span> <div class="complain__quantity"> <label for="complaint-quantity" class="complain__quantityLabel">{{translations.Com_Quantity}}:</label> <div class="complain__quantityControl min-js quantityControl-js"> <button aria-label="{{translations.ButtonMinusAddProduct}}" type="button" class="button-minus-add-product" data-field="quantity"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#minus-light"></use> </svg> </button> <input id="complaint-quantity" class="quantity-field quantity__field-js" name="quantity" data-decimal="false" type="number" min="1" max="" value="1"> <button aria-label="{{ translations.ButtonPlusAddProduct }}" type="button" class="button-plus-add-product" data-field="quantity"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#plus-light"></use> </svg> </button> </div> <span class="complain__quantityStatic quantityStatic-js hidden"></span> <span class="complain__quantityUnit productUnit-js"></span> </div> </div> </div> <div class="form complain__form inputs-container-js complain-form-view-js" data-success-info="{{ translations.ReportSuccessInfo }}"> <input type="hidden" name="__action" value="{% if isReturn -%}Order/ReturnAdd{% else -%}Order/ComplaintAdd{% endif -%}"/> <strong>{{ translations.ReportDetails }}</strong> {% unless isReturn -%} <div class="form__input-wrapper"> {% if config.Complaints.Defects <> null -%} {% assign defectsSize = config.Complaints.Defects | Size -%} <label for="defectId" class="hidden">{{ translations.ChooseComplaintCause }}</label> <select id="defectId" name="defectId" class="form__input-value form__input-value-js {% if settings.themeName == 'Dark' -%} darkTheme {% endif -%}" required> {% if defectsSize > 1 -%} <option value="-1">* {{translations.ChooseComplaintCause}}</option> {% endif -%} {% for def in config.Complaints.Defects -%} <option value="{{def.Id}}">{{def.Name}}</option> {% endfor -%} </select> {% endif -%} <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> </div> <div class="form__input-wrapper"> <span class="form__icons"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#calendar-regular"></use> </svg> </span> <input type="date" name="defectDate" id="defectDate" class="form__input-value form__icon_padding form__input-value-js orderDate-js" placeholder="yyyy-MM-dd" value="{{config.Now | Date: 'yyyy-MM-dd'}}" max="{{config.Now | Date: 'yyyy-MM-dd'}}" min="{{order.Date | Date: 'yyyy-MM-dd'}}"/> <label for="defectDate" class="form__input-info">* {{translations.Prf_DefectDate}}</label> </div> <div class="form__input-wrapper"> {% if config.Complaints.Requests <> null -%} {% assign requestsSize = config.Complaints.Requests | Size -%} <label for="requestId" class="hidden">{{ translations.Prf_ComplainRequest }}</label> <select id="requestId" name="requestId" class="form__input-value form__input-value-js {% if settings.themeName == 'Dark' -%} darkTheme {% endif -%}" required> {% if requestsSize > 1 -%} <option value="-1">* {{translations.Prf_ComplainRequest}}</option> {% endif %} {% for req in config.Complaints.Requests -%} <option value="{{req.Id}}">{{req.Name}}</option> {% endfor -%} </select> {% endif -%} <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> </div> {% else -%} {% assign returnTypes = config.Complaints.Returns | Size -%} {% if returnTypes > 1 -%} <div class="form__input-wrapper"> <label for="returnId" class="hidden">{{ translations.ChooseReturn }}</label> <select id="returnId" name="returnId" class="form__input-value form__input-value-js {% if settings.themeName == 'Dark' -%} darkTheme {% endif -%}" required> <option value="-1">* {{translations.ChooseReturn}}</option> {% for return in config.Complaints.Returns -%} <option value="{{return.Id}}">{{return.Name}}</option> {% endfor -%} </select> <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> </div> {% endif %} {% endunless -%} <div class="form__input-wrapper returnInputWrapper-js refundMethodWrapper-js"> <label for="refundMethod" class="complain__sectionLabel">{{ translations.RefundMethod }}</label> <select id="refundMethod" name="refundMethod" class="form__input-value form__input-value-js refundMethod-js {% if settings.themeName == 'Dark' -%}darkTheme{% endif -%}"> <option value="payment">{{ translations.RefundAsPaid }}{% if order.Payment.Name != null and order.Payment.Name != '' %} ({{ order.Payment.Name }}){% endif %}</option> <option value="account">{{ translations.RefundToBankAccount }}</option> </select> </div> <div class="form__input-wrapper accountNumberWrapper-js" style="display: none"> <input class="form__input-value form__input-value-js" id="accountNumber" type="text" name="accountNumber" maxlength="50" disabled /> <label for="accountNumber" class="form__input-info form__input-info-js">{{translations.Crt_BankAccountNumber}}</label> <p class="form__invalid-input form__validation-required-js" style="display: none">{{ translations.Com_FieldIsMandatory }}</p> </div> <div class="form__input-wrapper"> {{translations.Prf_AdditionalInfo}} <textarea aria-label="{{ translations.Prf_AdditionalInfo }}" class="form__input-value" name="message"></textarea> </div> <div class="form__input-wrapper"> <span class="form__requiredFields--info">* {{ translations.Com_RequiredFields }}</span> </div> {% if config.Complaints.AttachmentsEnabled -%} <div class="form__input-wrapper attachementsInputWrapper" data-not-added-info="{{translations.AttachementsNotAdded}}"> <button class="form__attachementsLabel form__attachementsLabel--btn form__attachementsLabel-js" data-page="complaints"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#paperclip-{{settings.iconStyle}}"></use> </svg> {{ translations.AddAttachment }} </button> {% capture maxSize -%}{{config.Complaints.AttachmentMaxSize | DividedBy: 1024}}KB{% endcapture -%} {% for i in (1..config.Complaints.AttachmentsMaxCount) -%} <div class="form__attachement-input-container form__attachement-input-container-attachments form__attachement-input-container--hidden"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use class="svgIconType" href="css/img/icons-sprite.svg#file-light"></use> </svg> <span class="form__attachement-input-container-attachments__text"></span> <input aria-label="{{ translations.AddAttachment }}" class="addAttachementInComplaint-js" type="file" name="file" accept="{{ config.Complaints.AttachmentExtensions }}" data-file-size="{{ config.Complaints.AttachmentMaxSize }}" data-size-exceeded="{{ translations.Com_FileSizeExceeded | Format: maxSize }}" data-invalid-file="{{ translations.Com_InvalidFile | Format: config.Complaints.AttachmentExtensions }}" /> <button class="form__clear-attachement-input clearFileInput-js" style="display: none"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#times-light"></use> </svg> </button> </div> {% endfor -%} </div> {% endif -%} <input type="hidden" class="productId-js" name="no" value=""/> <input type="hidden" class="orderId-js" name="orderId" value="{{order.Id}}"/> <button type="button" data-id="{{order.Id}}" class="primary-action-button orderComplaintOrReturnAdd-js">{{translations.Report}}</button> </div> <div class="complain__successView complain-success-view-js hidden"> <div class="complain__successIcon"> <svg aria-hidden="true" height="64" width="64" class="svgIcon"> <use href="css/img/icons-sprite.svg#check-circle-{{settings.iconStyle}}"></use> </svg> </div> <h2 class="complain__successTitle">{{ translations.ComplaintSuccessTitle }}</h2> <p class="complain__successDescription">{{ translations.ComplaintSuccessDescription }}</p> <div class="complain__successInfoBox"> <svg aria-hidden="true" height="20" width="20" class="svgIcon"> <use href="css/img/icons-sprite.svg#info-circle-{{settings.iconStyle}}"></use> </svg> <span> {{ translations.ComplaintSuccessConfirmationSent }} <strong>{{ order.Customer.Email }}</strong> </span> </div> <h3 class="complain__successStepsTitle">{{ translations.ComplaintSuccessStepsTitle }}</h3> <ol class="complain__successSteps"> <li>{{ translations.ComplaintSuccessStep1 }}</li> <li> {{ translations.ComplaintSuccessStep2 }} {{ config.Shop.Address.Street }} {{ config.Shop.Address.StreetNo }}{% if config.Shop.Address.UnitNo != '' %}/{{ config.Shop.Address.UnitNo }}{% endif %}, {{ config.Shop.Address.ZipCode }} {{ config.Shop.Address.City }} </li> <li>{{ translations.ComplaintSuccessStep3 }}</li> </ol> <div class="complain__successActions"> <button type="button" class="primary-action-button closePopupBtn-js">{{ translations.BtnClose }}</button> </div> </div> </div> </div> {% endif -%}

4. Modyfikacje pliku js/layout1.js

Poniższe zmiany dotyczą pliku js/layout1.js. Po edycji pamiętaj o zminifikowaniu pliku do layout1.min.js. a) W obiekcie customerProfile usuń całą metodę setComplainReturnRadioButtons (radiowy przełącznik reklamacja/zwrot nie jest już potrzebny – typ formularza jest teraz przekazywany przy otwieraniu popupu). b) W tym samym obiekcie zastąp całą metodę addDataToComplaintForm nową implementacją, która odczytuje typ formularza z atrybutu data-form-type przycisku i przekazuje go do szablonu jako parametr __include: addDataToComplaintForm: function (e) { const template = 'partials/common/complaint-popup.html'; const data = e.currentTarget; const formType = data.dataset.formType === 'return' ? 'return' : 'complaint'; $.get('', {__template: template, __include: "'" + formType + "'"}, function(result) { $('.customer__content-js').append(result.template); $('.popupDialog__complain').show(); $('body').addClass('customerProfileNoScroll'); const image = $('.productImage-js'); const productName = $('.productName-js'); const inputId = $('.productId-js'); const productQuantity = $('.quantity__field-js'); const quantityControl = $('.quantityControl-js'); const quantityStatic = $('.quantityStatic-js'); const productUnit = $('.productUnit-js'); const productDescription = $('.productDescription-js'); const orderId = $('.orderId-js'); const buttonOrderId = $('.orderComplaintOrReturnAdd-js'); const orderDate = $('.orderDate-js'); productName.text(data.dataset.productName); productUnit.text(data.dataset.productUnit || ''); productDescription.text(data.dataset.productDescription || ''); inputId.val(data.dataset.productId); productQuantity.attr('max', data.dataset.productQuantity); if (parseInt(data.dataset.productQuantity, 10) <= 1) { quantityControl.addClass('hidden'); quantityStatic.text(data.dataset.productQuantity).removeClass('hidden'); } else { quantityControl.removeClass('hidden'); quantityStatic.addClass('hidden'); } orderId.val(data.dataset.orderId); buttonOrderId.attr('data-id', data.dataset.orderId); orderDate.attr('min', data.dataset.orderDate); if (data.dataset.imageext != null && data.dataset.imageext != "") { image.attr('src', data.dataset.imageext); } else if (data.dataset.imageId != null && data.dataset.imageId != "") { image.attr('src', '/Image/?id=' + data.dataset.imageId); } if (image.attr('src') === '' || image.attr('src') == null) { image.closest('figure').addClass('noImage-js'); } setTimeout(function() { app.activateFocusTrap('.popupDialog__complain', e.target); }, 200); }); }, c) Zastąp metodę changeReturnComplaintForm nową wersją (obsługuje również pole numeru konta i wywołuje changeRefundMethod po przełączeniu na zwrot): changeReturnComplaintForm: function (e) { const form = $(e.currentTarget).closest('.inputs-container-js'); const complaintInputs = form.find('.complaintInputWrapper-js'); const returnInputs = form.find('.returnInputWrapper-js'); const accountWrapper = form.find('.accountNumberWrapper-js'); const accountInput = accountWrapper.find('input[name="accountNumber"]'); if ($(e.currentTarget).is(':checked') && e.currentTarget.dataset.name === 'complaint' ) { $.each(complaintInputs, function (index, value) { $(value).find('input, select').first().removeAttr('disabled'); $(value).show(300); }); returnInputs.each(function () { $(this).find('input, select').first().attr('disabled', 'true'); }); returnInputs.hide(300); accountInput.removeAttr('disabled').removeAttr('required').removeClass('form__validation-error-js'); accountWrapper.find('.form__validation-required-js').hide(); accountWrapper.show(300); } if ($(e.currentTarget).is(':checked') && e.currentTarget.dataset.name === 'return' ) { $.each(complaintInputs, function (index, value) { $(value).find('input, select').first().attr('disabled', 'true'); $(value).hide(300); }); returnInputs.each(function () { $(this).find('input, select').first().removeAttr('disabled'); }); returnInputs.show(300); customerProfile.changeRefundMethod(form); } }, d) Tuż za metodą changeReturnComplaintForm dodaj nową metodę changeRefundMethod (pokazuje / ukrywa pole numeru konta bankowego na podstawie wybranego sposobu zwrotu): changeRefundMethod: function (formOrEvent) { const form = formOrEvent && formOrEvent.currentTarget ? $(formOrEvent.currentTarget).closest('.inputs-container-js') : $(formOrEvent); const select = form.find('.refundMethod-js'); const accountWrapper = form.find('.accountNumberWrapper-js'); const accountInput = accountWrapper.find('input[name="accountNumber"]'); if (select.val() === 'account') { accountInput.removeAttr('disabled').attr('required', 'required'); accountWrapper.show(300); } else { accountInput.attr('disabled', 'true').removeAttr('required').removeClass('form__validation-error-js'); accountWrapper.find('.form__validation-required-js').hide(); accountWrapper.hide(300); } }, e) W metodzie wysyłającej formularz reklamacji/zwrotu (gdzie znajduje się pętla for (let i=0; i<dataFromHTML.length; i++)) zaraz po pętli dodaj fragment dołączający parametr qrHash z URL-a przy wysyłaniu zwrotu: if (form.find('input[name="__action"]').val() === 'Order/ReturnAdd') { const qrHash = new URLSearchParams(globalThis.location.search).get('qrHash'); if (qrHash) { fd.append('qrHash', qrHash); } } f) W tej samej metodzie, w callbacku success po pomyślnym wysłaniu, zamień fragment: if (data.action.Result) { const message = form.data('success-info'); app.showTemporaryPopup(message, 'success', '', 8000); $('.clearFileInput-js').hide(); app.hidePopup(e); sessionStorage.removeItem('complains'); sessionStorage.removeItem('order' + (e.currentTarget).dataset.id); $('.order' + (e.currentTarget).dataset.id).remove(); $('.popupDialog__complain').remove(); $('body').removeClass('customerProfileNoScroll'); customerProfile.showOrderDetails(e); } na: if (data.action.Result) { $('.clearFileInput-js').hide(); sessionStorage.removeItem('complains'); sessionStorage.removeItem('order' + (e.currentTarget).dataset.id); const popup = $(e.currentTarget).closest('.popupDialog__complain'); popup.find('.complain-form-view-js').addClass('hidden'); popup.find('.complain-success-view-js').removeClass('hidden'); popup.find('.popupDialog__wrapper').scrollTop(0); } g) W sekcji rejestracji zdarzeń profilu klienta (tam, gdzie znajdują się m.in. mainSection.on('change', '.radioComplaint-js, .radioReturn-js', ...)) tuż za istniejącym handlerem zmiany typu formularza dopisz nowy handler: mainSection.on('change', '.refundMethod-js', function (e) { customerProfile.changeRefundMethod(e); }); h) Znajdź globalny handler obsługujący keydown z selektorem zaczynającym się od .radioReturn-js label, .radioComplaint-js label, ... i usuń z niego dwa pierwsze selektory (po zmianie zaczyna się od .showHideSection-js): // PRZED $('body').on('keydown', '.radioReturn-js label, .radioComplaint-js label, .showHideSection-js, .checkBoxes__container label, .customerPagination__form-js, .discountsDetails-js, .customer-focus, .customer__menuActivate-js', function(e) { ... }); // PO $('body').on('keydown', '.showHideSection-js, .checkBoxes__container label, .customerPagination__form-js, .discountsDetails-js, .customer-focus, .customer__menuActivate-js', function(e) { ... }); i) W obiekcie app w pliku js/layout1.js obsłuż przekierowanie po zalogowaniu z parametrem #login-redirect= (używanym przez stronę szybkich zwrotów). W bloku rejestracji/logowania, w miejscu gdzie obsługiwany jest hash #back-to-cart, tuż po nim dodaj: if (globalThis.location.hash.startsWith('#login-redirect=')) { url = globalThis.location.hash.slice('#login-redirect='.length); } Następnie w handlerze sukcesu logowania, gdzie znajduje się sprawdzenie window.location.hash.includes('#back-to-cart') wraz z przekierowaniem, tuż za nim dodaj analogiczny blok przekierowujący w przypadku #login-redirect=: if (globalThis.location.hash.startsWith('#login-redirect=')) { globalThis.location.assign(globalThis.location.hash.slice('#login-redirect='.length)); return; }

5. Modyfikacje plików SCSS profilu klienta

Poniższe style należy dodać do plików scss/static-elements/customer-profile/customer-profile-g.scss (style ogólne), customer-profile-d.scss (desktop) i customer-profile-m.scss (mobile). Po zmianach pamiętaj o kompilacji SCSS – nie edytuj ręcznie wynikowych plików CSS.

Plik customer-profile-g.scss

a) Wewnątrz selektora opakowującego (tam, gdzie znajdują się istniejące reguły .orderContent__complainBtn) dodaj nowe reguły dla banera informacyjnego oraz kontenera grupującego przyciski reklamacji/zwrotu: .orderContent__returnInfo { display: flex; align-items: center; gap: 10px; margin: 16px 0 24px; padding: 12px 16px; background-color: color-mix(in srgb, #{$linkFontColor} 4%, transparent); border: 1px solid color-mix(in srgb, #{$linkFontColor} 20%, transparent); border-radius: 4px; font-size: 13px; line-height: 1.4; color: $primaryFontColor; &__icon { flex-shrink: 0; fill: $linkFontColor; } } .orderContent__complainBtns { display: flex; flex-wrap: wrap; gap: 16px; margin: 16px 0 4px; } b) Następnie zastąp istniejące style .orderContent__complainBtn nowym wyglądem przycisku (z tłem, obramowaniem i hoverem): .orderContent__complainBtn { display: inline-flex; align-items: center; gap: 6px; margin: 16px 0 4px; padding: 6px 12px; background: transparent; border: 1px solid transparent; border-radius: 4px; color: $linkFontColor; fill: $linkFontColor; font-size: 13px; font-weight: 500; line-height: 1.2; white-space: nowrap; cursor: pointer; transition: background-color 180ms, border-color 180ms; .orderContent__complainBtns & { margin: 0; } svg { margin: 0; flex-shrink: 0; } &:hover, &:focus-visible { background-color: color-mix(in srgb, #{$linkFontColor} 6%, transparent); border-color: color-mix(in srgb, #{$linkFontColor} 25%, transparent); outline: none; } } c) Dodaj style etykiety sekcji oraz kontenera sposobu zwrotu w popupie reklamacji: .complain__sectionLabel { display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: $primaryFontColor; } .refundMethodWrapper-js { margin-bottom: 18px; } d) Dodaj kompletne style ekranu sukcesu zwrotu (m.in. ikona, tytuł, lista kolejnych kroków, sekcja z e-mailem i przyciskiem zamknięcia): .complain__successView { text-align: center; padding: 16px 0 0; } .complain__successIcon { display: flex; justify-content: center; margin: 8px 0 20px; .svgIcon { width: 64px; height: 64px; fill: #2d8c4a; } } .complain__successTitle { font-size: 20px; font-weight: 600; line-height: 1.3; margin: 0 0 12px; color: $primaryFontColor; } .complain__successDescription { font-size: 14px; line-height: 1.5; color: $primaryFontColor; margin: 0 0 20px; } .complain__successInfoBox { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; margin: 0 0 24px; border: 1px solid #cfdcef; background-color: #f0f5fc; border-radius: 6px; text-align: left; .svgIcon { flex-shrink: 0; margin-top: 2px; fill: #3a6ea5; } span { font-size: 13px; line-height: 1.5; color: $primaryFontColor; } strong { display: block; font-weight: 600; margin-top: 2px; word-break: break-all; } } .complain__successStepsTitle { font-size: 15px; font-weight: 600; margin: 0 0 12px; text-align: left; color: $primaryFontColor; } .complain__successSteps { margin: 0 0 24px; padding-left: 22px; text-align: left; li { font-size: 14px; line-height: 1.6; margin-bottom: 6px; color: $primaryFontColor; } } .complain__successActions { display: flex; justify-content: flex-end; padding-top: 16px; padding-bottom: 30px; margin-top: 8px; border-top: 1px solid $borderColor; .primary-action-button { min-width: 140px; margin: 0; } @media screen and (max-width: 599px) { .primary-action-button { width: 100%; min-width: 0; } } } e) Zaktualizuj style załączników – znajdź istniejące reguły .form__clear-attachement-input oraz reguły z position: absolute; top: 11px; i zastąp je nowymi (które ustawiają załączniki w układzie statycznym z poprawnym overflowem i przyciskiem usuwania): .form__attachement-input-container-attachments__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .form__attachement-input-container--hidden, .form__attachement-input-container-attachments.form__attachement-input-container--hidden { display: none; } .form__clear-attachement-input { position: static; background: transparent; border: none; padding: 2px 4px; margin: 0 0 0 4px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; svg { fill: $linkFontColor; transition: opacity 200ms; } &:hover svg { opacity: 0.7; } }

Plik customer-profile-d.scss

Wewnątrz wrappera @media screen and (min-width: 769px) zamień istniejące style przycisku reklamacji: .customer .orderContent__complainBtn { position: absolute; bottom: 8px; } na poniższy fragment (dodaje pozycjonowanie kontenera grupującego przyciski oraz osobny selektor dla pojedynczych przycisków w wierszu produktu): .customer .orderContent__complainBtns { position: absolute; bottom: 8px; right: 0; margin: 0; } .customer .orderContent__productDetails > .orderContent__complainBtn { position: absolute; bottom: 8px; right: 0; margin: 0; }

Plik customer-profile-m.scss

W obrębie selektora .customer zamień istniejący media-query @media screen and (max-width: 359px) wraz z jego wnętrzem na rozszerzoną wersję (układająca przyciski reklamacji/zwrotu pionowo na szerokościach do 450px): @media screen and (max-width: 450px) { .customer__orderContent .orderContent__productsRow { max-height: none; } .customer__orderContent .orderContent__productDetails { display: flex; flex-direction: column; align-items: stretch; } .customer__orderContent .orderContent__complainBtns { display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: 100%; margin: 12px 0 4px; padding-top: 12px; border-top: 1px solid $borderColor; } .customer__orderContent .orderContent__complainBtn { display: flex; width: 100%; justify-content: center; padding: 10px 12px; margin: 12px 0 4px; border-color: color-mix(in srgb, #{$linkFontColor} 25%, transparent); } .customer__orderContent .orderContent__complainBtns .orderContent__complainBtn { margin: 0; } }

6. Szablon One Page Shop

Szablon One Page Shop ma praktycznie identyczną strukturę plików jak Topaz. Wszystkie powyższe modyfikacje (tłumaczenia, nowa strona zwrotów, edycje plików partials/common/complaint-popup.html oraz partials/customer/order-content.html, zmiany w js/layout1.js oraz w plikach SCSS profilu klienta i strony zwrotów) wykonaj 1:1 w plikach szablonu OPS pod tymi samymi ścieżkami. Treść kodu jest taka sama, ścieżki plików są takie same – instrukcja dla Topaza w pełni stosuje się również do One Page Shopa. Po wprowadzeniu wszystkich powyższych zmian w szablonie Topaz (oraz One Page Shop) pamiętaj o kompilacji oraz minifikacji plików js i scss, zgodnie z artykułem dostępnym pod linkiem https://pomoc.comarchesklep.pl/artykul/kompilacja-i-minifikacja-plikow/.
Wskazówka
Potrzebujesz pomocy lub masz pytania? Skontaktuj się z nami poprzez portal asysta.comarch.pl.