Build a Shopping Cart Using React js Laravel 11 & Stripe Payment Gateway Part 3
In the third part of this tutorial, we will start coding the front end, first, we will install the packages we need and later we will create the components and routes.
Install the packages
All the packages we will need are below you can add them to your 'package.json' file and run npm install.
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.2.4",
"@stripe/stripe-js": "^3.4.0",
"axios": "^1.6.8",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.2",
"react-router-dom": "^6.23.1",
"react-toastify": "^10.0.5"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"vite": "^5.2.0"
}
}
Add the store
Next, inside src add a new folder redux inside add a new folder store inside add a new file 'index.js' that will hold the store we need.
the image below contains the file structure of the front end:
import { configureStore } from '@reduxjs/toolkit'
import cartReducer from '../slices/cartSlice'
const store = configureStore({
reducer: {
cart: cartReducer
}
})
export default store
Create the cart slice
Next, inside redux add new folder slices inside add a new file 'cartSlice.js that will hold all the cart actions we need.
import { createSlice } from "@reduxjs/toolkit"
import { toast } from 'react-toastify'
const initialState = {
cartItems: []
}
export const cartSlice = createSlice({
name: 'cart',
initialState,
reducers: {
addToCart(state, action) {
const item = action.payload
let existingProduct = state.cartItems.find(product => product.id === item.id)
if(existingProduct) {
existingProduct.quantity += 1
toast.success('Product quantity increased')
}else{
item.quantity = 1
state.cartItems = [item, ...state.cartItems]
toast.success('Product added to the cart')
}
},
incrementQ(state, action) {
const item = action.payload
let existingProduct = state.cartItems.find(product => product.id === item.id)
existingProduct.quantity += 1
toast.success('Product quantity increased')
},
decrementQ(state, action) {
const item = action.payload
let existingProduct = state.cartItems.find(product => product.id === item.id)
existingProduct.quantity -= 1
if(existingProduct.quantity === 0){
state.cartItems = state.cartItems.filter(product => product.id !== existingProduct.id)
}
toast.success('Product quantity decreased')
},
removeFromCart(state, action) {
const item = action.payload
state.cartItems = state.cartItems.filter(product => product.id !== item.id)
toast.success('Product removed from the cart')
}
}
})
export const { addToCart, incrementQ, decrementQ, removeFromCart} = cartSlice.actions
const cartReducer = cartSlice.reducer
export default cartReducer
Add routes
Inside the file App.jsx let's add the code below:
import Home from "./components/Home"
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Header from "./components/layouts/Header"
import store from "./redux/store"
import { Provider } from 'react-redux'
import Cart from "./components/cart/Cart"
import PaymentSuccess from "./components/payments/PaymentSuccess"
function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/cart" element={<Cart />} />
<Route path="/payment/success" element={<PaymentSuccess />} />
</Routes>
</BrowserRouter>
</Provider>
)
}
export default App
Update the file main.jsx
Inside the file main.jsx let's add the code below:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'
import 'bootstrap-icons/font/bootstrap-icons.css'
import 'react-toastify/dist/ReactToastify.css'
import './index.css'
import { ToastContainer } from 'react-toastify'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<ToastContainer position="top-right" />
<div className="container">
<App />
</div>
</React.StrictMode>,
)