├── src
├── App.css
├── index.css
├── Store
│ ├── index.js
│ └── slices
│ │ └── cart-slice.js
├── App.jsx
├── main.jsx
├── components
│ ├── Header.jsx
│ ├── CartItem.jsx
│ └── ProductItem.jsx
├── Home
│ └── index.jsx
├── Cart
│ └── index.jsx
└── assets
│ └── react.svg
├── .vscode
└── extensions.json
├── postcss.config.js
├── vite.config.js
├── tailwind.config.js
├── .gitignore
├── index.html
├── README.md
├── .eslintrc.cjs
├── package.json
└── public
└── vite.svg
/src/App.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "bradlc.vscode-tailwindcss"
4 | ]
5 | }
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/Store/index.js:
--------------------------------------------------------------------------------
1 | import {configureStore} from "@reduxjs/toolkit";
2 | import cartReducer from "./slices/cart-slice";
3 | const store=configureStore({
4 | reducer:{
5 | cart: cartReducer
6 | }
7 | })
8 | export default store;
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/.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 | Shopping Cart
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 | import { Routes, Route } from "react-router-dom";
3 | import Home from "./Home";
4 | import Cart from "./Cart";
5 | import Header from "./components/Header";
6 | function App() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | } />
14 | } />
15 |
16 |
17 | );
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App.jsx";
4 | import "./index.css";
5 | import { BrowserRouter } from "react-router-dom";
6 | import { Provider } from "react-redux";
7 | import store from "./Store/index.js";
8 | ReactDOM.createRoot(document.getElementById("root")).render(
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 |
--------------------------------------------------------------------------------
/src/Store/slices/cart-slice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 | const initialState = [];
3 | const cartSlice = createSlice({
4 | name: "cart",
5 | initialState,
6 | reducers: {
7 | addToCart(state, action) {
8 | state.push(action.payload);
9 | },
10 | removeFromCart(state, action) {
11 | return state.filter((item) => item.id !== action.payload);
12 | },
13 | },
14 | });
15 |
16 | export const { addToCart,removeFromCart } = cartSlice.actions;
17 | export default cartSlice.reducer;
18 |
--------------------------------------------------------------------------------
/.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/components/Header.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 | export default function Header() {
3 | return (
4 |
5 |
20 |
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shopping-cart",
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.3",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0",
16 | "react-icons": "^5.0.1",
17 | "react-loader-spinner": "^6.1.6",
18 | "react-redux": "^9.1.0",
19 | "react-router-dom": "^6.22.3"
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.3",
32 | "vite": "^5.2.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/CartItem.jsx:
--------------------------------------------------------------------------------
1 | import { useDispatch } from "react-redux"
2 | import { removeFromCart } from "../Store/slices/cart-slice"
3 |
4 | export default function CartItem({item}) {
5 | const dispatch=useDispatch()
6 | function handleRemoveCart(){
7 | dispatch(removeFromCart(item?.id))
8 | }
9 | return
10 |
11 |
12 |

13 |
14 |
{item.title}
15 |
Price: {item?.price}
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | }
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/ProductItem.jsx:
--------------------------------------------------------------------------------
1 | import { useDispatch, useSelector } from "react-redux";
2 | import { addToCart, removeFromCart } from "../Store/slices/cart-slice";
3 | const ProductItem = ({ product }) => {
4 | const dispatch = useDispatch();
5 | const{cart}=useSelector(state=>state);
6 | function handleAddToCart() {
7 | dispatch(addToCart(product));
8 | }
9 | function handleRemoveCart() {
10 | dispatch(removeFromCart(product.id))
11 | }
12 | return (
13 |
14 |
15 |
16 |

21 |
22 |
23 |
24 | {product?.title}
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 | );
38 | };
39 |
40 | export default ProductItem;
41 |
--------------------------------------------------------------------------------
/src/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { Circles } from "react-loader-spinner";
3 | import ProductItem from "../components/ProductItem";
4 |
5 | export default function Home() {
6 | const [prouducts, setProducts] = useState([]);
7 | const [loading, setLoading] = useState(false);
8 | const [error, setError] = useState(null);
9 |
10 | async function fetchProuducts() {
11 | try {
12 | setLoading(true);
13 | const response = await fetch("https://fakestoreapi.com/products");
14 | const data = await response.json();
15 | setProducts(data);
16 | setLoading(false);
17 | } catch (error) {
18 | setError(error);
19 | setLoading(false)
20 | }
21 | }
22 | useEffect(() => {
23 | fetchProuducts();
24 | },[]);
25 | return (
26 |
27 | {loading ? (
28 |
32 |
38 |
39 | ):
40 |
41 | {prouducts && prouducts.length > 0 ? (
42 | prouducts.map((item) =>
)
43 | ) : (
44 |
No products found
45 | )}
46 |
47 | }
48 |
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/src/Cart/index.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useSelector } from "react-redux";
3 | import { Link } from "react-router-dom";
4 | import CartItem from "../components/CartItem";
5 | export default function Cart() {
6 | const [totalCart, setTotalCart] = useState(0);
7 | const { cart } = useSelector((state) => state);
8 |
9 | useEffect(() => {
10 | setTotalCart(cart.reduce((acc, curr) => acc + curr.price, 0));
11 | }, [cart]);
12 |
13 | return (
14 |
15 | {cart && cart.length > 0 ? (
16 | <>
17 |
18 |
19 | {cart.map((product) => (
20 |
21 | ))}
22 |
23 |
24 |
25 |
26 |
27 | You Cart Summary{" "}
28 |
29 |
30 |
31 | Total Items
32 |
33 | {cart.length}
34 |
35 |
36 |
37 | Total Amount
38 |
39 | {totalCart}
40 |
41 |
42 |
43 | >
44 | ) : (
45 |
46 |
47 | Your cart is empty
48 |
{" "}
49 |
50 |
53 |
54 |
55 | )}
56 |
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------