├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── images │ └── google.png ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── About.js ├── App.css ├── App.js ├── App.test.js ├── Cart.js ├── Contact.js ├── ErrorPage.js ├── GlobalStyle.js ├── Helpers └── FormatPrice.js ├── Home.js ├── Products.js ├── SingleProduct.js ├── components ├── AddToCart.js ├── CartAmountToggle.js ├── CartItem.js ├── FeatureProduct.js ├── FilterSection.js ├── Footer.js ├── GridView.js ├── Header.js ├── HeroSection.js ├── ListView.js ├── MyImage.js ├── Nav.js ├── PageNavigation.js ├── Product.js ├── ProductList.js ├── Services.js ├── Sort.js ├── Spinner.js ├── Stars.js └── Trusted.js ├── context ├── cart_context.js ├── filter_context.js └── productcontext.js ├── images ├── hero.jpg ├── loading.gif └── logo.png ├── index.css ├── index.js ├── reducer ├── cartReducer.js ├── filterReducer.js └── productReducer.js ├── reportWebVitals.js ├── setupTests.js └── styles ├── Button.js └── Container.js /.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 | .env 16 | .DS_Store 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 | 26 | # Local Netlify folder 27 | .netlify 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ecommerce-react 2 | https://ecommerce-akash.netlify.app/ 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecom", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@auth0/auth0-react": "^1.10.2", 7 | "@testing-library/jest-dom": "^5.16.4", 8 | "@testing-library/react": "^13.3.0", 9 | "@testing-library/user-event": "^13.5.0", 10 | "axios": "^0.27.2", 11 | "mathjs": "^11.8.2", 12 | "react": "^18.2.0", 13 | "react-dom": "^18.2.0", 14 | "react-icons": "^4.10.1", 15 | "react-router-dom": "^6.3.0", 16 | "react-scripts": "5.0.1", 17 | "react-select": "^5.7.4", 18 | "styled-components": "^5.3.5", 19 | "web-vitals": "^2.1.4" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashm-2003/ecommerce-react/354c3371b5c99d3a58d3bd6e17440f3815f63901/public/favicon.ico -------------------------------------------------------------------------------- /public/images/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashm-2003/ecommerce-react/354c3371b5c99d3a58d3bd6e17440f3815f63901/public/images/google.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashm-2003/ecommerce-react/354c3371b5c99d3a58d3bd6e17440f3815f63901/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashm-2003/ecommerce-react/354c3371b5c99d3a58d3bd6e17440f3815f63901/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/About.js: -------------------------------------------------------------------------------- 1 | 2 | import React, { useContext } from 'react' 3 | import styled from 'styled-components' 4 | import HeroSection from './components/HeroSection' 5 | import {useProductContext} from './context/productcontext' 6 | const About = () => { 7 | const {myName}= useProductContext() 8 | const data={ 9 | title:'Akash Ecommerce' 10 | } 11 | return ( 12 | 13 | {myName} 14 | 15 | 16 | ) 17 | } 18 | const Wrapper = styled.div` 19 | 20 | `; 21 | export default About -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | .flex{ 41 | display: flex; 42 | justify-content: end; 43 | align-items: center; 44 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Home from "./Home"; 3 | import About from "./About"; 4 | import Products from "./Products"; 5 | import Contact from "./Contact"; 6 | import SingleProduct from "./SingleProduct"; 7 | import Cart from "./Cart"; 8 | import Error from "./ErrorPage"; 9 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 10 | import { GlobalStyle } from "./GlobalStyle"; 11 | import { ThemeProvider } from "styled-components"; 12 | import Header from "./components/Header"; 13 | import Footer from "./components/Footer"; 14 | const theme = { 15 | colors: { 16 | heading: "rgb(24 24 29)", 17 | text: "rgba(29 ,29, 29, .8)", 18 | white: "#fff", 19 | black: " #212529", 20 | helper: "#8490ff", 21 | 22 | bg: "#F6F8FA", 23 | footer_bg: "#0a1435", 24 | btn: "rgb(98 84 243)", 25 | border: "rgba(98, 84, 243, 0.5)", 26 | hr: "#ffffff", 27 | gradient: 28 | "linear-gradient(0deg, rgb(132 144 255) 0%, rgb(98 189 252) 100%)", 29 | shadow: 30 | "rgba(0, 0, 0, 0.02) 0px 1px 3px 0px,rgba(27, 31, 35, 0.15) 0px 0px 0px 1px;", 31 | shadowSupport: " rgba(0, 0, 0, 0.16) 0px 1px 4px", 32 | }, 33 | media: { 34 | mobile: "768px", 35 | tab: "998px", 36 | }, 37 | }; 38 | const App = () => { 39 | return ( 40 |
41 | 42 | 43 | 44 |
45 | 46 | }> 47 | }> 48 | }> 49 | }> 50 | }> 51 | }> 52 | }> 53 | 54 |
58 | ); 59 | }; 60 | 61 | export default App; 62 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/Cart.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { useCartContext } from "./context/cart_context"; 3 | import CartItem from "./components/CartItem"; 4 | import { NavLink } from "react-router-dom"; 5 | import { Button } from "./styles/Button"; 6 | import FormatPrice from "./Helpers/FormatPrice"; 7 | const Cart = () => { 8 | const { cart, clearCart, total_amount, shipping_fee } = useCartContext() 9 | return 10 | <> 11 | {cart.length !== 0 ?
12 |
13 |

Item

14 |

Price

15 |

Quantity

16 |

Subtotal

17 |

Remove

18 |
19 |
20 | 21 |
22 | {cart.map((curElem, index) => { 23 | return ; 24 | })} 25 |
26 |
27 |
28 | 29 | 30 | 31 | 34 |
35 | 36 | {/* order total_amount */} 37 |
38 |
39 |
40 |

subtotal:

41 |

42 | 43 |

44 |
45 |
46 |

shipping fee:

47 |

48 | 49 |

50 |
51 |
52 |
53 |

order total:

54 |

55 | 56 |

57 |
58 |
59 |
60 |
: 61 |
62 |
63 |
Shop Something
64 | 65 | 66 | 67 |
68 |
} 69 | 70 | 71 |
; 72 | }; 73 | 74 | 75 | // const EmptyDiv = styled.div` 76 | // display: grid; 77 | // place-items: center; 78 | // height: 50vh; 79 | 80 | // h3 { 81 | // font-size: 4.2rem; 82 | // text-transform: capitalize; 83 | // font-weight: 300; 84 | // } 85 | // `; 86 | 87 | const Wrapper = styled.section` 88 | padding: 9rem 0; 89 | .flexColumn{ 90 | display: flex; 91 | flex-direction: column; 92 | justify-content: center; 93 | align-items: center; 94 | .emptyCartText{ 95 | margin-bottom: 2rem; 96 | font-size: 2.5rem; 97 | } 98 | } 99 | .grid-four-column { 100 | grid-template-columns: repeat(4, 1fr); 101 | } 102 | 103 | .grid-five-column { 104 | grid-template-columns: repeat(4, 1fr) 0.3fr; 105 | text-align: center; 106 | align-items: center; 107 | } 108 | .cart-heading { 109 | text-align: center; 110 | text-transform: uppercase; 111 | } 112 | hr { 113 | margin-top: 1rem; 114 | } 115 | .cart-item { 116 | padding: 3.2rem 0; 117 | display: flex; 118 | flex-direction: column; 119 | gap: 3.2rem; 120 | } 121 | 122 | .cart-user--profile { 123 | display: flex; 124 | justify-content: flex-start; 125 | align-items: center; 126 | gap: 1.2rem; 127 | margin-bottom: 5.4rem; 128 | 129 | img { 130 | width: 8rem; 131 | height: 8rem; 132 | border-radius: 50%; 133 | } 134 | h2 { 135 | font-size: 2.4rem; 136 | } 137 | } 138 | .cart-user--name { 139 | text-transform: capitalize; 140 | } 141 | .cart-image--name { 142 | /* background-color: red; */ 143 | align-items: center; 144 | display: grid; 145 | gap: 1rem; 146 | grid-template-columns: 0.4fr 1fr; 147 | text-transform: capitalize; 148 | text-align: left; 149 | img { 150 | max-width: 5rem; 151 | height: 5rem; 152 | object-fit: contain; 153 | color: transparent; 154 | } 155 | 156 | .color-div { 157 | display: flex; 158 | align-items: center; 159 | justify-content: flex-start; 160 | gap: 1rem; 161 | 162 | .color-style { 163 | width: 1.4rem; 164 | height: 1.4rem; 165 | 166 | border-radius: 50%; 167 | } 168 | } 169 | } 170 | 171 | .cart-two-button { 172 | margin-top: 2rem; 173 | display: flex; 174 | justify-content: space-between; 175 | 176 | .btn-clear { 177 | background-color: #e74c3c; 178 | } 179 | } 180 | 181 | .amount-toggle { 182 | display: flex; 183 | justify-content: center; 184 | align-items: center; 185 | gap: 2.4rem; 186 | font-size: 1.4rem; 187 | 188 | button { 189 | border: none; 190 | background-color: #fff; 191 | cursor: pointer; 192 | } 193 | 194 | .amount-style { 195 | font-size: 2.4rem; 196 | color: ${({ theme }) => theme.colors.btn}; 197 | } 198 | } 199 | 200 | .remove_icon { 201 | font-size: 1.6rem; 202 | color: #e74c3c; 203 | cursor: pointer; 204 | } 205 | 206 | .order-total--amount { 207 | width: 100%; 208 | margin: 4.8rem 0; 209 | text-transform: capitalize; 210 | display: flex; 211 | flex-direction: column; 212 | justify-content: flex-end; 213 | align-items: flex-end; 214 | 215 | .order-total--subdata { 216 | border: 0.1rem solid #f0f0f0; 217 | display: flex; 218 | flex-direction: column; 219 | gap: 1.8rem; 220 | padding: 3.2rem; 221 | } 222 | div { 223 | display: flex; 224 | gap: 3.2rem; 225 | justify-content: space-between; 226 | } 227 | 228 | div:last-child { 229 | background-color: #fafafa; 230 | } 231 | 232 | div p:last-child { 233 | font-weight: bold; 234 | color: ${({ theme }) => theme.colors.heading}; 235 | } 236 | } 237 | 238 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 239 | .grid-five-column { 240 | grid-template-columns: 1.5fr 1fr 0.5fr; 241 | } 242 | .cart-hide { 243 | display: none; 244 | } 245 | 246 | .cart-two-button { 247 | margin-top: 2rem; 248 | display: flex; 249 | justify-content: space-between; 250 | gap: 2.2rem; 251 | } 252 | 253 | .order-total--amount { 254 | width: 100%; 255 | text-transform: capitalize; 256 | justify-content: flex-start; 257 | align-items: flex-start; 258 | 259 | .order-total--subdata { 260 | width: 100%; 261 | border: 0.1rem solid #f0f0f0; 262 | display: flex; 263 | flex-direction: column; 264 | gap: 1.8rem; 265 | padding: 3.2rem; 266 | } 267 | } 268 | } 269 | `; 270 | export default Cart; -------------------------------------------------------------------------------- /src/Contact.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | const Contact = () => { 4 | return 5 |

Contact Us

6 | 7 |
8 |
9 |
10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
; 18 | }; 19 | const Wrapper = styled.section` 20 | padding: 9rem 0 5rem 0; 21 | text-align: center; 22 | 23 | .container { 24 | margin-top: 6rem; 25 | 26 | .contact-form { 27 | max-width: 50rem; 28 | margin: auto; 29 | 30 | .contact-inputs { 31 | display: flex; 32 | flex-direction: column; 33 | gap: 3rem; 34 | 35 | input[type="submit"] { 36 | cursor: pointer; 37 | transition: all 0.2s; 38 | 39 | &:hover { 40 | background-color: ${({ theme }) => theme.colors.white}; 41 | border: 1px solid ${({ theme }) => theme.colors.btn}; 42 | color: ${({ theme }) => theme.colors.btn}; 43 | transform: scale(0.9); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | `; 50 | export default Contact; -------------------------------------------------------------------------------- /src/ErrorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components'; 3 | import { Button } from './styles/Button'; 4 | import { NavLink } from 'react-router-dom'; 5 | const ErrorPage = () => { 6 | return ( 7 | 8 |
9 |
10 |

404

11 |

Sorry, the page you tried cannot be found

12 |

The page you are looking for dosen't exist. How you got here is a mystery. But you can click the button below to go back to the homepage 13 |

14 | 15 |
16 |
17 |
18 | ) 19 | } 20 | const Wrapper = styled.section` 21 | .flex{ 22 | display: flex; 23 | justify-content: center; 24 | align-items: center; 25 | flex-direction: column; 26 | } 27 | .box{ 28 | margin: 8rem 2rem; 29 | } 30 | `; 31 | export default ErrorPage -------------------------------------------------------------------------------- /src/GlobalStyle.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from "styled-components"; 2 | 3 | export const GlobalStyle = createGlobalStyle` 4 | 5 | * { 6 | margin: 0; 7 | padding: 0; 8 | box-sizing: border-box; 9 | font-family: "Work Sans", sans-serif; 10 | } 11 | 12 | 13 | html { 14 | font-size: 62.5%; 15 | /* scroll-behavior: smooth; */ 16 | /* 1rem = 10px */ 17 | overflow-x: hidden; 18 | } 19 | 20 | body { 21 | overflow-x: hidden; 22 | scrollbar-color: rgb(98 84 243); 23 | scrollbar-width: thin; 24 | } 25 | 26 | body::-webkit-scrollbar { 27 | width: 1.5rem; 28 | } 29 | 30 | body::-webkit-scrollbar-track { 31 | background-color: rgb(24 24 29); 32 | } 33 | 34 | body::-webkit-scrollbar-thumb { 35 | 36 | background: #fff; 37 | border: 5px solid transparent; 38 | border-radius: 9px; 39 | background-clip: content-box; 40 | } 41 | 42 | h1, 43 | h2, 44 | h3, 45 | h4 { 46 | font-family: "Work Sans", sans-serif; 47 | 48 | } 49 | 50 | h1 { 51 | color: ${({ theme }) => theme.colors.heading}; 52 | font-size: 6rem; 53 | font-weight: 900; 54 | } 55 | 56 | h2 { 57 | color: ${({ theme }) => theme.colors.heading}; 58 | font-size: 4.4rem; 59 | font-weight: 300; 60 | white-space: normal; 61 | 62 | } 63 | 64 | h3 { 65 | font-size: 1.8rem; 66 | font-weight: 400; 67 | } 68 | 69 | p, button { 70 | color: ${({ theme }) => theme.colors.text}; 71 | font-size: 1.65rem; 72 | line-height: 1.5; 73 | font-weight:400; 74 | 75 | } 76 | 77 | a { 78 | text-decoration: none; 79 | } 80 | 81 | li { 82 | list-style: none; 83 | } 84 | 85 | 86 | ${"" /* resuable code section */} 87 | 88 | .container { 89 | max-width: 120rem; 90 | margin: 0 auto; 91 | } 92 | 93 | .grid { 94 | display: grid; 95 | gap: 9rem; 96 | } 97 | 98 | .grid-two-column { 99 | grid-template-columns: repeat(2, 1fr); 100 | 101 | } 102 | 103 | 104 | .b{ 105 | border: 1px solid red; 106 | } 107 | .grid-three-column { 108 | grid-template-columns: repeat(3, 1fr); 109 | } 110 | 111 | .grid-four-column{ 112 | grid-template-columns: 1fr 1.2fr .5fr .8fr ; 113 | } 114 | 115 | .grid-five-column{ 116 | grid-template-columns: repeat(5, 1fr); 117 | } 118 | 119 | .common-heading { 120 | font-size: 3.8rem; 121 | font-weight: 600; 122 | margin-bottom: 6rem; 123 | text-transform: capitalize; 124 | } 125 | 126 | .intro-data { 127 | margin-bottom: 0; 128 | text-transform: uppercase; 129 | color: #5138ee; 130 | } 131 | 132 | .caption { 133 | position: absolute; 134 | top: 15%; 135 | right: 10%; 136 | text-transform: uppercase; 137 | background-color: ${({ theme }) => theme.colors.bg}; 138 | color: ${({ theme }) => theme.colors.helper}; 139 | padding: 0.8rem 2rem; 140 | font-size: 1.2rem; 141 | border-radius: 2rem; 142 | } 143 | 144 | input, textarea{ 145 | max-width: 50rem; 146 | color: ${({ theme }) => theme.colors.black}; 147 | padding: 1.6rem 2.4rem; 148 | border: 1px solid ${({ theme }) => theme.colors.border}; 149 | text-transform: uppercase; 150 | box-shadow: ${({ theme }) => theme.colors.shadowSupport}; 151 | } 152 | input[type="submit"]{ 153 | max-width: 16rem; 154 | margin-top: 2rem; 155 | background-color: ${({ theme }) => theme.colors.btn}; 156 | color: ${({ theme }) => theme.colors.white}; 157 | padding: 1.4rem 2.2rem; 158 | border-style: solid; 159 | border-width: .1rem; 160 | text-transform: uppercase; 161 | font-size: 1.8rem; 162 | cursor: pointer; 163 | } 164 | 165 | @media (max-width: ${({ theme }) => theme.media.tab}) { 166 | .container { 167 | max-width: 130rem; 168 | padding: 0 3.2rem; 169 | } 170 | } 171 | 172 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 173 | html { 174 | font-size: 50%; 175 | } 176 | 177 | .grid{ 178 | gap: 3.2rem; 179 | } 180 | .grid-two-column , .grid-three-column, .grid-four-column{ 181 | grid-template-columns: 1fr; 182 | } 183 | } 184 | 185 | `; 186 | -------------------------------------------------------------------------------- /src/Helpers/FormatPrice.js: -------------------------------------------------------------------------------- 1 | 2 | const FormatPrice = ({price}) => { 3 | return Intl.NumberFormat('en-IN',{style:'currency', currency:'INR', maximumFractionDigits:2}).format(price/100) 4 | } 5 | 6 | export default FormatPrice -------------------------------------------------------------------------------- /src/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components' 3 | import HeroSection from './components/HeroSection'; 4 | import Trusted from './components/Trusted'; 5 | import Services from './components/Services'; 6 | import FeatureProduct from './components/FeatureProduct'; 7 | const Home = () => { 8 | const data={ 9 | title:'Akash Store' 10 | } 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ) 19 | } 20 | const Wrapper = styled.div` 21 | 22 | `; 23 | export default Home -------------------------------------------------------------------------------- /src/Products.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import FilterSection from "./components/FilterSection"; 4 | import ProductList from "./components/ProductList"; 5 | import Sort from "./components/Sort"; 6 | import { useFilterContext } from "./context/filter_context"; 7 | const Products = () => { 8 | const {grid_view,filtered_products,setGridView}=useFilterContext(); 9 | return 10 |
11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 |
23 |
; 24 | }; 25 | 26 | const Wrapper = styled.section` 27 | .grid-filter-column { 28 | grid-template-columns: 0.2fr 1fr; 29 | } 30 | 31 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 32 | .grid-filter-column { 33 | grid-template-columns: 1fr; 34 | } 35 | } 36 | `; 37 | 38 | export default Products; 39 | -------------------------------------------------------------------------------- /src/SingleProduct.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { useParams } from "react-router-dom"; 3 | import { useEffect } from "react"; 4 | import { useProductContext } from "./context/productcontext"; 5 | import PageNavigation from "./components/PageNavigation"; 6 | import MyImage from "./components/MyImage"; 7 | import FormatPrice from "./Helpers/FormatPrice"; 8 | import { MdSecurity } from "react-icons/md"; 9 | import { TbTruckDelivery, TbReplace } from "react-icons/tb"; 10 | import Spinner from "./components/Spinner"; 11 | import Stars from "./components/Stars"; 12 | import AddToCart from "./components/AddToCart"; 13 | const SingleProduct = () =>{ 14 | // id: ID is alias name 15 | const {singleProduct,getSingleProduct,isSingleLoading}=useProductContext(); 16 | const {id:productId} = useParams(); 17 | const API =`https://api.pujakaitem.com/api/products` 18 | const runApi=async()=>{ 19 | getSingleProduct(`${API}?id=${productId}`); 20 | } 21 | useEffect(() => { 22 | runApi() 23 | // eslint-disable-next-line 24 | },[]) 25 | 26 | const {id,name,price,company,description,stock,reviews,stars,image}=singleProduct; 27 | return( 28 | 29 | 30 | {isSingleLoading? :
31 |
32 | {/* product imag */} 33 |
34 | 35 |
36 | {/* product data */} 37 |
38 |

{name}

39 | 40 |

41 | MRP: 42 | 43 | 44 | 45 |

46 |

47 | Deal of the Day: 48 |

49 |

{description}

50 |
51 |
52 | 53 |

Free Delivery

54 |
55 | 56 |
57 | 58 |

30 Days Replacement

59 |
60 | 61 |
62 | 63 |

Akash Delivered

64 |
65 | 66 |
67 | 68 |

2 Year Warranty

69 |
70 |
71 | 72 |
73 |

Available:{stock>0?" In Stock":" Out of Stock"}

74 |

75 | ID : {id} 76 |

77 |

78 | Brand : {company} 79 |

80 |
81 | 82 |
83 | {stock&&} 84 |
85 |
86 |
} 87 |
88 | ); 89 | } 90 | 91 | const Wrapper = styled.section` 92 | .container { 93 | padding: 9rem 0; 94 | } 95 | .product-data { 96 | display: flex; 97 | flex-direction: column; 98 | align-items: flex-start; 99 | justify-content: center; 100 | gap: 2rem; 101 | 102 | .product-data-warranty { 103 | width: 100%; 104 | display: flex; 105 | justify-content: space-between; 106 | align-items: center; 107 | border-bottom: 1px solid #ccc; 108 | margin-bottom: 1rem; 109 | 110 | .product-warranty-data { 111 | text-align: center; 112 | 113 | .warranty-icon { 114 | background-color: rgba(220, 220, 220, 0.5); 115 | border-radius: 50%; 116 | width: 4rem; 117 | height: 4rem; 118 | padding: 0.6rem; 119 | } 120 | p { 121 | font-size: 1.4rem; 122 | padding-top: 0.4rem; 123 | } 124 | } 125 | } 126 | .product-images{ 127 | display:flex; 128 | align-items:center; 129 | } 130 | .product-data-price { 131 | font-weight: bold; 132 | } 133 | .product-data-real-price { 134 | color: ${({ theme }) => theme.colors.btn}; 135 | } 136 | .product-data-info { 137 | display: flex; 138 | flex-direction: column; 139 | gap: 1rem; 140 | font-size: 1.8rem; 141 | 142 | span { 143 | font-weight: bold; 144 | } 145 | } 146 | 147 | hr { 148 | max-width: 100%; 149 | width: 90%; 150 | /* height: 0.2rem; */ 151 | border: 0.1rem solid #000; 152 | color: red; 153 | } 154 | } 155 | 156 | .product-images { 157 | display: flex; 158 | justify-content: center; 159 | align-items: center; 160 | } 161 | 162 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 163 | padding: 0 2.4rem; 164 | } 165 | `; 166 | 167 | export default SingleProduct; 168 | -------------------------------------------------------------------------------- /src/components/AddToCart.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { FaCheck } from 'react-icons/fa' 3 | import { NavLink } from 'react-router-dom' 4 | import styled from 'styled-components' 5 | import { useCartContext } from '../context/cart_context' 6 | import { Button } from '../styles/Button' 7 | import CartAmountToggle from './CartAmountToggle' 8 | const AddToCart = ({ product }) => { 9 | const { id, colors, stock } = product 10 | const [mainColor, setMainColor] = useState(colors[0]) 11 | const [amount, setAmount] = useState(1) 12 | 13 | const setDecrease = () => { 14 | amount > 1 ? setAmount(amount - 1) : setAmount(1) 15 | } 16 | const setIncrease = () => { 17 | amount < stock ? setAmount(amount + 1) : setAmount(stock) 18 | } 19 | const { addToCart } = useCartContext() 20 | 21 | return ( 22 | 23 |
24 |

25 | colors : 26 | {colors.map((curColor, index) => { 27 | return ( 28 | 35 | ); 36 | })} 37 |

38 |
39 | 40 | {/* add to cart */} 41 | 42 | addToCart(id, mainColor, amount, product)} className="btn"> 43 | 44 | 45 |
46 | ) 47 | } 48 | const Wrapper = styled.section` 49 | .colors p { 50 | display: flex; 51 | justify-content: flex-start; 52 | align-items: center; 53 | } 54 | .btnStyle { 55 | width: 2rem; 56 | height: 2rem; 57 | background-color: #000; 58 | border-radius: 50%; 59 | margin-left: 1rem; 60 | border: none; 61 | outline: none; 62 | opacity: 0.5; 63 | cursor: pointer; 64 | 65 | &:hover { 66 | opacity: 1; 67 | } 68 | } 69 | 70 | .active { 71 | opacity: 1; 72 | } 73 | 74 | .checkStyle { 75 | font-size: 1rem; 76 | color: #fff; 77 | } 78 | 79 | /* we can use it as a global one too */ 80 | .amount-toggle { 81 | margin-top: 3rem; 82 | margin-bottom: 1rem; 83 | display: flex; 84 | justify-content: space-around; 85 | align-items: center; 86 | font-size: 1.4rem; 87 | 88 | button { 89 | border: none; 90 | background-color: #fff; 91 | cursor: pointer; 92 | } 93 | 94 | .amount-style { 95 | font-size: 2.4rem; 96 | color: ${({ theme }) => theme.colors.btn}; 97 | } 98 | } 99 | `; 100 | export default AddToCart -------------------------------------------------------------------------------- /src/components/CartAmountToggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { FaMinus, FaPlus } from 'react-icons/fa' 3 | const CartAmountToggle = ({amount,setDecrease,setIncrease}) => { 4 | return ( 5 |
6 |
7 |
8 | 9 |
{amount}
10 | 11 |
12 |
13 |
14 | ) 15 | } 16 | 17 | export default CartAmountToggle -------------------------------------------------------------------------------- /src/components/CartItem.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import FormatPrice from "../Helpers/FormatPrice"; 3 | import CartAmountToggle from "./CartAmountToggle"; 4 | import { FaTrash } from "react-icons/fa"; 5 | import { useCartContext } from "../context/cart_context"; 6 | 7 | const CartItem = ({ id,mainColor:color, amount,product }) => { 8 | const {name,price,image,stock}=product 9 | const { removeItem,setAmount } = useCartContext(); 10 | const setDecrease = () => { 11 | amount > 1 ? setAmount(id,amount - 1,color) : setAmount(id,1,color); 12 | }; 13 | 14 | const setIncrease = () => { 15 | amount < stock ? setAmount(id,amount + 1,color) : setAmount(id,stock,color); 16 | }; 17 | 18 | return ( 19 |
20 |
21 |
22 |
23 | {id} 24 |
25 |
26 |
27 |

{name}

28 |
29 |

color:

30 |
33 |
34 |
35 |
36 | {/* price */} 37 |
38 |

39 | 40 |

41 |
42 | 43 | {/* Quantity */} 44 | 49 | 50 | {/* //Subtotal */} 51 |
52 |

53 | 54 |

55 |
56 | 57 |
58 | removeItem(id,color)} /> 59 |
60 |
61 | ); 62 | }; 63 | 64 | export default CartItem; -------------------------------------------------------------------------------- /src/components/FeatureProduct.js: -------------------------------------------------------------------------------- 1 | import { useProductContext } from "../context/productcontext"; 2 | import Spinner from "./Spinner"; 3 | import styled from "styled-components"; 4 | 5 | import Product from "./Product"; 6 | const FeatureProduct = () => { 7 | const { isLoading,featuredProducts} = useProductContext(); 8 | // {isLoading ? :

hello

} 9 | return ( 10 | 11 | {isLoading ? :
12 |
Check Now
13 |
Our Feature Service
14 |
15 | { 16 | featuredProducts.map((product) => { 17 | return 18 | }) 19 | } 20 |
21 |
} 22 |
23 | ) 24 | } 25 | const Wrapper = styled.section` 26 | padding: 9rem 0; 27 | background-color: ${({ theme }) => theme.colors.bg}; 28 | 29 | .container { 30 | max-width: 120rem; 31 | } 32 | 33 | 34 | `; 35 | export default FeatureProduct -------------------------------------------------------------------------------- /src/components/FilterSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useFilterContext } from '../context/filter_context'; 3 | import styled from 'styled-components'; 4 | import { Button } from '../styles/Button'; 5 | const FilterSection = () => { 6 | const { filter: { text, category, color }, updateFilterValue, all_products } = useFilterContext(); 7 | 8 | // map is used to get only that particular data of object 9 | // filter is used to get the entire object data 10 | const getUniqueData = (data, type) => { 11 | let newVal = data.map((item) => item[type]); 12 | if (type === 'colors') { 13 | newVal = ["all", ...new Set(newVal.flat(1))]; 14 | return newVal; 15 | } 16 | else { 17 | newVal = ["all", ...new Set(newVal)]; 18 | return newVal; 19 | } 20 | } 21 | // const getUniqueColor = (data, type) => { 22 | // let newVal = data.map((item) => item[type]); 23 | // if(type==='colors'){ 24 | // newVal = ["all", ...new Set(newVal.flat(1))]; 25 | // return newVal; 26 | // } 27 | // else{ 28 | // newVal = ["all", ...new Set(newVal)]; 29 | // return newVal; 30 | // } 31 | // } 32 | // we need unique category data from all products 33 | const categoryData = getUniqueData(all_products, 'category'); 34 | const companyData = getUniqueData(all_products, 'company'); 35 | const colorsData = getUniqueData(all_products, 'colors'); 36 | return ( 37 | 38 |
39 |
e.preventDefault()}> 40 | { updateFilterValue(e.target.value, 'text') }} 46 | /> 47 |
48 |
49 | 50 |
51 |

Category

52 |
53 | {categoryData.map((curElem, index) => { 54 | return ( 55 | 64 | ); 65 | })} 66 |
67 |
68 | 69 |
70 |

Company

71 | 72 |
73 | 86 |
87 |
88 | 89 |
90 |

Colors

91 | 92 |
93 | {colorsData.map((curColor, index) => { 94 | return ( 95 | 105 | ); 106 | })} 107 |
108 |
109 |
110 | 111 |
112 |
113 | ) 114 | } 115 | const Wrapper = styled.section` 116 | padding: 5rem 0; 117 | display: flex; 118 | flex-direction: column; 119 | gap: 3rem; 120 | 121 | h3 { 122 | padding: 2rem 0; 123 | font-size: bold; 124 | } 125 | 126 | .filter-search { 127 | input { 128 | padding: 0.6rem 1rem; 129 | width: 80%; 130 | } 131 | } 132 | 133 | .filter-category { 134 | div { 135 | display: flex; 136 | flex-direction: column; 137 | align-items: flex-start; 138 | gap: 1.4rem; 139 | 140 | button { 141 | border: none; 142 | background-color: ${({ theme }) => theme.colors.white}; 143 | text-transform: capitalize; 144 | cursor: pointer; 145 | 146 | &:hover { 147 | color: ${({ theme }) => theme.colors.btn}; 148 | } 149 | } 150 | 151 | .active { 152 | border-bottom: 1px solid #000; 153 | color: ${({ theme }) => theme.colors.btn}; 154 | } 155 | } 156 | } 157 | 158 | 159 | .filter-company--select { 160 | padding: 0.3rem 1.2rem; 161 | font-size: 1.6rem; 162 | color: ${({ theme }) => theme.colors.text}; 163 | text-transform: capitalize; 164 | } 165 | 166 | .filter-color-style { 167 | display: flex; 168 | justify-content: center; 169 | } 170 | 171 | .color-all--style { 172 | background-color: transparent; 173 | text-transform: capitalize; 174 | border: none; 175 | cursor: pointer; 176 | } 177 | .btnStyle { 178 | width: 2rem; 179 | height: 2rem; 180 | background-color: #000; 181 | border-radius: 50%; 182 | margin-left: 1rem; 183 | border: none; 184 | outline: none; 185 | opacity: 0.5; 186 | cursor: pointer; 187 | 188 | &:hover { 189 | opacity: 1; 190 | } 191 | } 192 | 193 | .active { 194 | opacity: 1; 195 | } 196 | 197 | .checkStyle { 198 | font-size: 1rem; 199 | color: #fff; 200 | } 201 | 202 | .filter_price { 203 | input { 204 | margin: 0.5rem 0 1rem 0; 205 | padding: 0; 206 | box-shadow: none; 207 | cursor: pointer; 208 | } 209 | } 210 | 211 | .filter-shipping { 212 | display: flex; 213 | align-items: center; 214 | gap: 1rem; 215 | } 216 | 217 | .filter-clear .btn { 218 | background-color: #ec7063; 219 | color: #000; 220 | } 221 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 222 | .filter-category { 223 | div { 224 | flex-direction: row; 225 | } 226 | } 227 | } 228 | `; 229 | export default FilterSection -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { Button } from '../styles/Button'; 4 | import { NavLink } from 'react-router-dom'; 5 | import { FaDiscord, FaInstagram, FaYoutube } from "react-icons/fa"; 6 | const Footer = () => { 7 | return ( 8 | 9 |
10 |
11 |
12 |

Ready to get started?

13 |

Talk to us today

14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 | 22 | {/* footer section */} 23 |
24 |
25 |
26 |

Akash Manna

27 |

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Illo, natus?

28 |
29 |
30 |

Subscribe

31 |
32 | 33 | 34 |
35 |
36 |
37 |

Follow Us

38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 |
46 | 49 | 50 | 51 |
52 |
53 |
54 |
55 |

Call Us

56 |

+91 220393021

57 |
58 |
59 |
60 |
61 |
62 |

63 | @{new Date().getFullYear()} Akash Manna. All Rights Reserved 64 |

65 |
66 |

PRIVACY POLICY

67 |

TERMS & CONDITIONS

68 |
69 |
70 |
71 |
72 |
73 | ) 74 | } 75 | const Wrapper = styled.section` 76 | margin-top: 2rem; 77 | footer{ 78 | background: ${({ theme }) => theme.colors.footer_bg}; 79 | padding-top:13rem; 80 | padding-bottom: 2rem; 81 | width: 100vw; 82 | h3 { 83 | color: ${({ theme }) => theme.colors.hr}; 84 | margin-bottom: 2.4rem; 85 | } 86 | .footer-social--icons { 87 | display: flex; 88 | gap: 2rem; 89 | 90 | div { 91 | padding: 1rem; 92 | border-radius: 50%; 93 | border: 2px solid ${({ theme }) => theme.colors.white}; 94 | height: 5rem; 95 | .icons { 96 | color: ${({ theme }) => theme.colors.white}; 97 | font-size: 2.4rem; 98 | position: relative; 99 | cursor: pointer; 100 | 101 | } 102 | } 103 | } 104 | } 105 | .footer-bottom--section { 106 | padding-top: 9rem; 107 | 108 | hr { 109 | margin-bottom: 2rem; 110 | color: ${({ theme }) => theme.colors.hr}; 111 | height: 0.1px; 112 | } 113 | } 114 | .contact-short { 115 | max-width: 60vw; 116 | margin: auto; 117 | padding: 5rem 10rem; 118 | background-color: ${({ theme }) => theme.colors.bg}; 119 | border-radius: 1rem; 120 | box-shadow: ${({ theme }) => theme.colors.shadowSupport}; 121 | transform: translateY(50%); 122 | 123 | .grid div:last-child { 124 | justify-self: end; 125 | align-self: center; 126 | } 127 | } 128 | @media (max-width: ${({ theme }) => theme.media.mobile}) { 129 | .contact-short { 130 | max-width: 80vw; 131 | margin: 4.8rem auto; 132 | transform: translateY(0%); 133 | text-align: center; 134 | 135 | .grid div:last-child { 136 | justify-self: center; 137 | } 138 | } 139 | 140 | footer { 141 | padding: 9rem 0 2rem 0; 142 | } 143 | 144 | .footer-bottom--section { 145 | padding-top: 4.8rem; 146 | } 147 | } 148 | `; 149 | export default Footer -------------------------------------------------------------------------------- /src/components/GridView.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Product from './Product' 3 | import styled from 'styled-components' 4 | const GridView = ({filtered_products}) => { 5 | return ( 6 |
7 |
8 | {filtered_products.map((product)=>{ 9 | return 10 | })} 11 |
12 | 13 |
14 | ) 15 | } 16 | 17 | const Wrapper = styled.section` 18 | 19 | background-color: ${({ theme }) => theme.colors.bg}; 20 | .grid{ 21 | gap:1rem; 22 | padding:2rem; 23 | } 24 | .container { 25 | max-width: 120rem; 26 | } 27 | 28 | 29 | ` 30 | export default GridView -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import React from 'react' 3 | import { NavLink } from "react-router-dom"; 4 | import Nav from "./Nav"; 5 | import logo from '../images/logo.png' 6 | const Header = () => { 7 | return ( 8 | 9 | 10 | logo 11 | 12 |