<div id="app">
</div>
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

h1, p {
  font-family: Lato;
}

.container {
  position: relative;
  width: 100%;
  overflow: hidden;
}

nav {
  position: fixed;
  width: 100%;
  height: 40px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: crimson;
}

nav > span {
  cursor: pointer;
  color: #fff;
  margin: 0 15px;
}



  .rotateBasket {
    animation-name: rotateBasket;
    animation-duration: 2s;
    animation-delay: 0s;
    animation-direction: normal;
    animation-iteration-count: 2;
    animation-fill-mode: forwards;
    animation-timing-function: linear;
  }
  
  @keyframes rotateBasket {
    0% {
      transform: rotate(0deg);
    }
    20% {
      transform: rotate(45deg);
    }
    40% {
      transform: rotate(-45deg);
    }
    60% {
      transform: rotate(45deg);
    }
    80% {
      transform: rotate(-45deg);
    }
    100% {
      transform: rotate(0deg);
    }
  }

  
.comments {
  margin: 40px auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  max-width: 1200px;
}

.comments > h1 {
  align-self: center;
  color: crimson;
  margin: 20px;
}

.comments > input {
  align-self: center;
  border: 1px solid lightgray;
  padding: 10px;
  box-shadow: 1px 3px 5px -7px rgb(221, 208, 208);
  width: 400px;
  margin-bottom: 20px;
}

.comments > span {
  align-self: center;
  color: crimson;
  margin-bottom: 15px;
  cursor: pointer;
}

.comments-wrapper {
  align-self: center;
  width: 400px;
  margin: 10px auto;
  display: flex;
  flex-direction: column;
}

.comments-wrapper  p {
  display: inline-flex;
  width: 100%;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  color: dimgray;
  margin: auto 5px;
  padding: 20px;
  border-radius: 7px;
  border: 1px solid rgba(214, 192, 192, 0.808);
}

@media all and (max-width: 450px){
  .input, .comments-wrapper {
    width: 100%;
    margin: 0 10px;
  }
  .comments-wrapper  p {
    margin: 0;
  }
}


.cats-all {
  margin: 40px auto;
  overflow: hidden;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
  max-width: 1200px;

}


.single-cat {
  overflow: hidden;
  height: 550px;
  width: 30.333%;
  margin: 10px 1.5%;
  display: inline-flex;
  flex-direction: column;
  border: 1px solid rgba(241, 235, 235, 0.452);
  border-radius: 7px;
  box-shadow: 1px 3px 5px -7px #000;
}

.single-cat > h3 {
  align-self: flex-start;
  color: crimson;
  font-size: 1.4em;
  margin: 20px;
}

.single-cat > img {
  margin: 0 auto;
  height: 340px;
}

.single-cat > p{
  padding: 20px;
}

.single-cat > span {
  padding: 20px;
  color: crimson;
  font-size: 1.2em;

  width: 30px;
  height: 30px;
  align-self: flex-start;
  margin:  20px;
  display: inline-flex;
  border-radius: 50%;
  justify-content: center;
  align-items: center;
  background-color: rgba(211, 205, 205, 0.651);
}

.single-cat > span > i {
  cursor: pointer;
}
@media all and (max-width: 960px){
  .single-cat {
    width: 45%;
    margin: 10px 2.5%;
  }
}

@media all and (max-width: 680px){
  .single-cat {
    width: 100%;
  }
}


.cart {
  margin: 40px auto;
  max-width: 1200px;
}

.items-wrapper {
  overflow: hidden;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
}


.items-wrapper > .single-cat {
  overflow: hidden;
  height: 550px;
  width: 30.333%;
  margin: 10px 1.5%;
  display: inline-flex;
  flex-direction: column;
  border: 1px solid rgba(241, 235, 235, 0.452);
  border-radius: 7px;
  box-shadow: 1px 3px 5px -7px #000;
}

.items-wrapper > .single-cat > h3 {
  align-self: flex-start;
  color: crimson;
  font-size: 1.4em;
  margin: 20px;
}

.items-wrapper > .single-cat > img {
  margin: 0 auto;
  height: 340px;
}

.single-cat > p{
  padding: 20px;
}

.single-cat > span {
  padding: 20px;
  color: crimson;
  font-size: 1.2em;

  width: 30px;
  height: 30px;
  align-self: flex-start;
  margin:  20px;
  display: inline-flex;
  border-radius: 50%;
  justify-content: center;
  align-items: center;
  background-color: rgba(211, 205, 205, 0.651);
}

.items-wrapper > .single-cat > span > i {
  cursor: pointer;
}

.cart > h3 {
  margin: 50px 20px;
}

@media all and (max-width: 960px){
  .single-cat {
    width: 45%;
    margin: 10px 2.5%;
  }
}

@media all and (max-width: 680px){
  .single-cat {
    width: 100%;
    margin: 0;
  }
}
let cats = [
  {
    id: "1",
    name: "cat 1",
    description: "Cat description goes here",
    price: "12.99",
    src:
      "https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/cats-images-for-project/adorable-animal-blur-cat-617278.jpg",
    count: "3"
  },
  {
    id: "2",
    name: "cat 2",
    description: "Cat description goes here",
    price: "22.99",
    src:
      "https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/cats-images-for-project/animal-cat-face-close-up-feline-416160.jpg",
    count: "2"
  },
  {
    id: "3",
    name: "cat 3",
    description: "Cat description goes here",
    price: "17.99",
    src:
      "https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/cats-images-for-project/adorable-animal-cat-302280.jpg",
    count: "5"
  },
  {
    id: "4",
    name: "cat 4",
    description: "Cat description goes here",
    price: "27.99",
    src:
      "https://raw.githubusercontent.com/ivanmmarkovic/misc/master/images/cats-images-for-project/adorable-animal-baby-blur-177809.jpg",
    count: "3"
  }
];

let comments = ["Do you have a cat with a hat?", "Nice"];

class App extends React.Component {
  constructor(props) {
    super();
    this.state = {
      cats: cats,
      cart: [],
      display: {
        cats: true,
        cart: false,
        comments: false
      },
      comments: comments,
      cartLinkClassName: "material-icons"
    }
  }
  addToCart(id) {
    console.log("Added :", id);
    let cats = this.state.cats;
    let cart = this.state.cart;
    for (let i = 0; i < cats.length; i++) {
      if (cats[i].id == id && cats[i].count > 0) {
        if (cart.length === 0) {
          cats[i].count = cats[i].count - 1;
          let cat = Object.assign({}, cats[i]);
          delete(cat.count);
          cat.howMany = typeof cat.howMany === "undefined" ? 1 : cat.howMany + 1;
          cart.push(cat);
        } else {
          let result = cart.filter((item) => item.id == cats[i].id);
          if (result.length === 1) {
            for (let j = 0; j < cart.length; j++) {
              if (cart[j].id == cats[i].id) {
                cats[i].count = cats[i].count - 1;
                cart[j].howMany++;
              }
            }
          } else {
            cats[i].count--;
            let cat = Object.assign({}, cats[i]);
            delete(cat.count);
            cat.howMany = typeof cat.howMany === "undefined" ? 1 : cat.howMany + 1;
            cart.push(cat);
          }
        }
      }
    }
    this.setState({
      cats: cats,
      cart: cart,
      cartLinkClassName: "material-icons rotateBasket"
    });
    setTimeout(() => this.setState({
      cartLinkClassName: "material-icons"
    }), 2000);
  }
  removeItem(id) {
    let cats = this.state.cats;
    let cart = this.state.cart;
    let itemsToGetBack = 0;
    for (let i = 0; i < cart.length; i++) {
      if (cart[i].id == id) {
        let cartIndex = i;
        itemsToGetBack = cart[i].howMany;
        cart.splice(cartIndex, 1);
      }
    }
    for (let i = 0; i < cats.length; i++) {
      if (cats[i].id == id) {
        cats[i].count = cats[i].count + itemsToGetBack;
      }
    }
    this.setState({
      cats: cats,
      cart: cart
    })
  }
  displayThisComponent(comp) {
    switch (comp) {
      case "cats":
        this.setState({
          display: {
            cats: true,
            cart: false,
            comments: false
          }
        });
        break;
      case "cart":
        this.setState({
          display: {
            cats: false,
            cart: true,
            comments: false
          }
        });
        break;
      case "comments":
        this.setState({
          display: {
            cats: false,
            cart: false,
            comments: true
          }
        });
        break;
    }
  }
  addComment(comment) {
    let comments = this.state.comments;
    comments.push(comment);
    this.setState({
      comments: comments
    })
  }
  render() {
    let cats = this.state.display.cats ? <Cats cats={this.state.cats} addToCart={this.addToCart.bind(this)} /> : "";
    let cart = this.state.display.cart ? <Cart cart={this.state.cart} removeItem={this.removeItem.bind(this)}/> : "";
    let comments = this.state.display.comments ? <Comments comments={this.state.comments} addComment={this.addComment.bind(this)}/> : "";
    return (
      <div className="container">
                <nav>
                  <span onClick={() => this.displayThisComponent("cats")}>
                    <i className="material-icons">store</i>
                  </span>
                  <span onClick={() => this.displayThisComponent("cart")}>
                    <i className={this.state.cartLinkClassName}>add_shopping_cart</i>
                  </span>
                  <span onClick={() => this.displayThisComponent("comments")}>
                    <i className="material-icons">chat_bubble</i>
                  </span>
                </nav>
                {cats}
                {cart}
                {comments}
            </div>
    );
  }
}

class Cats extends React.Component {
  render() {
    var addToCart = this.props.addToCart;
    var catsNodes = this.props.cats.map((cat, i) => <Cat key={i} cat={cat} addToCart={addToCart} />);
    return (
      <div className="cats-all" >
                {catsNodes}
            </div>
    );
  }
};

class Cat extends React.Component {
  render() {
    return (
      <div className="single-cat">
                <h3>{this.props.cat.name}</h3>
                <img src={this.props.cat.src} />
                <p><b>Price</b> {this.props.cat.price} | {this.props.cat.count} {" "}available</p>
                <span onClick={() => this.props.addToCart(this.props.cat.id)}><i className="material-icons">add_shopping_cart</i></span>
            </div>
    )
  }
};

class Cart extends React.Component {
  removeItem(id) {
    this.props.removeItem(id);
  }
  render() {
    const removeItem = this.removeItem.bind(this);
    let totalPrice = 0;
    for (let i = 0; i < this.props.cart.length; i++) {
      totalPrice = totalPrice + (this.props.cart[i].price * this.props.cart[i].howMany);
    }
    totalPrice = totalPrice.toFixed(2);
    let itemsNodes = this.props.cart.map((item, i) => {
      let singleCatTotal = (item.price * item.howMany).toFixed(2);
      return (
        <div key={i} className="single-cat">
                <h3>{item.name}</h3>
                <img src={item.src} />
                <p>{item.description}</p>
                <p>Items {item.howMany} | price {item.price} | total {singleCatTotal}</p>
                <span onClick={() => removeItem(item.id)}><i className="material-icons">delete</i></span>
            </div>
      )
    });
    return (
      <div className="cart">
                <div className="items-wraper">
                    {itemsNodes}
                </div>
                <h3>Total : {totalPrice}</h3>
            </div>
    );
  }
};

class Comments extends React.Component {
  constructor(props) {
    super();
    this.state = {
      comment: ""
    }
  }
  getComment(event) {
    this.setState({
      comment: event.target.value
    });
  }
  addComment() {
    if (this.state.comment != "") {
      this.props.addComment(this.state.comment);
    }
    this.setState({
      comment: ""
    })
  }
  render() {
    let commentsNodes = this.props.comments.map((comment, i) => <div key={i}><p>{comment}</p></div>);
    return (
      <div className="comments">
                <h1>Comments</h1>
                <input type="text" onChange={this.getComment.bind(this)} value={this.state.comment}/>
                <span><i className="material-icons" onClick={this.addComment.bind(this)}>message</i></span>
                <div className="comments-wrapper">
          {commentsNodes}
        </div>
            </div>
    )
  }
};

ReactDOM.render(
  <App cats={cats}/>,
  document.getElementById("app")
);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js