├── src ├── App.css ├── assets │ ├── logo.png │ └── images │ │ └── hero.avif ├── reducers │ ├── index.js │ ├── cartReducers.js │ └── filterReducers.js ├── context │ ├── index.js │ ├── CartContext.js │ └── FilterContext.js ├── services │ ├── index.js │ ├── productService.js │ ├── authService.js │ └── dataService.js ├── hooks │ └── useTitle.js ├── routes │ ├── ProtectedRoute.js │ └── AllRoutes.js ├── App.js ├── components │ ├── Other │ │ └── ScrollToTop.js │ ├── index.js │ ├── Elements │ │ ├── Rating.js │ │ ├── DropdownLoggedOut.js │ │ ├── DropdownLoggedIn.js │ │ └── ProductCard.js │ ├── Sections │ │ └── Search.js │ └── Layouts │ │ ├── Header.js │ │ └── Footer.js ├── pages │ ├── index.js │ ├── Cart │ │ ├── CartPage.js │ │ └── components │ │ │ ├── CartEmpty.js │ │ │ ├── CartCard.js │ │ │ ├── CartList.js │ │ │ └── Checkout.js │ ├── Order │ │ ├── OrderPage.js │ │ └── components │ │ │ ├── OrderFail.js │ │ │ └── OrderSuccess.js │ ├── Home │ │ ├── HomePage.js │ │ └── components │ │ │ ├── FeaturedProducts.js │ │ │ ├── Hero.js │ │ │ ├── Accordion.js │ │ │ ├── Faq.js │ │ │ └── Testimonials.js │ ├── Dashboard │ │ ├── components │ │ │ ├── DashboardEmpty.js │ │ │ └── DashboardCard.js │ │ └── DashboardPage.js │ ├── PageNotFound.js │ ├── Products │ │ ├── ProductsList.js │ │ └── components │ │ │ └── FilterBar.js │ ├── Register.js │ ├── Login.js │ └── ProductDetail.js ├── index.css └── index.js ├── netlify.toml ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── assets │ └── images │ │ ├── 10001.avif │ │ ├── 10002.avif │ │ ├── 10003.avif │ │ ├── 10004.avif │ │ ├── 10005.avif │ │ ├── 10006.avif │ │ ├── 10007.avif │ │ ├── 10008.avif │ │ ├── 10009.avif │ │ ├── 10010.avif │ │ ├── 10011.avif │ │ ├── 10012.avif │ │ ├── 10013.avif │ │ ├── 10014.avif │ │ └── 10015.avif ├── manifest.json └── index.html ├── data ├── routes.json └── db.json ├── tailwind.config.js ├── .gitignore ├── package.json └── README.md /src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[redirects]] 2 | from = "/*" 3 | to = "/index.html" 4 | status = 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/images/hero.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/src/assets/images/hero.avif -------------------------------------------------------------------------------- /public/assets/images/10001.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10001.avif -------------------------------------------------------------------------------- /public/assets/images/10002.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10002.avif -------------------------------------------------------------------------------- /public/assets/images/10003.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10003.avif -------------------------------------------------------------------------------- /public/assets/images/10004.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10004.avif -------------------------------------------------------------------------------- /public/assets/images/10005.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10005.avif -------------------------------------------------------------------------------- /public/assets/images/10006.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10006.avif -------------------------------------------------------------------------------- /public/assets/images/10007.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10007.avif -------------------------------------------------------------------------------- /public/assets/images/10008.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10008.avif -------------------------------------------------------------------------------- /public/assets/images/10009.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10009.avif -------------------------------------------------------------------------------- /public/assets/images/10010.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10010.avif -------------------------------------------------------------------------------- /public/assets/images/10011.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10011.avif -------------------------------------------------------------------------------- /public/assets/images/10012.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10012.avif -------------------------------------------------------------------------------- /public/assets/images/10013.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10013.avif -------------------------------------------------------------------------------- /public/assets/images/10014.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10014.avif -------------------------------------------------------------------------------- /public/assets/images/10015.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShubhamSarda/codebook/HEAD/public/assets/images/10015.avif -------------------------------------------------------------------------------- /src/reducers/index.js: -------------------------------------------------------------------------------- 1 | export { filterReducer } from "./filterReducers"; 2 | export { cartReducer } from "./cartReducers"; -------------------------------------------------------------------------------- /src/context/index.js: -------------------------------------------------------------------------------- 1 | export { useFilter, FilterProvider } from "./FilterContext"; 2 | export { useCart, CartProvider } from "./CartContext"; -------------------------------------------------------------------------------- /data/routes.json: -------------------------------------------------------------------------------- 1 | { 2 | "/products*": "/444/", 3 | "/featured_products*": "/444/", 4 | "/orders*": "/660/", 5 | "/users*": "/600/" 6 | } -------------------------------------------------------------------------------- /src/services/index.js: -------------------------------------------------------------------------------- 1 | export { login, register, logout } from "./authService"; 2 | export { getUser, getUserOrders, createOrder } from "./dataService"; 3 | export { getProductList, getProduct, getFeaturedList } from "./productService"; -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ["./src/**/*.{html,js}"], 3 | darkMode: 'class', 4 | theme: { 5 | extend: { 6 | colors: { 7 | dark: "#1E293B", 8 | } 9 | }, 10 | }, 11 | plugins: [], 12 | } -------------------------------------------------------------------------------- /src/hooks/useTitle.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export const useTitle = (title) => { 4 | 5 | useEffect(() => { 6 | document.title = `${title} - CodeBook`; 7 | }, [title]); 8 | 9 | return null; 10 | } -------------------------------------------------------------------------------- /src/routes/ProtectedRoute.js: -------------------------------------------------------------------------------- 1 | import { Navigate } from "react-router-dom"; 2 | 3 | export const ProtectedRoute = ({children}) => { 4 | const token = JSON.parse(sessionStorage.getItem("token")); 5 | 6 | return token ? children : 7 | } 8 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { AllRoutes } from './routes/AllRoutes'; 2 | import { Footer, Header } from './components'; 3 | 4 | function App() { 5 | return ( 6 |
7 |
8 | 9 |
10 |
11 | ); 12 | } 13 | 14 | export default App; -------------------------------------------------------------------------------- /src/components/Other/ScrollToTop.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | 4 | export const ScrollToTop = () => { 5 | const { pathname } = useLocation(); 6 | 7 | useEffect(() => { 8 | window.scrollTo(0, 0); 9 | }, [pathname]); 10 | 11 | return null; 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | export { Header } from "./Layouts/Header"; 2 | export { Footer } from "./Layouts/Footer"; 3 | 4 | export { ProductCard } from "./Elements/ProductCard"; 5 | export { Rating } from "./Elements/Rating"; 6 | 7 | export { DropdownLoggedIn } from "./Elements/DropdownLoggedIn"; 8 | export { DropdownLoggedOut } from "./Elements/DropdownLoggedOut"; 9 | 10 | export { ScrollToTop } from "./Other/ScrollToTop"; -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | export { HomePage } from "./Home/HomePage"; 2 | export { ProductsList } from "./Products/ProductsList"; 3 | export { ProductDetail } from "./ProductDetail"; 4 | 5 | export { CartPage } from "./Cart/CartPage"; 6 | export { OrderPage } from "./Order/OrderPage"; 7 | export { DashboardPage } from "./Dashboard/DashboardPage"; 8 | 9 | export { Login } from "./Login"; 10 | export { Register } from "./Register"; 11 | 12 | export { PageNotFound } from "./PageNotFound"; 13 | -------------------------------------------------------------------------------- /src/pages/Cart/CartPage.js: -------------------------------------------------------------------------------- 1 | import { useTitle } from "../../hooks/useTitle"; 2 | import { CartEmpty } from "./components/CartEmpty"; 3 | import { CartList } from "./components/CartList"; 4 | import { useCart } from "../../context" 5 | 6 | export const CartPage = () => { 7 | const { cartList } = useCart(); 8 | useTitle(`Cart (${cartList.length})`); 9 | 10 | return ( 11 |
12 | { cartList.length ? : } 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/Order/OrderPage.js: -------------------------------------------------------------------------------- 1 | import { useLocation } from "react-router-dom"; 2 | import { useTitle } from "../../hooks/useTitle"; 3 | import { OrderSuccess } from "./components/OrderSuccess"; 4 | import { OrderFail } from "./components/OrderFail"; 5 | 6 | export const OrderPage = () => { 7 | useTitle("Order Summary"); 8 | const { state } = useLocation(); 9 | 10 | return ( 11 |
12 | { state.status ? : } 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | @import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto&display=swap'); 5 | @import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css"); 6 | 7 | * { 8 | font-family: 'Roboto', sans-serif; 9 | } 10 | 11 | main { 12 | min-height: 90vh; 13 | max-width: 1280px; 14 | margin: auto; 15 | padding: 15px; 16 | } -------------------------------------------------------------------------------- /src/pages/Home/HomePage.js: -------------------------------------------------------------------------------- 1 | import { useTitle } from "../../hooks/useTitle"; 2 | import { Hero } from "./components/Hero"; 3 | import { FeaturedProducts } from "./components/FeaturedProducts"; 4 | import { Testimonials } from "./components/Testimonials"; 5 | import { Faq } from "./components/Faq"; 6 | 7 | export const HomePage = () => { 8 | useTitle("Access Latest Computer Science eBooks"); 9 | 10 | return ( 11 |
12 | 13 | 14 | 15 | 16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Elements/Rating.js: -------------------------------------------------------------------------------- 1 | export const Rating = ({rating}) => { 2 | let ratingArray = Array(5).fill(false); 3 | for(let i=0; i 9 | { ratingArray.map((value, index) => ( 10 | value ? ( 11 | 12 | ) : ( 13 | 14 | ) 15 | )) } 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/reducers/cartReducers.js: -------------------------------------------------------------------------------- 1 | export const cartReducer = (state, action) => { 2 | const { type, payload } = action; 3 | 4 | switch(type){ 5 | 6 | case "ADD_TO_CART": 7 | return {...state, cartList: payload.products, total: payload.total} 8 | 9 | case "REMOVE_FROM_CART": 10 | return {...state, cartList: payload.products, total: payload.total} 11 | 12 | case "CLEAR_CART": 13 | return {...state, cartList: payload.products, total: payload.total} 14 | 15 | default: 16 | throw new Error("No case found!"); 17 | } 18 | } -------------------------------------------------------------------------------- /src/pages/Dashboard/components/DashboardEmpty.js: -------------------------------------------------------------------------------- 1 | export const DashboardEmpty = () => { 2 | return ( 3 |
4 |
5 |

6 |

Oops! Your order dashboard looks empty!

7 |

Add eBooks to your cart from our store collection.

8 |
9 | Continue Shopping 10 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /src/pages/Cart/components/CartEmpty.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | 3 | export const CartEmpty = () => { 4 | return ( 5 |
6 |
7 |

8 |

Oops! Your cart looks empty!

9 |

Add eBooks to your cart from our store collection.

10 |
11 | Continue Shopping 12 |
13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { BrowserRouter as Router } from 'react-router-dom'; 4 | 5 | import { ToastContainer } from 'react-toastify'; 6 | import 'react-toastify/dist/ReactToastify.css'; 7 | 8 | import { FilterProvider, CartProvider } from "./context"; 9 | import { ScrollToTop } from "./components"; 10 | import './index.css'; 11 | import App from './App'; 12 | 13 | const root = ReactDOM.createRoot(document.getElementById('root')); 14 | root.render( 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); -------------------------------------------------------------------------------- /src/pages/Order/components/OrderFail.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | 3 | export const OrderFail = () => { 4 | return ( 5 |
6 |
7 |

8 |

Payment failed, please try again!

9 |
10 |
11 |

Your order is not confirmed.

12 |

Connect codebook@example.com for support.

13 |
14 | Check Cart Again 15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/reducers/filterReducers.js: -------------------------------------------------------------------------------- 1 | export const filterReducer = (state, action) => { 2 | const {type, payload} = action; 3 | 4 | switch(type){ 5 | 6 | case "PRODUCT_LIST": 7 | return { productList: payload.products } 8 | 9 | case "SORT_BY": 10 | return {...state, sortBy: payload.sortBy} 11 | 12 | case "RATINGS": 13 | return {...state, ratings: payload.ratings} 14 | 15 | case "BEST_SELLER_ONLY": 16 | return {...state, bestSellerOnly: payload.bestSellerOnly} 17 | 18 | case "ONLY_IN_STOCK": 19 | return {...state, onlyInStock: payload.onlyInStock} 20 | 21 | case "CLEAR_FILTER": 22 | return { 23 | ...state, 24 | onlyInStock: false, 25 | bestSellerOnly: false, 26 | sortBy: null, 27 | ratings: null 28 | } 29 | 30 | default: 31 | throw new Error("No Cae Found!"); 32 | } 33 | } -------------------------------------------------------------------------------- /src/pages/Cart/components/CartCard.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | import { useCart } from "../../../context"; 3 | 4 | export const CartCard = ({product}) => { 5 | const { removeFromCart } = useCart(); 6 | 7 | return ( 8 |
9 |
10 | 11 | {product.name} 12 | 13 |
14 | 15 |

{product.name}

16 | 17 | 18 |
19 |
20 |
21 | ${product.price} 22 |
23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/routes/AllRoutes.js: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from "react-router-dom"; 2 | import { HomePage, ProductsList, ProductDetail, Login, Register, CartPage, OrderPage, DashboardPage, PageNotFound } from "../pages"; 3 | import { ProtectedRoute } from "./ProtectedRoute"; 4 | 5 | export const AllRoutes = () => { 6 | return ( 7 | <> 8 | 9 | } /> 10 | } /> 11 | } /> 12 | 13 | } /> 14 | } /> 15 | 16 | } /> 17 | } /> 18 | } /> 19 | 20 | } /> 21 | 22 | 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/Order/components/OrderSuccess.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | 3 | export const OrderSuccess = ({data}) => { 4 | return ( 5 |
6 |
7 |

8 |

Thank you {data.user.name} for the order!

9 |

Your Order ID: {data.id}

10 |
11 |
12 |

Your order is confirmed.

13 |

Please check your mail ({data.user.email}) for the eBook.

14 |

Payment ID: xyz_123456789

15 |
16 | Continue Shopping 17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/services/productService.js: -------------------------------------------------------------------------------- 1 | export async function getProductList(searchTerm){ 2 | const response = await fetch(`${process.env.REACT_APP_HOST}/444/products?name_like=${searchTerm ? searchTerm : ""}`); 3 | if(!response.ok){ 4 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 5 | } 6 | const data = await response.json() 7 | return data; 8 | } 9 | 10 | export async function getProduct(id){ 11 | const response = await fetch(`${process.env.REACT_APP_HOST}/444/products/${id}`); 12 | if(!response.ok){ 13 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 14 | } 15 | const data = await response.json() 16 | return data; 17 | } 18 | 19 | export async function getFeaturedList(){ 20 | const response = await fetch(`${process.env.REACT_APP_HOST}/444/featured_products`); 21 | if(!response.ok){ 22 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 23 | } 24 | const data = await response.json() 25 | return data; 26 | } -------------------------------------------------------------------------------- /src/pages/PageNotFound.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { useTitle } from "../hooks/useTitle"; 3 | import Logo from "../assets/logo.png"; 4 | 5 | export const PageNotFound = () => { 6 | useTitle("Page Not Found"); 7 | 8 | return ( 9 |
10 |
11 |
12 |

404, Oops!

13 |
14 | CodeBook Page Not Found 15 |
16 |
17 |
18 | 19 | 20 | 21 |
22 |
23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Elements/DropdownLoggedOut.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | export const DropdownLoggedOut = ({setDropdown}) => { 4 | return ( 5 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/pages/Home/components/FeaturedProducts.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { toast } from "react-toastify"; 3 | import { ProductCard } from "../../../components"; 4 | import { getFeaturedList } from "../../../services"; 5 | 6 | export const FeaturedProducts = () => { 7 | const [products, setProducts] = useState([]); 8 | 9 | useEffect(() => { 10 | async function fetchProducts(){ 11 | try{ 12 | const data = await getFeaturedList(); 13 | setProducts(data); 14 | } catch(error){ 15 | toast.error(error.message, {closeButton: true, position: "bottom-center" }); 16 | } 17 | } 18 | fetchProducts(); 19 | }, []) 20 | 21 | return ( 22 |
23 |

Featured eBooks

24 |
25 | 26 | { products.map((product) => ( 27 | 28 | )) } 29 | 30 |
31 |
32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codebook", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-router-dom": "^6.4.0", 12 | "react-scripts": "5.0.1", 13 | "react-toastify": "^9.0.8", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "json-server": "^0.17.0", 42 | "json-server-auth": "^2.1.0", 43 | "tailwindcss": "^3.1.8" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/pages/Home/components/Hero.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | 3 | export const Hero = () => { 4 | return ( 5 |
6 |
7 |

The Ultimate eBook Store

8 |

CodeBook is the world's most popular and authoritative source for computer science ebooks. Find ratings and access to the newest books digitally.

9 | Explore eBooks 10 |
11 |
12 | CodeBook Hero Section 13 |
14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/pages/Dashboard/DashboardPage.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { toast } from "react-toastify"; 3 | import { useTitle } from "../../hooks/useTitle"; 4 | import { getUserOrders } from "../../services"; 5 | import { DashboardCard } from "./components/DashboardCard"; 6 | import { DashboardEmpty } from "./components/DashboardEmpty"; 7 | 8 | export const DashboardPage = () => { 9 | const [orders, setOrders] = useState([]); 10 | useTitle("Dashboard"); 11 | 12 | useEffect(() => { 13 | async function fetchOrders(){ 14 | try{ 15 | const data = await getUserOrders(); 16 | setOrders(data); 17 | } catch(error){ 18 | toast.error(error.message, { closeButton: true, position: "bottom-center" }); 19 | } 20 | } 21 | fetchOrders(); 22 | }, []); 23 | 24 | return ( 25 |
26 |
27 |

My Dashboard

28 |
29 | 30 |
31 | { orders.length && orders.map((order) => ( 32 | 33 | )) } 34 |
35 | 36 |
37 | { !orders.length && } 38 |
39 | 40 |
41 | ) 42 | } 43 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/DashboardCard.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | 3 | export const DashboardCard = ({order}) => { 4 | return ( 5 |
6 |
7 | Order Id: {order.id} 8 | Total: ${order.amount_paid} 9 |
10 | { order.cartList.map((product) => ( 11 |
12 |
13 | 14 | {product.name} 15 | 16 |
17 | 18 |

{product.name}

19 | 20 |
21 | ${product.price} 22 |
23 |
24 |
25 |
26 | )) } 27 |
28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /src/components/Sections/Search.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | 4 | export const Search = ({setSearchSection}) => { 5 | const navigate = useNavigate(); 6 | const searchRef = useRef(); 7 | 8 | const handleSearch = (event) => { 9 | event.preventDefault(); 10 | setSearchSection(false); 11 | navigate(`/products?q=${searchRef.current.value}`); 12 | } 13 | 14 | return ( 15 |
16 |
17 |
18 | 19 | 20 |
21 | 23 |
24 |
25 | ) 26 | } -------------------------------------------------------------------------------- /src/pages/Cart/components/CartList.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | import { useCart } from "../../../context"; 3 | import { CartCard } from "./CartCard" 4 | import { Checkout } from "./Checkout" 5 | 6 | export const CartList = () => { 7 | const [checkout, setCheckout] = useState(false); 8 | const { cartList, total } = useCart(); 9 | 10 | return ( 11 | <> 12 |
13 |

14 | My Cart ({cartList.length}) 15 |

16 |
17 | 18 |
19 | { cartList.map((product) => ( 20 | 21 | )) } 22 |
23 | 24 |
25 |
26 |

27 | Total Amount: 28 | ${total} 29 |

30 |
31 |
32 | 35 |
36 |
37 | { checkout && } 38 | 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /src/services/authService.js: -------------------------------------------------------------------------------- 1 | export async function login(authDetail){ 2 | const requestOptions = { 3 | method: "POST", 4 | headers: {"content-Type": "application/json"}, 5 | body: JSON.stringify(authDetail) 6 | } 7 | const response = await fetch(`${process.env.REACT_APP_HOST}/login`, requestOptions); 8 | if(!response.ok){ 9 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 10 | } 11 | const data = await response.json(); 12 | 13 | if(data.accessToken){ 14 | sessionStorage.setItem("token", JSON.stringify(data.accessToken)); 15 | sessionStorage.setItem("cbid", JSON.stringify(data.user.id)); 16 | } 17 | 18 | return data; 19 | } 20 | 21 | export async function register(authDetail){ 22 | const requestOptions = { 23 | method: "POST", 24 | headers: {"content-Type": "application/json"}, 25 | body: JSON.stringify(authDetail) 26 | } 27 | const response = await fetch(`${process.env.REACT_APP_HOST}/register`, requestOptions); 28 | if(!response.ok){ 29 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 30 | } 31 | const data = await response.json(); 32 | 33 | if(data.accessToken){ 34 | sessionStorage.setItem("token", JSON.stringify(data.accessToken)); 35 | sessionStorage.setItem("cbid", JSON.stringify(data.user.id)); 36 | } 37 | 38 | return data; 39 | } 40 | 41 | export function logout(){ 42 | sessionStorage.removeItem("token"); 43 | sessionStorage.removeItem("cbid"); 44 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Access Latest Computer Science E-Books - CodeBook 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/context/CartContext.js: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useReducer } from "react"; 2 | import { cartReducer } from "../reducers"; 3 | 4 | const cartInitialState = { 5 | cartList: [], 6 | total: 0 7 | } 8 | 9 | const CartContext = createContext(cartInitialState); 10 | 11 | export const CartProvider = ({children}) => { 12 | const [state, dispatch] = useReducer(cartReducer, cartInitialState); 13 | 14 | function addToCart(product){ 15 | const updatedList = state.cartList.concat(product); 16 | const updatedTotal = state.total + product.price; 17 | 18 | dispatch({ 19 | type: "ADD_TO_CART", 20 | payload: { 21 | products: updatedList, 22 | total: updatedTotal 23 | } 24 | }) 25 | } 26 | 27 | function removeFromCart(product){ 28 | const updatedList = state.cartList.filter(item => item.id !== product.id); 29 | const updatedTotal = state.total - product.price; 30 | 31 | dispatch({ 32 | type: "REMOVE_FROM_CART", 33 | payload: { 34 | products: updatedList, 35 | total: updatedTotal 36 | } 37 | }) 38 | } 39 | 40 | function clearCart(){ 41 | dispatch({ 42 | type: "CLEAR_CART", 43 | payload: { 44 | products: [], 45 | total: 0 46 | } 47 | }) 48 | } 49 | 50 | const value = { 51 | cartList: state.cartList, 52 | total: state.total, 53 | addToCart, 54 | removeFromCart, 55 | clearCart 56 | } 57 | 58 | return ( 59 | 60 | {children} 61 | 62 | ) 63 | } 64 | 65 | export const useCart = () => { 66 | const context = useContext(CartContext); 67 | return context; 68 | } -------------------------------------------------------------------------------- /src/pages/Home/components/Accordion.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export const Accordion = ({faq}) => { 4 | const {question, answer} = faq; 5 | const [show, setShow] = useState(false); 6 | 7 | return ( 8 |
9 |

10 | 15 |

16 | { show && ( 17 |
18 |
19 |

{answer}

20 |
21 |
22 | ) } 23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/pages/Home/components/Faq.js: -------------------------------------------------------------------------------- 1 | import { Accordion } from "./Accordion"; 2 | 3 | export const Faq = () => { 4 | const faqs = [ 5 | { 6 | "id": 1, 7 | "question": "Why should I use CodeBook?", 8 | "answer": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Repellendus earum dicta nesciunt, nulla alias consequuntur cumque incidunt saepe mollitia esse! Magni praesentium delectus excepturi nostrum illo repellendus cum eius neque, aperiam dolores quaerat quis dolore magnam doloremque minus sint nemo qui necessitatibus at. Perspiciatis, corrupti cum labore quos odio porro!" 9 | }, 10 | { 11 | "id": 2, 12 | "question": "Can I access my eBook on mobile?", 13 | "answer": "Lorem ipsum dolor sit amet consectetur adipisicing elit. At accusamus nobis tempore perferendis qui, quam, atque reprehenderit vero quaerat, assumenda pariatur eveniet. Maxime eaque, neque corrupti ad minus repudiandae consectetur!" 14 | }, 15 | { 16 | "id": 3, 17 | "question": "Do you offer refunds?", 18 | "answer": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse iste dolor deserunt expedita quam fugit et inventore amet pariatur. Animi." 19 | }, 20 | { 21 | "id": 4, 22 | "question": "Do you support Internation payments?", 23 | "answer": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse iste dolor deserunt expedita quam fugit et inventore amet pariatur. Animi." 24 | } 25 | ]; 26 | 27 | return ( 28 |
29 |

Question in mind?

30 |
31 | { faqs.map((faq) => ( 32 | 33 | )) } 34 |
35 |
36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /src/components/Elements/DropdownLoggedIn.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useEffect } from "react"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import { toast } from "react-toastify"; 5 | import { getUser, logout } from "../../services"; 6 | 7 | export const DropdownLoggedIn = ({setDropdown}) => { 8 | const navigate = useNavigate(); 9 | const [user, setUser] = useState({}); 10 | 11 | useEffect(() => { 12 | async function fetchData(){ 13 | try{ 14 | const data = await getUser(); 15 | data.email ? setUser(data) : handleLogout(); 16 | } catch(error){ 17 | toast.error(error.message, { closeButton: true, position: "bottom-center" }); 18 | } 19 | } 20 | fetchData(); 21 | }, []); //eslint-disable-line 22 | 23 | function handleLogout(){ 24 | logout(); 25 | setDropdown(false); 26 | navigate("/"); 27 | } 28 | 29 | return ( 30 | 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /src/services/dataService.js: -------------------------------------------------------------------------------- 1 | function getSession(){ 2 | const token = JSON.parse(sessionStorage.getItem("token")); 3 | const cbid = JSON.parse(sessionStorage.getItem("cbid")); 4 | return {token, cbid}; 5 | } 6 | 7 | export async function getUser(){ 8 | const browserData = getSession(); 9 | const requestOptions = { 10 | method: "GET", 11 | headers: {"Content-Type": "application/json", Authorization: `Bearer ${browserData.token}`} 12 | } 13 | const response = await fetch(`${process.env.REACT_APP_HOST}/600/users/${browserData.cbid}`, requestOptions); 14 | if(!response.ok){ 15 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 16 | } 17 | const data = await response.json(); 18 | return data; 19 | } 20 | 21 | export async function getUserOrders(){ 22 | const browserData = getSession(); 23 | const requestOptions = { 24 | method: "GET", 25 | headers: {"Content-Type": "application/json", Authorization: `Bearer ${browserData.token}`} 26 | } 27 | const response = await fetch(`${process.env.REACT_APP_HOST}/660/orders?user.id=${browserData.cbid}`, requestOptions); 28 | if(!response.ok){ 29 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 30 | } 31 | const data = await response.json(); 32 | return data; 33 | } 34 | 35 | export async function createOrder(cartList, total, user){ 36 | const browserData = getSession(); 37 | const order = { 38 | cartList: cartList, 39 | amount_paid: total, 40 | quantity: cartList.length, 41 | user: { 42 | name: user.name, 43 | email: user.email, 44 | id: user.id 45 | } 46 | } 47 | const requestOptions = { 48 | method: "POST", 49 | headers: { "Content-Type": "application/json", Authorization: `Bearer ${browserData.token}` }, 50 | body: JSON.stringify(order) 51 | } 52 | const response = await fetch(`${process.env.REACT_APP_HOST}/660/orders`, requestOptions); 53 | if(!response.ok){ 54 | throw { message: response.statusText, status: response.status }; //eslint-disable-line 55 | } 56 | const data = await response.json(); 57 | return data; 58 | } -------------------------------------------------------------------------------- /src/pages/Products/ProductsList.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | import { useTitle } from "../../hooks/useTitle"; 4 | 5 | import { ProductCard } from "../../components"; 6 | import { FilterBar } from "./components/FilterBar"; 7 | 8 | import { useFilter } from "../../context"; 9 | import { getProductList } from "../../services"; 10 | import { toast } from "react-toastify"; 11 | 12 | export const ProductsList = () => { 13 | const { products, initialProductList } = useFilter(); 14 | const [show, setShow] = useState(false); 15 | const search = useLocation().search; 16 | const searchTerm = new URLSearchParams(search).get("q"); 17 | useTitle("Explore eBooks Collection"); 18 | 19 | useEffect(() => { 20 | async function fetchProducts(){ 21 | try{ 22 | const data = await getProductList(searchTerm); 23 | initialProductList(data); 24 | } catch(error){ 25 | toast.error(error.message, {closeButton: true, position: "bottom-center" }); 26 | } 27 | } 28 | fetchProducts(); 29 | }, [searchTerm]); //eslint-disable-line 30 | 31 | return ( 32 |
33 |
34 |
35 | All eBooks ({products.length}) 36 | 37 | 40 | 41 |
42 | 43 |
44 | { products.map((product) => ( 45 | 46 | )) } 47 |
48 |
49 | 50 | { show && } 51 | 52 |
53 | ) 54 | } 55 | -------------------------------------------------------------------------------- /src/context/FilterContext.js: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useReducer } from "react" 2 | import { filterReducer } from "../reducers"; 3 | 4 | const filterInitialState = { 5 | productList: [], 6 | onlyInStock: false, 7 | bestSellerOnly: false, 8 | sortBy: null, 9 | ratings: null 10 | } 11 | 12 | const FilterContext = createContext(filterInitialState); 13 | 14 | export const FilterProvider = ({children}) => { 15 | const [state, dispatch] = useReducer(filterReducer, filterInitialState); 16 | 17 | function initialProductList(products){ 18 | dispatch({ 19 | type: "PRODUCT_LIST", 20 | payload: { 21 | products: products 22 | } 23 | }); 24 | } 25 | 26 | function bestSeller(products){ 27 | return state.bestSellerOnly ? products.filter(product => product.best_seller === true) : products; 28 | } 29 | 30 | function inStock(products){ 31 | return state.onlyInStock ? products.filter(product => product.in_stock === true) : products; 32 | } 33 | 34 | function sort(products){ 35 | if(state.sortBy === "lowtohigh"){ 36 | return products.sort((a, b) => Number(a.price) - Number(b.price)); 37 | } 38 | if(state.sortBy === "hightolow"){ 39 | return products.sort((a, b) => Number(b.price) - Number(a.price)); 40 | } 41 | return products; 42 | } 43 | 44 | function rating(products){ 45 | if(state.ratings === "4STARSABOVE"){ 46 | return products.filter(product => product.rating >= 4); 47 | } 48 | if(state.ratings === "3STARSABOVE"){ 49 | return products.filter(product => product.rating >= 3); 50 | } 51 | if(state.ratings === "2STARSABOVE"){ 52 | return products.filter(product => product.rating >= 2); 53 | } 54 | if(state.ratings === "1STARSABOVE"){ 55 | return products.filter(product => product.rating >= 1); 56 | } 57 | return products; 58 | } 59 | 60 | const filteredProductList = rating(sort(inStock(bestSeller(state.productList)))); 61 | 62 | const value = { 63 | state, 64 | dispatch, 65 | products: filteredProductList, 66 | initialProductList 67 | } 68 | return ( 69 | 70 | {children} 71 | 72 | ) 73 | } 74 | 75 | export const useFilter = () => { 76 | const context = useContext(FilterContext); 77 | return context; 78 | } -------------------------------------------------------------------------------- /src/components/Elements/ProductCard.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { useState } from "react"; 3 | import { Link } from "react-router-dom"; 4 | import { useCart } from "../../context"; 5 | import { Rating } from "./Rating"; 6 | 7 | export const ProductCard = ({product}) => { 8 | const { cartList, addToCart, removeFromCart } = useCart(); 9 | const [inCart, setInCart] = useState(false); 10 | const {id, name, overview, poster, price, rating, best_seller} = product; 11 | 12 | useEffect(() => { 13 | const productInCart = cartList.find(item => item.id === product.id); 14 | 15 | if(productInCart){ 16 | setInCart(true); 17 | } else { 18 | setInCart(false); 19 | } 20 | 21 | }, [cartList, product.id]); 22 | 23 | return ( 24 |
25 | 26 | { best_seller && Best Seller } 27 | {name} 28 | 29 |
30 | 31 |
{name}
32 | 33 |

{overview}

34 | 35 |
36 | 37 |
38 | 39 |

40 | 41 | ${price} 42 | 43 | { !inCart && } 44 | { inCart && } 45 |

46 |
47 |
48 | ) 49 | } 50 | -------------------------------------------------------------------------------- /src/components/Layouts/Header.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Link } from "react-router-dom"; 3 | import Logo from "../../assets/logo.png"; 4 | import { Search } from "../Sections/Search"; 5 | import { DropdownLoggedOut, DropdownLoggedIn } from "../index"; 6 | import { useCart } from "../../context"; 7 | 8 | export const Header = () => { 9 | const { cartList } = useCart(); 10 | const [darkMode, setDarkMode] = useState(JSON.parse(localStorage.getItem("darkMode")) || false); 11 | const [searchSection, setSearchSection] = useState(false); 12 | const [dropdown, setDropdown] = useState(false); 13 | const token = JSON.parse(sessionStorage.getItem("token")); 14 | 15 | useEffect(() => { 16 | localStorage.setItem("darkMode", JSON.stringify(darkMode)); 17 | 18 | if(darkMode){ 19 | document.documentElement.classList.add("dark"); 20 | } else { 21 | document.documentElement.classList.remove("dark"); 22 | } 23 | }, [darkMode]); 24 | 25 | return ( 26 |
27 | 46 | { searchSection && } 47 | 48 |
49 | ) 50 | } 51 | -------------------------------------------------------------------------------- /src/pages/Register.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from 'react-router-dom'; 2 | import { toast } from 'react-toastify'; 3 | import { useTitle } from "../hooks/useTitle"; 4 | import { register } from '../services'; 5 | 6 | export const Register = () => { 7 | useTitle("Register"); 8 | const navigate = useNavigate(); 9 | 10 | async function handleRegister(event){ 11 | event.preventDefault(); 12 | try{ 13 | const authDetail = { 14 | name: event.target.name.value, 15 | email: event.target.email.value, 16 | password: event.target.password.value 17 | } 18 | const data = await register(authDetail); 19 | data.accessToken ? navigate("/products") : toast.error(data); 20 | } catch(error){ 21 | toast.error(error.message, {closeButton: true, position: "bottom-center"}); 22 | } 23 | } 24 | 25 | return ( 26 |
27 |
28 |

Register

29 |
30 |
31 |
32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 | 44 |
45 |
46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /src/pages/Login.js: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { toast } from 'react-toastify'; 4 | import { useTitle } from "../hooks/useTitle"; 5 | import { login } from "../services"; 6 | 7 | export const Login = () => { 8 | useTitle("Login"); 9 | const navigate = useNavigate(); 10 | const email = useRef(); 11 | const password = useRef(); 12 | 13 | async function handleLogin(event){ 14 | event.preventDefault(); 15 | try{ 16 | const authDetail = { 17 | email: email.current.value, 18 | password: password.current.value 19 | } 20 | const data = await login(authDetail); 21 | data.accessToken ? navigate("/products") : toast.error(data); 22 | } catch(error){ 23 | toast.error(error.message, {closeButton: true, position: "bottom-center"}); 24 | } 25 | } 26 | 27 | async function handleLoginGuest(){ 28 | email.current.value = process.env.REACT_APP_GUEST_LOGIN; 29 | password.current.value = process.env.REACT_APP_GUEST_PASSWORD; 30 | try{ 31 | const authDetail = { 32 | email: email.current.value, 33 | password: password.current.value 34 | } 35 | const data = await login(authDetail); 36 | data.accessToken ? navigate("/products") : toast.error(data); 37 | } catch(error){ 38 | toast.error(error.message, {closeButton: true, position: "bottom-center"}); 39 | } 40 | } 41 | 42 | return ( 43 |
44 |
45 |

Login

46 |
47 |
48 |
49 | 50 | 51 |
52 |
53 | 54 | 55 |
56 | 57 |
58 | 59 |
60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /src/pages/ProductDetail.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react" 2 | import { useParams } from "react-router-dom"; 3 | import { toast } from "react-toastify"; 4 | import { useTitle } from "../hooks/useTitle"; 5 | import { Rating } from "../components"; 6 | import { useCart } from "../context"; 7 | import { getProduct } from "../services"; 8 | 9 | export const ProductDetail = () => { 10 | const { cartList, addToCart, removeFromCart } = useCart(); 11 | const [inCart, setInCart] = useState(false); 12 | const [product, setProduct] = useState({}); 13 | const { id } = useParams(); 14 | useTitle(product.name); 15 | 16 | useEffect(() => { 17 | async function fetchProducts(){ 18 | try{ 19 | const data = await getProduct(id); 20 | setProduct(data); 21 | } catch(error){ 22 | toast.error(error.message, {closeButton: true, position: "bottom-center" }); 23 | } 24 | } 25 | fetchProducts(); 26 | }, [id]); 27 | 28 | useEffect(() => { 29 | const productInCart = cartList.find(item => item.id === product.id); 30 | 31 | if(productInCart){ 32 | setInCart(true); 33 | } else { 34 | setInCart(false); 35 | } 36 | 37 | }, [cartList, product.id]); 38 | 39 | return ( 40 |
41 |
42 |

{product.name}

43 |

{product.overview}

44 |
45 |
46 | {product.name} 47 |
48 |
49 |

50 | $ 51 | {product.price} 52 |

53 |

54 | 55 | 56 | 57 |

58 |

59 | { product.best_seller && BEST SELLER } 60 | { product.in_stock && INSTOCK } 61 | { !product.in_stock && OUT OF STOCK } 62 | {product.size} MB 63 |

64 |

65 | { !inCart && } 66 | { inCart && } 67 |

68 |

69 | {product.long_description} 70 |

71 |
72 |
73 |
74 |
75 | ) 76 | } 77 | -------------------------------------------------------------------------------- /src/components/Layouts/Footer.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | export const Footer = () => { 4 | return ( 5 |
6 |
7 | © 2030 CodeBook. All Rights Reserved. 8 |
9 | 10 | 11 | Instagram page 12 | 13 | 14 | 15 | Twitter page 16 | 17 | 18 | 19 | GitHub account 20 | 21 |
22 |
23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/pages/Home/components/Testimonials.js: -------------------------------------------------------------------------------- 1 | export const Testimonials = () => { 2 | return ( 3 |
4 |

Student About CodeBook

5 |
6 |
7 |
8 |

Very easy this was to integrate

9 |

If you care for your time, I hands down would go with this."

10 |
11 |
12 | user 13 |
14 |
Bonnie Green
15 |
Developer at Random AI
16 |
17 |
18 |
19 |
20 |
21 |

Solid foundation for any project

22 |

Designing with Figma components that can be easily translated to the utility classes of Tailwind CSS is a huge timesaver!"

23 |
24 |
25 | user 26 |
27 |
Roberta Casas
28 |
Lead designer at Random
29 |
30 |
31 |
32 |
33 |
34 |

Mindblowing workflow

35 |

Aesthetically, the well designed components are beautiful and will undoubtedly level up your next application."

36 |
37 |
38 | user 39 |
40 |
Jese Leos
41 |
Software Engineer at Random
42 |
43 |
44 |
45 |
46 |
47 |

Efficient Collaborating

48 |

You have many examples that can be used to create a fast prototype for your team."

49 |
50 |
51 | user 52 |
53 |
Joseph McFall
54 |
CTO at Random
55 |
56 |
57 |
58 |
59 |
60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /src/pages/Cart/components/Checkout.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { toast } from "react-toastify"; 4 | import { useCart } from "../../../context"; 5 | import { createOrder, getUser } from "../../../services"; 6 | 7 | export const Checkout = ({setCheckout}) => { 8 | const { cartList, total, clearCart } = useCart(); 9 | const [user, setUser] = useState({}); 10 | 11 | const navigate = useNavigate(); 12 | 13 | useEffect(() => { 14 | async function fetchData(){ 15 | try{ 16 | const data = await getUser(); 17 | setUser(data); 18 | } catch(error){ 19 | toast.error(error.message, { closeButton: true, position: "bottom-center" }); 20 | } 21 | } 22 | fetchData(); 23 | }, []); 24 | 25 | async function handleOrderSubmit(event){ 26 | event.preventDefault(); 27 | try { 28 | const data = await createOrder(cartList, total, user); 29 | clearCart(); 30 | navigate("/order-summary", { state: {data: data, status: true} }); 31 | } catch(error) { 32 | toast.error(error.message, { closeButton: true, position: "bottom-center" }); 33 | navigate("/order-summary", { state: {status: false} }); 34 | } 35 | } 36 | 37 | return ( 38 |
39 |
40 | 86 |
87 | ) 88 | } 89 | -------------------------------------------------------------------------------- /src/pages/Products/components/FilterBar.js: -------------------------------------------------------------------------------- 1 | import { useFilter } from "../../../context"; 2 | 3 | export const FilterBar = ({setShow}) => { 4 | const {state, dispatch} = useFilter(); 5 | 6 | return ( 7 |
8 | 64 |
65 | ) 66 | } 67 | -------------------------------------------------------------------------------- /data/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "products": [ 3 | { 4 | "id": 10001, 5 | "name": "Basics To Advanced In React", 6 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 7 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 8 | "price": 29, 9 | "poster": "https://images.unsplash.com/photo-1633356122544-f134324a6cee?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 10 | "image_local": "/assets/images/10001.avif", 11 | "rating": 5, 12 | "in_stock": true, 13 | "size": 5, 14 | "best_seller": true 15 | }, 16 | { 17 | "id": 10002, 18 | "name": "Django Framework for Beginners", 19 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 20 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 21 | "price": 19, 22 | "poster": "https://images.unsplash.com/photo-1580894894513-541e068a3e2b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 23 | "image_local": "/assets/images/10002.avif", 24 | "rating": 5, 25 | "in_stock": true, 26 | "size": 2, 27 | "best_seller": false 28 | }, 29 | { 30 | "id": 10003, 31 | "name": "The Future of Design Systems", 32 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 33 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 34 | "price": 29, 35 | "poster": "https://images.unsplash.com/photo-1523726491678-bf852e717f6a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 36 | "image_local": "/assets/images/10003.avif", 37 | "rating": 3, 38 | "in_stock": true, 39 | "size": 1, 40 | "best_seller": false 41 | }, 42 | { 43 | "id": 10004, 44 | "name": "The Complete Guide to Backend Development", 45 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 46 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 47 | "price": 99, 48 | "poster": "https://images.unsplash.com/photo-1595617795501-9661aafda72a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 49 | "image_local": "/assets/images/10004.avif", 50 | "rating": 5, 51 | "in_stock": true, 52 | "size": 7, 53 | "best_seller": true 54 | }, 55 | { 56 | "id": 10005, 57 | "name": "Build a Blockchain from Scratch in Go", 58 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 59 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 60 | "price": 19, 61 | "poster": "https://images.unsplash.com/photo-1639322537228-f710d846310a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 62 | "image_local": "/assets/images/10005.avif", 63 | "rating": 3, 64 | "in_stock": true, 65 | "size": 3, 66 | "best_seller": false 67 | }, 68 | { 69 | "id": 10006, 70 | "name": "Frontend Fastlane Plan With Projects", 71 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 72 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 73 | "price": 99, 74 | "poster": "https://images.unsplash.com/photo-1522542550221-31fd19575a2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 75 | "image_local": "/assets/images/10006.avif", 76 | "rating": 5, 77 | "in_stock": true, 78 | "size": 10, 79 | "best_seller": false 80 | }, 81 | { 82 | "id": 10007, 83 | "name": "Master the Code Review", 84 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 85 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 86 | "price": 19, 87 | "poster": "https://images.unsplash.com/photo-1621839673705-6617adf9e890?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 88 | "image_local": "/assets/images/10007.avif", 89 | "rating": 5, 90 | "in_stock": true, 91 | "size": 2, 92 | "best_seller": false 93 | }, 94 | { 95 | "id": 10008, 96 | "name": "JavaScript Basics To Advance With Shubham", 97 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 98 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 99 | "price": 29, 100 | "poster": "https://images.unsplash.com/photo-1613490900233-141c5560d75d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 101 | "image_local": "/assets/images/10008.avif", 102 | "rating": 5, 103 | "in_stock": true, 104 | "size": 3, 105 | "best_seller": true 106 | }, 107 | { 108 | "id": 10009, 109 | "name": "Python Deep Dive With Projects", 110 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 111 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 112 | "price": 29, 113 | "poster": "https://images.unsplash.com/photo-1624953587687-daf255b6b80a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 114 | "image_local": "/assets/images/10009.avif", 115 | "rating": 5, 116 | "in_stock": true, 117 | "size": 3, 118 | "best_seller": false 119 | }, 120 | { 121 | "id": 10010, 122 | "name": "Mastering Software Technique", 123 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 124 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 125 | "price": 19, 126 | "poster": "https://images.unsplash.com/photo-1623479322729-28b25c16b011?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 127 | "image_local": "/assets/images/10010.avif", 128 | "rating": 4, 129 | "in_stock": true, 130 | "size": 1, 131 | "best_seller": false 132 | }, 133 | { 134 | "id": 10011, 135 | "name": "Web Development Foundation", 136 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 137 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 138 | "price": 29, 139 | "poster": "https://images.unsplash.com/photo-1507721999472-8ed4421c4af2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 140 | "image_local": "/assets/images/10011.avif", 141 | "rating": 5, 142 | "in_stock": true, 143 | "size": 3, 144 | "best_seller": true 145 | }, 146 | { 147 | "id": 10012, 148 | "name": "Mastering Git and GitHub - A Practical Guide", 149 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 150 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 151 | "price": 9, 152 | "poster": "https://images.unsplash.com/photo-1618401471353-b98afee0b2eb?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 153 | "image_local": "/assets/images/10012.avif", 154 | "rating": 5, 155 | "in_stock": true, 156 | "size": 1, 157 | "best_seller": false 158 | }, 159 | { 160 | "id": 10013, 161 | "name": "Everything About React v16", 162 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 163 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 164 | "price": 19, 165 | "poster": "https://images.unsplash.com/photo-1633356122102-3fe601e05bd2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 166 | "image_local": "/assets/images/10013.avif", 167 | "rating": 4, 168 | "in_stock": false, 169 | "size": 3, 170 | "best_seller": false 171 | }, 172 | { 173 | "id": 10014, 174 | "name": "Diving Deep With Python 2.7", 175 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 176 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 177 | "price": 19, 178 | "poster": "https://images.unsplash.com/photo-1515879218367-8466d910aaa4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 179 | "image_local": "/assets/images/10014.avif", 180 | "rating": 4, 181 | "in_stock": false, 182 | "size": 3, 183 | "best_seller": false 184 | }, 185 | { 186 | "id": 10015, 187 | "name": "Kickstart Your UI Design Career", 188 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 189 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 190 | "price": 9, 191 | "poster": "https://images.unsplash.com/photo-1587440871875-191322ee64b0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 192 | "image_local": "/assets/images/10015.avif", 193 | "rating": 2, 194 | "in_stock": false, 195 | "size": 1, 196 | "best_seller": false 197 | } 198 | ], 199 | "featured_products": [ 200 | { 201 | "id": 10004, 202 | "name": "The Complete Guide to Backend Development", 203 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 204 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 205 | "price": 99, 206 | "poster": "https://images.unsplash.com/photo-1595617795501-9661aafda72a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 207 | "image_local": "/assets/images/10004.avif", 208 | "rating": 5, 209 | "in_stock": true, 210 | "size": 7, 211 | "best_seller": true 212 | }, 213 | { 214 | "id": 10006, 215 | "name": "Frontend Fastlane Plan With Projects", 216 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 217 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 218 | "price": 99, 219 | "poster": "https://images.unsplash.com/photo-1522542550221-31fd19575a2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 220 | "image_local": "/assets/images/10006.avif", 221 | "rating": 5, 222 | "in_stock": true, 223 | "size": 10, 224 | "best_seller": false 225 | }, 226 | { 227 | "id": 10008, 228 | "name": "JavaScript Basics To Advance With Shubham", 229 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 230 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 231 | "price": 29, 232 | "poster": "https://images.unsplash.com/photo-1613490900233-141c5560d75d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 233 | "image_local": "/assets/images/10008.avif", 234 | "rating": 5, 235 | "in_stock": true, 236 | "size": 3, 237 | "best_seller": true 238 | } 239 | ], 240 | "orders": [ 241 | { 242 | "cartList": [ 243 | { 244 | "id": 10001, 245 | "name": "Basics To Advanced In React", 246 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 247 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 248 | "price": 29, 249 | "poster": "https://images.unsplash.com/photo-1633356122544-f134324a6cee?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 250 | "image_local": "/assets/images/10001.avif", 251 | "rating": 5, 252 | "in_stock": true, 253 | "size": 5, 254 | "best_seller": true 255 | }, 256 | { 257 | "id": 10008, 258 | "name": "JavaScript Basics To Advance With Shubham", 259 | "overview": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Error unde quisquam magni vel eligendi nam.", 260 | "long_description": "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta aut, vel ipsum maxime quam quia, quaerat tempore minus odio exercitationem illum et eos, quas ipsa aperiam magnam officiis libero expedita quo voluptas deleniti sit dolore? Praesentium tempora cumque facere consectetur quia, molestiae quam, accusamus eius corrupti laudantium aliquid! Tempore laudantium unde labore voluptates repellat, dignissimos aperiam ad ipsum laborum recusandae voluptatem non dolore. Reiciendis cum quo illum. Dolorem, molestiae corporis.", 261 | "price": 29, 262 | "poster": "https://images.unsplash.com/photo-1613490900233-141c5560d75d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=650&q=40", 263 | "image_local": "/assets/images/10008.avif", 264 | "rating": 5, 265 | "in_stock": true, 266 | "size": 3, 267 | "best_seller": true 268 | } 269 | ], 270 | "amount_paid": 58, 271 | "quantity": 2, 272 | "user": { 273 | "name": "Shubham Sarda", 274 | "email": "shubham@example.com", 275 | "id": 1 276 | }, 277 | "id": 1 278 | } 279 | ], 280 | "users": [ 281 | { 282 | "email": "shubham@example.com", 283 | "password": "$2a$10$K9aEH3/VDb2QU/EsjrHGJO7X5JxCcg0bMAnBtyT3kBW9FL7FnnygO", 284 | "name": "Shubham Sarda", 285 | "id": 1 286 | } 287 | ] 288 | } --------------------------------------------------------------------------------