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} + {data.data.title} + {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 ( + + ) +} + +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 ( + + ) +} + +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} +
+

{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 ( + + ) +} + +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