From 904e09d8f186df975c6205df5c129c28549b70dd Mon Sep 17 00:00:00 2001 From: DeepaMittal Date: Mon, 19 Feb 2024 19:17:27 +0530 Subject: [PATCH] Added cart feature --- .../src/components/Elements/ProductCard.js | 28 +++- car-ui-react/src/components/Layout/Header.js | 4 +- car-ui-react/src/context/.gitkeep | 0 car-ui-react/src/context/CartContext.js | 68 +++++++++ car-ui-react/src/context/FilterContext.js | 78 ++++++++++ car-ui-react/src/context/index.js | 2 + car-ui-react/src/data/db.json | 139 ------------------ car-ui-react/src/data/routes.json | 6 - car-ui-react/src/index.js | 7 +- car-ui-react/src/pages/Cart/CartPage.js | 6 +- .../src/pages/Cart/components/CartCard.js | 25 ++++ .../src/pages/Cart/components/CartList.js | 14 +- .../src/pages/Cart/components/Checkout.js | 52 +++++++ .../src/pages/Products/ProductsList.js | 2 - car-ui-react/src/reducers/cartReducers.js | 18 +++ car-ui-react/src/reducers/filterReducers.js | 33 +++++ car-ui-react/src/reducers/index.js | 2 + 17 files changed, 326 insertions(+), 158 deletions(-) delete mode 100644 car-ui-react/src/context/.gitkeep create mode 100644 car-ui-react/src/context/CartContext.js create mode 100644 car-ui-react/src/context/FilterContext.js create mode 100644 car-ui-react/src/context/index.js delete mode 100644 car-ui-react/src/data/db.json delete mode 100644 car-ui-react/src/data/routes.json create mode 100644 car-ui-react/src/reducers/cartReducers.js create mode 100644 car-ui-react/src/reducers/filterReducers.js create mode 100644 car-ui-react/src/reducers/index.js diff --git a/car-ui-react/src/components/Elements/ProductCard.js b/car-ui-react/src/components/Elements/ProductCard.js index 2745c3ae..ea92af5e 100644 --- a/car-ui-react/src/components/Elements/ProductCard.js +++ b/car-ui-react/src/components/Elements/ProductCard.js @@ -1,12 +1,27 @@ -import React from 'react'; -import carPicture from "../../assets/images/10001.avif" +import React, {useEffect, useState} from 'react'; +import {useCart} from "../../context"; + export const ProductCard = ({ product }) => { + const { brand, model, year, color, mileage, price, quantity, tax, poster, in_stock } = product; + const { cartList, addToCart, removeFromCart } = useCart(); + const [inCart, setInCart] = useState(false); + + useEffect(() => { + if (product) { + const productInCart = cartList.find(item => item.id === product.id); + if (productInCart) { + setInCart(true); + } else { + setInCart(false); + } + } + }, [cartList, product]); + if (!product) { - return null; // Or handle the case where product is undefined + return null; } - const { carId, brand, model, year, color, mileage, price, quantity, tax, poster, in_stock } = product; - + return (
@@ -40,7 +55,8 @@ export const ProductCard = ({ product }) => { INR {price} - + { !inCart && } + { inCart && }

diff --git a/car-ui-react/src/components/Layout/Header.js b/car-ui-react/src/components/Layout/Header.js index ff8b1012..52907aa2 100644 --- a/car-ui-react/src/components/Layout/Header.js +++ b/car-ui-react/src/components/Layout/Header.js @@ -1,9 +1,11 @@ import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import Logo from "../../assets/logo.png"; +import {useCart} from "../../context"; export const Header = () => { const [darkMode, setDarkMode] = useState(JSON.parse(localStorage.getItem("darkMode")) || false); + const {cartList} = useCart(); useEffect(() => { localStorage.setItem("darkMode", JSON.stringify(darkMode)); @@ -28,7 +30,7 @@ export const Header = () => { - 0 + {cartList.length} diff --git a/car-ui-react/src/context/.gitkeep b/car-ui-react/src/context/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/car-ui-react/src/context/CartContext.js b/car-ui-react/src/context/CartContext.js new file mode 100644 index 00000000..3437daf6 --- /dev/null +++ b/car-ui-react/src/context/CartContext.js @@ -0,0 +1,68 @@ +import { createContext, useContext, useReducer } from "react"; +import { cartReducer } from "../reducers"; + +const cartInitialState = { + cartList: [], + total: 0 +} + +const CartContext = createContext(cartInitialState); + +export const CartProvider = ({children}) => { + const [state, dispatch] = useReducer(cartReducer, cartInitialState); + + function addToCart(product){ + const updatedList = state.cartList.concat(product); + const updatedTotal = state.total + product.price; + + dispatch({ + type: "ADD_TO_CART", + payload: { + products: updatedList, + total: updatedTotal + } + }) + } + + function removeFromCart(product){ + const updatedList = state.cartList.filter(item => item.id !== product.id); + const updatedTotal = state.total - product.price; + + dispatch({ + type: "REMOVE_FROM_CART", + payload: { + products: updatedList, + total: updatedTotal + } + }) + } + + function clearCart(){ + dispatch({ + type: "CLEAR_CART", + payload: { + products: [], + total: 0 + } + }) + } + + const value = { + cartList: state.cartList, + total: state.total, + addToCart, + removeFromCart, + clearCart + } + + return ( + + {children} + + ) +} + +export const useCart = () => { + const context = useContext(CartContext); + return context; +} \ No newline at end of file diff --git a/car-ui-react/src/context/FilterContext.js b/car-ui-react/src/context/FilterContext.js new file mode 100644 index 00000000..4d87c6f6 --- /dev/null +++ b/car-ui-react/src/context/FilterContext.js @@ -0,0 +1,78 @@ +import { createContext, useContext, useReducer } from "react" +import { filterReducer } from "../reducers"; + +const filterInitialState = { + productList: [], + onlyInStock: false, + bestSellerOnly: false, + sortBy: null, + ratings: null +} + +const FilterContext = createContext(filterInitialState); + +export const FilterProvider = ({children}) => { + const [state, dispatch] = useReducer(filterReducer, filterInitialState); + + function initialProductList(products){ + dispatch({ + type: "PRODUCT_LIST", + payload: { + products: products + } + }); + } + + function bestSeller(products){ + return state.bestSellerOnly ? products.filter(product => product.best_seller === true) : products; + } + + function inStock(products){ + return state.onlyInStock ? products.filter(product => product.in_stock === true) : products; + } + + function sort(products){ + if(state.sortBy === "lowtohigh"){ + return products.sort((a, b) => Number(a.price) - Number(b.price)); + } + if(state.sortBy === "hightolow"){ + return products.sort((a, b) => Number(b.price) - Number(a.price)); + } + return products; + } + + function rating(products){ + if(state.ratings === "4STARSABOVE"){ + return products.filter(product => product.rating >= 4); + } + if(state.ratings === "3STARSABOVE"){ + return products.filter(product => product.rating >= 3); + } + if(state.ratings === "2STARSABOVE"){ + return products.filter(product => product.rating >= 2); + } + if(state.ratings === "1STARSABOVE"){ + return products.filter(product => product.rating >= 1); + } + return products; + } + + const filteredProductList = rating(sort(inStock(bestSeller(state.productList)))); + + const value = { + state, + dispatch, + products: filteredProductList, + initialProductList + } + return ( + + {children} + + ) +} + +export const useFilter = () => { + const context = useContext(FilterContext); + return context; +} \ No newline at end of file diff --git a/car-ui-react/src/context/index.js b/car-ui-react/src/context/index.js new file mode 100644 index 00000000..1e5031da --- /dev/null +++ b/car-ui-react/src/context/index.js @@ -0,0 +1,2 @@ +export { useFilter, FilterProvider } from "./FilterContext"; +export { useCart, CartProvider } from "./CartContext"; \ No newline at end of file diff --git a/car-ui-react/src/data/db.json b/car-ui-react/src/data/db.json deleted file mode 100644 index 348d132a..00000000 --- a/car-ui-react/src/data/db.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "products": [ - { - "carId": 4371, - "brand": "Ford", - "model": "Contour", - "year": 1198, - "color": "Teal", - "mileage": 70.811136, - "price": 1500000, - "quantity": 100, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://i.pinimg.com/736x/fa/be/08/fabe082d7ca96325961ddd6019583cb7--mystique-ford-contour.jpg", - "in_stock": true - }, - { - "carId": 4548, - "brand": "Mahindra", - "model": "XUV 700", - "year": 1950, - "color": "Black", - "mileage": 13.5465, - "price": 2000000, - "quantity": 200, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://www.cartoq.com/wp-content/uploads/2021/09/XUV700-Dark-Knight-edition-featured.jpg", - "in_stock": true - }, - { - "carId": 1556, - "brand": "Mahindra", - "model": "Scorpio N", - "year": 1950, - "color": "Black", - "mileage": 13.5465, - "price": 15000000, - "quantity": 200, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://static.autox.com/uploads/2022/06/Mahindra-Scorpio-N-exterior.png", - "in_stock": true - }, - { - "carId": 4752, - "brand": "Hundai", - "model": "i20 Grand", - "year": 1925, - "color": "Blue", - "mileage": 13.5465, - "price": 12000000, - "quantity": 100, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://paultan.org/image/2020/10/2021-Hyundai-i20-N-Exterior-7.jpg", - "in_stock": true - }, - { - "carId": 4654, - "brand": "Tata", - "model": "Harrier", - "year": 1900, - "color": "Orange", - "mileage": 13.5465, - "price": 18000000, - "quantity": 100, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://th.bing.com/th/id/OIP.5i-hWiOn_6RnqXoDoA-H2QHaEo?rs=1&pid=ImgDetMain", - "in_stock": false - }, - { - "carId": 1458, - "brand": "Tata", - "model": "Safari", - "year": 1900, - "color": "Grey", - "mileage": 13.5465, - "price": 25000000, - "quantity": 200, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://english.cdn.zeenews.com/sites/default/files/2022/10/31/1110417-tata-safari-classic-front.jpg", - "in_stock": true - }, - { - "carId": 5467, - "brand": "Toyota", - "model": "Fortuner", - "year": 1900, - "color": "White", - "mileage": 13.5465, - "price": 6000000, - "quantity": 300, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://th.bing.com/th/id/OIP.qzSsXvyXs_A9WpKfF97yJQHaFJ?rs=1&pid=ImgDetMain", - "in_stock": false - }, - { - "carId": 4567, - "brand": "Tata", - "model": "Tigor", - "year": 1900, - "color": "White", - "mileage": 13.5465, - "price": 12000000, - "quantity": 100, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://th.bing.com/th/id/OIP.EL6O-LdJztIEA7BuFBQWtwHaEK?rs=1&pid=ImgDetMain", - "in_stock": true - }, - { - "carId": 6424, - "brand": "Hundai", - "model": "Verna", - "year": 1985, - "color": "Black", - "mileage": 13.5465, - "price": 2000000, - "quantity": 50, - "tax": 1.4, - "timestamp": "2004-10-19 10: 23: 54", - "poster": "https://imgd.aeplcdn.com/642x336/n/cw/ec/121943/verna-facelift-exterior-right-front-three-quarter.jpeg?isig=0&q=75", - "in_stock": false - } - ], - "featured_products": [ - {} - ], - "orders": [ - {} - ], - "users": [ - {} - ] -} diff --git a/car-ui-react/src/data/routes.json b/car-ui-react/src/data/routes.json deleted file mode 100644 index d82a3846..00000000 --- a/car-ui-react/src/data/routes.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "/products*": "/444/", - "/featured_products*": "/444/", - "/orders*": "/660/", - "/users*": "/600/" -} \ No newline at end of file diff --git a/car-ui-react/src/index.js b/car-ui-react/src/index.js index 79884b16..fbe070a7 100644 --- a/car-ui-react/src/index.js +++ b/car-ui-react/src/index.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter as Router } from 'react-router-dom'; +import {CartProvider, FilterProvider} from "./context"; import './index.css'; import App from './App'; @@ -8,7 +9,11 @@ const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + + + + + ); diff --git a/car-ui-react/src/pages/Cart/CartPage.js b/car-ui-react/src/pages/Cart/CartPage.js index bef2e616..edb0112a 100644 --- a/car-ui-react/src/pages/Cart/CartPage.js +++ b/car-ui-react/src/pages/Cart/CartPage.js @@ -1,11 +1,13 @@ import { CartEmpty } from "./components/CartEmpty"; import { CartList } from "./components/CartList"; +import {useCart} from "../../context" export const CartPage = () => { - const carListLength = 0; + const { cartList } = useCart(); + return (
- { carListLength ? : } + { cartList.length ? : }
) } diff --git a/car-ui-react/src/pages/Cart/components/CartCard.js b/car-ui-react/src/pages/Cart/components/CartCard.js index e69de29b..ec9c28cc 100644 --- a/car-ui-react/src/pages/Cart/components/CartCard.js +++ b/car-ui-react/src/pages/Cart/components/CartCard.js @@ -0,0 +1,25 @@ +import { Link } from "react-router-dom" +import {useCart} from "../../../context"; + +export const CartCard = ({product}) => { + const { removeFromCart } = useCart(); + + return ( +
+
+ + {product.name} + +
+ +

{product.brand} {product.model}

+ + +
+
+
+ ${product.price} +
+
+ ) +} \ No newline at end of file diff --git a/car-ui-react/src/pages/Cart/components/CartList.js b/car-ui-react/src/pages/Cart/components/CartList.js index 833609d5..9f6fbcde 100644 --- a/car-ui-react/src/pages/Cart/components/CartList.js +++ b/car-ui-react/src/pages/Cart/components/CartList.js @@ -1,20 +1,31 @@ import { useState } from "react" +import {CartCard} from "./CartCard"; +import {Checkout} from "./Checkout"; +import {useCart} from "../../../context"; export const CartList = () => { const [checkout, setCheckout] = useState(false); + const {cartList , total} = useCart(); return ( <>

- My Cart ({2}) + My Cart ({cartList.length})

+
+ { cartList.map((product) => ( + + )) } +
+

Total Amount: + ${total}

@@ -23,6 +34,7 @@ export const CartList = () => {
+ {checkout && } ) } \ No newline at end of file diff --git a/car-ui-react/src/pages/Cart/components/Checkout.js b/car-ui-react/src/pages/Cart/components/Checkout.js index e69de29b..2b6974fd 100644 --- a/car-ui-react/src/pages/Cart/components/Checkout.js +++ b/car-ui-react/src/pages/Cart/components/Checkout.js @@ -0,0 +1,52 @@ +export const Checkout = ( {setCheckout}) => { + return ( +
+
+ +
+ ) +} \ No newline at end of file diff --git a/car-ui-react/src/pages/Products/ProductsList.js b/car-ui-react/src/pages/Products/ProductsList.js index 233a77f5..75c77c00 100644 --- a/car-ui-react/src/pages/Products/ProductsList.js +++ b/car-ui-react/src/pages/Products/ProductsList.js @@ -1,7 +1,5 @@ import { useEffect, useState } from "react"; import { ProductCard } from "../../components"; -import {Link} from "react-router-dom"; - export const ProductsList = () => { diff --git a/car-ui-react/src/reducers/cartReducers.js b/car-ui-react/src/reducers/cartReducers.js new file mode 100644 index 00000000..00c95851 --- /dev/null +++ b/car-ui-react/src/reducers/cartReducers.js @@ -0,0 +1,18 @@ +export const cartReducer = (state, action) => { + const { type, payload } = action; + + switch(type){ + + case "ADD_TO_CART": + return {...state, cartList: payload.products, total: payload.total} + + case "REMOVE_FROM_CART": + return {...state, cartList: payload.products, total: payload.total} + + case "CLEAR_CART": + return {...state, cartList: payload.products, total: payload.total} + + default: + throw new Error("No case found!"); + } +} \ No newline at end of file diff --git a/car-ui-react/src/reducers/filterReducers.js b/car-ui-react/src/reducers/filterReducers.js new file mode 100644 index 00000000..2bbc09e1 --- /dev/null +++ b/car-ui-react/src/reducers/filterReducers.js @@ -0,0 +1,33 @@ +export const filterReducer = (state, action) => { + const {type, payload} = action; + + switch(type){ + + case "PRODUCT_LIST": + return { productList: payload.products } + + case "SORT_BY": + return {...state, sortBy: payload.sortBy} + + case "RATINGS": + return {...state, ratings: payload.ratings} + + case "BEST_SELLER_ONLY": + return {...state, bestSellerOnly: payload.bestSellerOnly} + + case "ONLY_IN_STOCK": + return {...state, onlyInStock: payload.onlyInStock} + + case "CLEAR_FILTER": + return { + ...state, + onlyInStock: false, + bestSellerOnly: false, + sortBy: null, + ratings: null + } + + default: + throw new Error("No Cae Found!"); + } +} \ No newline at end of file diff --git a/car-ui-react/src/reducers/index.js b/car-ui-react/src/reducers/index.js new file mode 100644 index 00000000..992eeeee --- /dev/null +++ b/car-ui-react/src/reducers/index.js @@ -0,0 +1,2 @@ +export { filterReducer } from "./filterReducers"; +export { cartReducer } from "./cartReducers"; \ No newline at end of file