From b4923091fbda6426095c0be3a01dadb615ee61de Mon Sep 17 00:00:00 2001
From: vadim-os <osinsky_vadim@yahoo.com>
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 @@
+<svg width="145" height="24" viewBox="0 0 145 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M66.8341 9.17115C64.682 9.17115 63.1554 10.8551 63.1554 13.44V22.922H59.8702V6.23213H63.1161V8.27016C63.5164 7.59468 64.0902 7.03857 64.7778 6.65947C65.4655 6.28037 66.242 6.09207 67.0269 6.1141H68.2072V9.17115H66.8341ZM57.6 14.5771C57.6 9.6 54.059 5.87803 49.2669 5.87803C48.1346 5.88572 47.0151 6.11721 45.9726 6.55919C44.9301 7.00117 43.9854 7.64491 43.1926 8.45338C42.3999 9.26185 41.7748 10.2191 41.3534 11.27C40.932 12.321 40.7225 13.4449 40.737 14.5771C40.737 19.5502 44.5731 23.3115 49.5777 23.3115C50.9757 23.3379 52.3595 23.0278 53.6125 22.4075C54.8656 21.7871 55.9511 20.8746 56.7777 19.7469L54.3934 18C53.8464 18.7634 53.1227 19.383 52.284 19.8058C51.4453 20.2285 50.5168 20.4419 49.5777 20.4275C48.2402 20.4212 46.9493 19.936 45.9388 19.0597C44.9283 18.1835 44.2651 16.9743 44.0695 15.6511H57.6079L57.6 14.5771ZM44.1403 13.0466C44.7266 10.501 46.7607 8.7777 49.2275 8.7777C51.6944 8.7777 53.7246 10.501 54.2754 13.0466H44.1403ZM30.3305 5.87803C29.2326 5.87896 28.1458 6.09744 27.1328 6.52086C26.1198 6.94428 25.2008 7.56424 24.4289 8.34492V0H21.1436V22.922H24.3895V20.8052C25.962 22.396 28.1016 23.2974 30.3384 23.3115C31.4986 23.3361 32.6522 23.1289 33.7313 22.7019C34.8104 22.2749 35.7935 21.6368 36.6228 20.8249C37.4521 20.0131 38.1109 19.0438 38.5607 17.974C39.0106 16.9042 39.2423 15.7553 39.2423 14.5948C39.2423 13.4342 39.0106 12.2854 38.5607 11.2155C38.1109 10.1457 37.4521 9.17644 36.6228 8.36458C35.7935 7.55271 34.8104 6.91458 33.7313 6.4876C32.6522 6.06062 31.4986 5.85338 30.3384 5.87803H30.3305ZM30.0944 20.3764C28.9493 20.3818 27.8284 20.047 26.8739 19.4144C25.9194 18.7818 25.1743 17.8798 24.7332 16.8231C24.2921 15.7663 24.1749 14.6024 24.3964 13.4789C24.6179 12.3554 25.1681 11.323 25.9773 10.5127C26.7864 9.70246 27.8181 9.15082 28.9413 8.92779C30.0644 8.70477 31.2286 8.82042 32.2859 9.26007C33.3433 9.69972 34.2462 10.4435 34.8801 11.3972C35.5141 12.3508 35.8504 13.4713 35.8466 14.6164C35.8476 15.3717 35.6995 16.1198 35.4107 16.8177C35.1219 17.5156 34.6981 18.1496 34.1636 18.6833C33.6292 19.217 32.9946 19.6399 32.2963 19.9278C31.598 20.2156 30.8497 20.3627 30.0944 20.3607V20.3764ZM9.04525 20.219C12.2164 20.219 14.6793 17.7875 14.6793 14.1443V0H18.0826V22.922H14.7187V20.7541C13.9328 21.5664 12.9902 22.2107 11.9481 22.6483C10.906 23.0858 9.78596 23.3074 8.65574 23.2997C3.76525 23.2997 0 19.7351 0 14.3292V0H3.46623V14.1639C3.46623 17.8269 5.82689 20.219 9.04525 20.219Z" fill="#262626"/>
+<path d="M76.3789 0H92.4589V3.93443H80.7225V9.52131H92.1323V13.322H80.7225V19.0033H92.4589V22.9377H76.3789V0ZM136.867 23.3508C141.797 23.3508 144.574 20.9902 144.574 17.7482C144.574 15.4387 142.93 13.7154 139.487 12.9679L135.848 12.2243C133.735 11.8308 133.07 11.4374 133.07 10.6505C133.07 9.63148 134.089 9.0059 135.966 9.0059C138 9.0059 139.507 9.55279 139.9 11.4334H144.165C143.933 7.89246 141.387 5.55541 136.225 5.55541C131.764 5.55541 128.632 7.39672 128.632 10.9652C128.632 13.4321 130.355 15.0374 134.073 15.8203L138.142 16.7607C139.747 17.0754 140.176 17.5082 140.176 18.1731C140.176 19.2315 138.964 19.8964 137.004 19.8964C134.542 19.8964 133.133 19.3495 132.586 17.4689H128.298C128.923 21.002 131.543 23.3508 136.867 23.3508ZM127.058 22.922H122.443C119.547 22.922 117.942 21.12 117.942 18.8459V9.83607H114.696V5.99606H117.958V1.17639H122.246V5.99606H127.058V9.83607H122.246V17.7482C122.246 18.6492 122.872 19.082 123.852 19.082H127.058V22.922ZM108.566 6.00394V7.53049C107.057 6.25411 105.142 5.55677 103.164 5.56328C101.981 5.53838 100.804 5.75002 99.7032 6.18579C98.6024 6.62156 97.5996 7.27269 96.7537 8.10102C95.9077 8.92935 95.2357 9.91821 94.7768 11.0096C94.318 12.1011 94.0817 13.2731 94.0817 14.4571C94.0817 15.641 94.318 16.813 94.7768 17.9045C95.2357 18.9959 95.9077 19.9848 96.7537 20.8131C97.5996 21.6414 98.6024 22.2925 99.7032 22.7283C100.804 23.1641 101.981 23.3757 103.164 23.3508C105.142 23.3594 107.058 22.6618 108.566 21.3836V22.9141H112.843V5.99606L108.566 6.00394ZM103.519 19.6367C102.493 19.6484 101.487 19.3549 100.628 18.7933C99.7692 18.2318 99.0969 17.4277 98.6964 16.4832C98.2958 15.5387 98.1852 14.4964 98.3784 13.4888C98.5716 12.4812 99.0601 11.5539 99.7816 10.8245C100.503 10.0952 101.425 9.59686 102.431 9.39285C103.436 9.18883 104.48 9.28834 105.428 9.67875C106.377 10.0691 107.188 10.7328 107.759 11.5854C108.33 12.438 108.634 13.4409 108.633 14.4669C108.64 15.1432 108.512 15.814 108.257 16.4405C108.002 17.0671 107.626 17.6369 107.149 18.1169C106.673 18.597 106.106 18.9778 105.481 19.2373C104.857 19.4968 104.187 19.6299 103.511 19.6289L103.519 19.6367Z" fill="#5FB709"/>
+</svg>
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 @@
+<svg width="14" height="17" viewBox="0 0 14 17" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7 15.7859L11.2392 11.4636C13.5869 9.06988 13.5869 5.18495 11.2392 2.79123C8.89684 0.402923 5.10316 0.402923 2.76077 2.79123C0.413075 5.18495 0.413075 9.06988 2.76077 11.4636L7 15.7859Z" stroke="#262626"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7 9C8.10457 9 9 8.10457 9 7C9 5.89543 8.10457 5 7 5C5.89543 5 5 5.89543 5 7C5 8.10457 5.89543 9 7 9Z" stroke="#262626"/>
+</svg>
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 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.9217 11.0417L15 15M12.8788 6.76471C12.8788 9.94847 10.2196 12.5294 6.93939 12.5294C3.65916 12.5294 1 9.94847 1 6.76471C1 3.58095 3.65916 1 6.93939 1C10.2196 1 12.8788 3.58095 12.8788 6.76471Z" stroke="black" stroke-width="2"/>
+</svg>
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 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <title>React Uber eats</title>
-  </head>
-  <body>
-    <div id="root"></div>
-  </body>
+
+<head>
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" />
+  <link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap" rel="stylesheet">
+  <title>React Uber eats</title>
+</head>
+
+<body>
+  <div id="root"></div>
+</body>
+
 </html>
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 = () => (
-  <div className="App">
-    <h1>React Uber eats</h1>
-  </div>
+  <Provider store={store}>
+    <div className="page">
+      <Header />
+      <main className="content">
+        <RestaurantsListPage />
+
+      </main>
+
+      <footer>Uber Eats Footer</footer>
+    </div>
+  </Provider>
 );
 
 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 (
+    <header className="header">
+      <div className="content">
+        <div className="header__inner">
+          <img src="./images/logo.svg" alt="Uber Eats Logo" />
+          <div className="header__delivery-info">
+            <Input
+              name="address"
+              value={address}
+              onChange={handleInputChange}
+              placeholder="Address"
+              iconUrl="./images/place.svg"
+            />
+            <Input
+              name="time"
+              value={time}
+              onChange={handleInputChange}
+              placeholder="Time"
+              type="time"
+            />
+          </div>
+          <Input
+            name="search"
+            value={search}
+            onChange={handleInputChange}
+            placeholder="Search"
+            iconUrl="./images/search.svg"
+            className="header__search"
+          />
+
+          <a
+            className="header__link"
+            href="/sign-in"
+          >
+            Sign In
+          </a>
+        </div>
+      </div>
+
+    </header>
+  );
+};
+
+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 (
+    <div
+      className={rootClass}
+      onClick={focusInput}
+      role="presentation"
+    >
+      {!!iconUrl
+        && (
+          <img
+            src={iconUrl}
+            alt={placeholder}
+            className="control__icon"
+          />
+        )}
+      <input
+        ref={inputRef}
+        type={type}
+        value={value}
+        onChange={onChange}
+        onFocus={handleFocus}
+        onBlur={handleBlur}
+        name={name}
+        placeholder={placeholder}
+        className="control__input"
+      />
+    </div>
+  );
+};
+
+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,
+}) => (
+  <div className="restaurant-card">
+    <img src={imageUrl} alt={title} className="restaurant-card__img" />
+    <h2 className="restaurant-card__title">{title}</h2>
+    <div className="restaurant-card__categories">
+      {categories.join(' · ')}
+    </div>
+    <div className="restaurant-card__eta">
+      {etaRange}
+    </div>
+  </div>
+);
+
+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 (
+    <div className="restaurants-list">
+      {restaurantsListData.map((restaurant) => {
+        const {
+          heroImageUrl, title, categories, etaRange, uuid,
+        } = restaurant;
+
+        return (
+          <RestaurantCard
+            key={uuid}
+            imageUrl={heroImageUrl}
+            title={title}
+            categories={categories}
+            etaRange={etaRange ? etaRange.text : DEFAULT_ETA_RANGE}
+            uuid={uuid}
+          />
+        );
+      })}
+    </div>
+  );
+};
+
+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(<App />, 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 <osinsky_vadim@yahoo.com>
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:<user_name>/<task_repository>.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://<your_account>.github.io/<repo_name>/)` - 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 `(<branch_name>)` to original repo 
+- Create `Pull Request` from forked repo `(<branch_name>)` 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 <osinsky_vadim@yahoo.com>
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
diff --git a/public/images/arrowDown.svg b/public/images/arrowDown.svg
new file mode 100644
index 0000000..2576a2a
--- /dev/null
+++ b/public/images/arrowDown.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.4175 0L0 1.34583L7 8L14 1.34583L12.5825 0L7 5.30417L1.4175 0Z" fill="white"/>
+</svg>
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 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" fill="black"/>
+</svg>
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 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15.1164 0H0.883093C0.395706 0 0 0.394915 0 0.883093V15.1164C0 15.6046 0.395706 16 0.883093 16H8.54587V9.80386H6.46091V7.38879H8.54587V5.60785C8.54587 3.54159 9.80755 2.41586 11.6512 2.41586C12.5351 2.41586 13.293 2.48199 13.5141 2.5107V4.67049L12.2353 4.67101C11.2328 4.67101 11.0395 5.1476 11.0395 5.84654V7.388H13.4311L13.1184 9.80281H11.0392V15.9992H15.1161C15.604 15.9992 16 15.6032 16 15.1164V0.882566C15.9997 0.394915 15.6043 0 15.1164 0Z" fill="white"/>
+</svg>
diff --git a/public/images/googleplay.png b/public/images/googleplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..b988c6fc6c7bda6b791001fa65940fd525d51c4d
GIT binary patch
diff --git a/public/images/instagram.svg b/public/images/instagram.svg
new file mode 100644
index 0000000..7c3e6a0
--- /dev/null
+++ b/public/images/instagram.svg
@@ -0,0 +1,5 @@
+<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.9175 0H4.74833C2.31372 0 0.333008 1.98081 0.333008 4.41542V11.5846C0.333008 14.0193 2.31372 16 4.74833 16H11.9175C14.3523 16 16.333 14.0192 16.333 11.5846V4.41542C16.3331 1.98081 14.3523 0 11.9175 0ZM14.9135 11.5846C14.9135 13.2365 13.5695 14.5804 11.9176 14.5804H4.74833C3.09649 14.5805 1.75261 13.2365 1.75261 11.5846V4.41542C1.75261 2.76358 3.09649 1.4196 4.74833 1.4196H11.9175C13.5694 1.4196 14.9134 2.76358 14.9134 4.41542V11.5846H14.9135Z" fill="white"/>
+<path d="M8.33276 3.87734C6.05941 3.87734 4.20996 5.72679 4.20996 8.00014C4.20996 10.2734 6.05941 12.1227 8.33276 12.1227C10.6061 12.1227 12.4556 10.2734 12.4556 8.00014C12.4556 5.72679 10.6061 3.87734 8.33276 3.87734ZM8.33276 10.7031C6.84227 10.7031 5.62956 9.49053 5.62956 8.00004C5.62956 6.50947 6.84218 5.29685 8.33276 5.29685C9.82333 5.29685 11.036 6.50947 11.036 8.00004C11.036 9.49053 9.82324 10.7031 8.33276 10.7031Z" fill="white"/>
+<path d="M12.6289 2.67383C12.3554 2.67383 12.0867 2.78456 11.8936 2.97857C11.6995 3.17163 11.5879 3.44041 11.5879 3.71487C11.5879 3.98847 11.6996 4.25715 11.8936 4.45116C12.0866 4.64423 12.3554 4.7559 12.6289 4.7559C12.9034 4.7559 13.1712 4.64423 13.3652 4.45116C13.5592 4.25715 13.67 3.98838 13.67 3.71487C13.67 3.44041 13.5592 3.17163 13.3652 2.97857C13.1722 2.78456 12.9034 2.67383 12.6289 2.67383Z" fill="white"/>
+</svg>
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 @@
+<svg width="145" height="24" viewBox="0 0 145 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M66.8341 9.17115C64.682 9.17115 63.1554 10.8551 63.1554 13.44V22.922H59.8702V6.23213H63.1161V8.27016C63.5164 7.59468 64.0902 7.03857 64.7778 6.65947C65.4655 6.28037 66.242 6.09207 67.0269 6.1141H68.2072V9.17115H66.8341ZM57.6 14.5771C57.6 9.6 54.059 5.87803 49.2669 5.87803C48.1346 5.88572 47.0151 6.11721 45.9726 6.55919C44.9301 7.00117 43.9854 7.64491 43.1926 8.45338C42.3999 9.26185 41.7748 10.2191 41.3534 11.27C40.932 12.321 40.7225 13.4449 40.737 14.5771C40.737 19.5502 44.5731 23.3115 49.5777 23.3115C50.9757 23.3379 52.3595 23.0278 53.6125 22.4075C54.8656 21.7871 55.9511 20.8746 56.7777 19.7469L54.3934 18C53.8464 18.7634 53.1227 19.383 52.284 19.8058C51.4453 20.2285 50.5168 20.4419 49.5777 20.4275C48.2402 20.4212 46.9493 19.936 45.9388 19.0597C44.9283 18.1835 44.2651 16.9743 44.0695 15.6511H57.6079L57.6 14.5771ZM44.1403 13.0466C44.7266 10.501 46.7607 8.7777 49.2275 8.7777C51.6944 8.7777 53.7246 10.501 54.2754 13.0466H44.1403ZM30.3305 5.87803C29.2326 5.87896 28.1458 6.09744 27.1328 6.52086C26.1198 6.94428 25.2008 7.56424 24.4289 8.34492V0H21.1436V22.922H24.3895V20.8052C25.962 22.396 28.1016 23.2974 30.3384 23.3115C31.4986 23.3361 32.6522 23.1289 33.7313 22.7019C34.8104 22.2749 35.7935 21.6368 36.6228 20.8249C37.4521 20.0131 38.1109 19.0438 38.5607 17.974C39.0106 16.9042 39.2423 15.7553 39.2423 14.5948C39.2423 13.4342 39.0106 12.2854 38.5607 11.2155C38.1109 10.1457 37.4521 9.17644 36.6228 8.36458C35.7935 7.55271 34.8104 6.91458 33.7313 6.4876C32.6522 6.06062 31.4986 5.85338 30.3384 5.87803H30.3305ZM30.0944 20.3764C28.9493 20.3818 27.8284 20.047 26.8739 19.4144C25.9194 18.7818 25.1743 17.8798 24.7332 16.8231C24.2921 15.7663 24.1749 14.6024 24.3964 13.4789C24.6179 12.3554 25.1681 11.323 25.9773 10.5127C26.7864 9.70246 27.8181 9.15082 28.9413 8.92779C30.0644 8.70477 31.2286 8.82042 32.2859 9.26007C33.3433 9.69972 34.2462 10.4435 34.8801 11.3972C35.5141 12.3508 35.8504 13.4713 35.8466 14.6164C35.8476 15.3717 35.6995 16.1198 35.4107 16.8177C35.1219 17.5156 34.6981 18.1496 34.1636 18.6833C33.6292 19.217 32.9946 19.6399 32.2963 19.9278C31.598 20.2156 30.8497 20.3627 30.0944 20.3607V20.3764ZM9.04525 20.219C12.2164 20.219 14.6793 17.7875 14.6793 14.1443V0H18.0826V22.922H14.7187V20.7541C13.9328 21.5664 12.9902 22.2107 11.9481 22.6483C10.906 23.0858 9.78596 23.3074 8.65574 23.2997C3.76525 23.2997 0 19.7351 0 14.3292V0H3.46623V14.1639C3.46623 17.8269 5.82689 20.219 9.04525 20.219Z" fill="white"/>
+<path d="M76.3789 0H92.4589V3.93443H80.7225V9.52131H92.1323V13.322H80.7225V19.0033H92.4589V22.9377H76.3789V0ZM136.867 23.3508C141.797 23.3508 144.574 20.9902 144.574 17.7482C144.574 15.4387 142.93 13.7154 139.487 12.9679L135.848 12.2243C133.735 11.8308 133.07 11.4374 133.07 10.6505C133.07 9.63148 134.089 9.0059 135.966 9.0059C138 9.0059 139.507 9.55279 139.9 11.4334H144.165C143.933 7.89246 141.387 5.55541 136.225 5.55541C131.764 5.55541 128.632 7.39672 128.632 10.9652C128.632 13.4321 130.355 15.0374 134.073 15.8203L138.142 16.7607C139.747 17.0754 140.176 17.5082 140.176 18.1731C140.176 19.2315 138.964 19.8964 137.004 19.8964C134.542 19.8964 133.133 19.3495 132.586 17.4689H128.298C128.923 21.002 131.543 23.3508 136.867 23.3508ZM127.058 22.922H122.443C119.547 22.922 117.942 21.12 117.942 18.8459V9.83607H114.696V5.99606H117.958V1.17639H122.246V5.99606H127.058V9.83607H122.246V17.7482C122.246 18.6492 122.872 19.082 123.852 19.082H127.058V22.922ZM108.566 6.00394V7.53049C107.057 6.25411 105.142 5.55677 103.164 5.56328C101.981 5.53838 100.804 5.75002 99.7032 6.18579C98.6024 6.62156 97.5996 7.27269 96.7537 8.10102C95.9077 8.92935 95.2357 9.91821 94.7768 11.0096C94.318 12.1011 94.0817 13.2731 94.0817 14.4571C94.0817 15.641 94.318 16.813 94.7768 17.9045C95.2357 18.9959 95.9077 19.9848 96.7537 20.8131C97.5996 21.6414 98.6024 22.2925 99.7032 22.7283C100.804 23.1641 101.981 23.3757 103.164 23.3508C105.142 23.3594 107.058 22.6618 108.566 21.3836V22.9141H112.843V5.99606L108.566 6.00394ZM103.519 19.6367C102.493 19.6484 101.487 19.3549 100.628 18.7933C99.7692 18.2318 99.0969 17.4277 98.6964 16.4832C98.2958 15.5387 98.1852 14.4964 98.3784 13.4888C98.5716 12.4812 99.0601 11.5539 99.7816 10.8245C100.503 10.0952 101.425 9.59686 102.431 9.39285C103.436 9.18883 104.48 9.28834 105.428 9.67875C106.377 10.0691 107.188 10.7328 107.759 11.5854C108.33 12.438 108.634 13.4409 108.633 14.4669C108.64 15.1432 108.512 15.814 108.257 16.4405C108.002 17.0671 107.626 17.6369 107.149 18.1169C106.673 18.597 106.106 18.9778 105.481 19.2373C104.857 19.4968 104.187 19.6299 103.511 19.6289L103.519 19.6367Z" fill="#5FB709"/>
+</svg>
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 @@
+<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5251 0.99999L10.5251 0.999987C10.4415 0.989444 10.3578 0.978882 10.2729 0.978882C10.2552 0.978882 10.2378 0.981238 10.2205 0.983588C10.2054 0.985622 10.1904 0.987652 10.1754 0.988148C10.1481 0.987651 10.1211 0.985616 10.094 0.98358C10.0628 0.981232 10.0316 0.978882 10 0.978882C4.48607 0.978882 0 5.45581 0 10.9577C0 16.4603 4.48607 20.9365 10 20.9365C10.0317 20.9365 10.0631 20.9342 10.0944 20.932L10.0945 20.932C10.1213 20.93 10.1481 20.9281 10.175 20.9276C10.1902 20.9281 10.2053 20.93 10.2204 20.932C10.2378 20.9343 10.2552 20.9365 10.2729 20.9365C10.3623 20.9365 10.4503 20.9253 10.5382 20.914C10.561 20.9111 10.5837 20.9082 10.6064 20.9055C15.8379 20.5905 20 16.2561 20 10.9577C20 5.6593 15.8379 1.32529 10.6064 1.00989C10.5793 1.00683 10.5522 1.00341 10.5251 0.99999ZM7.00617 2.75938C5.99331 3.92619 5.17045 5.60156 4.71867 7.58022C3.31367 7.42804 2.46581 7.25092 2.12402 7.16895C3.11692 5.12304 4.86741 3.542 7.00617 2.75938ZM1.65096 8.33105C1.38846 9.16001 1.24561 10.0424 1.24561 10.9576C1.24708 12.0328 1.44885 13.0983 1.84061 14.0999C2.24096 14.0033 3.13311 13.8183 4.58132 13.6615C4.42775 12.803 4.33739 11.8995 4.33739 10.9576C4.33817 10.2381 4.38913 9.5196 4.48989 8.80718C2.80168 8.62008 1.88953 8.3952 1.65096 8.33105ZM2.38499 15.2518C2.83785 15.1556 3.64928 15.0099 4.84856 14.8848C5.32035 16.6268 6.08785 18.099 7.00713 19.1568C5.05128 18.4427 3.41303 17.0588 2.38428 15.2518H2.38499ZM5.98828 14.7785C6.63507 17.2782 8.21292 19.1325 9.28435 19.5801V14.6477C8.21292 14.6605 6.91828 14.7097 5.98828 14.7785ZM9.2846 13.4052C8.21318 13.4187 6.75496 13.4736 5.76068 13.5506C5.62389 12.7273 5.58496 11.8563 5.58496 10.9579C5.58496 10.2594 5.59853 9.57939 5.68318 8.92257C6.69282 9.0024 8.21318 9.05978 9.2846 9.07403V13.4048V13.4052ZM5.854 7.69091C6.81186 7.76397 8.21257 7.81814 9.284 7.83133V7.83097V2.33621C8.21257 2.81662 6.45222 4.91288 5.854 7.69091ZM17.8435 7.10074C17.6482 7.16061 16.8567 7.38086 15.2914 7.56582C14.9382 5.69123 14.3007 4.09391 13.4692 2.94064C15.3753 3.76496 16.9253 5.24895 17.8435 7.10038V7.10074ZM14.1368 7.68891C13.55 4.87631 11.7843 2.76115 10.7129 2.31745V7.83146C11.7843 7.81827 13.1943 7.76375 14.1368 7.68891ZM10.7129 9.07406C11.7843 9.06016 13.2861 9.00135 14.2832 8.91867C14.3654 9.57656 14.3861 10.2576 14.3861 10.9579C14.3861 11.8574 14.354 12.7299 14.2211 13.5542C13.2393 13.4751 11.7843 13.418 10.7129 13.4052V9.07406ZM10.7129 14.6477V19.5986V19.599C11.7843 19.1849 13.3707 17.3146 14.0065 14.7814C13.0886 14.7108 11.7843 14.6605 10.7129 14.6477ZM13.4692 18.9757C14.2185 17.9365 14.8153 16.5416 15.1835 14.9033C16.415 15.0448 17.1907 15.2094 17.5817 15.3078C16.6401 16.9385 15.1984 18.2242 13.4692 18.9757ZM15.4803 8.79411C15.6682 10.4179 15.643 12.0593 15.4053 13.6766L15.4056 13.6762C16.9256 13.8544 17.7903 14.069 18.1342 14.1691C18.5306 13.1741 18.7556 12.0925 18.7556 10.9581C18.7551 9.83681 18.5368 8.72626 18.1128 7.68789L18.3138 8.25454C18.2574 8.2745 17.4053 8.56353 15.4803 8.79411Z" fill="white"/>
+</svg>
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 @@
+<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.3333 1.89305C18.6218 2.21429 17.8582 2.43216 17.056 2.52942C17.8751 2.02968 18.5022 1.23702 18.7993 0.295398C18.031 0.758193 17.1829 1.09424 16.2792 1.27641C15.5556 0.489895 14.5262 0 13.3846 0C11.1943 0 9.41835 1.80937 9.41835 4.03969C9.41835 4.35601 9.45338 4.66496 9.52105 4.96039C6.22534 4.79174 3.30294 3.18301 1.34702 0.738495C1.00511 1.33425 0.810611 2.02842 0.810611 2.76943C0.810611 4.1714 1.51132 5.40841 2.57446 6.13213C1.92449 6.10999 1.31318 5.92782 0.77801 5.62502V5.67549C0.77801 7.63256 2.14559 9.2659 3.95895 9.63764C3.62671 9.72873 3.27637 9.7792 2.91394 9.7792C2.65783 9.7792 2.41016 9.75335 2.16733 9.70411C2.6723 11.3104 4.13655 12.4785 5.8714 12.5105C4.51469 13.5937 2.804 14.2374 0.945945 14.2374C0.625807 14.2374 0.310471 14.2177 0 14.182C1.75539 15.3304 3.83938 16 6.07921 16C13.375 16 17.3629 9.84321 17.3629 4.50374L17.3496 3.98063C18.1289 3.41439 18.803 2.70297 19.3333 1.89305Z" fill="white"/>
+</svg>
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 = () => (
   <Provider store={store}>
-    <div className="page">
-      <Header />
-      <main className="content">
+    <Header />
+    <main className="page">
+      <div className="content">
         <RestaurantsListPage />
-
-      </main>
-
-      <footer>Uber Eats Footer</footer>
-    </div>
+      </div>
+    </main>
+    <Footer />
   </Provider>
 );
 
diff --git a/src/components/Error/Error.js b/src/components/Error/Error.js
new file mode 100644
index 0000000..cb4b357
--- /dev/null
+++ b/src/components/Error/Error.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import './Error.scss';
+
+const Error = ({ message }) => (
+  <div className="error">
+    <p className="error__text">
+      {message}
+    </p>
+    <a href="/" className="error__link">
+      Try again
+    </a>
+  </div>
+);
+
+Error.propTypes = {
+  message: PropTypes.string,
+};
+
+Error.defaultProps = {
+  message: 'Something went wrong',
+};
+
+export default Error;
diff --git a/src/components/Error/Error.scss b/src/components/Error/Error.scss
new file mode 100644
index 0000000..6acb920
--- /dev/null
+++ b/src/components/Error/Error.scss
@@ -0,0 +1,15 @@
+@import "../../styles/utils.scss";
+
+.error {
+  @extend %flex-row-center;
+  flex-flow: column nowrap;
+  font-size: 24px;
+
+  &__link {
+    color: $color-green;
+
+    &:hover {
+      text-decoration: underline;
+    }
+  }
+}
diff --git a/src/components/Error/index.js b/src/components/Error/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/Footer/Footer.js b/src/components/Footer/Footer.js
new file mode 100644
index 0000000..63e154d
--- /dev/null
+++ b/src/components/Footer/Footer.js
@@ -0,0 +1,109 @@
+import React from 'react';
+import './Footer.scss';
+import Select from '../Select/Select';
+
+const Footer = () => (
+  <footer className="footer">
+    <div className="content">
+      <div className="footer__top-part">
+        <div className="footer__main">
+          <div className="footer__logo-container">
+            <img
+              className="footer__logo"
+              src="./images/logo_footer.svg"
+              alt="Uber Eats Logo"
+            />
+            <Select
+              name="Language"
+              options={[
+                {
+                  value: 'en', label: 'English',
+                },
+                {
+                  value: 'ua', label: 'Українська',
+                },
+              ]}
+              value="en"
+              iconUrl="./images/planet.svg"
+            />
+          </div>
+
+          <div className="foooter__mobile-apps">
+            <a
+              href="/#"
+              className="footer__mobile-app"
+            >
+              <img
+                src="./images/googleplay.png"
+                alt="Play Store"
+              />
+            </a>
+            <a
+              href="/#"
+              className="footer__mobile-app"
+            >
+              <img
+                src="./images/appstore.png"
+                alt="Apple Store"
+              />
+            </a>
+          </div>
+        </div>
+
+        <div className="footer__top-links links">
+          <a href="/#" className="links__link links__link--intended">
+            About UberEats
+          </a>
+          <a href="/#" className="links__link">
+            Read our blog
+          </a>
+          <a href="/#" className="links__link">
+            Sign up to deliver
+          </a>
+          <a href="/#" className="links__link">
+            Add your restaurant
+          </a>
+        </div>
+        <div className="footer__top-links links">
+          <a href="/#" className="links__link links__link--intended">
+            Get help
+          </a>
+          <a href="/#" className="links__link">
+            Read FAQs
+          </a>
+          <a href="/#" className="links__link">
+            View all cities
+          </a>
+        </div>
+      </div>
+
+      <div className="footer__bottom-part">
+        <p className="footer__copyright">
+          © 2019 Uber Technologies Inc.
+        </p>
+
+        <div className="footer__misc">
+          <div className="footer__bottom-links links">
+            <a href="/#" alt="" className="links__link">Privacy policy</a>
+            <a href="/#" alt="" className="links__link">Terms of  use</a>
+            <a href="/#" alt="" className="links__link">Pricing</a>
+          </div>
+
+          <div className="footer__social social">
+            <a href="/#" className="social__link">
+              <img src="./images/facebook.svg" alt="Facebook" />
+            </a>
+            <a href="/#" className="social__link">
+              <img src="./images/twitter.svg" alt="Twitter" />
+            </a>
+            <a href="/#" className="social__link">
+              <img src="./images/instagram.svg" alt="Instagram" />
+            </a>
+          </div>
+        </div>
+      </div>
+    </div>
+  </footer>
+);
+
+export default Footer;
diff --git a/src/components/Footer/Footer.scss b/src/components/Footer/Footer.scss
new file mode 100644
index 0000000..3f90c5a
--- /dev/null
+++ b/src/components/Footer/Footer.scss
@@ -0,0 +1,138 @@
+@import "../../styles/utils.scss";
+
+.footer {
+  padding: 64px 0;
+  background-color: #262626;
+
+  @media (max-width: $breakpoint-tablet) {
+    padding: 40px 0;
+  }
+
+  &__top-part {
+    margin-bottom: 40px;
+    padding-bottom: 40px;
+    border-bottom: 1px solid #c4c4c4;
+  }
+
+  &__main {
+    display: flex;
+    flex-flow: column nowrap;
+    justify-content: space-between;
+  }
+
+  &__logo-container {
+    @extend %flex-row-center;
+
+    margin-bottom: 40px;
+
+    @media (max-width: $breakpoint-tablet) {
+      flex-direction: column;
+      align-items: flex-start;
+    }
+  }
+
+  &__mobile-app {
+    display: inline-block;
+
+    @media (max-width: $breakpoint-tablet) {
+      display: inline-block;
+      margin-bottom: 40px;
+    }
+
+    &:first-of-type {
+      margin-right: 48px;
+    }
+  }
+
+  &__logo {
+    margin-right: 40px;
+
+    @media (max-width: $breakpoint-tablet) {
+      margin-bottom: 40px;
+    }
+  }
+
+  &__top-part,
+  &__bottom-part {
+    @extend %flex-row-center;
+    align-items: flex-start;
+
+    @media (max-width: $breakpoint-phone-lg) {
+      flex-direction: column;
+    }
+  }
+
+  &__main,
+  &__copyright {
+    flex-basis: 45vw;
+    padding-right: 40px;
+
+    @media (max-width: $breakpoint-phone-lg) {
+      flex-basis: initial;
+    }
+  }
+
+  &__top-links:last-of-type {
+    margin-left: 10vw;
+
+    @media (max-width: $breakpoint-phone-lg) {
+      margin-left: 0;
+    }
+  }
+
+  &__copyright {
+    font-size: 14px;
+    color: #ffffff;
+
+    @media (max-width: $breakpoint-phone-lg) {
+      order: 1;
+    }
+  }
+
+  &__bottom-links {
+    @extend %flex-row-center;
+
+    margin-bottom: 40px;
+
+    @media (max-width: $breakpoint-phone-lg) {
+      flex-direction: column;
+      align-items: flex-start;
+      margin-top: 20px;
+      order: 1;
+    }
+
+    .links__link:not(:last-of-type) {
+      margin-right: 40px;
+    }
+  }
+
+  &__misc {
+    @media (max-width: $breakpoint-phone-lg) {
+      display: flex;
+      flex-direction: column;
+      margin-top: 20px;
+    }
+  }
+}
+
+.links {
+  &__link {
+    display: block;
+    margin-bottom: 16px;
+
+    color: #ffffff;
+    white-space: nowrap;
+
+    &:hover {
+      text-decoration: underline;
+    }
+
+    &--intended {
+      font-weight: 500;
+    }
+  }
+}
+
+.social__link {
+  margin-right: 20px;
+}
diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
index cf1bd64..da2cb84 100644
--- a/src/components/Header/Header.js
+++ b/src/components/Header/Header.js
@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-// import PropTypes from 'prop-types';
 import './Header.scss';
 import Input from '../Input/Input';
 
@@ -7,6 +6,8 @@ const Header = () => {
   const [address, setAddress] = useState('');
   const [time, setTime] = useState('');
   const [search, setSearch] = useState('');
+  const [isMobileSearchVisible, setMobileSearchVisible] = useState(false);
+  const [isMobileDeliveryVisible, setMobileDeliveryVisible] = useState(false);
 
   const handleInputChange = ({ target }) => {
     switch (target.name) {
@@ -23,11 +24,30 @@ const Header = () => {
     }
   };
 
+  const toggleSearch = () => {
+    setMobileSearchVisible(!isMobileSearchVisible);
+    setMobileDeliveryVisible(false);
+  };
+
+  const toggleDelivery = () => {
+    setMobileDeliveryVisible(!isMobileDeliveryVisible);
+    setMobileSearchVisible(false);
+  };
+
+  const closeMobile = () => {
+    setMobileDeliveryVisible(false);
+    setMobileSearchVisible(false);
+  };
+
   return (
     <header className="header">
       <div className="content">
         <div className="header__inner">
-          <img src="./images/logo.svg" alt="Uber Eats Logo" />
+          <img
+            className="header__logo"
+            src="./images/logo.svg"
+            alt="Uber Eats Logo"
+          />
           <div className="header__delivery-info">
             <Input
               name="address"
@@ -44,14 +64,38 @@ const Header = () => {
               type="time"
             />
           </div>
-          <Input
-            name="search"
-            value={search}
-            onChange={handleInputChange}
-            placeholder="Search"
-            iconUrl="./images/search.svg"
-            className="header__search"
-          />
+          <div className="header__search">
+            <Input
+              name="search"
+              value={search}
+              onChange={handleInputChange}
+              placeholder="Search"
+              iconUrl="./images/search.svg"
+            />
+          </div>
+
+          <div className="header__toggle-buttons">
+            <button
+              onClick={toggleDelivery}
+              type="button"
+              className="header__toggle-btn"
+            >
+              <img
+                src="./images/place.svg"
+                alt="location icon"
+              />
+            </button>
+            <button
+              onClick={toggleSearch}
+              type="button"
+              className="header__toggle-btn"
+            >
+              <img
+                src="./images/search.svg"
+                alt="search icon"
+              />
+            </button>
+          </div>
 
           <a
             className="header__link"
@@ -60,14 +104,59 @@ const Header = () => {
             Sign In
           </a>
         </div>
-      </div>
+        {(isMobileSearchVisible || isMobileDeliveryVisible) && (
+          <div className="header__mobile-controls mobile-controls">
+            {isMobileSearchVisible && (
+              <Input
+                label="Find"
+                name="search"
+                value={search}
+                onChange={handleInputChange}
+                placeholder="Search"
+                iconUrl="./images/search.svg"
+                isSmall={false}
+              />
+            )}
 
-    </header>
-  );
-};
+            {isMobileDeliveryVisible && (
+              <>
+                <Input
+                  label="When"
+                  name="time"
+                  value={time}
+                  onChange={handleInputChange}
+                  placeholder="Time"
+                  type="time"
+                  isSmall={false}
+                />
+                <Input
+                  label="To"
+                  name="address"
+                  value={address}
+                  onChange={handleInputChange}
+                  placeholder="Address"
+                  iconUrl="./images/place.svg"
+                  isSmall={false}
+                />
+              </>
+            )}
 
-Header.propTypes = {
+            <button
+              onClick={closeMobile}
+              type="button"
+              className="mobile-controls__close"
+            >
+              <img
+                src="./images/close.svg"
+                alt="close icon"
+              />
+            </button>
+          </div>
+        )}
 
+      </div>
+    </header>
+  );
 };
 
 export default Header;
diff --git a/src/components/Header/Header.scss b/src/components/Header/Header.scss
index 747c06b..dc39546 100644
--- a/src/components/Header/Header.scss
+++ b/src/components/Header/Header.scss
@@ -1,9 +1,10 @@
-@import "../../styles/extends.scss";
+@import "../../styles/utils.scss";
 
 .header {
   position: sticky;
   top: 0;
   padding: 16px 0;
+  z-index: 1;
 
   background-color: #ffffff;
 
@@ -11,14 +12,31 @@
     @extend %flex-row-center;
   }
 
+  &__logo {
+    height: 24px;
+    width: auto;
+
+    @media (max-width: $breakpoint-phone) {
+      height: 14px;
+    }
+  }
+
   &__delivery-info {
     @extend %flex-row-center;
 
     margin-left: 7vw;
+
+    @media (max-width: $breakpoint-tablet) {
+      display: none;
+    }
   }
 
   &__search {
     margin-left: auto;
+
+    @media (max-width: $breakpoint-tablet) {
+      display: none;
+    }
   }
 
   &__link {
@@ -31,4 +49,46 @@
       text-decoration: underline;
     }
   }
+
+  &__toggle-buttons {
+    display: none;
+    margin-left: auto;
+
+    @media (max-width: $breakpoint-tablet) {
+      display: flex;
+    }
+  }
+
+  &__toggle-btn {
+    display: flex;
+    align-items: center;
+    padding: 11px 5px;
+    cursor: pointer;
+    border: 1px solid transparent;
+
+    &:not(:last-of-type) {
+      margin-right: 20px;
+    }
+
+    &:focus {
+      border-color: $color-grey;
+    }
+  }
+}
+
+.mobile-controls {
+  display: none;
+  position: relative;
+  padding-top: 30px;
+
+  @media (max-width: $breakpoint-tablet) {
+    display: flex;
+  }
+
+  &__close {
+    position: absolute;
+    top: 10px;
+    right: 0;
+    cursor: pointer;
+  }
 }
diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js
index d29df04..b546be5 100644
--- a/src/components/Input/Input.js
+++ b/src/components/Input/Input.js
@@ -1,13 +1,12 @@
-import React, { useState, createRef, useCallback } from 'react';
+import React, { useState, useCallback } from 'react';
 import PropTypes from 'prop-types';
 import cn from 'classnames';
 import './Input.scss';
 
 const Input = ({
-  iconUrl, value, onChange, type, placeholder, name, className,
+  iconUrl, value, onChange, type, placeholder, name, className, isSmall, label,
 }) => {
   const [isFocused, setIsFocused] = useState(false);
-  const inputRef = createRef();
 
   const handleFocus = useCallback(
     () => {
@@ -21,41 +20,52 @@ const Input = ({
     }, [],
   );
 
-  const focusInput = () => {
-    inputRef.current.focus();
-  };
+  const inputWrapperClass = cn('control__input-wrapper', {
+    'control__input-wrapper--focused': isFocused,
+    [className]: !!className,
+  });
 
-  const rootClass = cn('control', {
-    'control--focused': isFocused,
+  const inputClass = cn('control__input', {
+    'control__input--small': isSmall,
+    'control__input--time': type === 'time',
     [className]: !!className,
   });
 
   return (
-    <div
-      className={rootClass}
-      onClick={focusInput}
-      role="presentation"
+    <label
+      htmlFor={name}
+      className="control"
     >
-      {!!iconUrl
-        && (
-          <img
-            src={iconUrl}
-            alt={placeholder}
-            className="control__icon"
-          />
-        )}
-      <input
-        ref={inputRef}
-        type={type}
-        value={value}
-        onChange={onChange}
-        onFocus={handleFocus}
-        onBlur={handleBlur}
-        name={name}
-        placeholder={placeholder}
-        className="control__input"
-      />
-    </div>
+      {label && (
+        <p className="control__label">
+          {label}
+        </p>
+      )}
+      <div
+        className={inputWrapperClass}
+      >
+        {!!iconUrl
+          && (
+            <img
+              src={iconUrl}
+              alt={placeholder}
+              className="control__icon"
+            />
+          )}
+        <input
+          type={type}
+          value={value}
+          onChange={onChange}
+          onFocus={handleFocus}
+          onBlur={handleBlur}
+          name={name}
+          id={name}
+          placeholder={placeholder}
+          className={inputClass}
+        />
+      </div>
+    </label>
+
   );
 };
 
@@ -67,6 +77,8 @@ Input.propTypes = {
   placeholder: PropTypes.string,
   name: PropTypes.string.isRequired,
   className: PropTypes.string,
+  label: PropTypes.string,
+  isSmall: PropTypes.bool,
 };
 
 Input.defaultProps = {
@@ -74,6 +86,8 @@ Input.defaultProps = {
   type: 'text',
   placeholder: '',
   className: '',
+  label: '',
+  isSmall: true,
 };
 
 export default Input;
diff --git a/src/components/Input/Input.scss b/src/components/Input/Input.scss
index 51f3e25..47aea4c 100644
--- a/src/components/Input/Input.scss
+++ b/src/components/Input/Input.scss
@@ -1,15 +1,16 @@
-@import "../../styles/extends.scss";
+@import "../../styles/utils.scss";
 
 .control {
-  $border-color: #e0e0e0;
-  @extend %flex-row-center;
+  &__input-wrapper {
+    @extend %flex-row-center;
 
-  padding: 11px 16px;
-  border: 1px solid $border-color;
-  border-radius: 2px;
+    padding: 11px 16px;
+    border: 1px solid $color-grey;
+    border-radius: 2px;
+  }
 
   &--focused {
-    border-color: darken($border-color, 20);
+    border-color: darken($color-grey, 20);
   }
 
   &__icon {
@@ -22,6 +23,23 @@
   &__input {
     max-height: 24px;
     line-height: 24px;
+
+    &--time {
+      max-width: 75px;
+    }
+
+    &--small {
+      @media (max-width: $breakpoint-tablet-lg) {
+        max-width: 76px;
+      }
+    }
+  }
+
+  &__label {
+    font-style: 14px;
+    color: #626262;
+
+    margin-bottom: 8px;
   }
 
   & + & {
diff --git a/src/components/Loader/Loader.js b/src/components/Loader/Loader.js
new file mode 100644
index 0000000..ecd8e35
--- /dev/null
+++ b/src/components/Loader/Loader.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import './Loader.scss';
+
+const Loader = () => (
+  <div className="loader-container">
+    <div className="lds-spinner">
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+      <div />
+    </div>
+  </div>
+);
+
+export default Loader;
diff --git a/src/components/Loader/Loader.scss b/src/components/Loader/Loader.scss
new file mode 100644
index 0000000..e42826e
--- /dev/null
+++ b/src/components/Loader/Loader.scss
@@ -0,0 +1,99 @@
+@import "../../styles/utils.scss";
+
+.loader-container {
+  @extend %absolute-center;
+}
+
+.lds-spinner {
+  color: official;
+  display: inline-block;
+  position: relative;
+  width: 80px;
+  height: 80px;
+}
+
+.lds-spinner div {
+  transform-origin: 40px 40px;
+  animation: lds-spinner 1.2s linear infinite;
+}
+
+.lds-spinner div:after {
+  content: " ";
+  display: block;
+  position: absolute;
+  top: 3px;
+  left: 37px;
+  width: 6px;
+  height: 18px;
+  border-radius: 20%;
+  background: rgb(163, 161, 161);
+}
+
+.lds-spinner div:nth-child(1) {
+  transform: rotate(0deg);
+  animation-delay: -1.1s;
+}
+
+.lds-spinner div:nth-child(2) {
+  transform: rotate(30deg);
+  animation-delay: -1s;
+}
+
+.lds-spinner div:nth-child(3) {
+  transform: rotate(60deg);
+  animation-delay: -0.9s;
+}
+
+.lds-spinner div:nth-child(4) {
+  transform: rotate(90deg);
+  animation-delay: -0.8s;
+}
+
+.lds-spinner div:nth-child(5) {
+  transform: rotate(120deg);
+  animation-delay: -0.7s;
+}
+
+.lds-spinner div:nth-child(6) {
+  transform: rotate(150deg);
+  animation-delay: -0.6s;
+}
+
+.lds-spinner div:nth-child(7) {
+  transform: rotate(180deg);
+  animation-delay: -0.5s;
+}
+
+.lds-spinner div:nth-child(8) {
+  transform: rotate(210deg);
+  animation-delay: -0.4s;
+}
+
+.lds-spinner div:nth-child(9) {
+  transform: rotate(240deg);
+  animation-delay: -0.3s;
+}
+
+.lds-spinner div:nth-child(10) {
+  transform: rotate(270deg);
+  animation-delay: -0.2s;
+}
+
+.lds-spinner div:nth-child(11) {
+  transform: rotate(300deg);
+  animation-delay: -0.1s;
+}
+
+.lds-spinner div:nth-child(12) {
+  transform: rotate(330deg);
+  animation-delay: 0s;
+}
+
+@keyframes lds-spinner {
+  0% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
diff --git a/src/components/Loader/index.js b/src/components/Loader/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/RestaurantCard/RestaurantCard.scss b/src/components/RestaurantCard/RestaurantCard.scss
index 8c2ff8e..2c18349 100644
--- a/src/components/RestaurantCard/RestaurantCard.scss
+++ b/src/components/RestaurantCard/RestaurantCard.scss
@@ -1,13 +1,19 @@
+@import "../../styles/utils.scss";
+
 .restaurant-card {
-  $height: 367px;
+  --height: 367px;
 
-  height: $height;
+  height: var(--height);
   width: 100%;
 
   cursor: pointer;
 
+  @media (max-width: $breakpoint-phone) {
+    --height: 330px;
+  }
+
   &__img {
-    height: $height * 0.76;
+    height: calc(var(--height) * 0.7);
     width: 100%;
 
     object-fit: cover;
@@ -19,6 +25,7 @@
 
   &__categories {
     font-style: 14px;
+    line-height: 1;
     color: #757575;
 
     margin-bottom: 8px;
diff --git a/src/components/RestaurantsListPage/RestaurantsListPage.js b/src/components/RestaurantsListPage/RestaurantsListPage.js
index 4352571..53cce6d 100644
--- a/src/components/RestaurantsListPage/RestaurantsListPage.js
+++ b/src/components/RestaurantsListPage/RestaurantsListPage.js
@@ -2,14 +2,29 @@ import React, { useEffect } from 'react';
 import PropTypes from 'prop-types';
 import RestaurantCard from '../RestaurantCard/RestaurantCard';
 import './RestaurantsListPage.scss';
+import Loader from '../Loader/Loader';
+import Error from '../Error/Error';
 
 const DEFAULT_ETA_RANGE = '20 - 30 min';
 
-const RestaurantsListPage = ({ loadRestaurants, restaurantsListData }) => {
+const RestaurantsListPage = ({
+  loadRestaurants,
+  restaurantsListData,
+  error,
+  isLoading,
+}) => {
   useEffect(() => {
     loadRestaurants();
   }, [loadRestaurants]);
 
+  if (isLoading) {
+    return <Loader />;
+  }
+
+  if (error) {
+    return <Error message={error} />;
+  }
+
   return (
     <div className="restaurants-list">
       {restaurantsListData.map((restaurant) => {
@@ -35,10 +50,14 @@ const RestaurantsListPage = ({ loadRestaurants, restaurantsListData }) => {
 RestaurantsListPage.propTypes = {
   restaurantsListData: PropTypes.arrayOf(PropTypes.shape()),
   loadRestaurants: PropTypes.func.isRequired,
+  error: PropTypes.string,
+  isLoading: PropTypes.bool,
 };
 
 RestaurantsListPage.defaultProps = {
   restaurantsListData: [],
+  error: null,
+  isLoading: false,
 };
 
 export default RestaurantsListPage;
diff --git a/src/components/RestaurantsListPage/RestaurantsListPage.scss b/src/components/RestaurantsListPage/RestaurantsListPage.scss
index a87ec4f..e31a078 100644
--- a/src/components/RestaurantsListPage/RestaurantsListPage.scss
+++ b/src/components/RestaurantsListPage/RestaurantsListPage.scss
@@ -1,5 +1,19 @@
+@import "../../styles/utils.scss";
+
 .restaurants-list {
+  --card-width: 348px;
+
   display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(348px, 1fr));
+  grid-template-columns: repeat(auto-fill, minmax(var(--card-width), 1fr));
   gap: 40px 20px;
+
+  @media (max-width: $breakpoint-tablet-lg) {
+    --card-width: 340px;
+
+    row-gap: 20px;
+  }
+
+  @media (max-width: $breakpoint-phone) {
+    --card-width: 280px;
+  }
 }
diff --git a/src/components/RestaurantsListPage/index.js b/src/components/RestaurantsListPage/index.js
index bf7f848..d274a5e 100644
--- a/src/components/RestaurantsListPage/index.js
+++ b/src/components/RestaurantsListPage/index.js
@@ -1,10 +1,16 @@
 import { connect } from 'react-redux';
 import RestaurantsListPage from './RestaurantsListPage';
 import { loadRestaurantsAction } from '../../store/actions';
-import { selectRestaurantsList } from '../../store/selectors';
+import {
+  selectRestaurantsList,
+  selectRestaurantsLoadError,
+  selectIsLoading,
+} from '../../store/selectors';
 
 const mapStateToProps = state => ({
   restaurantsListData: selectRestaurantsList(state),
+  error: selectRestaurantsLoadError(state),
+  isLoading: selectIsLoading(state),
 });
 
 const mapDispatchToProps = {
diff --git a/src/components/Select/Select.js b/src/components/Select/Select.js
new file mode 100644
index 0000000..928269c
--- /dev/null
+++ b/src/components/Select/Select.js
@@ -0,0 +1,55 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import './Select.scss';
+
+const Select = ({ name, value, onSelect, options, iconUrl }) => (
+  <div className="select">
+    <select
+      name={name}
+      defaultValue={value}
+      onChange={onSelect}
+      className="select__input"
+    >
+      {options.map(({ value: optionValue, label }) => (
+        <option
+          key={optionValue}
+          value={optionValue}
+        >
+          {label}
+        </option>
+
+      ))}
+    </select>
+    <img
+      className="select__icon"
+      src={iconUrl}
+      alt="select language"
+    />
+
+    <img
+      className="select__arrow"
+      src="./images/arrowDown.svg"
+      alt="arrow downselect language"
+    />
+  </div>
+
+);
+
+Select.propTypes = {
+  name: PropTypes.string.isRequired,
+  value: PropTypes.string.isRequired,
+  onSelect: PropTypes.func,
+  options: PropTypes.arrayOf(PropTypes.shape({
+    value: PropTypes.string,
+    label: PropTypes.string,
+  })),
+  iconUrl: PropTypes.string,
+};
+
+Select.defaultProps = {
+  onSelect: () => { },
+  options: [],
+  iconUrl: '',
+};
+
+export default Select;
diff --git a/src/components/Select/Select.scss b/src/components/Select/Select.scss
new file mode 100644
index 0000000..0a64911
--- /dev/null
+++ b/src/components/Select/Select.scss
@@ -0,0 +1,34 @@
+.select {
+  position: relative;
+
+  &__input {
+    -moz-appearance: none;
+    -webkit-appearance: none;
+
+    padding: 10px 40px;
+
+    color: #ffffff;
+    background-color: transparent;
+    border: 1px solid #979797;
+
+    cursor: pointer;
+  }
+
+  &__icon {
+    position: absolute;
+    top: 12px;
+    left: 10px;
+
+    width: 20px;
+    height: 20px;
+  }
+
+  &__arrow {
+    position: absolute;
+    top: 20px;
+    right: 10px;
+
+    width: 14px;
+    height: 8px;
+  }
+}
diff --git a/src/components/Select/index.js b/src/components/Select/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/store/actions.js b/src/store/actions.js
index 6893cc9..48a15ae 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -1,5 +1,8 @@
 export const ACTION_TYPES = {
   SAVE_RESTAURANTS: 'SAVE_RESTAURANTS',
+  START_LOADING: 'START_LOADING',
+  FINISH_LOADING: 'FINISH_LOADING',
+  SET_LOAD_RESTAURANTS_ERROR: 'SET_LOAD_RESTAURANTS_ERROR',
 };
 
 const saveRestaurants = data => ({
@@ -7,10 +10,27 @@ const saveRestaurants = data => ({
   payload: data,
 });
 
+const startLoading = () => ({
+  type: ACTION_TYPES.START_LOADING,
+});
+
+const finishLoading = () => ({
+  type: ACTION_TYPES.FINISH_LOADING,
+});
+
+const setRestaurantsLoadError = error => ({
+  type: ACTION_TYPES.SET_LOAD_RESTAURANTS_ERROR,
+  payload: error,
+});
+
 const URL = 'https://mate-uber-eats-api.herokuapp.com/api/v1/restaurants';
 
 export const loadRestaurantsAction = () => (dispatch) => {
+  dispatch(startLoading());
+
   fetch(URL)
     .then(response => response.json())
-    .then(data => dispatch(saveRestaurants(data.data)));
+    .then(data => dispatch(saveRestaurants(data.data)))
+    .catch(error => dispatch(setRestaurantsLoadError(error.message)))
+    .finally(() => dispatch(finishLoading()));
 };
diff --git a/src/store/index.js b/src/store/index.js
index 5cb5092..8cbd8dc 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,28 +1,11 @@
 import { createStore, compose, applyMiddleware } from 'redux';
 import thunk from 'redux-thunk';
-import { ACTION_TYPES } from './actions';
+import { rootReducer } from './rootReducer';
 
 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,
+  rootReducer,
   composeEnhancers(applyMiddleware(...middlewares))
 );
diff --git a/src/store/rootReducer.js b/src/store/rootReducer.js
new file mode 100644
index 0000000..11955a7
--- /dev/null
+++ b/src/store/rootReducer.js
@@ -0,0 +1,36 @@
+import { ACTION_TYPES } from './actions';
+
+const initialState = {
+  restaurantsListData: null,
+  isLoading: false,
+  error: null,
+};
+
+export const rootReducer = (state = initialState, action) => {
+  switch (action.type) {
+    case ACTION_TYPES.SAVE_RESTAURANTS:
+      return {
+        ...state,
+        error: null,
+        restaurantsListData: action.payload,
+      };
+    case ACTION_TYPES.SET_LOAD_RESTAURANTS_ERROR:
+      return {
+        ...state,
+        error: action.payload,
+        restaurantsListData: null,
+      };
+    case ACTION_TYPES.START_LOADING:
+      return {
+        ...state,
+        isLoading: true,
+      };
+    case ACTION_TYPES.FINISH_LOADING:
+      return {
+        ...state,
+        isLoading: false,
+      };
+    default:
+      return state;
+  }
+};
diff --git a/src/store/selectors.js b/src/store/selectors.js
index 050aeb1..5fed4d9 100644
--- a/src/store/selectors.js
+++ b/src/store/selectors.js
@@ -14,3 +14,13 @@ export const selectRestaurantsList = createSelector(
     return feedItems.map(({ uuid }) => storesMap[uuid]);
   }
 );
+
+export const selectRestaurantsLoadError = createSelector(
+  rootSelector,
+  ({ error }) => error
+);
+
+export const selectIsLoading = createSelector(
+  rootSelector,
+  ({ isLoading }) => isLoading
+);
diff --git a/src/styles/extends.scss b/src/styles/extends.scss
index db10f11..cc57eef 100644
--- a/src/styles/extends.scss
+++ b/src/styles/extends.scss
@@ -3,3 +3,15 @@
   flex-flow: row nowrap;
   align-items: center;
 }
+
+%absolute-center{
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
diff --git a/src/styles/index.scss b/src/styles/index.scss
index c4e191b..a72d30e 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -1,3 +1,5 @@
+@import "./utils.scss";
+
 *,
 ::after,
 ::before {
@@ -7,6 +9,7 @@
 body,
 button,
 a,
+select,
 input {
   font-family: Roboto, sans-serif;
   font-size: 16px;
@@ -23,8 +26,22 @@ a {
   text-decoration: none;
 }
 
+button {
+  border: none;
+  background: none;
+  outline: none;
+}
+
 .content {
   max-width: 1160px;
   padding: 0 34px;
   margin: 0 auto;
+
+  @media (max-width: $breakpoint-phone) {
+    padding: 0 20px;
+  }
+
+  @media (min-width: $breakpoint-large) {
+    max-width: 1520px;
+  }
 }
diff --git a/src/styles/utils.scss b/src/styles/utils.scss
new file mode 100644
index 0000000..8e9efb3
--- /dev/null
+++ b/src/styles/utils.scss
@@ -0,0 +1,2 @@
+@import "./variables.scss";
+@import "./extends.scss";
diff --git a/src/styles/variables.scss b/src/styles/variables.scss
new file mode 100644
index 0000000..73d4b18
--- /dev/null
+++ b/src/styles/variables.scss
@@ -0,0 +1,8 @@
+$color-green: #5eb707;
+$color-grey: #e0e0e0;
+
+$breakpoint-large: 1281px;
+$breakpoint-tablet-lg: 956px;
+$breakpoint-tablet: 768px;
+$breakpoint-phone: 550px;
+$breakpoint-phone-lg: 620px;
