From b4923091fbda6426095c0be3a01dadb615ee61de Mon Sep 17 00:00:00 2001 From: vadim-os Date: Wed, 15 Jan 2020 14:58:31 +0200 Subject: [PATCH 1/3] uber eats 1-2 --- .bash_profile | 1 + package.json | 10 ++- public/images/logo.svg | 4 + public/images/place.svg | 4 + public/images/search.svg | 3 + public/index.html | 21 +++-- src/App.js | 18 ++++- src/components/Header/Header.js | 73 +++++++++++++++++ src/components/Header/Header.scss | 34 ++++++++ src/components/Header/index.js | 0 src/components/Input/Input.js | 79 +++++++++++++++++++ src/components/Input/Input.scss | 30 +++++++ src/components/Input/index.js | 0 .../RestaurantCard/RestaurantCard.js | 33 ++++++++ .../RestaurantCard/RestaurantCard.scss | 35 ++++++++ src/components/RestaurantCard/index.js | 0 .../RestaurantsListPage.js | 44 +++++++++++ .../RestaurantsListPage.scss | 5 ++ src/components/RestaurantsListPage/index.js | 17 ++++ src/index.js | 1 + src/store/actions.js | 16 ++++ src/store/index.js | 28 +++++++ src/store/selectors.js | 16 ++++ src/styles/extends.scss | 5 ++ src/styles/index.scss | 30 +++++++ 25 files changed, 494 insertions(+), 13 deletions(-) create mode 100644 .bash_profile create mode 100644 public/images/logo.svg create mode 100644 public/images/place.svg create mode 100644 public/images/search.svg create mode 100644 src/components/Header/Header.js create mode 100644 src/components/Header/Header.scss create mode 100644 src/components/Header/index.js create mode 100644 src/components/Input/Input.js create mode 100644 src/components/Input/Input.scss create mode 100644 src/components/Input/index.js create mode 100644 src/components/RestaurantCard/RestaurantCard.js create mode 100644 src/components/RestaurantCard/RestaurantCard.scss create mode 100644 src/components/RestaurantCard/index.js create mode 100644 src/components/RestaurantsListPage/RestaurantsListPage.js create mode 100644 src/components/RestaurantsListPage/RestaurantsListPage.scss create mode 100644 src/components/RestaurantsListPage/index.js create mode 100644 src/store/actions.js create mode 100644 src/store/index.js create mode 100644 src/store/selectors.js create mode 100644 src/styles/extends.scss create mode 100644 src/styles/index.scss diff --git a/.bash_profile b/.bash_profile new file mode 100644 index 0000000..604eca8 --- /dev/null +++ b/.bash_profile @@ -0,0 +1 @@ +alias cc="bash ~/scripts/create-component.sh" diff --git a/package.json b/package.json index 7bd01de..d57cbfa 100755 --- a/package.json +++ b/package.json @@ -7,11 +7,17 @@ "author": "Mate Academy", "license": "GPL-3.0", "dependencies": { + "classnames": "^2.2.6", + "node-sass": "^4.13.0", "prop-types": "^15.7.2", - "react": "^16.8.6", + "react": "^16.12.0", "react-dom": "^16.8.6", + "react-redux": "^7.1.3", "react-router-dom": "^5.0.1", - "react-scripts": "3.0.1" + "react-scripts": "3.0.1", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0", + "reselect": "^4.0.0" }, "devDependencies": { "@mate-academy/eslint-config-react": "*", diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 0000000..7418753 --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/place.svg b/public/images/place.svg new file mode 100644 index 0000000..a2f570f --- /dev/null +++ b/public/images/place.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/search.svg b/public/images/search.svg new file mode 100644 index 0000000..7e37c73 --- /dev/null +++ b/public/images/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/index.html b/public/index.html index 4269d67..3b32b3f 100644 --- a/public/index.html +++ b/public/index.html @@ -1,11 +1,16 @@ - - - - React Uber eats - - -
- + + + + + + + React Uber eats + + + +
+ + diff --git a/src/App.js b/src/App.js index d494a99..3eb5082 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,22 @@ import React from 'react'; import './App.css'; +import { Provider } from 'react-redux'; +import { store } from './store/index'; +import RestaurantsListPage from './components/RestaurantsListPage'; +import Header from './components/Header/Header'; const App = () => ( -
-

React Uber eats

-
+ +
+
+
+ + +
+ +
Uber Eats Footer
+
+
); export default App; diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js new file mode 100644 index 0000000..cf1bd64 --- /dev/null +++ b/src/components/Header/Header.js @@ -0,0 +1,73 @@ +import React, { useState } from 'react'; +// import PropTypes from 'prop-types'; +import './Header.scss'; +import Input from '../Input/Input'; + +const Header = () => { + const [address, setAddress] = useState(''); + const [time, setTime] = useState(''); + const [search, setSearch] = useState(''); + + const handleInputChange = ({ target }) => { + switch (target.name) { + case 'address': + setAddress(target.value); + break; + case 'time': + setTime(target.value); + break; + case 'search': + setSearch(target.value); + break; + default: + } + }; + + return ( +
+
+
+ Uber Eats Logo +
+ + +
+ + + + Sign In + +
+
+ +
+ ); +}; + +Header.propTypes = { + +}; + +export default Header; diff --git a/src/components/Header/Header.scss b/src/components/Header/Header.scss new file mode 100644 index 0000000..747c06b --- /dev/null +++ b/src/components/Header/Header.scss @@ -0,0 +1,34 @@ +@import "../../styles/extends.scss"; + +.header { + position: sticky; + top: 0; + padding: 16px 0; + + background-color: #ffffff; + + &__inner { + @extend %flex-row-center; + } + + &__delivery-info { + @extend %flex-row-center; + + margin-left: 7vw; + } + + &__search { + margin-left: auto; + } + + &__link { + margin-left: 40px; + color: #1f1f1f; + padding: 13px 0; + white-space: nowrap; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/src/components/Header/index.js b/src/components/Header/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js new file mode 100644 index 0000000..d29df04 --- /dev/null +++ b/src/components/Input/Input.js @@ -0,0 +1,79 @@ +import React, { useState, createRef, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import './Input.scss'; + +const Input = ({ + iconUrl, value, onChange, type, placeholder, name, className, +}) => { + const [isFocused, setIsFocused] = useState(false); + const inputRef = createRef(); + + const handleFocus = useCallback( + () => { + setIsFocused(true); + }, [], + ); + + const handleBlur = useCallback( + () => { + setIsFocused(false); + }, [], + ); + + const focusInput = () => { + inputRef.current.focus(); + }; + + const rootClass = cn('control', { + 'control--focused': isFocused, + [className]: !!className, + }); + + return ( +
+ {!!iconUrl + && ( + {placeholder} + )} + +
+ ); +}; + +Input.propTypes = { + iconUrl: PropTypes.string, + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + type: PropTypes.string, + placeholder: PropTypes.string, + name: PropTypes.string.isRequired, + className: PropTypes.string, +}; + +Input.defaultProps = { + iconUrl: '', + type: 'text', + placeholder: '', + className: '', +}; + +export default Input; diff --git a/src/components/Input/Input.scss b/src/components/Input/Input.scss new file mode 100644 index 0000000..51f3e25 --- /dev/null +++ b/src/components/Input/Input.scss @@ -0,0 +1,30 @@ +@import "../../styles/extends.scss"; + +.control { + $border-color: #e0e0e0; + @extend %flex-row-center; + + padding: 11px 16px; + border: 1px solid $border-color; + border-radius: 2px; + + &--focused { + border-color: darken($border-color, 20); + } + + &__icon { + width: 14px; + height: 14px; + + margin-right: 10px; + } + + &__input { + max-height: 24px; + line-height: 24px; + } + + & + & { + margin-left: 20px; + } +} diff --git a/src/components/Input/index.js b/src/components/Input/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/RestaurantCard/RestaurantCard.js b/src/components/RestaurantCard/RestaurantCard.js new file mode 100644 index 0000000..b64cdec --- /dev/null +++ b/src/components/RestaurantCard/RestaurantCard.js @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import './RestaurantCard.scss'; + +const RestaurantCard = ({ + imageUrl, title, categories, etaRange, uuid, +}) => ( +
+ {title} +

{title}

+
+ {categories.join(' · ')} +
+
+ {etaRange} +
+
+); + +RestaurantCard.propTypes = { + imageUrl: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + categories: PropTypes.arrayOf(PropTypes.string), + etaRange: PropTypes.string, + uuid: PropTypes.string.isRequired, +}; + +RestaurantCard.defaultProps = { + categories: [], + etaRange: '', +}; + +export default RestaurantCard; diff --git a/src/components/RestaurantCard/RestaurantCard.scss b/src/components/RestaurantCard/RestaurantCard.scss new file mode 100644 index 0000000..8c2ff8e --- /dev/null +++ b/src/components/RestaurantCard/RestaurantCard.scss @@ -0,0 +1,35 @@ +.restaurant-card { + $height: 367px; + + height: $height; + width: 100%; + + cursor: pointer; + + &__img { + height: $height * 0.76; + width: 100%; + + object-fit: cover; + } + + &__title { + margin: 12px 0 4px; + } + + &__categories { + font-style: 14px; + color: #757575; + + margin-bottom: 8px; + } + + &__eta { + font-size: 14px; + + display: inline-block; + padding: 2px 8px; + + background-color: #f5f5f5; + } +} diff --git a/src/components/RestaurantCard/index.js b/src/components/RestaurantCard/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/RestaurantsListPage/RestaurantsListPage.js b/src/components/RestaurantsListPage/RestaurantsListPage.js new file mode 100644 index 0000000..4352571 --- /dev/null +++ b/src/components/RestaurantsListPage/RestaurantsListPage.js @@ -0,0 +1,44 @@ +import React, { useEffect } from 'react'; +import PropTypes from 'prop-types'; +import RestaurantCard from '../RestaurantCard/RestaurantCard'; +import './RestaurantsListPage.scss'; + +const DEFAULT_ETA_RANGE = '20 - 30 min'; + +const RestaurantsListPage = ({ loadRestaurants, restaurantsListData }) => { + useEffect(() => { + loadRestaurants(); + }, [loadRestaurants]); + + return ( +
+ {restaurantsListData.map((restaurant) => { + const { + heroImageUrl, title, categories, etaRange, uuid, + } = restaurant; + + return ( + + ); + })} +
+ ); +}; + +RestaurantsListPage.propTypes = { + restaurantsListData: PropTypes.arrayOf(PropTypes.shape()), + loadRestaurants: PropTypes.func.isRequired, +}; + +RestaurantsListPage.defaultProps = { + restaurantsListData: [], +}; + +export default RestaurantsListPage; diff --git a/src/components/RestaurantsListPage/RestaurantsListPage.scss b/src/components/RestaurantsListPage/RestaurantsListPage.scss new file mode 100644 index 0000000..a87ec4f --- /dev/null +++ b/src/components/RestaurantsListPage/RestaurantsListPage.scss @@ -0,0 +1,5 @@ +.restaurants-list { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(348px, 1fr)); + gap: 40px 20px; +} diff --git a/src/components/RestaurantsListPage/index.js b/src/components/RestaurantsListPage/index.js new file mode 100644 index 0000000..bf7f848 --- /dev/null +++ b/src/components/RestaurantsListPage/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import RestaurantsListPage from './RestaurantsListPage'; +import { loadRestaurantsAction } from '../../store/actions'; +import { selectRestaurantsList } from '../../store/selectors'; + +const mapStateToProps = state => ({ + restaurantsListData: selectRestaurantsList(state), +}); + +const mapDispatchToProps = { + loadRestaurants: loadRestaurantsAction, +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(RestaurantsListPage); diff --git a/src/index.js b/src/index.js index b597a44..b421ab3 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; +import './styles/index.scss'; ReactDOM.render(, document.getElementById('root')); diff --git a/src/store/actions.js b/src/store/actions.js new file mode 100644 index 0000000..6893cc9 --- /dev/null +++ b/src/store/actions.js @@ -0,0 +1,16 @@ +export const ACTION_TYPES = { + SAVE_RESTAURANTS: 'SAVE_RESTAURANTS', +}; + +const saveRestaurants = data => ({ + type: ACTION_TYPES.SAVE_RESTAURANTS, + payload: data, +}); + +const URL = 'https://mate-uber-eats-api.herokuapp.com/api/v1/restaurants'; + +export const loadRestaurantsAction = () => (dispatch) => { + fetch(URL) + .then(response => response.json()) + .then(data => dispatch(saveRestaurants(data.data))); +}; diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..5cb5092 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,28 @@ +import { createStore, compose, applyMiddleware } from 'redux'; +import thunk from 'redux-thunk'; +import { ACTION_TYPES } from './actions'; + +const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; +const middlewares = [thunk]; + +const initialState = { + restaurantsListData: null, +}; + +const reducer = (state = initialState, action) => { + switch (action.type) { + case ACTION_TYPES.SAVE_RESTAURANTS: + return { + ...state, + restaurantsListData: action.payload, + }; + + default: + return state; + } +}; + +export const store = createStore( + reducer, + composeEnhancers(applyMiddleware(...middlewares)) +); diff --git a/src/store/selectors.js b/src/store/selectors.js new file mode 100644 index 0000000..050aeb1 --- /dev/null +++ b/src/store/selectors.js @@ -0,0 +1,16 @@ +import { createSelector } from 'reselect'; + +const rootSelector = state => state; + +export const selectRestaurantsList = createSelector( + rootSelector, + ({ restaurantsListData }) => { + if (!restaurantsListData) { + return []; + } + + const { feedItems, storesMap } = restaurantsListData; + + return feedItems.map(({ uuid }) => storesMap[uuid]); + } +); diff --git a/src/styles/extends.scss b/src/styles/extends.scss new file mode 100644 index 0000000..db10f11 --- /dev/null +++ b/src/styles/extends.scss @@ -0,0 +1,5 @@ +%flex-row-center { + display: flex; + flex-flow: row nowrap; + align-items: center; +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..c4e191b --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,30 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +body, +button, +a, +input { + font-family: Roboto, sans-serif; + font-size: 16px; + line-height: 1.5; +} + +input { + border: none; + background: transparent; + outline: none; +} + +a { + text-decoration: none; +} + +.content { + max-width: 1160px; + padding: 0 34px; + margin: 0 auto; +} From 6e690cece27a72abc2dc3b71741e902b134d06e4 Mon Sep 17 00:00:00 2001 From: vadim-os Date: Wed, 15 Jan 2020 15:01:00 +0200 Subject: [PATCH 2/3] uber eats 1-2 --- README.md | 22 +++++++++++----------- package.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 84c7a15..95b0a45 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ Base API url: https://mate-uber-eats-api.herokuapp.com/api/v1/ - use `redux-thunk` to handle async actions - create separate component for restaurant card - use https://mate-uber-eats-api.herokuapp.com/api/v1/restaurants endpoint to fetch data - - accept optional query parameter `location`: `london|kyiv` - - `RestaurantCard` should be clickable fully (not only the image) + - accept optional query parameter `location`: `london|kyiv` + - `RestaurantCard` should be clickable fully (not only the image) 2. Implement basic header markup 3. Implement footer 4. Add functionality and styles for mobile and tablet versions - `Location`, `Deliver now` and `Search` should be replaced whith buttons on the small screens. - Block with inputs should apper below the header after click on the button. + Block with inputs should apper below the header after click on the button. 5. Implement `RestaurantPage` - use `uuid` in the URL - fetch data from https://mate-uber-eats-api.herokuapp.com/api/v1/restaurants/:uuid @@ -57,7 +57,7 @@ Base API url: https://mate-uber-eats-api.herokuapp.com/api/v1/ - open basket sidebar when click on busket button, close on click outside or close icon - add item to basket when click submit in MenuItemModal - show list added items in basket - - add ability to change item count, remove item + - add ability to change item count, remove item - when user click edit on item - open MenuItemModal with additional remove button. After submit, edit current item instead of add new one - clear basket when user click order button 5. Restore user session after close-open tab @@ -69,27 +69,27 @@ Base API url: https://mate-uber-eats-api.herokuapp.com/api/v1/ ## Workflow - Fork the repository with task -- Clone forked repository +- Clone forked repository ```bash git clone git@github.com:/.git ``` - Run `npm install` to install dependencies. - Then develop -## Development mode +## Development mode - Run `npm start` to start development server on `http://localhost:3000` - When you run server the command line window will no longer be available for - writing commands until you stop server (`ctrl + c`). All other commands you + When you run server the command line window will no longer be available for + writing commands until you stop server (`ctrl + c`). All other commands you need to run in new command line window. - Follow [HTML, CSS styleguide](https://mate-academy.github.io/style-guides/htmlcss.html) - Follow [the simplified JS styleguide](https://mate-academy.github.io/style-guides/javascript-standard-modified) - run `npm run lint` to check code style -- When you finished add correct `homepage` to `package.json` and run `npm run deploy` +- When you finished add correct `homepage` to `package.json` and run `npm run deploy` - Add links to your demo in readme.md. - - `[DEMO LINK](https://.github.io//)` - this will be a + - `[DEMO LINK](https://vadim-os.github.io/react_uber-eats/)` - this will be a link to your index.html - Commit and push all recent changes. -- Create `Pull Request` from forked repo `()` to original repo +- Create `Pull Request` from forked repo `()` to original repo (`master`). - Add a link at `PR` to Google Spreadsheets. diff --git a/package.json b/package.json index d57cbfa..45eb61e 100755 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "homepage": "https://mate-academy.github.io/react_uber-eats", + "homepage": "https://vadim-os.github.io/react_uber-eats", "name": "react_uber-eats", "version": "0.1.0", "private": true, From ecdcbd8a9a6f8d482d4616da767fa7d109452502 Mon Sep 17 00:00:00 2001 From: vadim-os Date: Sun, 19 Jan 2020 15:12:01 +0200 Subject: [PATCH 3/3] uber eats 1-4 --- public/images/appstore.png | Bin 0 -> 3656 bytes public/images/arrowDown.svg | 3 + public/images/close.svg | 3 + public/images/facebook.svg | 3 + public/images/googleplay.png | Bin 0 -> 4112 bytes public/images/instagram.svg | 5 + public/images/logo_footer.svg | 4 + public/images/planet.svg | 3 + public/images/twitter.svg | 3 + src/App.css | 7 +- src/App.js | 15 +- src/components/Error/Error.js | 25 ++++ src/components/Error/Error.scss | 15 ++ src/components/Error/index.js | 0 src/components/Footer/Footer.js | 109 ++++++++++++++ src/components/Footer/Footer.scss | 138 ++++++++++++++++++ src/components/Footer/index.js | 0 src/components/Header/Header.js | 119 +++++++++++++-- src/components/Header/Header.scss | 62 +++++++- src/components/Input/Input.js | 78 ++++++---- src/components/Input/Input.scss | 32 +++- src/components/Loader/Loader.js | 23 +++ src/components/Loader/Loader.scss | 99 +++++++++++++ src/components/Loader/index.js | 0 .../RestaurantCard/RestaurantCard.scss | 13 +- .../RestaurantsListPage.js | 21 ++- .../RestaurantsListPage.scss | 16 +- src/components/RestaurantsListPage/index.js | 8 +- src/components/Select/Select.js | 55 +++++++ src/components/Select/Select.scss | 34 +++++ src/components/Select/index.js | 0 src/store/actions.js | 22 ++- src/store/index.js | 21 +-- src/store/rootReducer.js | 36 +++++ src/store/selectors.js | 10 ++ src/styles/extends.scss | 12 ++ src/styles/index.scss | 17 +++ src/styles/utils.scss | 2 + src/styles/variables.scss | 8 + 39 files changed, 931 insertions(+), 90 deletions(-) create mode 100644 public/images/appstore.png create mode 100644 public/images/arrowDown.svg create mode 100644 public/images/close.svg create mode 100644 public/images/facebook.svg create mode 100644 public/images/googleplay.png create mode 100644 public/images/instagram.svg create mode 100644 public/images/logo_footer.svg create mode 100644 public/images/planet.svg create mode 100644 public/images/twitter.svg create mode 100644 src/components/Error/Error.js create mode 100644 src/components/Error/Error.scss create mode 100644 src/components/Error/index.js create mode 100644 src/components/Footer/Footer.js create mode 100644 src/components/Footer/Footer.scss create mode 100644 src/components/Footer/index.js create mode 100644 src/components/Loader/Loader.js create mode 100644 src/components/Loader/Loader.scss create mode 100644 src/components/Loader/index.js create mode 100644 src/components/Select/Select.js create mode 100644 src/components/Select/Select.scss create mode 100644 src/components/Select/index.js create mode 100644 src/store/rootReducer.js create mode 100644 src/styles/utils.scss create mode 100644 src/styles/variables.scss diff --git a/public/images/appstore.png b/public/images/appstore.png new file mode 100644 index 0000000000000000000000000000000000000000..6c2ff057d7a82875e0cf1889073a0b8bb08f873d GIT binary patch literal 3656 zcmV-O4!7}%P)1%Q_J$2HHdHkBE*2~(Q6n}ifMtw|U9s1(f}>+)2u4(3hB}mw-eKqrz4zXG z@7(YF&V2XH%Vy!rz9k{R{%78>``+Dm+qtLw&k3bO@yjp2lt1yr6LYp~*;04&=FJ&; zD_v4Jq)@6+#cuCiv$8gb4^ z3WpXBJM1ty`Q($OTD59B?zrQQjw&Q|(+@xV@VdQw_paWoSu@$WbEl+mXky2X9WsCZ zd{H?leZ&z*)V%S=8%L$BT)DDNj~+eJQ-YBK*uH(cbm`JXHf-2XJ8kXSwG~xBB!v__ zR;^lvdr>J({fqQnyLL%&K%E{*q2vR3P`N0RCdGhq<;uxJ4?QGJn>Lm6&p%(HqHNi+ za`D9%OJ-)KTyVh!Qo3|$DJtaT$Ml_seOgohC(vn{K*EF1ze9DJm4X zaIiQXJ9dyqKK$@Q`TOs`MSUg7$jFeQz*k>=B^usKRB#~P zc;gK@^UO14UqOQhx#gByg739!*OuFFzg>z7MJgOjhRwX|uDi^nEL*lrrca+PQK8|L zEL^xy9)0vtQEyrX4jd@I{`zZRt}eXrLV51F=j=q$mj3U(_g>qmV~#mSG(@wu6)IGa z>#x7w!nb?wxkt`D_gq_Ov{5{uK^}SJ5$l)t05n6@s#WFr=bx90F1jdad%_7PSX<`2 zC(U-sDW^!ynl(+>H8QY!r=EJMTyxDeHm)b1d{T}+`sjSWQM$qU`s=U1OduFLpj~!$ zwylQ;^S$l1+oW#Yx;CDuC{p2g>ZzyX>Z`8~zJLGy_o5E4>}d;k6S<;^$Ww9x$PufLWnue{P06ti~r*=O6hZoc_u+u+8H8_Or3d}15ivSmw) z^~1oF_36_`Dp#&-Dx5ZKh!RCMH@ths;WY#rjg7(dam9k)wQ1AF-o+S*3>XLFLc2cv z@Wb-pgAd9dfBcc}cW_V4^~fWSl=IFzFE|i2YSb`Ot9+F_@x&8$AEDro;5+o{)ysr2 z3W|&gWsont@IvsNMMdiOC5X+@5cE~2P8|~t7HQ_pnUb5ED?k18lW7+=i3J=mV1Q|r z>eZ{utFOLl0tSBn{dXBNW{hnrW@`EJ7_OnE(9A5*12=%0&_(R-*?}A zCeR)TT7w1+%miL?$t5OyXr7@%hsx=vpKgMI;G(q?MUiO^)Fo8TPT#16DH3y5%Nkr|kIFlz&HVMakV565VU1}%c_19mwQ^~}A zn|br*NusD&v7)KWN|h?v$;9acojP^0(>-U-9J9@65EgFa$dP6;IAI79zvEOD7NbXx zHlO3Ix8AZ1!{?baX_8c_QpNlL%!Ah&Y{<54+e|AkH|86=nH&~QGuj0cfk3bx@k~%G zNNu2*aO^Q<@vwgVdQryP%q(k+5Nf_mBH@cKzHlmSh;BlcN~hCM&8=9m!o_0KrcJIz zixy68xzojP@t~6K8a8a`RGf8Qd+)vXoC=6jwQcw4 z`=ys&axcF4qEn~VsnFW}GtM}}+NxG_YNniSW`TLorhfhUPBo8Hhtckxbka#qH{Cw# zfpbqk{dC+lU~c?Q1=HPn>#a_O)b3w*-F5ETYp=D>D#X_Av(G-WaU{CGdKjGghc2>k z=;?GyvASeI|B3dUx{CJl!V$^mAY>#8NQNW=I7yg;6iOx{2?usQHsnhbix)4JTD5AK z4NjqCB4LLVCk%%uS#;>oLHhOUCkGR7&eeY*qiGS850wv8B&<2kIp>^!C5#HfF36u` zii(I>@bbC%ygvc636)QHJbd_Y89#o!3>q}ZqPPPY2@6NE<^&MFMG0fWAY3Jh$Mx7_ zk69SKKS0O`xdsCZc?PLP$PDom)*Ns?FtyP12MiL8R&+63vRJonom1*LvNx>)>XgH9 zg9i_G$}KpJ|DEy;#qQM;GAaXWbNcbeADt3rcAxN^&^a7x6G9Wd4;wbD*vFaZ<)f8^ zeGcU{Bv}yUTyez}Mo>k8asb8zQu9jEj9daN=(us?^0kAUf@s3|g%E=b;~oSZj&L~7 zquhg0&qPp=Mi6(HP}oz5FbZH|L3=b8#Fz3q0RznUaDtIOA>UwI@!6pA0W?2t0ng4l z>ns~1WE;L2(V4ew{(Q>RWf6BpThC#pHLQ>T=#OBS3s z$ezOX>o15aO(r>2*{)i(YDN|TwfP0wHfq$!ofJ$uGo15KdWb4WPNF6ZNo=$~<@fCle*`|Y>w znNs3T*-!i2q)C%tEX;G|%9S=xG^+}p(|ndY{`lh~X^u!FnA%mhFTlVP6%IXJPEU(d zZD7nLi^rm(vSWo!6K~cJEUxAkoQB|b>4~!YY^-NTVG{w1s}#90v9G=Mnp16L_s5PM z>-6Ln7!PEiNB{o)jitrhgxjc3&7wjmkt>0++y7SIEP3Tpt+C2o* zZ!U~1P{-GVhyFBgWzUq3H)dKLVKdpvMY+Cx`&#=?KmD}$go6R?D|GMP-KgWj_N^I5 zI~kgO4^E8cP3&EMq5Sp34?oy_RnJZ{pTT`L1-}Qdaoqd(K+Aq|SB}?oX zRC&BHz5MdaPEAxWCj>Hr6A z@xc}>SYU@Hd_bV?@y8GvO@t;a9Fa&c!ccE3lLcvV(%6Loc9zJ5WD;Q`ehX=8Z{Mkd z2*XDUdg^83#EHRu{0C|@fbZM=&n}Zx3;RO&9LyI`h!YRgUXX}`93+j8uR?hOncM#d z<`3wTB&CN6uc$f7*RLNV*;YysJm?#ri9&H|Rmc`|!AFsZBSVhQlPDr(WeG!7Wmzpl zvd~i|syYkR7H3RPwSCqETad2ynNR8>2(`oY7=VR#F;3Z{MT_j;*it|UtXT4jlzhCl zv2A|-`Dd#sp+1D_EY&FXeQ%`-{+)XA3q13}0_0C_)kfEF%LyRRK~?alzQ7p z!a;q5+D!A7{lKGu4Wm{Q=`IW?>0|Tp!rQiO8{B8nI5BVwoJ3y{7JeQJ&)4AXhY_1% z2bA!E!u$yb8_Jw0Nu<2Mr{(uF7K9PR%TxJ!TT=D$e(T{=@*_r!F#abVC{jukk?T27 z)4%=po0Zr_g*sFPHga#EPzU_;&p%eX5e5rK;W4Td!3qDl1&KmJMZZaelQ-OOgMB8{ z3xm@~i0TCvVezV;khU+!`XRKb6`7o3kP=4oy1rzFvhcSzOj`6_8 z(+|Q(*d8zJj)bTwdoDa}Wd~gpsA+QQFC^q75s?r^XJ%#=cutf6h&Fsw(V#&CyN3fy zSW9F>_?VZMXZMv$FlUaoAAR&uFt&gH{nsgf;xaNaoSKTDEs;{VPe?98XdG4b3tZ*O zmCf-angF@Exq(xvzKw;K>cd#w2B9&}h(y%HS$m=@oKosN^x)Y&^?`z#ker+xyQltA zzH#7`6RLZMw`$d@_8Zlt=3Fz6MD{i5dJcclF$Fzg4uMF3Fspg<=B{(+&Nlh*b3#QW ztrF^of*L^N5sy!RmDCesZF~gcg@ce)$t|av!(x9gL^W#E2!8K{gQ$Us1tFxppAUsi z;pl@40rC+=7^<~gr%s*ng}y`!K0NjCj4ErvyZ})L{j*+#+-$Ue$DV|Piy|c@1?_iS zK1ug?-A-316Qq(k6)#M>idsKn*yF@^;j#52-?^SOY zL{HSI;+4lbqyJRXp_LhJcbK{@hMn?cr3Ms z+qTA3v{OEblZxZYe)woBVI-?LO7i73hi4J@c6rSKSyd9}Qk+*(JVy$L22#S2!XA;X zd4O$tl|2~$e-3;b>~uWeA{KJ`_2 z=8{6mf&bqJ_yaH{8JnuB(aiW*wav=Ml*?A3sHgFGCj5+~aHwIk%D^!GXG!Hz{-b=% aw*LaBZifUW!g}Wb0000 + + diff --git a/public/images/close.svg b/public/images/close.svg new file mode 100644 index 0000000..b536414 --- /dev/null +++ b/public/images/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/facebook.svg b/public/images/facebook.svg new file mode 100644 index 0000000..22565b3 --- /dev/null +++ b/public/images/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/googleplay.png b/public/images/googleplay.png new file mode 100644 index 0000000000000000000000000000000000000000..b988c6fc6c7bda6b791001fa65940fd525d51c4d GIT binary patch literal 4112 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 O0000 + + + + diff --git a/public/images/logo_footer.svg b/public/images/logo_footer.svg new file mode 100644 index 0000000..c3894d1 --- /dev/null +++ b/public/images/logo_footer.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/planet.svg b/public/images/planet.svg new file mode 100644 index 0000000..b8806c7 --- /dev/null +++ b/public/images/planet.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/twitter.svg b/public/images/twitter.svg new file mode 100644 index 0000000..9c8b7bd --- /dev/null +++ b/public/images/twitter.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/App.css b/src/App.css index 8b13789..4a63ea4 100644 --- a/src/App.css +++ b/src/App.css @@ -1 +1,6 @@ - +.page { + position: relative; + padding-top: 40px; + min-height: 100vh; + margin-bottom: 40px; +} diff --git a/src/App.js b/src/App.js index 3eb5082..6184dbb 100644 --- a/src/App.js +++ b/src/App.js @@ -4,18 +4,17 @@ import { Provider } from 'react-redux'; import { store } from './store/index'; import RestaurantsListPage from './components/RestaurantsListPage'; import Header from './components/Header/Header'; +import Footer from './components/Footer/Footer'; const App = () => ( -
-
-
+
+
+
- -
- -
Uber Eats Footer
-
+ + +