62. Product list and ordering Frontend

Next, we will adjust the order list page and implement order filters. To achieve this, we will make updates to the store.html file.

These changes will enhance the functionality and usability of the order list and its filtering options.

store.html
{% extends 'base.html' %}
{% load static %}


{% block body %}
<main class="principal principal--padding-b">
    <section class="loja">
      <form class="menu" method="POST" action="">
        {% csrf_token %}
        <div class="menu__cabecalho">
          <div class="menu__titulos">
            <div>
              <img
                class="menu__icone"
                src="{% static 'images/filter-big-1-svgrepo-com.svg' %}"
                alt="Ícone filtrar"
              />
            </div>
            <p class="menu__titulo">Filtrar</p>
          </div>

          <p class="menu__fechar-filtro">X</p>
        </div>

        <div class="menu__preco">
          <p class="menu__subtitulo">Faixa de Preço</p>

          <div class="range_container">
            <div class="sliders_control">
              <input
                id="fromSlider"
                type="range"
                value=0
                min=0
                max={{ max_price }}
                step=0.01
              />
              <input
                id="toSlider"
                type="range"
                value={{ max_price }}
                min=0
                max={{ max_price }}
                step=0.01
              />
            </div>

            <div class="menu__controles">
              <div class="form_control">
                <div class="form_control_container">
                  <input
                    class="form_control_container__time__input"
                    type="number"
                    name="min_price"
                    id="fromInput"
                    value=0
                    min=0
                    max={{ max_price }}
                    step=0.01
                  />
                </div>
                <p>até</p>
                <div class="form_control_container">
                  <input
                    class="form_control_container__time__input"
                    type="number"
                    id="toInput"
                    name="max_price"
                    value={{ max_price }}
                    min=0
                    max={{ max_price }}
                    step=0.01
                  />
                </div>
              </div>

              <button type="submit" class="menu__botao">Filtrar</button>
            </div>
          </div>
        </div>


        <div class="menu__expansivel">
          <div
            class="menu__expansivel-cabecalho menu__expansivel-cabecalho--aberto"
          >
            <p class="menu__subtitulo">Tamanho</p>
          </div>

          <div class="menu__expansivel-conteudo">
            <div class="menu__tamanhos">
            {% for size in sizes %}
              <div class="menu__tamanho">
                <div class="menu__tamanho-quadrado">{{ size }}</div>
                <input
                  class="menu__checkbox"
                  type="radio"
                  name="size"
                  value="{{ size }}"
                />
              </div>
            {% endfor %}

            </div>
          </div>
        </div>

        
        <div class="menu__expansivel">
          <div
            class="menu__expansivel-cabecalho menu__expansivel-cabecalho--aberto"
          >
            <p class="menu__subtitulo">Tipo</p>
          </div>

          <div class="menu__expansivel-conteudo">
            <div class="menu__categorias">
            {% for type in types %}
              <div class="menu__categoria">
                <div class="menu__categoria-quadrado"></div>
                <div class="menu__categoria-texto">{{ type.slug }}</div>
                <input
                  class="menu__checkbox"
                  type="radio"
                  name="type"
                  value="{{ type.slug }}"
                />
              </div>
            {% endfor %}

            </div>
          </div>
        </div>
      </form>

      <div class="produtos">
        <div class="produtos__cabecalho">
          <button class="produtos__cabecalho-filtrar">Filtrar</button>

          <div class="produtos__cabecalho-ordenarpor">
            <div class="produtos__cabecalho-imgicone">
              <img
                class="produtos__cabecalho-icone"
                src="{% static 'images/sort-vertical-svgrepo-com.svg' %}"
                alt=""
              />
            </div>
            <p class="produtos__subtitulo">Ordenar por:</p>
            <select class="produtos__select" onchange="redirectToPage()">
              
              {% if order == "highest-price" %}
              <option value="" selected>Maior preço</option> <!-- Necessary to start by default -->
              {% elif order == "lowest-price" %}
              <option value="" selected>Menor preço</option> <!-- Necessary to start by default -->
              {% elif order == "most-sold" %}
              <option value="" selected>Mais Vendidos</option> <!-- Necessary to start by default -->
              {% else %}
              <option value="" selected>Selecone uma opção</option> <!-- Necessary to start by default -->
              {% endif %}

              <option class="item-order" value="highest-price">Maior preço</option> <!--Used in the main.js javascript, it returns the value used in the js-->
              <option class="item-order" value="lowest-price">Menor preço</option>
              <option class="item-order" value="most-sold">Mais Vendidos</option>
            </select>
          </div>

        </div>

        <div class="produtos__grade">
          {% for product in products %}
          <a
            href="{% url 'view_product' product.id %}"
            class="produto"
          >
            <div class="produto__imagem">
              <img
                src="{{ product.image.url }}"
                alt="Imagem do Produto"
              />
            </div>

            <div class="produto__textos">
              <p class="produto__titulo">{{ product.name }}</p>
              <div class="produto__preco">
                <p class="produto__avista">R$ {{ product.price }}</p>
              </div>
            </div>
          </a>
          {% endfor %}

        </div>
      </div>


    </section>
</main>

{% endblock %}

In the store view function, include the order variable in the context to ensure the selected order option is passed to the template.

views.py/store function
context = {"products" : products, "min_price" : min_price, "max_price" : max_price, "sizes" : sizes, "categories" : categories, "types" : types, "order" : order} 

The updates above added the final product section to the HTML file, using the appropriate CSS classes for styling.

Notably, the href of the filter was replaced with a select element, and URLs are now passed through the value attribute instead of the name attribute. Consequently, the main.js file will be updated to reflect these changes, as the filter functionality for altering the URL is handled via JavaScript.

main.js
/*
the url is a instance of the URL class
document.URL gets the current URL
*/
var url = new URL(document.URL);
var items = document.getElementsByClassName("item-order"); //returns a list of the three href elements

for (i = 0; i < items.length; i++)
{
    url.searchParams.set("order", items[i].value); //(name, value)
    items[i].value = url.href;
};

Now, the products are displayed correctly, and the order filters function as intended, providing the desired sorting and filtering capabilities.

Last updated