React-Redux Amazon Clone Project
Tags: react, javascript, html, css
Published: 2021-06-23 23:23:42

#Final Chapter 

It Has been a journey at Flat Iron School, with many ups and downs without a doubt. Since the beginning of the course, I knew this is what I wanted to do and this final push to finish a 5-month extensive course where it consisted of code every single day sharpened my critical thinking skills as well as my coding skills.

#Intro

For this project I wanted to do something special, Thinking about what other companies look for and what they might look for in a Software Engineer I decided to do an amazon clone with full payment functionality.

##Lets Talk Code

to Start the project I ran

`npx create-react-app Amazon-Clone` 

The way I decided to tackle this project was by splitting everything into sections. The way I started was with something simple and worked my way up therefore, I chose to start with the NavBar. Keeping it simple gave my NavBar a search bar and 3 options that can be customizable and hidden so users who aren't logged in have to Sign In or Sign up for them to use those features.

##Next Step

The next step of this project I went with was I created the Home Page which I will be extracting the Products I need From my 

`Rails API’s`

using 

`gem 'faker'`

With this, I was able to extract my products and create multiple rows using a flexbox using these CSS settings below

```
.home {

  justify-content: center;
  margin-left: auto;
  margin-right: auto;
  max-width: 1500px;
}



.home__row {
  text-align: center;
  display: inline-block;
  z-index: 1;
  margin-left: 5px;
  margin-right: 5px;

}

.home__image {
  width: 100%;
  z-index: -1;
  margin-bottom: -150px;
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
}

.star{
  color: yellow;
  display: flex;
}
.product {
  text-align: left;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  margin: 10px;
  padding: 20px;
  width: 85%;
  max-height: 400px;
  min-width: 100px;
  background-color: white;
  z-index: 1;
}



.product > img {
  max-height: 200px;
  width: 100%;
  object-fit: contain;
  margin-bottom: 15px;
}

.product > button {
  background: #f0c14b;
  border: 1px solid;
  margin-top: 10px;
  border-color: #a88734 #9c7e31 #846a29;
  color: #111;
}

.product__price {
  margin-top: 5px;
}

.product_info {
  width: 100%;
  height: 100px;
  margin-bottom: 15px;
}
```
this enabled me to place the cards in a row with the customization I needed. For this Home page, I needed to have the cards ready right when the DOM loaded and With the skills, I Learned I understood that
`
ComponentDidMount
`

would be a good choice, making a fetch to my back end and have those products ready before the page fully loads.

##Card Layout

On the Home page, the card layout had to be unique since Amazon carries a simple but eye-catching way of setting things up. Therefore, each Product card needed to have the image, title, rating, description, and add to button which is the call to action to enable customers for a quick add to cart for a quick purchase.

###Add To Cart

referencing the above text the Add to cart had to be a dispatch action that enabled me to add the specific product with its attributes to a new array called basket so then later on I would be able to use it. I was able to learn Context, and redux-tool-kit so I did both but stuck with redux-tool-kit for project requirement purposes.  The way the reducer is set up is unique and amazing since the state of this toolkit reducer is an updated state meaning we no longer need spread operators.

####How I set my reducer

To enable redux-tool-kit we have to 

`npm install @reduxjs/toolkit react-redux`

For documentation, you can click [Here](https://redux-toolkit.js.org/tutorials/quick-start) for a Quickstart.

this gives us access to a variety of tools such as 

`configureStore, createSlice, and createAsyncThunk`

Which is what I needed to meet the requirements. For the reducer, I Had to think of each action that I Needed which where 

`addToBasket, removeFromCart, setUserDetails, setUser, emptyBasket`

and this is how I set it up 

```
const basketStore = createSlice({
  name: "basket",
  initialState:{
    basket: [],
    user: localStorage.user,
    userDetails: []
  },
  reducers:{
    addToBasket: (state, action) => {
      state.basket.push(action.payload)
    },
    removeFromCart: (state, action) => {
      const index = state.basket.findIndex(
        (basketItem) => basketItem.id === action.id)
      if (index >= 0){
        state.basket.splice(index,1);
          }else{
       console.warn("No Items Found with the Id of:", action.id)
      }
    },
    emptyBasket: (state, action) => {
      state.basket.clear()
    },
    setUser: (state, action) => {
      console.log(state,action, "kkk")
      state.user = action.payload
    },
    setUserDetails: (state, action) =>{
      state.userDetails.push(action.payload)
    }
  }
})
```

After all of this, I was able to implement the checkout functionality that enabled me to use stripe.

##Setting up stripe 

to set stripe up I needed to install two packages

`npm install @stripe/react-stripe-js`

and 

`npm install @stripe/stripe-js` 

this was needed to use certain elements to have stripe work. To make stripe fully functional I decided to use firebase to enable payment but used Rails to store my orders to later retrieve them. for firebase I had to install the firebase packages it gives you when creating a new app and doing 

`firebase init`

this let me pick the option function which enabled me to set sort of like another back end but only for stripe. the function consisted of this code 

```
const functions = require("firebase-functions");
const express = require('express');
const cors = require('cors')
const stripe = require("stripe")('ENV')

const app = express();

// - Middlewares
app.use(cors({ origin: true }));
app.use(express.json());

// - API routes
app.get("/", (request, response) => response.status(200).send("hello world"));

app.post("/payments/create", async (request, response) => {
  const total = request.query.total;

  console.log("total:", total);

  const paymentIntent = await stripe.paymentIntents.create({
    amount: total, // subunits of the currency
    currency: "usd",
  });

  // OK - Created
  response.status(201).send({
    clientSecret: paymentIntent.client_secret,
  });
});

// - Listen command
exports.api = functions.https.onRequest(app);
```

which connected firebase as a back end to send a request to stripe every time my functions fired.

#Biggest Challenge 
One of the biggest challenges I had coming into this project was trying to organize myself to do a step-by-step for this project. I have a strong tendency to overstress initial projects with a blank slate of code since I just learned that language. I’m still learning to understand when it’s okay to take a step back breathe and plan the code out and not just freestyle it and think one step at a time instead of ten. 
#Coding Biggest Challenge
For my project’s coding, the biggest challenge had to be implementing stripe. I started by trying to use rails as the back end to send requests but quickly found out that rails had many many extra steps to pull stripe off making firebase my second choice.

##Grand Finally
To wrap things up, this has been an amazing journey from looking back 5 months ago and not understanding one single line of code to now reading it as if it was second nature to me. I was lucky enough to reach out to people in the class and make a strong foundation as well as my whole amazing Cohort and if I had the chance to re-live and do it from day one I would.