Chupachar
@Chupachar
front-end dev

Почему отрабатывает if после отработки else?

Всем привет, по ходу разработки функционала у меня возникло 2 вопроса. В данной работе по клику на кнопку "Добавить авто в корзину" добавляются карточки с актуальными введенными данными в корзину. Так же присутствует кнопка "Добавить транспорт", по клику которой добавляются дополнительный блок с инпутом и селектом для более гибкого ввода данных в корзину.

https://jsfiddle.net/vnwo28ue/47/
https://codepen.io/Andy41/pen/OJwqpXE?editors=1111

Вопрос заключается в том, что на 42 строке имеется переменная let limitCar = 2, которая подразумевает макс количество автомобилей вообще которое является пределом и на 44 строке мне нужно сравнить общую сумму автомобилей + количество автомобилей в одной карточке с limitCar такого вида:
if (amountSum + dataCars.carAmount > limitCar) {}
Сравнивается и работает вроде правильно, но если допустим выбрать при let limitCar = 2 в первом селекте 1 авто а во втором 2, то отработает if с предупреждением что общая сумма больше чем лимит и затем отработает else с добавлением карточки в корзину у которой количество было выбрано 1. Как можно это исправить? Может дело в amountSum?
И второй вопрос, на 89 строке я очищаю все карточки автомобилей из корзины и хранилища, но после повторного добавления авто в корзину возвращаются удаленные карточки. Я понимаю что это как то связано с глобальным getItem, но исправить не получается.
<div class="block">
  <div class="parent">
    <div class="child">
      <input type="text" class="model" placeholder="Введите модель авто">
      <select class="amount">
        <option value="" disabled selected>Количество</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <button class="add">Добавить транспорт</button>
    </div>
  </div>
  <button class="btn">Добавить авто в корзину</button>
</div>
<button class="delete-all" style="background: #e75757;">Удалить все авто из корзины</button>
<div class="cart">
  <span class="cart-title">Корзина</span>
  <div class="info"></div>
</div>


const parent = document.querySelector(".block");
const info = document.querySelector(".info");
LSKeyCars = "cars";
let getCars = JSON.parse(localStorage.getItem(LSKeyCars) || "[]");


let amountSum = getCars.reduce( //общая сумма авто (считаю для условия if на 44 строке)
  (acc, curr) => acc + curr.carAmount,
  0
);
console.log('amountSum before click: ', amountSum)

const renderCars = () => {
  info.innerHTML = getCars
    .map(
      (car) =>
      `<div class="item" id="${car.id}">
       	<div class="title">ЛИЧНЫЙ ТРАНСПОРТ</div>
       	<div>Модель авто: ${car.carModel}</div>
       	<div>Количество авто: ${car.carAmount}</div>
       </div>`
    )
    .join("");
};
renderCars();

let dataCars; //объект с пользов. данными в глобальной обл. видимости
parent.addEventListener("click", function() { //отрендерить данные из LS
  const childArr = [...document.querySelectorAll(".child")];
  if (e.target.classList.contains("btn")) {
    childArr.map(item => { // перебираю все карточки в корзине
      const amount = +item.querySelector(".amount").value;
      const model = item.querySelector(".model").value;

      dataCars = { //объект с пользов. данными
        id: Math.floor(Math.random() * 100),
        carModel: model,
        carAmount: amount,
      };

      let limitCar = 2 //максимальный лимит количества автомобилей
      // если общая сумма + количество из 1 карточки > лимита то не рендерить
      if (amountSum + dataCars.carAmount > limitCar) {
        alert(
          "Количество автомобилей превышает количество взрослых"
        );
      } else {
        getCars.push(dataCars);
        localStorage.setItem("cars", JSON.stringify(getCars));
        renderCars();

        let sumCar = getCars.reduce( // общая сумма авто при клике
          (acc, curr) => acc + curr.carAmount,
          0
        );
        amountSum = sumCar;
        console.log('amountSum after click: ', amountSum)
      }
    })
  }
});

//add select car
const add = document.querySelector(".add");
const child = document.querySelector('.child')
add.addEventListener("click", function() {
  child.insertAdjacentHTML(
    "afterend",
    `<div class="child">
				<input type="text" class="model" placeholder="Введите модель авто">
			<select class="amount">
				<option value="" disabled selected>Количество</option>
				<option value="1">1</option>
				<option value="2">2</option>
				<option value="3">3</option>
			</select>
      	<span class="remove">X<span>
    	</div>`)
})

const remove = document.querySelector('.remove')
parent.addEventListener('click', function(e) {
  if (e.target.classList.contains("remove")) {
    e.target.parentNode.remove()
  }
});

//полностью очистить корзину(конкретно items автомобилей) 
const allRemove = document.querySelector('.delete-all')
allRemove.addEventListener('click', function() {
	//пытаюсь получить актуальный state массива 
  const currentCars = JSON.parse(localStorage.getItem("cars") || "[]");
  const info = document.querySelector(".info");
  if (currentCars) {
    localStorage.removeItem("cars");
    while (info.firstChild) {
      info.removeChild(info.firstChild);
      let sumCar = getCars.reduce( // общая сумма не пересчитывается
        (acc, curr) => acc + curr.carAmount,
        0
      );
      amountSum = sumCar;
      console.log('amountSum allDelete click: ', amountSum)
    }
  }
})
  • Вопрос задан
  • 145 просмотров
Решения вопроса 1
XanXanXan
@XanXanXan
childArr.map(item => { // перебираю все карточки в корзине
.map() обычно используется не для простого перебора, а чтобы вернуть перебранный массив.

в первом селекте 1 авто а во втором 2
В этому случае «перебираются» 2 элемента через этот .map().

При обработке первого элемента отработает случай else, так как на тот момент amountSum будет равно 0 (в storage ничего нет) + dataCars.carAmount = 1. Всего 1, что меньше limitCar.
При обработке второго элемента уже будет amountSum = 1 (записалось при обработке 1-го элемента) + dataCars.carAmount = 2. Всего три что больше limitCar и поэтому будет предупреждение (случай из if).

но после повторного добавления авто в корзину возвращаются удаленные карточки
let getCars = JSON.parse(localStorage.getItem(LSKeyCars) || "[]");
Это записывается один раз. А после очистки корзины не переписывается, если не перезагружать страницу. Поэтому карточки берутся из этой переменной, а не из обновлённых данных storage.

spoiler

const CARS_LIMIT = 2;

const optionsBlock = document.querySelector('.parent');
const cart = document.querySelector('.info');

const addOptionButton = document.querySelector('.add');
const addToCartButton = document.querySelector('.btn');
const clearCartButton = document.querySelector('.delete-all');

addOptionButton.addEventListener('click', addOption);
addToCartButton.addEventListener('click', addItemToCart);
clearCartButton.addEventListener('click', clearCart);

optionsBlock.addEventListener('click', ({ target }) => {
    if (target.closest('.remove')) {
        target.parentNode.remove();
    }
});

function addOption() {
    optionsBlock.insertAdjacentHTML('beforeend',
        `<div class="child">
              <span class="remove">✖</span>
                  <input type="text" class="model" placeholder="Введите модель авто">
              <select class="amount">
                  <option value="" disabled selected>Количество</option>
                  <option value="1">1</option>
                  <option value="2">2</option>
                  <option value="3">3</option>
              </select>
          </div>`)
}

function clearCart() {
    localStorage.removeItem('cars');
    renderCart();
}

function addItemToCart() {
    const currentCarsState = getStorageState() ?? [];
    const carInfoOptions = [...document.querySelectorAll('.child')];

    const carsAmount = currentCarsState.reduce((acc, { carAmount }) => acc + carAmount, 0);

    const { carsData, selectedAmount } = carInfoOptions.reduce((acc, carInfo) => {
        const carAmount = +carInfo.querySelector('.amount').value;
        const carModel = carInfo.querySelector('.model').value;

        const currentCarData = {
            id: Math.floor(Math.random() * 100), //плохой вариант, т.к. случайные числа могут повторяться
            carModel,
            carAmount,
        };

        acc.carsData.push(currentCarData);
        acc.selectedAmount += carAmount;

        return acc;

    }, { carsData: [], selectedAmount: 0 })

    if (carsAmount + selectedAmount > CARS_LIMIT) {
        alert('Количество автомобилей превышает количество взрослых');
        return;
    }

    localStorage.setItem('cars', JSON.stringify([...currentCarsState, ...carsData]));
    renderCart();
}

function getStorageState() {
    return JSON.parse(localStorage.getItem('cars'));
}

function renderCart() {
    const cartData = getStorageState();
    cart.innerHTML = !cartData ? '' : cartData.map(car => `<div class="item" id="${car.id}">
    <div class="title">ЛИЧНЫЙ ТРАНСПОРТ</div>
    <div>Модель авто: ${car.carModel}</div>
    <div>Количество авто: ${car.carAmount}</div>
  </div>`).join('');
}

Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы