Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Dúvida] Na última subtração não zera as estatísticas, alguém pode me ajudar?

Implementei algumas validações no código, como diminuir os atributos do robô, não permitir que o contador fique negativo, porém quando chega no valor do contador igual a 1, para fazer a última subtração, não faz.

Arquivo javascript

const controle = document.querySelectorAll("[data-controle]")
const estatisticas = document.querySelectorAll("[data-estatistica]")

const pecas = {
  "bracos": {
    "forca": 29,
    "poder": 35,
    "energia": -21,
    "velocidade": -5
  },
  "blindagem": {
    "forca": 41,
    "poder": 20,
    "energia": 0,
    "velocidade": -20
  },
  "nucleos": {
    "forca": 0,
    "poder": 7,
    "energia": 48,
    "velocidade": -24
  },
  "pernas": {
    "forca": 27,
    "poder": 21,
    "energia": -32,
    "velocidade": 42
  },
  "foguetes": {
    "forca": 0,
    "poder": 28,
    "energia": 0,
    "velocidade": -2
  }
}

controle.forEach((elemento) => {
  elemento.addEventListener("click", (evento) => {

    // o "parentNode" busca o pai do elemento
    manipulaDados(evento.target.dataset.controle, evento.target.parentNode)

    atualizaEstatisticas(evento.target.dataset.controle, evento.target.parentNode, evento.target.dataset.peca)
  })
})

function manipulaDados(operacao, controle) {

  // Aqui o "querySelector" vai busca apenas no elemento filho do "parentNode" passado como parâmentro
  const peca = controle.querySelector("[data-contador]")

  if (operacao === "-" && peca.value > 0) {
    peca.value = parseInt(peca.value) - 1
  }
  else if(operacao === "+" && peca.value < 99){
    peca.value = parseInt(peca.value) + 1
  }
}

function atualizaEstatisticas(operacao, controle, peca) {
  const contador = controle.querySelector("[data-contador]")

  //console.log(pecas[peca]) // Utilizando anotação de colchetes para acessar o objeto pecas;
  estatisticas.forEach((elemento) => {

    if (operacao === "-" && contador.value > 0) {
      elemento.textContent = parseInt(elemento.textContent) - pecas[peca][elemento.dataset.estatistica]
    } 
    else if (operacao === "+" && contador.value < 99) {
      elemento.textContent = parseInt(elemento.textContent) + pecas[peca][elemento.dataset.estatistica]
    }
  })
}
5 respostas

Oi, Allan!

Você pode compartilhar seu código completo?

Aqui está o arquivo html

<!DOCTYPE html>
<html lang="pt-br">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" type="image/jpg" href="img/favicon.ico" />
  <title>Robotron 2000</title>

  <link rel="stylesheet" href="css/style.css">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Teko:wght@300;500&display=swap" rel="stylesheet">
</head>

<body>
  <main>
    <section class="robotron">
      
      <img class="robo" src="img/robotron.png" alt="Robotron" id="robotron">
      <figcaption class="titulo">ROBOTRON <br>2000</figcaption>
    </section>

    <section class="box estatisticas">
      <div class="estatistica">
        <p class="estatistica-titulo">Força</p>
        <div class="estatistica-valor">
          <p class="estatistica-numero" data-estatistica="forca">0</p>
        </div>
      </div>
      <div class="estatistica">
        <p class="estatistica-titulo">Poder</p>
        <div class="estatistica-valor">
          <p class="estatistica-numero" data-estatistica="poder">0</p>
        </div>
      </div>
      <div class="estatistica">
        <p class="estatistica-titulo">Energia</p>
        <div class="estatistica-valor">
          <p class="estatistica-numero" data-estatistica="energia">0</p>
        </div>
      </div>
      <div class="estatistica">
        <p class="estatistica-titulo">Velocidade</p>
        <div class="estatistica-valor">
          <p class="estatistica-numero" data-estatistica="velocidade">0</p>
        </div>
      </div>
    </section>

    <section class="equipamentos">
      <form action="" class="montador">
        <div class="box montador-conteudo">
          <div class="peca">
            <label for="" class="peca-titulo">Braços</label>
            <div class="controle">
              <buttom class="controle-ajuste" data-controle="-" data-peca="bracos">-</buttom>
              <input type="text" class="controle-contador" value="0" data-contador>
              <buttom class="controle-ajuste" data-controle="+" data-peca="bracos">+</buttom>
            </div>
          </div>
          <hr class="linha">
          <div class="peca">
            <label for="" class="peca-titulo">Blindagem</label>
            <div class="controle">
              <buttom class="controle-ajuste" data-controle="-" data-peca="blindagem">-</buttom>
              <input type="text" class="controle-contador" value="0" data-contador>
              <buttom class="controle-ajuste" data-controle="+" data-peca="blindagem">+</buttom>
            </div>
          </div>
          <hr class="linha">
          <div class="peca">
            <label for="" class="peca-titulo">Núcleos</label>
            <div class="controle">
              <buttom class="controle-ajuste" data-controle="-" data-peca="nucleos">-</buttom>
              <input type="text" class="controle-contador" value="0" data-contador>
              <buttom class="controle-ajuste" data-controle="+" data-peca="nucleos">+</buttom>
            </div>
          </div>
          <hr class="linha">
          <div class="peca">
            <label for="" class="peca-titulo">Pernas</label>
            <div class="controle">
              <buttom class="controle-ajuste" data-controle="-" data-peca="pernas">-</buttom>
              <input type="text" class="controle-contador" value="0" data-contador>
              <buttom class="controle-ajuste" data-controle="+" data-peca="pernas">+</buttom>
            </div>
          </div>
          <hr class="linha">
          <div class="peca">
            <label for="" class="peca-titulo">Foguetes</label>
            <div class="controle">
              <buttom class="controle-ajuste" data-controle="-" data-peca="foguetes">-</buttom>
              <input type="text" class="controle-contador" value="0" data-contador>
              <buttom class="controle-ajuste" data-controle="+" data-peca="foguetes">+</buttom>
            </div>
          </div>
        </div>
        <input type="submit" value="Iniciar produção" class="producao" id="producao">
      </form>
    </section>
  </main>
  <script src="./js/main.js"></script>
</body>

</html>

E o arquivo css

:root {
    --main-cinza: #CCCCCC;
    --main-branco: #FFFFFF;
    --main-preto: #000000;
}

* {
    box-sizing: border-box;
}

body {
    background: url(../img/fundo.jpg);
    background-position: center center;
    background-size: cover cover;
    padding: 0;
    margin: 0;
    font-weight: 300;
}

body, input {
    font-family: 'Teko', sans-serif;
}

main {
    width: 80vw;
    height: 80vh;
    margin: 10vh 8vw 10vh 12vw;
    display: flex;
    gap: 1vw;
}

.robotron {
    background: url(../img/estrutura.png) no-repeat;
    background-position: center center;
    margin: 0;
    flex-basis: 40%;
    position: relative;
}

.robo {
    height: 110%;
    z-index: 1;
    position: absolute;
    left: -20%;
    top: -5%;
}

.titulo {
    transform: rotate(180deg);
    font-weight: 500;
    font-size: 130px;
    position: absolute;
    bottom: 7rem;
    left: -3rem;
    line-height: 0.8;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    color: rgba(255,255,255,0.8)
}

.box {
    background: rgba(0,0,0,0.6);
    clip-path: polygon(calc(100% - 30px) 0, 100% 30px, 100% calc(100% - 30px), calc(100% - 30px) 100%, 30px 100%, 0 calc(100% - 30px), 0 30px, 30px 0);
    border-left: 5px solid var(--main-cinza);
    height: 80%;
}

/****************************** Equipamentos *****/

.equipamentos {
    flex-basis: 32%;
}

.montador {
    height: 100%;;
}

.montador-conteudo {
    padding: 2em 10%;
}

.peca {
    padding: 1em 0;
}

.peca-titulo {
    color: var(--main-branco);
    text-transform: uppercase;
    font-size: 2.5em;
}

.controle {
    background: var(--main-preto);
    border-radius: 25px;
    float: right;
    display: inline-flex;
    padding: 5px;
    align-items: center;
    align-self: flex-end;
}

.controle-contador {
    width: 40px;
    height: 35px;
    background: none;
    border: 0;
    margin: 0 1rem;
    color: var(--main-branco);
    text-align: center;
    font-size: 2.5em;
    display: inline-flex;
    align-items: center;
    padding-top: 8px;
}

.controle-ajuste {
    display: inline-block;
    width: 40px;
    height: 40px;
    line-height: 44px;
    border-radius: 50%;
    color: var(--main-cinza);
    font-size: 4em;
    background: var(--main-preto);
    text-align: center;
    border: 3px solid var(--main-cinza);
    cursor: pointer;
}

.linha {
    border-color: var(--main-cinza);
}

.producao {
    margin-top: 1em;
    font-size: 2em;
    text-transform: uppercase;
    padding: 0.2em 1em;
    float: right;
    border: 3px solid var(--main-branco);
    background: var(--main-branco);
    clip-path: polygon(100% 0, 100% calc(100% - 30px), calc(100% - 30px) 100%, 0 100%, 0 0);
    cursor: pointer;
}

.producao:hover {
    background: var(--main-preto);
    color: var(--main-branco)
}



/****************************** Estatísticas *****/
.estatisticas {
    flex-basis: 23%;
    padding: 2em 2em 0;
}

.estatistica {
    color: var(--main-branco);
    display: flex;
    align-items: flex-start;
    height: 25%;
}

.estatistica-titulo {
    font-size: 1.5em;
    border-bottom: 1px solid var(--main-cinza);
    flex-basis: 40%;
    text-transform: uppercase;
    order: 1
}

.estatistica-valor {
    flex-basis: 60%;
    position: relative;
    margin: 10px 0 0;
    order: 2;
    margin: -10px 0 0;
}

.estatistica-valor::after {
    content: "";
    display: block;
    padding-bottom: 100%;
    border: 1px solid var(--main-cinza);
    border-radius: 50%;
}

.estatistica-numero {
    position: absolute;
    top: 50%;
    transform: translateY(-46%);
    width: 100%;
    line-height: 100%;
    text-align: center;
    font-size: 3em;
    margin: 0;
}

.estatistica:nth-child(2n) .estatistica-titulo {
    order: 2;
    text-align: right;
}

.estatistica:nth-child(2n) .estatistica-valor {
    order: 1;
    flex-basis: 35%;
    margin: 10px 0 0;
}

@media screen and (max-width: 1600px) {
    body { 
        font-size: 14px;
    }
    main {
        width: 90vw;
        height: 80vh;
        margin: 5vh auto;
    }
}

@media screen and (max-width: 1200px) {
    body { 
        font-size: 13px;
    }

    main {
        width: 96vw;
        height: 80vh;
        margin: 10vh auto;
    }
}

Pronto, Allan! Encontrei o problema. É coisa besta.

Na parte de alterar as estatísticas (arquivo JS), dentro do teu condicional ao invés de colocar "> 0" coloca ">= 0". Porque se tu deixa só o ">" ele não vai considerar o valor 0, então vai parar no 1 mesmo.

Espero que dê tudo certo! :)

solução!

Oi Moana, obrigado pela colaboração, resolvi um problema, mas criou outro, que é, ao colocar a condicional ">=0", o botão de "-" continua diminuindo os valores de "força", "poder", "energia" e "velocidade", mesmo ele mostrando o valor "0".

Então encontrei essa proposta de resolução.

  1. As duas funções "manipulaDados" e "atualizaEstatisticas", manipulam o mesmo data-attribute "[data-contador]";
  2. Elas são chamadas no mesmo evento de click, e na ordem em que são declaradas;
  3. Quando se coloca a primero a função "manipulaDados", ela altera o valor em "-1" ou "+1" do "[data-attribute]", que nessa função é atribuída a constante "peca", e na função "atualizaEstatisticas", é atribuída a constante "contador";
  4. Veja no console.log nas linhas 46 e 58, a constante "contador" é sempre uma valor maior ou menor do que a constante "peca";
  5. O que faz que quando entramos na condicional da linha linha 63 dentro da função "atualizaEstatisticas" ele já está com valor "0", por isso não faz a última subtração;

Então a resolução é chamar a função "atualizaEstatistica" antes da função "manipulaDados", ou seja pelo menos uma linha acima.

const controle = document.querySelectorAll("[data-controle]")
const estatisticas = document.querySelectorAll("[data-estatistica]")

const pecas = {
  bracos: {
    forca: 29,
    poder: 35,
    energia: -21,
    velocidade: -5
  },
  blindagem: {
    forca: 41,
    poder: 20,
    energia: 0,
    velocidade: -20
  },
  nucleos: {
    forca: 0,
    poder: 7,
    energia: 48,
    velocidade: -24
  },
  pernas: {
    forca: 27,
    poder: 21,
    energia: -32,
    velocidade: 42
  },
  foguetes: {
    forca: 0,
    poder: 28,
    energia: 0,
    velocidade: -2
  }
}

controle.forEach((elemento) => {
  elemento.addEventListener("click", (evento) => {
  
    manipulaDados(evento.target.dataset.controle, evento.target.parentNode)
    atualizaEstatisticas(evento.target.dataset.controle, evento.target.parentNode, evento.target.dataset.peca)
  })
})

function manipulaDados(operacao, controle) {
  const peca = controle.querySelector("[data-contador]")
  console.log("peca = " + peca.value)

  if (operacao === "-" && peca.value > 0) {
    peca.value = parseInt(peca.value) - 1
  }
  else if (operacao === "+" && peca.value < 99) {
    peca.value = parseInt(peca.value) + 1;
  }
}

function atualizaEstatisticas(operacao, controle, peca) {
  const contador = controle.querySelector("[data-contador]")
  console.log("contador = " + contador.value)

  estatisticas.forEach((elemento) => {
    if (operacao === "-" && contador.value > 0) {
      elemento.textContent = parseInt(elemento.textContent) - pecas[peca][elemento.dataset.estatistica]
    }
    else if (operacao === "+" && contador.value < 99) {
      elemento.textContent = parseInt(elemento.textContent) + pecas[peca][elemento.dataset.estatistica]
    }
  })
}