21
React-Redux Amazon Clone Project
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.
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.
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.
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.
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.
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.
To enable redux-tool-kit we have to
npm install @reduxjs/toolkit react-redux
For documentation, you can click Here 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.
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.
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.
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.
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.
21