JavaScriptでアプリを作成しました【Build a Shopping Cart】

公式サイト：[Bootstrap](https://getbootstrap.jp/)
公式サイト：[The suoer fast color paletts generator!](https://coolors.co/)

```
   ├── images
   ├── src
        ├── cart.js
        ├── Data.js
        ├── main.js
        └── style.css
   ├── cart.html
   └── index.html
```

```src/cart.js
let ShoppingCart = document.getElementById('shopping-cart');
let label = document.getElementById('label');

/**
 * ! Basket to hold all the selected items
 * ? the getItem part is retrieving data from the local storage
 * ? if local storage is blank, basket becomes an empty array
 */

let basket = JSON.parse(localStorage.getItem('data')) || [];

/**
 * ! To calculate total amount of selected Items
 */

let calculation = () => {
  let cartIcon = document.getElementById('cartAmount');
  cartIcon.innerHTML = basket.map((x) => x.item).reduce((x, y) => x + y, 0);
};

calculation();

/**
 * ! Generates the Cart Page with product cards composed of
 * ! images, title, price, buttons, & Total price
 * ? When basket is blank -> show's Cart is Empty
 */

let generateCartItems = () => {
  if (basket.length !== 0) {
    return (ShoppingCart.innerHTML = basket
      .map((x) => {
        let { id, item } = x;
        let search = shopItemsData.find((x) => x.id === id) || [];
        let { img, price, name } = search;
        return `
      <div class="cart-item">
        <img width="100" src=${img} alt="" />

        <div class="details">
        
          <div class="title-price-x">
            <h4 class="title-price">
              <p>${name}</p>
              <p class="cart-item-price">$ ${price}</p>
            </h4>
            <i onclick="removeItem(${id})" class="bi bi-x-lg"></i>
          </div>

          <div class="cart-buttons">
            <div class="buttons">
              <i onclick="decrement(${id})" class="bi bi-dash-lg"></i>
              <div id=${id} class="quantity">${item}</div>
              <i onclick="increment(${id})" class="bi bi-plus-lg"></i>
            </div>
          </div>

          <h3>$ ${item * price}</h3>
        
        </div>
      </div>
      `;
      })
      .join(''));
  } else {
    ShoppingCart.innerHTML = '';
    label.innerHTML = `
    <h2>Cart is Empty</h2>
    <a href="index.html">
      <button class="HomeBtn">Back to Home</button>
    </a>
    `;
  }
};

generateCartItems();

/**
 * ! used to increase the selected product item quantity by 1
 */

let increment = (id) => {
  let selectedItem = id;
  let search = basket.find((x) => x.id === selectedItem.id);

  if (search === undefined) {
    basket.push({
      id: selectedItem.id,
      item: 1,
    });
  } else {
    search.item += 1;
  }

  generateCartItems();
  update(selectedItem.id);
  localStorage.setItem('data', JSON.stringify(basket));
};

/**
 * ! used to decrease the selected product item quantity by 1
 */

let decrement = (id) => {
  let selectedItem = id;
  let search = basket.find((x) => x.id === selectedItem.id);

  if (search === undefined) return;
  else if (search.item === 0) return;
  else {
    search.item -= 1;
  }

  update(selectedItem.id);
  basket = basket.filter((x) => x.item !== 0);
  generateCartItems();
  localStorage.setItem('data', JSON.stringify(basket));
};

/**
 * ! To update the digits of picked items on each item card
 */

let update = (id) => {
  let search = basket.find((x) => x.id === id);
  document.getElementById(id).innerHTML = search.item;
  calculation();
  TotalAmount();
};

/**
 * ! Used to remove 1 selected product card from basket
 * ! using the X [cross] button
 */

let removeItem = (id) => {
  let selectedItem = id;
  basket = basket.filter((x) => x.id !== selectedItem.id);
  calculation();
  generateCartItems();
  TotalAmount();
  localStorage.setItem('data', JSON.stringify(basket));
};

/**
 * ! Used to calculate total amount of the selected Products
 * ! with specific quantity
 * ? When basket is blank, it will show nothing
 */

let TotalAmount = () => {
  if (basket.length !== 0) {
    let amount = basket
      .map((x) => {
        let { id, item } = x;
        let filterData = shopItemsData.find((x) => x.id === id);
        return filterData.price * item;
      })
      .reduce((x, y) => x + y, 0);

    return (label.innerHTML = `
    <h2>Total Bill : $ ${amount}</h2>
    <button class="checkout">Checkout</button>
    <button onclick="clearCart()" class="removeAll">Clear Cart</button>
    `);
  } else return;
};

TotalAmount();

/**
 * ! Used to clear cart, and remove everything from local storage
 */

let clearCart = () => {
  basket = [];
  generateCartItems();
  calculation();
  localStorage.setItem('data', JSON.stringify(basket));
};
```

```src/Data.js
let shopItemsData = [
  {
    id: 'jfhgbvnscs',
    name: 'Casual Shirt',
    price: 45,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-1.jpg',
  },
  {
    id: 'ioytrhndcv',
    name: 'Office Shirt',
    price: 100,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-2.jpg',
  },
  {
    id: 'wuefbncxbsn',
    name: 'T Shirt',
    price: 25,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-3.jpg',
  },
  {
    id: 'thyfhcbcv',
    name: 'Mens Suit',
    price: 300,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-4.jpg',
  },
  {
    id: 'thiecbawdjksadjk',
    name: 'Mens Tie',
    price: 25,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-5.png',
  },
  {
    id: 'iuertrywebncdjksadjk',
    name: 'Casual shoes',
    price: 200,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-6.png',
  },
  {
    id: 'thierytbvcbvzdhadjk',
    name: 'black suit',
    price: 450,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-7.png',
  },
  {
    id: 'trfoiwfcnbcawdjksadjk',
    name: 'polo shirt',
    price: 45,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-8.png',
  },
  {
    id: 'cbvxbcvsceldk',
    name: 'denim shirt',
    price: 85,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-9.png',
  },
  {
    id: 'oiopijmjkhuihb',
    name: 'denim pants',
    price: 120,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-10.png',
  },
  {
    id: 'oiopijewyiohbjhib',
    name: 'basic cap',
    price: 35,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-11.png',
  },
  {
    id: 'rtytytuyuytyytbvncv',
    name: 'leather boots',
    price: 350,
    desc: 'Lorem ipsum dolor sit amet consectetur adipisicing.',
    img: 'images/img-12.png',
  },
];
```
```src/main.js
let shop = document.getElementById('shop');

/**
 * ! Basket to hold all the selected items
 * ? the getItem part is retrieving data from the local storage
 * ? if local storage is blank, basket becomes an empty array
 */

let basket = JSON.parse(localStorage.getItem('data')) || [];

/**
 * ! Generates the shop with product cards composed of
 * ! images, title, price, buttons, description
 */

let generateShop = () => {
  return (shop.innerHTML = shopItemsData
    .map((x) => {
      let { id, name, desc, img, price } = x;
      let search = basket.find((y) => y.id === id) || [];
      return `
    <div id=product-id-${id} class="item">
      <img width="220" src=${img} alt="">
      <div class="details">
        <h3>${name}</h3>
        <p>${desc}</p>
        <div class="price-quantity">
          <h2>$ ${price} </h2>
          <div class="buttons">
            <i onclick="decrement(${id})" class="bi bi-dash-lg"></i>
            <div id=${id} class="quantity">${
        search.item === undefined ? 0 : search.item
      }</div>
            <i onclick="increment(${id})" class="bi bi-plus-lg"></i>
          </div>
        </div>
      </div>
  </div>
    `;
    })
    .join(''));
};

generateShop();

/**
 * ! used to increase the selected product item quantity by 1
 */

let increment = (id) => {
  let selectedItem = id;
  let search = basket.find((x) => x.id === selectedItem.id);

  if (search === undefined) {
    basket.push({
      id: selectedItem.id,
      item: 1,
    });
  } else {
    search.item += 1;
  }

  console.log(basket);
  update(selectedItem.id);
  localStorage.setItem('data', JSON.stringify(basket));
};

/**
 * ! used to decrease the selected product item quantity by 1
 */

let decrement = (id) => {
  let selectedItem = id;
  let search = basket.find((x) => x.id === selectedItem.id);

  if (search === undefined) return;
  else if (search.item === 0) return;
  else {
    search.item -= 1;
  }

  update(selectedItem.id);
  basket = basket.filter((x) => x.item !== 0);
  console.log(basket);
  localStorage.setItem('data', JSON.stringify(basket));
};

/**
 * ! To update the digits of picked items on each item card
 */

let update = (id) => {
  let search = basket.find((x) => x.id === id);
  document.getElementById(id).innerHTML = search.item;
  calculation();
};

/**
 * ! To calculate total amount of selected Items
 */

let calculation = () => {
  let cartIcon = document.getElementById('cartAmount');
  cartIcon.innerHTML = basket.map((x) => x.item).reduce((x, y) => x + y, 0);
};

calculation();
```

```src/style.css
/**
* ! Changing default styles of the browser
**/

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
}

i {
  cursor: pointer;
}

a {
  text-decoration: none;
  color: white;
}

/**
* ! Navbar STyles are here
**/

.navbar {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  background-color: #212529;
  color: white;
  padding: 25px 60px;
  margin-bottom: 30px;
}

.cart {
  position: relative;
  background-color: #fff;
  color: #212529;
  font-size: 30px;
  padding: 5px;
  border-radius: 4px;
}

.cartAmount {
  position: absolute;
  top: -15px;
  right: -10px;
  font-size: 16px;
  background-color: red;
  color: white;
  padding: 3px;
  border-radius: 3px;
}

/**
* ! Shop items styles are here
**/

.shop {
  display: grid;
  grid-template-columns: repeat(4, 223px);
  gap: 30px;
  justify-content: center;
}

@media (max-width: 1000px) {
  .shop {
    grid-template-columns: repeat(2, 223px);
  }
}

@media (max-width: 500px) {
  .shop {
    grid-template-columns: repeat(1, 223px);
  }
}

.item {
  border: 2px solid #212529;
  border-radius: 4px;
}

.details {
  display: flex;
  flex-direction: column;
  padding: 10px;
  gap: 10px;
}

.price-quantity {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

.buttons {
  display: flex;
  flex-direction: row;
  gap: 8px;
  font-size: 16px;
}

.bi-dash-lg {
  color: red;
}

.bi-plus-lg {
  color: blue;
}

/**
* ! style rules for label and some buttons
**/

.text-center {
  text-align: center;
  margin-bottom: 20px;
}

.HomeBtn,
.checkout,
.removeAll {
  background-color: #212529;
  color: white;
  border: none;
  padding: 6px;
  border-radius: 3px;
  cursor: pointer;
  margin-top: 10px;
}

.checkout {
  background-color: blue;
}
.removeAll {
  background-color: red;
}
.bi-x-lg {
  color: red;
  font-weight: bold;
}

/**
* ! style rules for shopping-cart
**/

.shopping-cart {
  display: grid;
  grid-template-columns: repeat(1, 320px);
  justify-content: center;
  gap: 15px;
}

/**
* ! style rules for cart-item
**/

.cart-item {
  border: 2px solid #212529;
  border-radius: 5px;
  display: flex;
}

.title-price-x {
  width: 195px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* border: 2px solid red; */
}

.title-price {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cart-item-price {
  background-color: #212529;
  color: white;
  border-radius: 4px;
  padding: 3px 6px;
}
```
```chart.html
<!DOCTYPE html>
<html lang="en">
  <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" />
    <title>Clothing Store</title>
    <link rel="stylesheet" href="src/style.css" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css"
    />
  </head>

  <body>
    <div class="navbar">
      <a href="index.html">
        <h2>Clothing Store</h2>
      </a>

      <a href="cart.html">
        <div class="cart">
          <i class="bi bi-cart2"></i>
          <div id="cartAmount" class="cartAmount">0</div>
        </div>
      </a>
    </div>

    <div id="label" class="text-center"></div>

    <div class="shopping-cart" id="shopping-cart"></div>
  </body>
  <script src="src/Data.js"></script>
  <script src="src/cart.js"></script>
</html>
```
```index.html
<!DOCTYPE html>
<html lang="en">

<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">
  <title>Clothing Store</title>
  <link rel="stylesheet" href="src/style.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
</head>

<body>
  <div class="navbar">
    <a href="index.html">
      <h2>Clothing Store</h2>
    </a>

    <a href="cart.html">
      <div class="cart">
        <i class="bi bi-cart2"></i>
        <div id="cartAmount" class="cartAmount">0</div>
      </div>
    </a>

  </div>

  <div id="label" class="text-center"></div>

  <div class="shopping-cart" id="shopping-cart"></div>
</body>
<script src="src/Data.js"></script>
<script src="src/cart.js"></script>

</html>
```
```index.html
<!DOCTYPE html>
<html lang="en">
  <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" />
    <title>Clothing Store</title>
    <link rel="stylesheet" href="src/style.css" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css"
    />
  </head>

  <body>
    <div class="navbar">
      <a href="index.html">
        <h2>Clothing Store</h2>
      </a>

      <a href="cart.html">
        <div class="cart">
          <i class="bi bi-cart2"></i>
          <div id="cartAmount" class="cartAmount">0</div>
        </div>
      </a>
    </div>

    <div class="shop" id="shop"></div>
  </body>
  <script src="src/Data.js"></script>
  <script src="src/main.js"></script>
</html>
```


## 参考サイト
[Build a Shopping Cart with JavaScript – Project Tutorial](https://www.youtube.com/watch?v=cT_ZYrS3tKc&t=5924s)