diff --git a/package-lock.json b/package-lock.json
index 3b27464..7049ad8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,8 +8,10 @@
"name": "react-course",
"version": "0.0.0",
"dependencies": {
+ "@heroicons/react": "^2.0.16",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.8.1"
},
"devDependencies": {
"@types/react": "^18.0.27",
@@ -729,6 +731,14 @@
"node": ">=12"
}
},
+ "node_modules/@heroicons/react": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.16.tgz",
+ "integrity": "sha512-x89rFxH3SRdYaA+JCXwfe+RkE1SFTo9GcOkZettHer71Y3T7V+ogKmfw5CjTazgS3d0ClJ7p1NA+SP7VQLQcLw==",
+ "peerDependencies": {
+ "react": ">= 16"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -811,6 +821,14 @@
"node": ">= 8"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.2.tgz",
+ "integrity": "sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@@ -1803,6 +1821,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.8.1.tgz",
+ "integrity": "sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==",
+ "dependencies": {
+ "@remix-run/router": "1.3.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.8.1.tgz",
+ "integrity": "sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==",
+ "dependencies": {
+ "@remix-run/router": "1.3.2",
+ "react-router": "6.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -2533,6 +2581,12 @@
"dev": true,
"optional": true
},
+ "@heroicons/react": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.16.tgz",
+ "integrity": "sha512-x89rFxH3SRdYaA+JCXwfe+RkE1SFTo9GcOkZettHer71Y3T7V+ogKmfw5CjTazgS3d0ClJ7p1NA+SP7VQLQcLw==",
+ "requires": {}
+ },
"@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -2597,6 +2651,11 @@
"fastq": "^1.6.0"
}
},
+ "@remix-run/router": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.2.tgz",
+ "integrity": "sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA=="
+ },
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@@ -3268,6 +3327,23 @@
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
"dev": true
},
+ "react-router": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.8.1.tgz",
+ "integrity": "sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==",
+ "requires": {
+ "@remix-run/router": "1.3.2"
+ }
+ },
+ "react-router-dom": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.8.1.tgz",
+ "integrity": "sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==",
+ "requires": {
+ "@remix-run/router": "1.3.2",
+ "react-router": "6.8.1"
+ }
+ },
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index d856062..96ef4e2 100644
--- a/package.json
+++ b/package.json
@@ -9,8 +9,10 @@
"preview": "vite preview"
},
"dependencies": {
+ "@heroicons/react": "^2.0.16",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.8.1"
},
"devDependencies": {
"@types/react": "^18.0.27",
diff --git a/src/App.jsx b/src/App.jsx
deleted file mode 100644
index f779d2c..0000000
--- a/src/App.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import './App.css'
-
-function App() {
-
- return (
-
- Hola mundo bebé
-
- )
-}
-
-export default App
diff --git a/src/Components/Card/index.jsx b/src/Components/Card/index.jsx
new file mode 100644
index 0000000..100bc14
--- /dev/null
+++ b/src/Components/Card/index.jsx
@@ -0,0 +1,59 @@
+import { useContext } from 'react'
+import { PlusIcon, CheckIcon } from '@heroicons/react/24/solid'
+import { ShoppingCartContext } from '../../Context'
+
+const Card = (data) => {
+ const context = useContext(ShoppingCartContext)
+
+ const showProduct = (productDetail) => {
+ context.openProductDetail()
+ context.setProductToShow(productDetail)
+ }
+
+ const addProductsToCart = (event, productData) => {
+ event.stopPropagation()
+ context.setCount(context.count + 1)
+ context.setCartProducts([...context.cartProducts, productData])
+ context.openCheckoutSideMenu()
+ context.closeProductDetail()
+ }
+
+ const renderIcon = (id) => {
+ const isInCart = context.cartProducts.filter(product => product.id === id).length > 0
+
+ if (isInCart) {
+ return (
+
+
+
+ )
+ } else {
+ return (
+ addProductsToCart(event, data.data)}>
+
+
+ )
+ }
+ }
+
+ return (
+ showProduct(data.data)}>
+
+ {data.data.category.name}
+
+ {renderIcon(data.data.id)}
+
+
+ {data.data.title}
+ ${data.data.price}
+
+
+ )
+}
+
+export default Card
\ No newline at end of file
diff --git a/src/Components/CheckoutSideMenu/index.jsx b/src/Components/CheckoutSideMenu/index.jsx
new file mode 100644
index 0000000..d049cd7
--- /dev/null
+++ b/src/Components/CheckoutSideMenu/index.jsx
@@ -0,0 +1,68 @@
+import { useContext } from 'react'
+import { Link } from 'react-router-dom'
+import { XMarkIcon } from '@heroicons/react/24/solid'
+import { ShoppingCartContext } from '../../Context'
+import OrderCard from '../../Components/OrderCard'
+import { totalPrice } from '../../utils'
+import './styles.css'
+
+const CheckoutSideMenu = () => {
+ const context = useContext(ShoppingCartContext)
+
+ const handleDelete = (id) => {
+ const filteredProducts = context.cartProducts.filter(product => product.id != id)
+ context.setCartProducts(filteredProducts)
+ }
+
+ const handleCheckout = () => {
+ const orderToAdd = {
+ date: '01.02.23',
+ products: context.cartProducts,
+ totalProducts: context.cartProducts.length,
+ totalPrice: totalPrice(context.cartProducts)
+ }
+
+ context.setOrder([...context.order, orderToAdd])
+ context.setCartProducts([])
+ context.setSearchByTitle(null)
+ }
+
+ return (
+
+
+
My Order
+
+ context.closeCheckoutSideMenu()}>
+
+
+
+ {
+ context.cartProducts.map(product => (
+
+ ))
+ }
+
+
+
+ Total:
+ ${totalPrice(context.cartProducts)}
+
+
+
handleCheckout()}>Checkout
+
+
+
+ )
+}
+
+export default CheckoutSideMenu
\ No newline at end of file
diff --git a/src/Components/CheckoutSideMenu/styles.css b/src/Components/CheckoutSideMenu/styles.css
new file mode 100644
index 0000000..5a2d504
--- /dev/null
+++ b/src/Components/CheckoutSideMenu/styles.css
@@ -0,0 +1,5 @@
+.checkout-side-menu {
+ width: 360px;
+ height: calc(100vh - 68px);
+ top: 68px;
+}
\ No newline at end of file
diff --git a/src/Components/Layout/index.jsx b/src/Components/Layout/index.jsx
new file mode 100644
index 0000000..0504846
--- /dev/null
+++ b/src/Components/Layout/index.jsx
@@ -0,0 +1,9 @@
+const Layout = ({ children }) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default Layout
\ No newline at end of file
diff --git a/src/Components/Navbar/index.jsx b/src/Components/Navbar/index.jsx
new file mode 100644
index 0000000..271aefe
--- /dev/null
+++ b/src/Components/Navbar/index.jsx
@@ -0,0 +1,119 @@
+import { useContext } from 'react'
+import { NavLink } from 'react-router-dom'
+import { ShoppingBagIcon } from '@heroicons/react/24/solid'
+import { ShoppingCartContext, UserContext } from '../../Context'
+
+const Navbar = () => {
+ const context = useContext(ShoppingCartContext)
+ const userContext = useContext(UserContext)
+ const activeStyle = 'underline underline-offset-4'
+
+ return (
+
+
+
+
+ Shopi
+
+
+
+ context.setSearchByCategory()}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ All
+
+
+
+ context.setSearchByCategory('clothes')}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ Clothes
+
+
+
+ context.setSearchByCategory('electronics')}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ Electronics
+
+
+
+ context.setSearchByCategory('furnitures')}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ Furnitures
+
+
+
+ context.setSearchByCategory('toys')}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ Toys
+
+
+
+ context.setSearchByCategory('others')}
+ className={({ isActive }) =>
+ isActive ? activeStyle : undefined
+ }>
+ Others
+
+
+
+ {
+ userContext.isLoggedIn && userContext.user? (
+
+ ) : (
+
+
+
+ isActive ? activeStyle : undefined
+ }>
+ Sign In
+
+
+
+ )
+ }
+
+ )
+}
+
+export default Navbar
\ No newline at end of file
diff --git a/src/Components/OrderCard/index.jsx b/src/Components/OrderCard/index.jsx
new file mode 100644
index 0000000..e0dc13a
--- /dev/null
+++ b/src/Components/OrderCard/index.jsx
@@ -0,0 +1,26 @@
+import { XMarkIcon } from '@heroicons/react/24/solid'
+
+const OrderCard = props => {
+ const { id, title, imageUrl, price, handleDelete } = props
+ let renderXMarkIcon
+ if (handleDelete) {
+ renderXMarkIcon = handleDelete(id)} className='h-6 w-6 text-black cursor-pointer'>
+ }
+
+ return (
+
+
+
+
+
+
{title}
+
+
+
{price}
+ {renderXMarkIcon}
+
+
+ )
+}
+
+export default OrderCard
\ No newline at end of file
diff --git a/src/Components/OrdersCard/index.jsx b/src/Components/OrdersCard/index.jsx
new file mode 100644
index 0000000..4094786
--- /dev/null
+++ b/src/Components/OrdersCard/index.jsx
@@ -0,0 +1,22 @@
+import { ChevronRightIcon } from '@heroicons/react/24/solid'
+
+const OrdersCard = props => {
+ const { totalPrice, totalProducts } = props
+
+ return (
+
+
+
+ 01.02.23
+ {totalProducts} articles
+
+
+ ${totalPrice}
+
+
+
+
+ )
+}
+
+export default OrdersCard
\ No newline at end of file
diff --git a/src/Components/ProductDetail/index.jsx b/src/Components/ProductDetail/index.jsx
new file mode 100644
index 0000000..6c6a338
--- /dev/null
+++ b/src/Components/ProductDetail/index.jsx
@@ -0,0 +1,35 @@
+import { useContext } from 'react'
+import { XMarkIcon } from '@heroicons/react/24/solid'
+import { ShoppingCartContext } from '../../Context'
+import './styles.css'
+
+const ProductDetail = () => {
+ const context = useContext(ShoppingCartContext)
+
+ return (
+
+
+
Detail
+
+ context.closeProductDetail()}>
+
+
+
+
+
+
+ ${context.productToShow.price}
+ ${context.productToShow.title}
+ ${context.productToShow.description}
+
+
+ )
+}
+
+export default ProductDetail
\ No newline at end of file
diff --git a/src/Components/ProductDetail/styles.css b/src/Components/ProductDetail/styles.css
new file mode 100644
index 0000000..f544704
--- /dev/null
+++ b/src/Components/ProductDetail/styles.css
@@ -0,0 +1,5 @@
+.product-detail {
+ width: 360px;
+ height: calc(100vh - 68px);
+ top: 68px;
+}
\ No newline at end of file
diff --git a/src/Context/index.jsx b/src/Context/index.jsx
new file mode 100644
index 0000000..6ac1559
--- /dev/null
+++ b/src/Context/index.jsx
@@ -0,0 +1,123 @@
+import { createContext, useState, useEffect } from 'react'
+
+export const ShoppingCartContext = createContext()
+
+export const UserContext = createContext()
+
+export const UserProvider = ({children})=>{
+
+ const [user, setUser] = useState(JSON.parse(localStorage.getItem("user")))
+ const [isLoggedIn, setIsLoggedIn] = useState(JSON.parse(localStorage.getItem("isLoggedIn")))
+ const [registeredUsers, setRegisteredUsers] = useState(JSON.parse(localStorage.getItem("registeredUsers")))
+
+ return (
+
+ {children}
+
+ )
+}
+
+export const ShoppingCartProvider = ({children}) => {
+ // Shopping Cart · Increment quantity
+ const [count, setCount] = useState(0)
+
+ // Product Detail · Open/Close
+ const [isProductDetailOpen, setIsProductDetailOpen] = useState(false)
+ const openProductDetail = () => setIsProductDetailOpen(true)
+ const closeProductDetail = () => setIsProductDetailOpen(false)
+
+ // Checkout Side Menu · Open/Close
+ const [isCheckoutSideMenuOpen, setIsCheckoutSideMenuOpen] = useState(false)
+ const openCheckoutSideMenu = () => setIsCheckoutSideMenuOpen(true)
+ const closeCheckoutSideMenu = () => setIsCheckoutSideMenuOpen(false)
+
+ // Product Detail · Show product
+ const [productToShow, setProductToShow] = useState({})
+
+ // Shopping Cart · Add products to cart
+ const [cartProducts, setCartProducts] = useState([])
+
+ // Shopping Cart · Order
+ const [order, setOrder] = useState([])
+
+ // Get products
+ const [items, setItems] = useState(null)
+ const [filteredItems, setFilteredItems] = useState(null)
+
+ // Get products by title
+ const [searchByTitle, setSearchByTitle] = useState(null)
+
+ // Get products by category
+ const [searchByCategory, setSearchByCategory] = useState(null)
+
+ useEffect(() => {
+ fetch('https://api.escuelajs.co/api/v1/products')
+ .then(response => response.json())
+ .then(data => setItems(data))
+ }, [])
+
+ const filteredItemsByTitle = (items, searchByTitle) => {
+ return items?.filter(item => item.title.toLowerCase().includes(searchByTitle.toLowerCase()))
+ }
+
+ const filteredItemsByCategory = (items, searchByCategory) => {
+ return items?.filter(item => item.category.name.toLowerCase().includes(searchByCategory.toLowerCase()))
+ }
+
+ const filterBy = (searchType, items, searchByTitle, searchByCategory) => {
+ if (searchType === 'BY_TITLE') {
+ return filteredItemsByTitle(items, searchByTitle)
+ }
+
+ if (searchType === 'BY_CATEGORY') {
+ return filteredItemsByCategory(items, searchByCategory)
+ }
+
+ if (searchType === 'BY_TITLE_AND_CATEGORY') {
+ return filteredItemsByCategory(items, searchByCategory).filter(item => item.title.toLowerCase().includes(searchByTitle.toLowerCase()))
+ }
+
+ if (!searchType) {
+ return items
+ }
+ }
+
+ useEffect(() => {
+ if (searchByTitle && searchByCategory) setFilteredItems(filterBy('BY_TITLE_AND_CATEGORY', items, searchByTitle, searchByCategory))
+ if (searchByTitle && !searchByCategory) setFilteredItems(filterBy('BY_TITLE', items, searchByTitle, searchByCategory))
+ if (!searchByTitle && searchByCategory) setFilteredItems(filterBy('BY_CATEGORY', items, searchByTitle, searchByCategory))
+ if (!searchByTitle && !searchByCategory) setFilteredItems(filterBy(null, items, searchByTitle, searchByCategory))
+ }, [items, searchByTitle, searchByCategory])
+
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/App.css b/src/Pages/App/App.css
similarity index 100%
rename from src/App.css
rename to src/Pages/App/App.css
diff --git a/src/Pages/App/index.jsx b/src/Pages/App/index.jsx
new file mode 100644
index 0000000..83b3135
--- /dev/null
+++ b/src/Pages/App/index.jsx
@@ -0,0 +1,60 @@
+import { useContext } from 'react'
+import { useRoutes, BrowserRouter } from 'react-router-dom'
+import { ShoppingCartProvider, UserProvider, UserContext } from '../../Context'
+import Home from '../Home'
+import MyAccount from '../MyAccount'
+import MyOrder from '../MyOrder'
+import MyOrders from '../MyOrders'
+import NotFound from '../NotFound'
+import SignIn from '../SignIn'
+import SignUp from '../Signup'
+import Navbar from '../../Components/Navbar'
+import CheckoutSideMenu from '../../Components/CheckoutSideMenu'
+import './App.css'
+
+const AppRoutes = () => {
+ let routes = useRoutes([
+ { path: '/', element: },
+ { path: '/clothes', element: },
+ { path: '/electronics', element: },
+ { path: '/furnitures', element: },
+ { path: '/toys', element: },
+ { path: '/others', element: },
+ { path: '/my-account', element: },
+ { path: '/my-order', element: },
+ { path: '/my-orders', element: },
+ { path: '/my-orders/last', element: },
+ { path: '/my-orders/:id', element: },
+ { path: '/sign-in', element: },
+ { path: '/sign-up', element: },
+ { path: '/*', element: },
+ ])
+
+ return routes
+}
+
+const App = () => {
+ const userContext = useContext(UserContext)
+ const userLocalStorage = localStorage.getItem("user")
+ const isLoggedInLocalStorage = localStorage.getItem("isLoggedIn")
+ const registeredUsers = localStorage.getItem("registeredUsers")
+ if (!userLocalStorage && !isLoggedInLocalStorage && !registeredUsers){
+ localStorage.setItem("user", "null")
+ localStorage.setItem("isLoggedIn", "false")
+ localStorage.setItem("registeredUsers", "[]")
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default App
diff --git a/src/Pages/Home/index.jsx b/src/Pages/Home/index.jsx
new file mode 100644
index 0000000..1f93b85
--- /dev/null
+++ b/src/Pages/Home/index.jsx
@@ -0,0 +1,41 @@
+import { useContext } from 'react'
+import Layout from '../../Components/Layout'
+import Card from '../../Components/Card'
+import ProductDetail from '../../Components/ProductDetail'
+import { ShoppingCartContext } from '../../Context'
+
+function Home() {
+ const context = useContext(ShoppingCartContext)
+ const renderView = () => {
+ if (context.filteredItems?.length > 0) {
+ return (
+ context.filteredItems?.map(item => (
+
+ ))
+ )
+ } else {
+ return (
+ We don't have anything :(
+ )
+ }
+ }
+
+ return (
+
+
+
Exclusive Products
+
+ context.setSearchByTitle(event.target.value)} />
+
+ {renderView()}
+
+
+
+ )
+}
+
+export default Home
\ No newline at end of file
diff --git a/src/Pages/MyAccount/index.jsx b/src/Pages/MyAccount/index.jsx
new file mode 100644
index 0000000..e245155
--- /dev/null
+++ b/src/Pages/MyAccount/index.jsx
@@ -0,0 +1,33 @@
+import { useContext } from 'react'
+import { NavLink } from 'react-router-dom'
+import Layout from '../../Components/Layout'
+import { UserContext } from '../../Context'
+
+function MyAccount() {
+ const userContext = useContext(UserContext)
+ const logOut = () =>{
+ userContext.setUser(null)
+ userContext.setIsLoggedIn(false)
+ localStorage.setItem("user", JSON.stringify(null))
+ localStorage.setItem("isLoggedIn", "false")
+ }
+ return (
+
+
+
+ My Account
+
+
+
Name: {userContext.user.name}
+
Email: {userContext.user.email}
+
+
Edit
+
+ Log Out
+
+
+
+ )
+}
+
+export default MyAccount
\ No newline at end of file
diff --git a/src/Pages/MyOrder/index.jsx b/src/Pages/MyOrder/index.jsx
new file mode 100644
index 0000000..f6a947c
--- /dev/null
+++ b/src/Pages/MyOrder/index.jsx
@@ -0,0 +1,39 @@
+import { useContext } from 'react'
+import { Link } from 'react-router-dom'
+import { ChevronLeftIcon } from '@heroicons/react/24/solid'
+import { ShoppingCartContext } from '../../Context'
+import Layout from '../../Components/Layout'
+import OrderCard from '../../Components/OrderCard'
+
+function MyOrder() {
+ const context = useContext(ShoppingCartContext)
+ const currentPath = window.location.pathname
+ let index = currentPath.substring(currentPath.lastIndexOf('/') + 1)
+ if (index === 'last') index = context.order?.length - 1
+
+ return (
+
+
+
+
+
+
My Order
+
+
+ {
+ context.order?.[index]?.products.map(product => (
+
+ ))
+ }
+
+
+ )
+}
+
+export default MyOrder
\ No newline at end of file
diff --git a/src/Pages/MyOrders/index.jsx b/src/Pages/MyOrders/index.jsx
new file mode 100644
index 0000000..ab48c3f
--- /dev/null
+++ b/src/Pages/MyOrders/index.jsx
@@ -0,0 +1,28 @@
+import { useContext } from 'react'
+import { Link } from 'react-router-dom'
+import Layout from '../../Components/Layout'
+import { ShoppingCartContext } from '../../Context'
+import OrdersCard from '../../Components/OrdersCard'
+
+function MyOrders() {
+ const context = useContext(ShoppingCartContext)
+
+ return (
+
+
+
My Orders
+
+ {
+ context.order.map((order, index) => (
+
+
+
+ ))
+ }
+
+ )
+}
+
+export default MyOrders
\ No newline at end of file
diff --git a/src/Pages/NotFound/index.jsx b/src/Pages/NotFound/index.jsx
new file mode 100644
index 0000000..7ae7187
--- /dev/null
+++ b/src/Pages/NotFound/index.jsx
@@ -0,0 +1,11 @@
+import Layout from '../../Components/Layout'
+
+function NotFound() {
+ return (
+
+ NotFound
+
+ )
+}
+
+export default NotFound
\ No newline at end of file
diff --git a/src/Pages/SignIn/index.jsx b/src/Pages/SignIn/index.jsx
new file mode 100644
index 0000000..acc809d
--- /dev/null
+++ b/src/Pages/SignIn/index.jsx
@@ -0,0 +1,50 @@
+import { useContext } from 'react'
+import { NavLink } from 'react-router-dom'
+import Layout from '../../Components/Layout'
+import { UserContext } from '../../Context'
+
+function SignIn() {
+ const userContext = useContext(UserContext)
+ const logIn = (event) => {
+ const email = document.getElementById('email').value;
+ const password = document.getElementById('password').value;
+ const verifyUser = userContext.registeredUsers.filter(registeredUser => registeredUser.email === email)
+ const isEmailRegistered = userContext.registeredUsers == []? false: verifyUser.length > 0
+ if(!isEmailRegistered){
+ event.preventDefault();
+ window.alert('Email not registered! Please Sign Up to continue.');
+ return
+ }
+ if (verifyUser[0].password != password){
+ event.preventDefault();
+ window.alert('Wrong Password.');
+ return
+ }
+ userContext.setUser(verifyUser[0])
+ userContext.setIsLoggedIn(true)
+ localStorage.setItem("user", JSON.stringify(verifyUser[0]))
+ localStorage.setItem("isLoggedIn", "true")
+ }
+ return (
+
+
+
+ Welcome
+
+
Your email:
+
+
Your password:
+
+
+ Log in
+
+
Forgot my password
+
+ Sign Up
+
+
+
+ )
+}
+
+export default SignIn
\ No newline at end of file
diff --git a/src/Pages/Signup/index.jsx b/src/Pages/Signup/index.jsx
new file mode 100644
index 0000000..862fc11
--- /dev/null
+++ b/src/Pages/Signup/index.jsx
@@ -0,0 +1,68 @@
+import { useContext } from 'react'
+import { NavLink } from 'react-router-dom'
+import Layout from '../../Components/Layout'
+import { UserContext } from '../../Context'
+
+
+function SignUp() {
+ const userContext = useContext(UserContext)
+ const createUser = (event) => {
+ const name = document.getElementById('name').value;
+ const email = document.getElementById('email').value;
+ const password = document.getElementById('password').value;
+ const verifyUser = userContext.registeredUsers.filter(registeredUser => registeredUser.email === email)
+ const isEmailRegistered = userContext.registeredUsers == []? false: verifyUser.length > 0
+ if(isEmailRegistered){
+ event.preventDefault();
+ window.alert('Email already registered! Use another address.');
+ return
+ }
+ if(name===''){
+ event.preventDefault();
+ window.alert('Name required.');
+ return
+ }
+ if(email===''){
+ event.preventDefault();
+ window.alert('Email required.');
+ return
+ }
+ if(password===''){
+ event.preventDefault();
+ window.alert('Password required.');
+ return
+ }
+ const newUser = {
+ 'name': name,
+ 'email': email,
+ 'password': password
+ }
+
+ userContext.setUser(newUser)
+ userContext.setIsLoggedIn(true)
+ userContext.setRegisteredUsers([...userContext.registeredUsers, newUser])
+ localStorage.setItem("user", JSON.stringify(newUser))
+ localStorage.setItem("isLoggedIn", "true")
+ localStorage.setItem("registeredUsers", JSON.stringify([...userContext.registeredUsers, newUser]))
+ }
+ return (
+
+
+
+ Welcome
+
+
Your name:
+
+
Your email:
+
+
Your password:
+
+
+ Create
+
+
+
+ )
+}
+
+export default SignUp
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index 5cc5991..48c9fe3 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
-import App from './App'
+import App from './Pages/App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
diff --git a/src/utils/index.js b/src/utils/index.js
new file mode 100644
index 0000000..f4e5801
--- /dev/null
+++ b/src/utils/index.js
@@ -0,0 +1,10 @@
+/**
+ * This function calculates total price of a new order
+ * @param {Array} products cartProduct: Array of Objects
+ * @returns {numer} Total price
+ */
+export const totalPrice = (products) => {
+ let sum = 0
+ products.forEach(product => sum += product.price)
+ return sum
+}
\ No newline at end of file