├── src ├── services │ └── api.js ├── index.js ├── routes │ └── index.jsx ├── App.js ├── pages │ └── Dashboard │ │ ├── styles.js │ │ └── index.jsx ├── styles │ └── global.js ├── components │ ├── Header │ │ ├── index.jsx │ │ └── styles.js │ ├── ModalAddFood │ │ ├── styles.js │ │ └── index.jsx │ ├── ModalEditFood │ │ ├── styles.js │ │ └── index.jsx │ ├── Input │ │ ├── styles.js │ │ └── index.jsx │ ├── Modal │ │ └── index.jsx │ └── Food │ │ ├── index.jsx │ │ └── styles.js └── assets │ └── logo.svg ├── .gitignore ├── public └── index.html ├── server.json ├── README.md └── package.json /src/services/api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const api = axios.create({ 4 | baseURL: 'http://localhost:3333', 5 | }); 6 | 7 | export default api; 8 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /src/routes/index.jsx: -------------------------------------------------------------------------------- 1 | import { Switch, Route } from 'react-router-dom'; 2 | 3 | import Dashboard from '../pages/Dashboard'; 4 | 5 | const Routes = () => ( 6 | 7 | 8 | 9 | ); 10 | 11 | export default Routes; 12 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { BrowserRouter as Router } from 'react-router-dom'; 2 | 3 | import Routes from './routes'; 4 | 5 | import GlobalStyle from './styles/global'; 6 | 7 | const App = () => ( 8 | <> 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /src/pages/Dashboard/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const FoodsContainer = styled.div` 4 | width: 100%; 5 | max-width: 1280px; 6 | margin: 0 auto; 7 | padding: 40px 0; 8 | margin-top: -140px; 9 | 10 | display: grid; 11 | 12 | grid-template-columns: repeat(3, 1fr); 13 | grid-gap: 32px; 14 | `; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/styles/global.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | 3 | export default createGlobalStyle` 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | outline: 0; 9 | } 10 | 11 | body { 12 | background: #fff; 13 | color: #FFF; 14 | -webkit-font-smoothing: antialiased; 15 | } 16 | 17 | body, input, button { 18 | font-family: 'Poppins', sans-serif; 19 | font-size: 16px; 20 | } 21 | 22 | h1, h2, h3, h4, h5, h6, strong { 23 | font-weight: 500; 24 | } 25 | 26 | button { 27 | cursor: pointer; 28 | } 29 | `; 30 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | GoRestaurant 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /src/components/Header/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { FiPlusSquare } from 'react-icons/fi'; 3 | 4 | import { Container } from './styles'; 5 | import Logo from '../../assets/logo.svg'; 6 | 7 | class Header extends Component { 8 | render() { 9 | const { openModal } = this.props; 10 | 11 | return ( 12 | 13 |
14 | GoRestaurant 15 | 28 |
29 |
30 | ) 31 | } 32 | }; 33 | 34 | export default Header; 35 | -------------------------------------------------------------------------------- /src/components/ModalAddFood/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Form as Unform } from '@unform/web'; 3 | 4 | export const Form = styled(Unform)` 5 | padding: 48px 40px; 6 | display: flex; 7 | flex-direction: column; 8 | 9 | h1 { 10 | font-weight: 600; 11 | font-size: 36px; 12 | line-height: 36px; 13 | margin-bottom: 40px; 14 | } 15 | 16 | button { 17 | margin-top: 48px; 18 | align-self: flex-end; 19 | } 20 | 21 | button { 22 | font-weight: 600; 23 | border-radius: 8px; 24 | border: 0; 25 | background: #39b100; 26 | color: #fff; 27 | 28 | display: flex; 29 | flex-direction: row; 30 | align-items: center; 31 | 32 | .text { 33 | padding: 16px 24px; 34 | } 35 | 36 | .icon { 37 | display: flex; 38 | padding: 16px 16px; 39 | background: #41c900; 40 | border-radius: 0 8px 8px 0; 41 | margin: 0 auto; 42 | } 43 | } 44 | `; 45 | -------------------------------------------------------------------------------- /src/components/ModalEditFood/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Form as Unform } from '@unform/web'; 3 | 4 | export const Form = styled(Unform)` 5 | padding: 48px 40px; 6 | display: flex; 7 | flex-direction: column; 8 | 9 | h1 { 10 | font-weight: 600; 11 | font-size: 36px; 12 | line-height: 36px; 13 | margin-bottom: 40px; 14 | } 15 | 16 | button { 17 | margin-top: 48px; 18 | align-self: flex-end; 19 | } 20 | 21 | button { 22 | font-weight: 600; 23 | border-radius: 8px; 24 | border: 0; 25 | background: #39b100; 26 | color: #fff; 27 | 28 | display: flex; 29 | flex-direction: row; 30 | align-items: center; 31 | 32 | .text { 33 | padding: 16px 24px; 34 | } 35 | 36 | .icon { 37 | display: flex; 38 | padding: 16px 16px; 39 | background: #41c900; 40 | border-radius: 0 8px 8px 0; 41 | margin: 0 auto; 42 | } 43 | } 44 | `; 45 | -------------------------------------------------------------------------------- /src/components/Input/styles.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | align-items: center; 6 | 7 | background: #fff; 8 | border-radius: 8px; 9 | padding: 18px 24px; 10 | width: 100%; 11 | font-size: 16px; 12 | 13 | & + div { 14 | margin-top: 24px; 15 | } 16 | 17 | h1 { 18 | margin-bottom: 40px; 19 | font-weight: 600; 20 | font-size: 36px; 21 | line-height: 36px; 22 | } 23 | 24 | ${props => 25 | props.isFocused && 26 | css` 27 | color: #ff9000; 28 | border-color: #ff9000; 29 | `} 30 | 31 | ${props => 32 | props.isFilled && 33 | css` 34 | color: #ff9000; 35 | `} 36 | 37 | input { 38 | flex: 1; 39 | background: transparent; 40 | border: 0; 41 | color: #b7b7cc; 42 | 43 | &::placeholder { 44 | color: #b7b7cc; 45 | } 46 | } 47 | 48 | svg { 49 | margin-right: 16px; 50 | } 51 | `; 52 | -------------------------------------------------------------------------------- /server.json: -------------------------------------------------------------------------------- 1 | { 2 | "foods": [ 3 | { 4 | "id": 1, 5 | "name": "Ao molho", 6 | "description": "Macarrão ao molho branco, fughi e cheiro verde das montanhas", 7 | "price": "19.90", 8 | "available": true, 9 | "image": "https://storage.googleapis.com/golden-wind/bootcamp-gostack/desafio-food/food1.png" 10 | }, 11 | { 12 | "id": 2, 13 | "name": "Veggie", 14 | "description": "Macarrão com pimentão, ervilha e ervas finas colhidas no himalaia.", 15 | "price": "21.90", 16 | "available": true, 17 | "image": "https://storage.googleapis.com/golden-wind/bootcamp-gostack/desafio-food/food2.png" 18 | }, 19 | { 20 | "id": 3, 21 | "name": "A la Camarón", 22 | "description": "Macarrão com vegetais de primeira linha e camarão dos 7 mares.", 23 | "price": "25.90", 24 | "available": false, 25 | "image": "https://storage.googleapis.com/golden-wind/bootcamp-gostack/desafio-food/food3.png" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /src/components/Header/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | background: #c72828; 5 | padding: 30px 0; 6 | 7 | header { 8 | width: 1280px; 9 | margin: 0 auto; 10 | padding: 0 0 160px; 11 | display: flex; 12 | align-items: center; 13 | justify-content: space-between; 14 | 15 | nav { 16 | div { 17 | button { 18 | font-weight: 600; 19 | border-radius: 8px; 20 | border: 0; 21 | background: #39b100; 22 | color: #fff; 23 | 24 | display: flex; 25 | flex-direction: row; 26 | align-items: center; 27 | 28 | .text { 29 | padding: 16px 24px; 30 | } 31 | 32 | .icon { 33 | display: flex; 34 | padding: 16px 16px; 35 | background: #41c900; 36 | border-radius: 0 8px 8px 0; 37 | margin: 0 auto; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | `; 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Rocketseat Education 3 |

4 | 5 |

6 | Rocketseat Project 7 | License 8 |

9 | 10 | 11 | ## 💻 Projeto 12 | 13 | ignite-template-reactjs-refactoring-classes-ts 14 | 15 | ## 📝 Licença 16 | 17 | Esse projeto está sob a licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes. 18 | 19 | --- 20 | 21 |

22 | Feito com 💜 by Rocketseat 23 |

24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 |

32 | 33 | banner 34 | 35 |

36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "refactoring-classes-ts", 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 | "@unform/core": "^2.1.6", 10 | "@unform/web": "^2.1.6", 11 | "axios": "^0.21.1", 12 | "react": "^17.0.1", 13 | "react-dom": "^17.0.1", 14 | "react-icons": "^4.2.0", 15 | "react-modal": "^3.12.1", 16 | "react-router-dom": "^5.2.0", 17 | "react-scripts": "4.0.3", 18 | "styled-components": "^5.2.1", 19 | "yup": "^0.32.9" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject", 26 | "server": "json-server server.json -p 3333" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "devDependencies": { 47 | "json-server": "^0.16.3" 48 | } 49 | } -------------------------------------------------------------------------------- /src/components/Input/index.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | useEffect, 3 | useRef, 4 | useState, 5 | useCallback, 6 | } from 'react'; 7 | 8 | import { useField } from '@unform/core'; 9 | 10 | import { Container } from './styles'; 11 | 12 | const Input = ({ name, icon: Icon, ...rest }) => { 13 | const inputRef = useRef(null); 14 | 15 | const [isFocused, setIsFocused] = useState(false); 16 | const [isFilled, setIsFilled] = useState(false); 17 | 18 | const { fieldName, defaultValue, registerField } = useField(name); 19 | 20 | const handleInputFocus = useCallback(() => { 21 | setIsFocused(true); 22 | }, []); 23 | 24 | const handleInputBlur = useCallback(() => { 25 | setIsFocused(false); 26 | 27 | setIsFilled(!!inputRef.current?.value); 28 | }, []); 29 | 30 | useEffect(() => { 31 | registerField({ 32 | name: fieldName, 33 | ref: inputRef.current, 34 | path: 'value', 35 | }); 36 | }, [fieldName, registerField]); 37 | 38 | return ( 39 | 40 | {Icon && } 41 | 42 | 49 | 50 | ); 51 | }; 52 | 53 | export default Input; 54 | -------------------------------------------------------------------------------- /src/components/ModalAddFood/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component, createRef } from 'react'; 2 | import { FiCheckSquare } from 'react-icons/fi'; 3 | 4 | import { Form } from './styles'; 5 | import Modal from '../Modal'; 6 | import Input from '../Input'; 7 | 8 | class ModalAddFood extends Component { 9 | constructor(props) { 10 | super(props); 11 | 12 | this.formRef = createRef(); 13 | } 14 | 15 | handleSubmit = async data => { 16 | const { setIsOpen, handleAddFood } = this.props; 17 | 18 | handleAddFood(data); 19 | setIsOpen(); 20 | }; 21 | 22 | render() { 23 | const { isOpen, setIsOpen } = this.props; 24 | 25 | return ( 26 | 27 |
28 |

Novo Prato

29 | 30 | 31 | 32 | 33 | 34 | 35 | 41 |
42 |
43 | ); 44 | } 45 | }; 46 | 47 | export default ModalAddFood; 48 | -------------------------------------------------------------------------------- /src/components/ModalEditFood/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component, createRef } from 'react'; 2 | import { FiCheckSquare } from 'react-icons/fi'; 3 | 4 | import { Form } from './styles'; 5 | import Modal from '../Modal'; 6 | import Input from '../Input'; 7 | 8 | class ModalEditFood extends Component { 9 | constructor(props) { 10 | super(props); 11 | 12 | this.formRef = createRef() 13 | } 14 | 15 | handleSubmit = async (data) => { 16 | const { setIsOpen, handleUpdateFood } = this.props; 17 | 18 | handleUpdateFood(data); 19 | setIsOpen(); 20 | }; 21 | 22 | render() { 23 | const { isOpen, setIsOpen, editingFood } = this.props; 24 | 25 | return ( 26 | 27 |
28 |

Editar Prato

29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 42 |
43 |
44 | ); 45 | } 46 | }; 47 | 48 | export default ModalEditFood; 49 | -------------------------------------------------------------------------------- /src/components/Modal/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import ReactModal from 'react-modal'; 3 | 4 | class Modal extends Component { 5 | constructor(props) { 6 | super(props); 7 | 8 | const { isOpen } = this.props; 9 | this.state = { 10 | modalStatus: isOpen 11 | } 12 | } 13 | 14 | componentDidUpdate(prevProps) { 15 | const { isOpen } = this.props; 16 | 17 | if (prevProps.isOpen !== isOpen) { 18 | console.log(this.props) 19 | this.setState({ modalStatus: isOpen }) 20 | } 21 | } 22 | 23 | render() { 24 | const { children, setIsOpen } = this.props; 25 | const { modalStatus } = this.state; 26 | 27 | return ( 28 | 52 | {children} 53 | 54 | ); 55 | } 56 | }; 57 | 58 | export default Modal; 59 | -------------------------------------------------------------------------------- /src/components/Food/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { FiEdit3, FiTrash } from 'react-icons/fi'; 3 | 4 | import { Container } from './styles'; 5 | import api from '../../services/api'; 6 | 7 | class Food extends Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | const { available } = this.props.food; 12 | this.state = { 13 | isAvailable: available 14 | }; 15 | } 16 | 17 | toggleAvailable = async () => { 18 | const { food } = this.props; 19 | const { isAvailable } = this.state; 20 | 21 | await api.put(`/foods/${food.id}`, { 22 | ...food, 23 | available: !isAvailable, 24 | }); 25 | 26 | this.setState({ isAvailable: !isAvailable }); 27 | } 28 | 29 | setEditingFood = () => { 30 | const { food, handleEditFood } = this.props; 31 | 32 | handleEditFood(food); 33 | } 34 | 35 | render() { 36 | const { isAvailable } = this.state; 37 | const { food, handleDelete } = this.props; 38 | 39 | return ( 40 | 41 |
42 | {food.name} 43 |
44 |
45 |

{food.name}

46 |

{food.description}

47 |

48 | R$ {food.price} 49 |

50 |
51 |
52 |
53 | 61 | 62 | 70 |
71 | 72 |
73 |

{isAvailable ? 'Disponível' : 'Indisponível'}

74 | 75 | 85 |
86 |
87 |
88 | ); 89 | } 90 | }; 91 | 92 | export default Food; 93 | -------------------------------------------------------------------------------- /src/components/Food/styles.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | background: #f0f0f5; 5 | border-radius: 8px; 6 | 7 | header { 8 | background: #ffb84d; 9 | border-radius: 8px 8px 0px 0px; 10 | height: 192px; 11 | overflow: hidden; 12 | transition: 0.3s opacity; 13 | text-align: center; 14 | 15 | ${props => 16 | !props.available && 17 | css` 18 | opacity: 0.3; 19 | `}; 20 | 21 | img { 22 | pointer-events: none; 23 | user-select: none; 24 | } 25 | } 26 | 27 | section.body { 28 | padding: 30px; 29 | 30 | h2 { 31 | color: #3d3d4d; 32 | } 33 | 34 | p { 35 | color: #3d3d4d; 36 | 37 | margin-top: 16px; 38 | } 39 | 40 | .price { 41 | font-style: normal; 42 | font-size: 24px; 43 | line-height: 34px; 44 | color: #39b100; 45 | 46 | b { 47 | font-weight: 600; 48 | } 49 | } 50 | } 51 | 52 | section.footer { 53 | display: flex; 54 | justify-content: space-between; 55 | align-items: center; 56 | 57 | padding: 20px 30px; 58 | background: #e4e4eb; 59 | border-radius: 0px 0px 8px 8px; 60 | 61 | div.icon-container { 62 | display: flex; 63 | 64 | button { 65 | background: #fff; 66 | padding: 10px; 67 | border-radius: 8px; 68 | display: flex; 69 | border: none; 70 | transition: 0.1s; 71 | 72 | svg { 73 | color: #3d3d4d; 74 | } 75 | 76 | & + button { 77 | margin-left: 6px; 78 | } 79 | } 80 | } 81 | 82 | div.availability-container { 83 | display: flex; 84 | align-items: center; 85 | 86 | p { 87 | color: #3d3d4d; 88 | } 89 | 90 | .switch { 91 | position: relative; 92 | display: inline-block; 93 | width: 88px; 94 | height: 32px; 95 | margin-left: 12px; 96 | 97 | & input { 98 | opacity: 0; 99 | width: 0; 100 | height: 0; 101 | } 102 | 103 | .slider { 104 | position: absolute; 105 | cursor: pointer; 106 | top: 0; 107 | left: 0; 108 | right: 0; 109 | bottom: 0; 110 | background-color: #c72828; 111 | -webkit-transition: 0.4s; 112 | transition: 0.4s; 113 | border-radius: 16px; 114 | 115 | &:before { 116 | position: absolute; 117 | content: ''; 118 | height: 20px; 119 | width: 40px; 120 | left: 8px; 121 | bottom: 6px; 122 | background-color: white; 123 | -webkit-transition: 0.4s; 124 | transition: 0.4s; 125 | border-radius: 10px; 126 | } 127 | } 128 | 129 | input:checked + .slider { 130 | background-color: #39b100; 131 | } 132 | 133 | input:focus + .slider { 134 | box-shadow: 0 0 1px #2196f3; 135 | } 136 | 137 | input:checked + .slider:before { 138 | -webkit-transform: translateX(32px); 139 | -ms-transform: translateX(32px); 140 | transform: translateX(32px); 141 | } 142 | } 143 | } 144 | } 145 | `; 146 | -------------------------------------------------------------------------------- /src/pages/Dashboard/index.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | import Header from '../../components/Header'; 4 | import api from '../../services/api'; 5 | import Food from '../../components/Food'; 6 | import ModalAddFood from '../../components/ModalAddFood'; 7 | import ModalEditFood from '../../components/ModalEditFood'; 8 | import { FoodsContainer } from './styles'; 9 | 10 | class Dashboard extends Component { 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | foods: [], 15 | editingFood: {}, 16 | modalOpen: false, 17 | editModalOpen: false, 18 | } 19 | } 20 | 21 | async componentDidMount() { 22 | const response = await api.get('/foods'); 23 | 24 | this.setState({ foods: response.data }); 25 | } 26 | 27 | handleAddFood = async food => { 28 | const { foods } = this.state; 29 | 30 | try { 31 | const response = await api.post('/foods', { 32 | ...food, 33 | available: true, 34 | }); 35 | 36 | this.setState({ foods: [...foods, response.data] }); 37 | } catch (err) { 38 | console.log(err); 39 | } 40 | } 41 | 42 | handleUpdateFood = async food => { 43 | const { foods, editingFood } = this.state; 44 | 45 | try { 46 | const foodUpdated = await api.put( 47 | `/foods/${editingFood.id}`, 48 | { ...editingFood, ...food }, 49 | ); 50 | 51 | const foodsUpdated = foods.map(f => 52 | f.id !== foodUpdated.data.id ? f : foodUpdated.data, 53 | ); 54 | 55 | this.setState({ foods: foodsUpdated }); 56 | } catch (err) { 57 | console.log(err); 58 | } 59 | } 60 | 61 | handleDeleteFood = async id => { 62 | const { foods } = this.state; 63 | 64 | await api.delete(`/foods/${id}`); 65 | 66 | const foodsFiltered = foods.filter(food => food.id !== id); 67 | 68 | this.setState({ foods: foodsFiltered }); 69 | } 70 | 71 | toggleModal = () => { 72 | const { modalOpen } = this.state; 73 | 74 | this.setState({ modalOpen: !modalOpen }); 75 | } 76 | 77 | toggleEditModal = () => { 78 | const { editModalOpen } = this.state; 79 | 80 | this.setState({ editModalOpen: !editModalOpen }); 81 | } 82 | 83 | handleEditFood = food => { 84 | this.setState({ editingFood: food, editModalOpen: true }); 85 | } 86 | 87 | render() { 88 | const { modalOpen, editModalOpen, editingFood, foods } = this.state; 89 | 90 | return ( 91 | <> 92 |
93 | 98 | 104 | 105 | 106 | {foods && 107 | foods.map(food => ( 108 | 114 | ))} 115 | 116 | 117 | ); 118 | } 119 | }; 120 | 121 | export default Dashboard; 122 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | --------------------------------------------------------------------------------