├── src ├── App.css ├── index.css ├── shoppingcart │ ├── image │ │ ├── Tshirt-red.jpg │ │ ├── shirt-black.jpg │ │ ├── shirt-blue.jpg │ │ ├── shirt-white.jpg │ │ └── shirt-purple.jpg │ ├── Redux │ │ ├── cartAction.js │ │ └── cartReducer.js │ ├── Header.jsx │ ├── Home.jsx │ ├── Checkout.jsx │ └── Product.jsx ├── main.jsx ├── App.jsx └── assets │ └── react.svg ├── README.md ├── postcss.config.js ├── vite.config.js ├── tailwind.config.js ├── .gitignore ├── index.html ├── .eslintrc.cjs ├── package.json └── public └── vite.svg /src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ecommerce Shopping Cart -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/shoppingcart/image/Tshirt-red.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-with-zain-hunzai/Ecommerce-Shopping-Cart/HEAD/src/shoppingcart/image/Tshirt-red.jpg -------------------------------------------------------------------------------- /src/shoppingcart/image/shirt-black.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-with-zain-hunzai/Ecommerce-Shopping-Cart/HEAD/src/shoppingcart/image/shirt-black.jpg -------------------------------------------------------------------------------- /src/shoppingcart/image/shirt-blue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-with-zain-hunzai/Ecommerce-Shopping-Cart/HEAD/src/shoppingcart/image/shirt-blue.jpg -------------------------------------------------------------------------------- /src/shoppingcart/image/shirt-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-with-zain-hunzai/Ecommerce-Shopping-Cart/HEAD/src/shoppingcart/image/shirt-white.jpg -------------------------------------------------------------------------------- /src/shoppingcart/image/shirt-purple.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-with-zain-hunzai/Ecommerce-Shopping-Cart/HEAD/src/shoppingcart/image/shirt-purple.jpg -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React cart 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/shoppingcart/Redux/cartAction.js: -------------------------------------------------------------------------------- 1 | export function addtocart(id, title, price, rating, image) { 2 | return { 3 | type: "Add_item_to_cart", 4 | id: id, 5 | title: title, 6 | price: price, 7 | rating: rating, 8 | image: image 9 | }; 10 | } 11 | 12 | export function removefromcart(id) { 13 | return { 14 | type: "Remove_item_from_cart", 15 | id 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App.jsx'; 4 | import './index.css'; 5 | import { Provider } from 'react-redux'; 6 | import { configureStore } from '@reduxjs/toolkit'; 7 | import { cartReducer } from './shoppingcart/Redux/cartReducer.js'; 8 | 9 | const store = configureStore({ 10 | reducer: { 11 | cart: cartReducer, 12 | }, 13 | }); 14 | 15 | ReactDOM.createRoot(document.getElementById('root')).render( 16 | 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import Header from './shoppingcart/Header'; 3 | import Home from './shoppingcart/Home'; 4 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 5 | import Checkout from './shoppingcart/Checkout'; 6 | 7 | function App() { 8 | return ( 9 | < > 10 | 11 | 12 |
13 | 14 | } 17 | /> 18 | } 21 | /> 22 | } 25 | /> 26 | 27 | 28 | 29 | ); 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-carts", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@reduxjs/toolkit": "^2.2.5", 14 | "prop-types": "^15.8.1", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0", 17 | "react-redux": "^9.1.2", 18 | "react-router-dom": "^6.23.1", 19 | "react-toastify": "^10.0.5" 20 | }, 21 | "devDependencies": { 22 | "@types/react": "^18.2.66", 23 | "@types/react-dom": "^18.2.22", 24 | "@vitejs/plugin-react": "^4.2.1", 25 | "autoprefixer": "^10.4.19", 26 | "eslint": "^8.57.0", 27 | "eslint-plugin-react": "^7.34.1", 28 | "eslint-plugin-react-hooks": "^4.6.0", 29 | "eslint-plugin-react-refresh": "^0.4.6", 30 | "postcss": "^8.4.38", 31 | "tailwindcss": "^3.4.4", 32 | "vite": "^5.2.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/shoppingcart/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, useLocation } from 'react-router-dom'; 3 | import { useSelector } from 'react-redux'; 4 | import { IoIosCart } from "react-icons/io"; 5 | import 'tailwindcss/tailwind.css'; 6 | 7 | const Header = () => { 8 | const cart = useSelector((state) => state.cart); 9 | const location = useLocation(); 10 | 11 | return ( 12 |
13 |
14 | {location.pathname === '/Checkout' && ( 15 | 16 | Back to Home 17 | 18 | )} 19 |
20 | 21 | 22 | Cart 23 | 24 | 25 | {cart.cart.length} 26 | 27 | 28 | 29 |
30 |
31 |
32 | ); 33 | }; 34 | 35 | export default Header; 36 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/shoppingcart/Redux/cartReducer.js: -------------------------------------------------------------------------------- 1 | const initialState = { 2 | cart: [] 3 | }; 4 | 5 | export const getTotal = (cart) => { 6 | return ( 7 | cart.reduce((amount, item) => parseInt(item.price) + amount, 0) 8 | ) 9 | } 10 | 11 | export function cartReducer(state = initialState, action) { 12 | switch (action.type) { 13 | case "Add_item_to_cart": { 14 | const newItem = { 15 | id: action.id, 16 | title: action.title, 17 | price: action.price, 18 | rating: action.rating, 19 | image: action.image, 20 | currency: action.currency 21 | }; 22 | return { 23 | ...state, 24 | cart: [...state.cart, newItem] 25 | }; 26 | } 27 | case "Remove_item_from_cart": { 28 | const index = state.cart.findIndex((cartItem) => cartItem.id === action.id); 29 | let newCart = [...state.cart]; 30 | if (index >= 0) { 31 | newCart.splice(index, 1); 32 | } else { 33 | console.warn("Cannot delete item with id: ", action.id); 34 | } 35 | return { 36 | ...state, 37 | cart: newCart 38 | }; 39 | } 40 | default: 41 | return state; 42 | } 43 | } 44 | 45 | export default cartReducer; 46 | 47 | 48 | 49 | // 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/shoppingcart/Home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Product from './Product' 3 | import Image1 from './image/Tshirt-red.jpg' 4 | import Image2 from './image/shirt-blue.jpg' 5 | import Image3 from './image/shirt-black.jpg' 6 | import Image4 from './image/shirt-white.jpg' 7 | import Image5 from './image/shirt-purple.jpg' 8 | const Home = () => { 9 | return ( 10 |
11 |
12 | 20 | 28 | 29 | 36 | 43 | 51 |
52 |
53 | 54 |
55 |
56 | ) 57 | } 58 | 59 | export default Home 60 | -------------------------------------------------------------------------------- /src/shoppingcart/Checkout.jsx: -------------------------------------------------------------------------------- 1 | import { useSelector, useDispatch } from 'react-redux'; 2 | import { removefromcart } from './Redux/cartAction'; 3 | import { getTotal } from './Redux/cartReducer'; 4 | import { MdDeleteOutline } from "react-icons/md"; 5 | 6 | const Checkout = () => { 7 | const cart = useSelector(state => state.cart.cart); 8 | const dispatch = useDispatch(); 9 | 10 | console.log("Cart items in Checkout component:", cart); 11 | 12 | if (!Array.isArray(cart) || cart.length === 0) { 13 | return

Your cart is empty.

; 14 | } 15 | 16 | return ( 17 |
18 |
19 | {cart.map(item => ( 20 |
21 | {item.title} 22 |
23 |

{item.title}

24 |

{item.rating}

25 |

{item.price}$

26 | 33 |
34 |
35 | ))} 36 |
37 |
38 |

Subtotal:

39 |

Total: ${getTotal(cart)}

40 |
41 |
42 | ); 43 | }; 44 | 45 | export default Checkout; 46 | -------------------------------------------------------------------------------- /src/shoppingcart/Product.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { useDispatch } from 'react-redux'; 3 | import { addtocart } from './Redux/cartAction'; 4 | import { IoIosCart } from "react-icons/io"; 5 | import PropTypes from 'prop-types'; 6 | import 'tailwindcss/tailwind.css'; 7 | 8 | const Product = ({ id, title, price, rating, image, currency, }) => { 9 | const dispatch = useDispatch(); 10 | const [quantity, setQuantity] = useState(1); 11 | const [isDisabled, setIsDisabled] = useState(false); 12 | 13 | const handleClick = () => { 14 | dispatch(addtocart(id, title, price, rating, image, quantity)); 15 | setIsDisabled(true); 16 | }; 17 | 18 | return ( 19 |
20 |
21 |
22 | {title} 23 |
24 |

{title}

25 |

Rating{rating}

26 |
27 |

{price}{currency}

28 | 29 |
30 | 31 | 40 |
41 |
42 | 49 |
50 |
51 | ); 52 | }; 53 | 54 | Product.propTypes = { 55 | id: PropTypes.number.isRequired, 56 | title: PropTypes.string.isRequired, 57 | price: PropTypes.number.isRequired, 58 | rating: PropTypes.string.isRequired, 59 | image: PropTypes.string.isRequired, 60 | currency: PropTypes.string.isRequired, 61 | }; 62 | 63 | export default Product; 64 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------