├── 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 |

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 |

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 |
--------------------------------------------------------------------------------