Aula 77 – Loja Online – Ajax no Contact Form

Aula 77 – Loja Online – Ajax no Contact Form

Loja Online - Django

Loja Online – Django

Pacote Programador Fullstack

Pacote Programador Fullstack

Voltar para página principal do blog

Todas as aulas desse curso

Aula 76                       Aula 78

Redes Sociais:

facebook

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Quer aprender python3 de graça e com certificado? Acesse então:

https://workover.com.br/python-codigo-fluente

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


Aula 77 – Loja Online – Ajax no Contact Form

Vamos refatorar o contact form pra usar o Ajax nele.

Como no e_commerce/e_commerce/urls.py o name do endpoint contact é contact, então vamos colocar o action no arquivo abaixo como contact, da seguinte forma: ‘{% url “contact” %}’.

Isso garante que o Jquery atue no lugar certo.

Outra coisa que vamos fazer é colocar o as_p no form, para renderizar o form como parágrafo e como vamos reutilizar ele, colocaremos uma classe chamada contact-form que vai funcionar como um seletor para o Jquery.

Além disso, por uma questão de formatação visual, vamos colocar o <p>{{ content }}</p> dentro da div interna, a que tem a class=’col-md-6 …’.

e_commerce/templates/contact/view.html 


{% extends "base.html" %}

{% block content %}
  <div class='text-center'>
    <h1>{{ title }}</h1>
  </div>
  <div class='container'>
    <div class='row'>
      <div class='col'>
        <div class='col-md-6 col-12 mx-auto'>
          <p>{{ content }}</p>
          <form class='contact-form' method='POST' action='{% url "contact" %}'> {% csrf_token %}
            {{ form.as_p }}
            <button type='submit' class='btn btn-default'>Enviar</button>
          </form>
        </div>
      </div>
    </div>
  </div>
{% endblock %}

Agora vamos para o django_ecommerce/e_commerce/templates/base.html.

Primeiro pegamos o formulário do html com o seletor contact-form.

Em seguida, poderíamos colocar o “POST” como método, mas, vamos pegar o método diretamente do formulário, através do atributo(attr) e atribuir o método a constante contactFormMethod.

Também através do attr, vamos pegar a action, ou seja, o endpoint.

Logo depois temos o método submit do formulário que recebe uma função como argumento e essa função recebe um evento.

Dentro da função temos o event.preventDefault() que já foi explicado na aula 68.

Em seguida serializamos o formulário.

Imagine um exemplo simples de form, só com dois campos, first_name e last_name.

Vamos supor que o usuário tenha preenchido com: Fulano no first_name e Silva no last_name, o serialize vai pegar os dados do form e transformar em uma string assim: FirstName=Fulano&LastName=Silva.

Depois temos o const thisForm = $(this) que pega o formulário em específico que está sendo preenchido.

Logo após temo a parte do Ajax onde temos um grande objeto com as chave method, url, data, success e error.

As chaves success e o error recebem funções como valores, funções essas que retornam objetos, isto é, dicionários chave: valor, dentro de um alert.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        // Contact Form Handler
        const contactForm = $(".contact-form")
        const contactFormMethod = contactForm.attr("method")
        const contactFormEndpoint = contactForm.attr("action")
        contactForm.submit(function(event){
            event.preventDefault()
            const contactFormData = contactForm.serialize()
            const thisForm = $(this)
            $.ajax({
                method: contactFormMethod,
                url: contactFormEndpoint,
                data: contactFormData,
                success: function(data){
                    contactForm[0].reset()
                    $.alert({
                        title: "Sucesso!",
                        content: "Obrigado, dados enviados com sucesso!",
                        theme: "modern",
                    })
                },
                error: function(error){
                    $.alert({
                        title: "Oops!",
                        content: "Ocorreu um erro, tente mais tarde novamente!",
                        theme: "modern",
                    })
                },
            })
        })
        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']") // input name='q'
        const typingTimer = 0;
        const typingInterval = 500 // .5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            // key released
            clearTimeout(typingTimer)
            typingTimer = setTimeout(performSearch, typingInterval)
        })
        searchInput.keydown(function(event){
            // key pressed
            clearTimeout(typingTimer)
        })
        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function performSearch(){
            displaySearching()
            var query = searchInput.val()
            setTimeout(function(){
              window.location.href='/search/?q=' + query
           }, 1000)
        }

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
            })
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
              })
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Retornando a menssagem através JsonResponse

Agora vamos retornar a mensagem: “Obrigado!” através do JsonResponse caso seja uma request Ajax, ao invés de usar uma string em hard code como fizemos acima.

e_commerce/e_commerce/views.py


from django.contrib.auth import authenticate, get_user_model
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect

from .forms import ContactForm

def is_ajax(request):
    return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
def home_page(request):
    context = {
                    "title": "Home Page",
                    "content": "Bem vindo a Home Page",
              }
    if request.user.is_authenticated:
        context["premium_content"] = "Você é um usuário Premium"
    return render(request, "home_page.html", context)
    
def about_page(request):
    context = {
                    "title": "Página Sobre",
                    "content": "Bem vindo a página sobre"
              }
    return render(request, "about/view.html", context)

def contact_page(request):
    contact_form = ContactForm(request.POST or None)
    context = {
                    "title": "Página de Contato",
                    "content": "Bem vindo a página de contato",
                    "form": contact_form	
              }
    if contact_form.is_valid():
        print(contact_form.cleaned_data)
        if is_ajax(request):
            return JsonResponse({"message": "Obrigado!"})
    if contact_form.errors:
        errors = contact_form.errors.as_json()
        if is_ajax(request):
            return HttpResponse(errors, status=400, content_type='application/json')

    return render(request, "contact/view.html", context)

Agora, no content do alert do success, vamos substituir a string hardcode Obrigado, dados enviados com sucesso!“, pela mensagem retornada pelo e_commerce/e_commerce/views.py quando for uma request Ajax como foi dito anteriormente.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        // Contact Form Handler
        const contactForm = $(".contact-form")
        const contactFormMethod = contactForm.attr("method")
        const contactFormEndpoint = contactForm.attr("action")
        contactForm.submit(function(event){
            event.preventDefault()
            const contactFormData = contactForm.serialize()
            const thisForm = $(this)
            $.ajax({
                method: contactFormMethod,
                url: contactFormEndpoint,
                data: contactFormData,
                success: function(data){
                    contactForm[0].reset()
                    $.alert({
                        title: "Sucesso!",
                        content: data.message,
                        theme: "modern",
                    })
                },
                error: function(error){
                    $.alert({
                        title: "Oops!",
                        content: "Ocorreu um erro, tente mais tarde novamente!",
                        theme: "modern",
                    })
                },
            })
        })
        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']") // input name='q'
        const typingTimer = 0;
        const typingInterval = 500 // .5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            // key released
            clearTimeout(typingTimer)
            typingTimer = setTimeout(performSearch, typingInterval)
        })
        searchInput.keydown(function(event){
            // key pressed
            clearTimeout(typingTimer)
        })
        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function performSearch(){
            displaySearching()
            var query = searchInput.val()
            setTimeout(function(){
              window.location.href='/search/?q=' + query
           }, 1000)
        }

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
            })
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
              })
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Agora a parte de quando ocorre um erro.

Por exemplo, quando o usuário digita um email que não seja gmail.

No caso do exemplo, estamos fazendo essa validação no forms.py na função clean_email().

Vamos simular mais um erro, só a título de ilustração, é a parte do clean_content().

e_commerce/e_commerce/forms.py


from django import forms
from django.contrib.auth import get_user_model

User = get_user_model()
class ContactForm(forms.Form):
    full_name = forms.CharField(
        widget=forms.TextInput(
            attrs={
                    "class": "form-control", 
                    "placeholder": "Seu nome completo"
                }
            )
        )
    email     = forms.EmailField(
        widget=forms.EmailInput(
            attrs={
                    "class": "form-control", 
                    "placeholder": "Digite seu email"
                }
            )
        )
    content   = forms.CharField(
        widget=forms.Textarea(
            attrs={
                    "class": "form-control", 
                    "placeholder": "Digite sua mensagem"
                }
            )
        )
    
    def clean_email(self):
        email = self.cleaned_data.get("email")
        if not "gmail.com" in email:
            raise forms.ValidationError("O Email deve ser do gmail.com")
        return email

    def clean_content(self):
        raise forms.ValidationError("O conteúdo está errado.")

E no base.html, vamos formatar a mensagem que vai ser dada no alert.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
      $(document).ready(function(){
        // Contact Form Handler
        const contactForm = $(".contact-form")
        const contactFormMethod = contactForm.attr("method")
        const contactFormEndpoint = contactForm.attr("action")
        contactForm.submit(function(event){
            event.preventDefault()
            const contactFormData = contactForm.serialize()
            const thisForm = $(this)
            $.ajax({
                method: contactFormMethod,
                url: contactFormEndpoint,
                data: contactFormData,
                success: function(data){
                    contactForm[0].reset()
                    $.alert({
                        title: "Sucesso!",
                        content: data.message,
                        theme: "modern",
                    })
                },
                error: function(error){
                    console.log(error.responseJSON)
                    const jsonData = error.responseJSON
                    let msg = ""
                    $.each(jsonData, function(key, value){
                        msg += key + ": " + value[0].message + "<br />"
                    })
                    $.alert({
                        title: "Oops!",
                        content: msg,
                        theme: "modern",
                    })
                },
            })
        })
        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']") // input name='q'
        const typingTimer = 0;
        const typingInterval = 500 // .5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            // key released
            clearTimeout(typingTimer)
            typingTimer = setTimeout(performSearch, typingInterval)
        })
        searchInput.keydown(function(event){
            // key pressed
            clearTimeout(typingTimer)
        })
        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function performSearch(){
            displaySearching()
            var query = searchInput.val()
            setTimeout(function(){
              window.location.href='/search/?q=' + query
           }, 1000)
        }

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
            })
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
              })
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Se você testar agora usando um email que não seja gmail, vai mostrar as duas mensagens de erro no alert.

Trocando o botão

Vamos mudar o botão de submit, simular um atraso de resposta para dá tempo de ver o “Enviando…“.

Durante esse atraso ele mostra o “Enviando…” depois o botão volta ao submit.

e_commerce/templates/base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Base Template</title>
    {% include 'base/css.html' %}
    {% block base_head %}{% endblock base_head %}
  </head>
  <body>
    {% include 'base/navbar.html' with nome_da_marca='Loja virtual' %}
    <div class='container'>
      {% block content %} {% endblock %}
    </div>
    {% include 'base/js.html' %}
    <script>
        $(document).ready(function(){
            // Contact Form Handler
            var contactForm = $(".contact-form")
            var contactFormMethod = contactForm.attr("method")
            var contactFormEndpoint = contactForm.attr("action")
            function displaySubmitting(submitBtn, defaultText, doSubmit){
                if (doSubmit){
                    submitBtn.addClass("disabled")
                    submitBtn.html("<i class='fa fa-spin fa-spinner'></i> Enviando...")
                } else {
                    submitBtn.removeClass("disabled")
                    submitBtn.html(defaultText)
                }
            }
            contactForm.submit(function(event){
                event.preventDefault()
                const contactFormSubmitBtn = contactForm.find("[type='submit']")
                const contactFormSubmitBtnTxt = contactFormSubmitBtn.text()
                const contactFormData = contactForm.serialize()
                const thisForm = $(this)
                displaySubmitting(contactFormSubmitBtn, "", true)
                $.ajax({
                    method: contactFormMethod,
                    url: contactFormEndpoint,
                    data: contactFormData,
                    success: function(data){
                        contactForm[0].reset()
                        $.alert({
                            title: "Success!",
                            content: data.message,
                            theme: "modern",
                        })
                        setTimeout(function(){
                            displaySubmitting(contactFormSubmitBtn, contactFormSubmitBtnTxt, false)
                        }, 500)
                    },
                    error: function(error){
                        console.log(error.responseJSON)
                        const jsonData = error.responseJSON
                        let msg = ""
                        $.each(jsonData, function(key, value){
                            msg += key + ": " + value[0].message + "<br/>"
                        })
                        $.alert({
                            title: "Oops!",
                            content: msg,
                            theme: "modern",
                        })
                        setTimeout(function(){
                            displaySubmitting(contactFormSubmitBtn, contactFormSubmitBtnTxt, false)
                        }, 500)
                }
            })
        })

        // Auto Search
        const searchForm = $(".search-form")
        const searchInput = searchForm.find("[name='q']") // input name='q'
        const typingTimer = 0;
        const typingInterval = 500 // .5 seconds
        const searchBtn = searchForm.find("[type='submit']")
        searchInput.keyup(function(event){
            // key released
            clearTimeout(typingTimer)
            typingTimer = setTimeout(performSearch, typingInterval)
        })
        searchInput.keydown(function(event){
            // key pressed
            clearTimeout(typingTimer)
        })
        function displaySearching(){
            searchBtn.addClass("disabled")
            searchBtn.html("<i class='fa fa-spin fa-spinner'></i> Searching...")
        }

        function performSearch(){
            displaySearching()
            var query = searchInput.val()
            setTimeout(function(){
              window.location.href='/search/?q=' + query
           }, 1000)
        }

        //Cart + Add Product
        const productForm = $(".form-product-ajax")
        productForm.submit(function(event){
        event.preventDefault();
        // console.log("O formulário não foi enviado!");
        // o this pega os dados relacionados a esse form
        const thisForm = $(this);
        //const actionEndpoint = thisForm.attr("action");
        const actionEndpoint = thisForm.attr("data-endpoint");
        const httpMethod = thisForm.attr("method");
        const formData = thisForm.serialize();
        $.ajax({
          url: actionEndpoint,
          method: httpMethod,
          data: formData,
          success: function(data){
            // console.log("Sucesso")
            // console.log(data)
            // console.log("Adicionado", data.added)
            // console.log("Removido", data.removed)
            const submitSpan = thisForm.find(".submit-span")
            if(data.added){
              submitSpan.html("No carrinho <button type='submit' class='btn btn-link'>Excluir</button>")
            } else {
              submitSpan.html("<button type='submit' class='btn btn-success'>Adicionar</button>")
            }
            const navbarCount = $(".navbar-cart-count")
            navbarCount.text(data.cartItemCount)
            const currentPath = window.location.href
            if(currentPath.indexOf("cart") != -1){
              refreshCart()
            }
          },
          error: function(errorData){
            $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
            })
            console.log("Erro")
            console.log(errorData)
          }
        })
      })
      function refreshCart(){
        //console.log("Excluído do carrinho atual!")
        const cartTable = $(".cart-table")
        const cartBody = cartTable.find(".cart-body")
        //cartBody.html("<h1>Mudou!</h1>")
        const productsRow = cartBody.find(".cart-product")
        const currentUrl = window.location.href 
        const refreshCartUrl = '/api/cart/';
        const refreshCartMethod = "GET";
        const data = {};
        $.ajax({
          url: refreshCartUrl,
          method: refreshCartMethod,
          data: data,
          success: function(data){
            console.log(data)
            const hiddenCartItemRemoveForm = $(".cart-item-remove-form")
            if(data.products.length > 0){
              productsRow.html(" ")
              let i = data.products.length
              $.each(data.products, function(index, value){
                const newCartItemRemove = hiddenCartItemRemoveForm.clone()
                newCartItemRemove.css("display", "block")
                newCartItemRemove.find(".cart-item-product-id").val(value.id)
                cartBody.prepend("<tr><th scope=\"row\">" + i + 
                "</th><td><a href='" + value.url + "'>" + 
                value.name + "</a>" + newCartItemRemove.html() + "</td><td>" + value.price + "</td></tr>")
                i--
              })
              cartBody.find(".cart-subtotal").text(data.subtotal)
              cartBody.find(".cart-total").text(data.total)
            } else {
                  window.location.href = currentUrl
              }
            },
            error: function(errorData){
              $.alert({
                title: "Oops!",
                content: "Ocorreu um erro, tente mais tarde novamente!",
                theme: "modern",
              })
              console.log("Erro")
              console.log(errorData)
            }
          })
        }
      })
    </script>
  </body>
</html>

Ficamos por aqui e até a próxima. 😉

Voltar para página principal do blog

Todas as aulas desse curso

Aula 76                       Aula 78

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

Dêem um joinha 👍 na página do Código Fluente no
Facebook.

Sigam o Código Fluente no Instagram e no TikTok.

Código Fluente no Pinterest.

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Nos vemos na próxima então, \o/  😉 Bons Estudos!

 

About The Author
-

2 Comentários

  • alaor
    Reply

    otimo curso. parabens. no meu caso so tenho problema ao instalar no heroku, o painel administrativo fica todo baguncado e sem a parte grafica.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>