├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.css ├── App.js ├── Assets │ ├── burguer.png │ ├── burguers-icon.svg │ ├── combo.png │ ├── combos-icon.svg │ ├── desserts-icon.svg │ ├── desserts.png │ ├── drink.png │ ├── drinks-icon.svg │ ├── pizza-icon.svg │ └── pizza.png ├── Components │ ├── Checkout │ │ ├── Checkout.js │ │ ├── Checkout.module.css │ │ └── Form │ │ │ ├── Form.js │ │ │ ├── Form.module.css │ │ │ └── Fragments │ │ │ ├── Address.js │ │ │ ├── Address.module.css │ │ │ ├── AddressDefault.js │ │ │ ├── AddressDefault.module.css │ │ │ ├── Input.js │ │ │ ├── Input.module.css │ │ │ ├── RadioDelivery.js │ │ │ ├── RadioDelivery.module.css │ │ │ ├── RadioPayment.js │ │ │ └── RadioPayment.module.css │ ├── Finish │ │ ├── Finish.js │ │ └── Finish.module.css │ └── Home │ │ ├── Cart │ │ ├── Cart.js │ │ ├── Cart.module.css │ │ ├── CartItem.js │ │ ├── CartItem.module.css │ │ ├── ObsItem.js │ │ └── ObsItem.module.css │ │ ├── Home.js │ │ ├── Home.module.css │ │ ├── Nav │ │ ├── HomeNav.js │ │ └── HomeNav.module.css │ │ └── Product │ │ ├── ProductItem.js │ │ ├── ProductItem.module.css │ │ ├── Products.js │ │ └── Products.module.css ├── GlobalContext.js ├── Hooks │ ├── useForm.js │ └── useMedia.js └── index.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_* 2 | *.log 3 | logs 4 | /node_modules 5 | /build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RDelivery 2 | 3 | A delivery website created with ReactJS for online ordering. 4 | 5 | ## Demo 6 | 7 | View project in production: https://danielmafra.github.io/rdelivery/ 8 | 9 | #### Desktop demo: 10 | 11 | ![RDelivery](https://i.imgur.com/LOGjGji.gif) 12 | 13 | #### Smartphone demo: 14 | 15 | ![RDelivery](https://i.imgur.com/BLBDuYr.gif) 16 | 17 | ## Run Locally 18 | 19 | Clone the project 20 | 21 | ```bash 22 | git clone https://github.com/DanielMafra/RDelivery-frontend-ReactJS.git 23 | ``` 24 | 25 | Go to the project directory 26 | 27 | ```bash 28 | cd RDelivery-frontend-ReactJS 29 | ``` 30 | 31 | Install dependencies 32 | 33 | ```bash 34 | yarn install 35 | ``` 36 | 37 | Start the server 38 | 39 | ```bash 40 | yarn start 41 | ``` 42 | 43 | ## Deployment 44 | 45 | To deploy this project run 46 | 47 | ```bash 48 | yarn build 49 | ``` 50 | 51 | ## API 52 | 53 | - This project uses a fake My JSON Server API for list products. 54 | 55 | If you want to register your own products, just clone this repository, modify and upload it to GitHub: https://github.com/DanielMafra/api.git 56 | 57 | After that, just follow the instructions that are in https://my-json-server.typicode.com/ 58 | 59 | - The project also uses the ViaCEP API to get the address more dynamically. 60 | 61 | You can find out more about at https://viacep.com.br/ 62 | 63 | ## Features 64 | 65 | - Consume data through API 66 | - Breakpoints for Desktop and Smartphone 67 | - Increment and decrement products in the cart 68 | - Add note to product 69 | - Form data validation 70 | - ContextAPI and custom Hooks 71 | - Phone field mask 72 | - Get address via API through zip code 73 | - Save the address used in localStorage 74 | - Use the address in localStorage as default 75 | 76 | ## Authors 77 | 78 | This project was coded by [@danielmafra](https://www.github.com/danielmafra) using a UI Design created by [@isadorastan](https://github.com/isadorastan). 79 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rdelivery", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "history": "^5.0.0", 10 | "react": "^17.0.2", 11 | "react-dom": "^17.0.2", 12 | "react-router-dom": "^6.0.0-beta.0", 13 | "react-scripts": "4.0.3", 14 | "web-vitals": "^1.0.1" 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 | } 41 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | RDelivery 26 | 27 | 28 | 29 | 30 |
31 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/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/App.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | } 8 | 9 | body { 10 | font-family: 'Poppins', sans-serif; 11 | } 12 | 13 | img { 14 | display: block; 15 | max-width: 100%; 16 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | import { BrowserRouter, Routes, Route } from 'react-router-dom'; 4 | import Home from './Components/Home/Home'; 5 | import Checkout from './Components/Checkout/Checkout'; 6 | import Finish from './Components/Finish/Finish'; 7 | import { GlobalStorage } from './GlobalContext'; 8 | 9 | function App() { 10 | return ( 11 | 12 | 13 | 14 | } /> 15 | } /* this route is only for use on GitHub Pages */ /> 16 | } /> 17 | } /> 18 | 19 | 20 | 21 | ); 22 | } 23 | 24 | export default App; 25 | -------------------------------------------------------------------------------- /src/Assets/burguer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/src/Assets/burguer.png -------------------------------------------------------------------------------- /src/Assets/burguers-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Assets/combo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/src/Assets/combo.png -------------------------------------------------------------------------------- /src/Assets/combos-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Assets/desserts-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Assets/desserts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/src/Assets/desserts.png -------------------------------------------------------------------------------- /src/Assets/drink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/src/Assets/drink.png -------------------------------------------------------------------------------- /src/Assets/drinks-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Assets/pizza-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Assets/pizza.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanielMafra/RDelivery-frontend-ReactJS/9f2129d4fe0fae658ba49c0f21becf77452b1724/src/Assets/pizza.png -------------------------------------------------------------------------------- /src/Components/Checkout/Checkout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import useMedia from '../../Hooks/useMedia'; 4 | import Cart from '../Home/Cart/Cart'; 5 | import Form from './Form/Form'; 6 | import styles from './Checkout.module.css'; 7 | 8 | const Checkout = () => { 9 | const mobile = useMedia('(max-width: 480px)'); 10 | 11 | return ( 12 |
13 |
14 | ← Voltar 15 |
16 |
17 |
18 |
19 | {!mobile ? ( 20 | 21 | ) : ( 22 | '' 23 | )} 24 |
25 | ); 26 | }; 27 | 28 | export default Checkout; -------------------------------------------------------------------------------- /src/Components/Checkout/Checkout.module.css: -------------------------------------------------------------------------------- 1 | .checkout { 2 | background-color: #fafafa; 3 | display: flex; 4 | height: 100vh; 5 | } 6 | 7 | .mainCheckout { 8 | margin-top: 16px; 9 | margin-left: 16px; 10 | } 11 | 12 | .mainCheckout a { 13 | text-decoration: none; 14 | color: #000; 15 | font-weight: 600; 16 | font-size: 24px; 17 | } 18 | 19 | .formArea { 20 | margin-top: 32px; 21 | margin-left: 64px; 22 | justify-self: center; 23 | } 24 | 25 | @keyframes enterLeft { 26 | to { 27 | opacity: 1; 28 | transform: initial; 29 | } 30 | } 31 | 32 | @media (max-width: 480px){ 33 | 34 | .checkout { 35 | height: auto; 36 | } 37 | 38 | .openCheckout { 39 | display: block; 40 | opacity: 0; 41 | transform: translateX(500px); 42 | animation: enterLeft .3s forwards; 43 | } 44 | 45 | .mainCheckout { 46 | height: 100%; 47 | margin: 16px 0px 0px 0px; 48 | } 49 | 50 | .formArea{ 51 | margin-left: 0px; 52 | max-width: 100vw; 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Form.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import useForm from '../../../Hooks/useForm'; 3 | import { GlobalContext } from '../../../GlobalContext'; 4 | import { useNavigate } from 'react-router-dom'; 5 | import Input from './Fragments/Input'; 6 | import RadioDelivery from './Fragments/RadioDelivery'; 7 | import styles from './Form.module.css'; 8 | 9 | const Form = () => { 10 | const { typeBuy, number, complement, address, typePayment, cart, total, order, setOrder, user } = React.useContext(GlobalContext); 11 | const phone = useForm('phone'); 12 | const name = useForm(); 13 | const navigate = useNavigate(); 14 | 15 | function handleSubmit(event) { 16 | event.preventDefault(); 17 | if (name.validate() && phone.validate()) { 18 | if (typeBuy !== '' && typeBuy === 'store') { 19 | setOrder({ 20 | name: name.value, 21 | phone: phone.value, 22 | cart: { 23 | ...cart, 24 | totalPrice: total 25 | } 26 | }); 27 | navigate('/completed'); 28 | console.log(order); 29 | } else if (typeBuy !== '' && typeBuy === 'delivery' && address !== null) { 30 | if (number !== '' && complement !== '' && typePayment !== '') { 31 | setOrder({ 32 | name: name.value, 33 | phone: phone.value, 34 | cart: { 35 | ...cart, 36 | totalPrice: total, 37 | }, 38 | address: { 39 | ...address, 40 | number: number, 41 | complement: complement 42 | }, 43 | payment: typePayment 44 | }); 45 | navigate('/completed'); 46 | console.log(order); 47 | } 48 | } else if (typeBuy !== '' && typeBuy === 'delivery' && user !== null) { 49 | setOrder({ 50 | name: name.value, 51 | phone: phone.value, 52 | cart: { 53 | ...cart, 54 | totalPrice: total, 55 | }, 56 | address: { 57 | ...user 58 | }, 59 | payment: typePayment 60 | }); 61 | navigate('/completed'); 62 | console.log(order); 63 | } 64 | } 65 | } 66 | 67 | return ( 68 | 69 |

Seus dados

70 | 71 | 72 |

Entrega

73 | 74 | 75 | 76 | ); 77 | }; 78 | 79 | export default Form; -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Form.module.css: -------------------------------------------------------------------------------- 1 | .form { 2 | background-color: #fff; 3 | padding: 32px 48px; 4 | border-radius: 8px; 5 | width: 721px; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | .title { 11 | font-size: 22px; 12 | font-weight: 600; 13 | line-height: 1; 14 | margin-bottom: 32px; 15 | } 16 | 17 | .subTitle { 18 | line-height: 1; 19 | margin-top: 44px; 20 | } 21 | 22 | .form button.confirm { 23 | background-color: #ff2351; 24 | color: #fff; 25 | font-size: 16px; 26 | font-weight: 600; 27 | border: none; 28 | border-radius: 8px; 29 | width: 348px; 30 | height: 46px; 31 | cursor: pointer; 32 | transition: .3s; 33 | align-self: center; 34 | margin-top: 56px; 35 | } 36 | 37 | .form button.confirm:hover { 38 | background-color: rgb(255, 35, 51); 39 | transform: scale(1.01); 40 | } 41 | 42 | @media (max-width: 480px){ 43 | 44 | .form { 45 | padding: 16px; 46 | max-width: 90%; 47 | margin: 0 auto; 48 | } 49 | 50 | .form button.confirm { 51 | max-width: 100%; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/Address.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../../GlobalContext'; 3 | import RadioPayment from './RadioPayment'; 4 | import styles from './Address.module.css'; 5 | 6 | const Address = () => { 7 | const { cep, setCep, number, setNumber, complement, setComplement, address } = React.useContext(GlobalContext); 8 | const [error, setError] = React.useState(false); 9 | 10 | function validateCep() { 11 | if (cep.length < 8) { 12 | setError(true); 13 | } else { 14 | setError(false); 15 | } 16 | } 17 | 18 | return ( 19 |
20 | 21 | { setCep(event.target.value); setError(false) }} onBlur={validateCep} value={cep} /> 22 | {error &&

Digite um CEP válido

} 23 | {address && ( 24 | <> 25 |
26 |

{address.rua}

27 |

{address.cidade} / {address.uf} - {address.bairro}

28 |
29 | 30 | setNumber(event.target.value)} value={number} /> 31 | 32 | setComplement(event.target.value)} value={complement} /> 33 |

Pagamento

34 |

Método de pagamento:

35 | 36 | 37 | )} 38 |
39 | ) 40 | } 41 | 42 | export default Address; -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/Address.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-top: 38px; 3 | } 4 | 5 | .input { 6 | border: 1px solid #dadada; 7 | display: block; 8 | width: 100%; 9 | font-size: 16px; 10 | padding: 12px 16px; 11 | border-radius: 8px; 12 | background: transparent; 13 | transition: 0.3s; 14 | } 15 | 16 | .input::placeholder { 17 | font-family: 'Poppins'; 18 | font-size: 16px; 19 | color: #848484; 20 | } 21 | 22 | .input:focus, 23 | .input:hover { 24 | outline: none; 25 | border-color: #fdc844; 26 | background: transparent; 27 | 28 | } 29 | 30 | .label { 31 | display: block; 32 | font-weight: 500; 33 | line-height: 1; 34 | padding-bottom: 8px; 35 | } 36 | 37 | .complement { 38 | display: block; 39 | font-weight: 500; 40 | line-height: 1; 41 | padding-bottom: 8px; 42 | margin-top: 20px; 43 | } 44 | 45 | .error { 46 | color: #ff2351; 47 | font-size: 14px; 48 | margin-top: 4px; 49 | } 50 | 51 | .address { 52 | margin-top: 38px; 53 | margin-bottom: 38px; 54 | color: #848484; 55 | } 56 | 57 | .subTitle { 58 | line-height: 1; 59 | margin-top: 52px; 60 | } 61 | 62 | .typePay { 63 | font-weight: 600; 64 | margin-top: 24px; 65 | margin-bottom: 14px; 66 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/AddressDefault.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../../GlobalContext'; 3 | import RadioPayment from './RadioPayment'; 4 | import styles from './AddressDefault.module.css'; 5 | 6 | const AddressDefault = () => { 7 | const { user, setUser } = React.useContext(GlobalContext); 8 | 9 | function handleAddress() { 10 | setUser(null); 11 | } 12 | 13 | return ( 14 |
15 |

Endereço padrão:

16 |
17 |

{user.rua}, {user.number}

18 |

{user.cidade} - {user.uf}

19 |

{user.complement}

20 | 21 |
22 |

Pagamento

23 |

Método de pagamento:

24 | 25 |
26 | ) 27 | } 28 | 29 | export default AddressDefault; -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/AddressDefault.module.css: -------------------------------------------------------------------------------- 1 | .defaultAddress { 2 | font-weight: 600; 3 | margin-top: 24px; 4 | margin-bottom: 14px; 5 | } 6 | 7 | .cardAddress { 8 | border: 1px solid #dadada; 9 | border-radius: 8px; 10 | padding: 16px 32px; 11 | width: 60%; 12 | margin-top: 32px; 13 | } 14 | 15 | .cardAddress p { 16 | color: #848484; 17 | } 18 | 19 | .cardAddress p:nth-child(2), 20 | .cardAddress p:nth-child(3){ 21 | margin-top: 8px; 22 | } 23 | 24 | .editAddress { 25 | border: none; 26 | background-color: transparent; 27 | font-size: 12px; 28 | color: #ff2351; 29 | text-decoration: underline; 30 | cursor: pointer; 31 | } 32 | 33 | .subTitle { 34 | line-height: 1; 35 | margin-top: 52px; 36 | } 37 | 38 | .typePay { 39 | font-weight: 600; 40 | margin-top: 24px; 41 | margin-bottom: 14px; 42 | } 43 | 44 | @media (max-width: 480px){ 45 | 46 | .cardAddress { 47 | width: 100%; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/Input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './Input.module.css'; 3 | 4 | const Input = ({ label, type, name, value, placeholder, onChange, error, onBlur }) => { 5 | return ( 6 |
7 | 8 | 9 | {error &&

{error}

} 10 |
11 | ) 12 | } 13 | 14 | export default Input; -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/Input.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-bottom: 20px; 3 | } 4 | 5 | .input { 6 | border: 1px solid #dadada; 7 | display: block; 8 | width: 100%; 9 | font-size: 16px; 10 | padding: 12px 16px; 11 | border-radius: 8px; 12 | background: transparent; 13 | transition: 0.3s; 14 | } 15 | 16 | .input::placeholder { 17 | font-family: 'Poppins'; 18 | font-size: 16px; 19 | color: #848484; 20 | } 21 | 22 | .input:focus, 23 | .input:hover { 24 | outline: none; 25 | border-color: #fdc844; 26 | background: transparent; 27 | 28 | } 29 | 30 | .label { 31 | display: block; 32 | font-weight: 500; 33 | line-height: 1; 34 | padding-bottom: 8px; 35 | } 36 | 37 | .error { 38 | color: #ff2351; 39 | font-size: 14px; 40 | margin-top: 4px; 41 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/RadioDelivery.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../../GlobalContext'; 3 | import Address from './Address'; 4 | import AddressDefault from './AddressDefault'; 5 | import styles from './RadioDelivery.module.css'; 6 | 7 | const RadioDelivery = () => { 8 | const { typeBuy, setTypeBuy, user } = React.useContext(GlobalContext); 9 | 10 | return ( 11 |
12 | 16 | 20 | {typeBuy === 'delivery' && user !== null ? ( 21 | 22 | ) : ( 23 | '' 24 | )} 25 | {typeBuy === 'delivery' && user === null ? ( 26 |
27 | ) : ( 28 | '' 29 | )} 30 |
31 | ) 32 | } 33 | 34 | export default RadioDelivery; 35 | -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/RadioDelivery.module.css: -------------------------------------------------------------------------------- 1 | .radioDelivery { 2 | margin-top: 24px; 3 | } 4 | 5 | .radio { 6 | cursor: pointer; 7 | margin-right: 12px; 8 | } 9 | 10 | .label { 11 | color: #848484; 12 | font-size: 16px; 13 | } 14 | 15 | .label:nth-child(2){ 16 | margin-left: 54px; 17 | } -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/RadioPayment.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../../GlobalContext'; 3 | import styles from './RadioPayment.module.css'; 4 | 5 | const RadioPayment = () => { 6 | const { typePayment, setTypePayment } = React.useContext(GlobalContext); 7 | 8 | return ( 9 |
10 | 14 | 18 |
19 | ) 20 | } 21 | 22 | export default RadioPayment; -------------------------------------------------------------------------------- /src/Components/Checkout/Form/Fragments/RadioPayment.module.css: -------------------------------------------------------------------------------- 1 | .radioPayment { 2 | margin-top: 24px; 3 | } 4 | 5 | .radio { 6 | cursor: pointer; 7 | margin-right: 12px; 8 | } 9 | 10 | .label { 11 | color: #848484; 12 | font-size: 16px; 13 | } 14 | 15 | .label:nth-child(2){ 16 | margin-left: 54px; 17 | } -------------------------------------------------------------------------------- /src/Components/Finish/Finish.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../GlobalContext'; 3 | import styles from './Finish.module.css'; 4 | import CartItem from '../Home/Cart/CartItem'; 5 | 6 | const Finish = () => { 7 | const { cart, total, typeBuy } = React.useContext(GlobalContext); 8 | 9 | return ( 10 |
11 |
12 | 13 |

Pedido finalizado

14 |
15 |
16 |
17 | {cart.map((item) => )} 18 |
19 |
20 |

Total

21 |

R$ {total},00

22 |
23 |
24 | {typeBuy === "delivery" ? ( 25 |

Seu pedido será entregue em até 60 minutos.

26 | ) : ( 27 |

Em 25 minutos seu pedido estará pronto para ser retirado em nossa loja.

28 | )} 29 |
30 | ) 31 | } 32 | 33 | export default Finish; 34 | -------------------------------------------------------------------------------- /src/Components/Finish/Finish.module.css: -------------------------------------------------------------------------------- 1 | .finishContainer { 2 | background-color: #fafafa; 3 | padding-top: 32px; 4 | padding-bottom: 32px; 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: center; 8 | align-items: center; 9 | } 10 | 11 | .orderFinish { 12 | display: flex; 13 | align-items: center; 14 | } 15 | 16 | .orderFinish h2 { 17 | margin-left: 8px; 18 | color: #008000; 19 | } 20 | 21 | ion-icon { 22 | font-size: 24px; 23 | color: #008000; 24 | } 25 | 26 | .total { 27 | display: flex; 28 | justify-content: flex-end; 29 | margin-top: 38px; 30 | } 31 | 32 | .total h4:nth-child(1){ 33 | font-size: 18px; 34 | font-weight: 600; 35 | } 36 | 37 | .price { 38 | margin-left: 16px; 39 | font-size: 18px; 40 | font-weight: 600; 41 | color: #fdc844; 42 | } 43 | 44 | .orderContainer { 45 | background-color: #ffffff; 46 | padding: 16px 32px; 47 | border-radius: 8px; 48 | margin-top: 32px; 49 | } 50 | 51 | .orderStore { 52 | margin-top: 64px; 53 | } 54 | 55 | @keyframes enterLeft { 56 | to { 57 | opacity: 1; 58 | transform: initial; 59 | } 60 | } 61 | 62 | @media (max-width: 480px){ 63 | 64 | .finishContainer { 65 | background-color: #ffffff; 66 | opacity: 0; 67 | transform: translateX(500px); 68 | animation: enterLeft .3s forwards; 69 | } 70 | 71 | .orderStore { 72 | margin: 64px 24px; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/Components/Home/Cart/Cart.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../GlobalContext'; 3 | import { useNavigate } from 'react-router-dom'; 4 | import useMedia from '../../../Hooks/useMedia'; 5 | import CartItem from './CartItem'; 6 | import styles from './Cart.module.css'; 7 | 8 | const Cart = ({ isCheckout }) => { 9 | const mobile = useMedia('(max-width: 480px)'); 10 | const { cart, total, openCart, setOpenCart } = React.useContext(GlobalContext); 11 | const navigate = useNavigate(); 12 | 13 | function handleOpenCart() { 14 | setOpenCart(!openCart); 15 | } 16 | 17 | return ( 18 |
19 | {mobile && ( 20 | 21 | )} 22 |

Seu pedido

23 | {cart.length > 0 ? ( 24 |
25 |
26 | {cart.map((item) => )} 27 |
28 |
29 |

Total

30 |

R$ {total},00

31 |
32 |
33 | {!isCheckout ? ( 34 | 35 | ) : ( 36 | '' 37 | )} 38 |
39 |
40 | ) : ( 41 |

Você ainda não adicionou nenhum item ao carrinho.

42 | )} 43 |
44 | ); 45 | }; 46 | 47 | export default Cart; -------------------------------------------------------------------------------- /src/Components/Home/Cart/Cart.module.css: -------------------------------------------------------------------------------- 1 | .cart { 2 | background-color: #fff; 3 | padding: 48px 54px; 4 | /*width: 30%;*/ 5 | position: fixed; 6 | right: 0; 7 | height: 100vh; 8 | overflow: auto; 9 | } 10 | 11 | .title { 12 | font-size: 24px; 13 | font-weight: 600; 14 | margin-bottom: 32px; 15 | } 16 | 17 | .items { 18 | display: flex; 19 | flex-direction: column; 20 | } 21 | 22 | .none { 23 | font-size: 14px; 24 | } 25 | 26 | .total { 27 | display: flex; 28 | justify-content: flex-end; 29 | margin-top: 38px; 30 | } 31 | 32 | .total h4:nth-child(1){ 33 | font-size: 18px; 34 | font-weight: 600; 35 | } 36 | 37 | .price { 38 | margin-left: 16px; 39 | font-size: 18px; 40 | font-weight: 600; 41 | color: #fdc844; 42 | } 43 | 44 | .btn { 45 | display: flex; 46 | justify-content: center; 47 | margin-top: 92px; 48 | } 49 | 50 | .btn button { 51 | background-color: #ff2351; 52 | color: #fff; 53 | font-size: 18px; 54 | font-weight: 600; 55 | border: none; 56 | border-radius: 8px; 57 | width: 397px; 58 | height: 51px; 59 | cursor: pointer; 60 | transition: .3s; 61 | } 62 | 63 | .btn button:hover { 64 | background-color: rgb(255, 35, 51); 65 | transform: scale(1.01); 66 | } 67 | 68 | .enterLeft { 69 | opacity: 0; 70 | transform: translateX(-20px); 71 | animation: enterLeft .3s forwards; 72 | } 73 | 74 | @keyframes enterLeft { 75 | to { 76 | opacity: 1; 77 | transform: initial; 78 | } 79 | } 80 | 81 | @media (max-width: 480px){ 82 | 83 | .closeCart { 84 | display: none; 85 | } 86 | 87 | .openCart { 88 | display: block; 89 | opacity: 0; 90 | transform: translateX(500px); 91 | animation: enterLeft .3s forwards; 92 | } 93 | 94 | .btnCloseCart { 95 | color: #000; 96 | font-weight: 600; 97 | font-size: 24px; 98 | border: none; 99 | cursor: pointer; 100 | background-color: transparent; 101 | } 102 | 103 | .title { 104 | margin-top: 32px; 105 | } 106 | 107 | .cart { 108 | width: 100%; 109 | padding: 16px; 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /src/Components/Home/Cart/CartItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './CartItem.module.css'; 3 | import { GlobalContext } from '../../../GlobalContext'; 4 | 5 | const CartItem = ({ product, isFinish }) => { 6 | const { incrementItem, decrementItem, openObs, setOpenObs, setIdObs } = React.useContext(GlobalContext); 7 | 8 | function openObsBox() { 9 | setOpenObs(!openObs); 10 | setIdObs(product.id); 11 | } 12 | 13 | return ( 14 |
15 |
16 | {!isFinish && } 17 |

{product.quantity}

18 | {!isFinish && } 19 |
20 |
21 | {product.title} 22 |
23 |
24 |

{product.title}

25 | {!isFinish && } 26 |
27 |

R$ {product.currentPrice},00

28 |
29 | ); 30 | }; 31 | 32 | export default CartItem; -------------------------------------------------------------------------------- /src/Components/Home/Cart/CartItem.module.css: -------------------------------------------------------------------------------- 1 | .item { 2 | margin-bottom: 18px; 3 | border-bottom: 1px solid #dadada; 4 | padding: 24px 0px; 5 | display: flex; 6 | align-items: center; 7 | } 8 | 9 | .quantity { 10 | display: flex; 11 | align-items: center; 12 | } 13 | 14 | .quantity p { 15 | margin-right: 8px; 16 | margin-left: 8px; 17 | font-size: 18px; 18 | font-weight: 500; 19 | color: #fdc844; 20 | } 21 | 22 | .quantity button { 23 | font-family: "Poppins"; 24 | font-size: 18px; 25 | font-weight: 600; 26 | border: none; 27 | background-color: transparent; 28 | cursor: pointer; 29 | } 30 | 31 | .bgImage { 32 | background-color: rgba(253, 200, 68, .3); 33 | border-radius: 8px; 34 | width: 81px; 35 | height: 66px; 36 | padding: 10px 8px; 37 | margin-left: 36px; 38 | margin-right: 28px; 39 | } 40 | 41 | .product h4 { 42 | font-size: 18px; 43 | font-weight: 600; 44 | } 45 | 46 | .product button { 47 | border: none; 48 | background-color: transparent; 49 | font-size: 12px; 50 | color: #848484; 51 | text-decoration: underline; 52 | cursor: pointer; 53 | } 54 | 55 | .price { 56 | margin-left: 24px; 57 | font-size: 18px; 58 | font-weight: 600; 59 | color: #fdc844; 60 | } 61 | 62 | .enterLeft { 63 | opacity: 0; 64 | transform: translateX(-20px); 65 | animation: enterLeft .3s forwards; 66 | } 67 | 68 | @keyframes enterLeft { 69 | to { 70 | opacity: 1; 71 | transform: initial; 72 | } 73 | } 74 | 75 | @media (max-width: 480px){ 76 | 77 | .bgImage { 78 | width: 54px; 79 | height: auto; 80 | padding: 10px 8px; 81 | margin-left: 16px; 82 | margin-right: 16px; 83 | } 84 | 85 | .product h4 { 86 | font-size: 16px; 87 | font-weight: 600; 88 | } 89 | 90 | .product button { 91 | text-align: initial; 92 | } 93 | 94 | .price { 95 | font-size: 16px; 96 | margin-left: 16px; 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /src/Components/Home/Cart/ObsItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GlobalContext } from '../../../GlobalContext'; 3 | import styles from './ObsItem.module.css'; 4 | 5 | const ObsItem = () => { 6 | const { openObs, setOpenObs, idObs, obs, setObs, addObs } = React.useContext(GlobalContext); 7 | 8 | function closeObsBox() { 9 | setOpenObs(!openObs); 10 | } 11 | 12 | function saveObs() { 13 | addObs(idObs); 14 | closeObsBox(); 15 | } 16 | 17 | return ( 18 |
19 |
20 | 21 |

Adicionar observação

22 |