Browse Source

sixth lesson: routing && spa

Ivan Asmer 3 years ago
parent
commit
db9cf5bd58
4 changed files with 253 additions and 199 deletions
  1. 96 0
      package-lock.json
  2. 1 0
      package.json
  3. 85 199
      src/App.js
  4. 71 0
      src/App.scss

+ 96 - 0
package-lock.json

@@ -7278,6 +7278,19 @@
       "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
       "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
     },
+    "history": {
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
+      "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "loose-envify": "^1.2.0",
+        "resolve-pathname": "^3.0.0",
+        "tiny-invariant": "^1.0.2",
+        "tiny-warning": "^1.0.0",
+        "value-equal": "^1.0.1"
+      }
+    },
     "hmac-drbg": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -7288,6 +7301,14 @@
         "minimalistic-crypto-utils": "^1.0.1"
       }
     },
+    "hoist-non-react-statics": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+      "requires": {
+        "react-is": "^16.7.0"
+      }
+    },
     "hoopy": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -10307,6 +10328,15 @@
       "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
       "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
     },
+    "mini-create-react-context": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
+      "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
+      "requires": {
+        "@babel/runtime": "^7.12.1",
+        "tiny-warning": "^1.0.3"
+      }
+    },
     "mini-css-extract-plugin": {
       "version": "0.11.3",
       "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz",
@@ -12900,6 +12930,52 @@
       "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
       "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
     },
+    "react-router": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
+      "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "history": "^4.9.0",
+        "hoist-non-react-statics": "^3.1.0",
+        "loose-envify": "^1.3.1",
+        "mini-create-react-context": "^0.4.0",
+        "path-to-regexp": "^1.7.0",
+        "prop-types": "^15.6.2",
+        "react-is": "^16.6.0",
+        "tiny-invariant": "^1.0.2",
+        "tiny-warning": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+        },
+        "path-to-regexp": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+          "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+          "requires": {
+            "isarray": "0.0.1"
+          }
+        }
+      }
+    },
+    "react-router-dom": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
+      "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "history": "^4.9.0",
+        "loose-envify": "^1.3.1",
+        "prop-types": "^15.6.2",
+        "react-router": "5.2.0",
+        "tiny-invariant": "^1.0.2",
+        "tiny-warning": "^1.0.0"
+      }
+    },
     "react-scripts": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",
@@ -13344,6 +13420,11 @@
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
     },
+    "resolve-pathname": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
+      "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
+    },
     "resolve-url": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -15175,6 +15256,16 @@
       "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
     },
+    "tiny-invariant": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
+      "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
+    },
+    "tiny-warning": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+      "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+    },
     "tmpl": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -15661,6 +15752,11 @@
         "spdx-expression-parse": "^3.0.0"
       }
     },
+    "value-equal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
+      "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
+    },
     "vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "node-sass": "^5.0.0",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
+    "react-router-dom": "^5.2.0",
     "react-scripts": "4.0.3",
     "web-vitals": "^1.1.1"
   },

+ 85 - 199
src/App.js

@@ -1,215 +1,101 @@
 import {useState} from 'react';
 import logo from './logo.svg';
 import './App.scss';
+import {BrowserRouter as Router, Route, Link} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
 
-const addresses = [
-        {
-          "Warehouses": 100500,
-          "MainDescription": "СУПЕРКиїв",
-          "Area": "",
-          "Region": "Київська",
-          "SettlementTypeCode": "м.",
-          "Ref": "e718a680-4b33-11e4-ab6d-005056801329",
-          "DeliveryCity": "8d5a980d-391c-11dd-90d9-001a92567626"
-        },
-        {
-          "Warehouses": 568,
-          "MainDescription": "Київ",
-          "Area": "",
-          "Region": "Київська",
-          "SettlementTypeCode": "м.",
-          "Ref": "e718a680-4b33-11e4-ab6d-005056801329",
-          "DeliveryCity": "8d5a980d-391c-11dd-90d9-001a92567626"
-        },
-        {
-          "Warehouses": 0,
-          "MainDescription": "Київ",
-          "Area": "Миколаївська",
-          "Region": "Доманівський",
-          "SettlementTypeCode": "с.",
-          "Ref": "0db2df4b-4b3a-11e4-ab6d-005056801329",
-          "DeliveryCity": "06f8795a-4079-11de-b509-001d92f78698"
-        },
-        {
-          "Warehouses": 0,
-          "MainDescription": "Київець",
-          "Area": "Львівська",
-          "Region": "Миколаївський",
-          "SettlementTypeCode": "с.",
-          "Ref": "0df25497-4b3a-11e4-ab6d-005056801329",
-          "DeliveryCity": "acecfca8-1488-11df-8caf-000c2965ae0e"
-        },
-        {
-          "Warehouses": 0,
-          "MainDescription": "Київка",
-          "Area": "Херсонська",
-          "Region": "Голопристанський",
-          "SettlementTypeCode": "с.",
-          "Ref": "0dd153b3-4b3a-11e4-ab6d-005056801329",
-          "DeliveryCity": "db5c88e7-391c-11dd-90d9-001a92567626"
-        },
-        {
-          "Warehouses": 0,
-          "MainDescription": "Київське",
-          "Area": "Запорізька",
-          "Region": "Новомиколаївський",
-          "SettlementTypeCode": "с.",
-          "Ref": "0e40bf5a-4b3a-11e4-ab6d-005056801329",
-          "DeliveryCity": "cfbeaca4-4063-11de-b509-001d92f78698"
-        },
-        {
-          "Warehouses": 0,
-          "MainDescription": "Київське",
-          "Area": "Миколаївська",
-          "Region": "Баштанський",
-          "SettlementTypeCode": "с.",
-          "Ref": "0d94f546-4b3a-11e4-ab6d-005056801329",
-          "DeliveryCity": "000655dc-4079-11de-b509-001d92f78698"
-        }
-      ]
+const Logo = () =>
+<img src={logo} className="Logo"/>
 
-const Address = ({Warehouses=0, MainDescription, Area, Region}) =>
-<div>
-    <span className='MainDescription'>{MainDescription}</span>
-    <span className='Area'>{Area}</span>
-    <span className='Region'>{Region}</span>
-    {!!Warehouses && <span className='Warehouses'>{Warehouses}</span>}
-</div>
-
-const tags = [
-    <Address Warehouses="1" Area="Харковская" Region="Мерефянский" MainDescription="Test"/>,
-    <div>
-        МОЙ ДИВ
-    </div>,
-    <input />
+const defaultMenuItems = [
+    {title: 'Home', to: '/'},
+    {title: 'About', to: '/about'},
+    {title: 'Login', to: '/login'},
+    {title: 'Logout', to: '/logout'},
+    {title: '2 + 2', to: '/add/2/2'},
+    {title: '20 + 200', to: '/add/20/200'},
 ]
 
-const episodes =[
-        {
-          "name": "Pilot",
-          "air_date": "December 2, 2013",
-          "created": "2017-11-10T12:56:33.798Z"
-        },
-        {
-          "name": "Lawnmower Dog",
-          "air_date": "December 9, 2013",
-          "created": "2017-11-10T12:56:33.916Z"
-        },
-        {
-          "name": "Anatomy Park",
-          "air_date": "December 16, 2013",
-          "created": "2017-11-10T12:56:34.022Z"
-        },
-        {
-          "name": "M. Night Shaym-Aliens!",
-          "air_date": "January 13, 2014",
-          "created": "2017-11-10T12:56:34.129Z"
-        },
-        {
-          "name": "Meeseeks and Destroy",
-          "air_date": "January 20, 2014",
-          "created": "2017-11-10T12:56:34.236Z"
-        },
-        {
-          "name": "Rick Potion #9",
-          "air_date": "January 27, 2014",
-          "created": "2017-11-10T12:56:34.339Z"
-        },
-        {
-          "name": "Raising Gazorpazorp",
-          "air_date": "March 10, 2014",
-          "created": "2017-11-10T12:56:34.441Z"
-        },
-        {
-          "name": "Rixty Minutes",
-          "air_date": "March 17, 2014",
-          "created": "2017-11-10T12:56:34.543Z"
-        },
-        {
-          "name": "Something Ricked This Way Comes",
-          "air_date": "March 24, 2014",
-          "created": "2017-11-10T12:56:34.645Z"
-        },
-        {
-          "name": "Close Rick-counters of the Rick Kind",
-          "air_date": "April 7, 2014",
-          "created": "2017-11-10T12:56:34.747Z"
-        },
-        {
-          "name": "Ricksy Business",
-          "air_date": "April 14, 2014",
-          "created": "2017-11-10T12:56:34.850Z"
-        },
-        {
-          "name": "A Rickle in Time",
-          "air_date": "July 26, 2015",
-          "created": "2017-11-10T12:56:34.953Z"
-        },
-        {
-          "name": "Mortynight Run",
-          "air_date": "August 2, 2015",
-          "created": "2017-11-10T12:56:35.055Z"
-        },
-        {
-          "name": "Auto Erotic Assimilation",
-          "air_date": "August 9, 2015",
-          "created": "2017-11-10T12:56:35.158Z"
-        },
-        {
-          "name": "Total Rickall",
-          "air_date": "August 16, 2015",
-          "created": "2017-11-10T12:56:35.261Z"
-        },
-        {
-          "name": "Get Schwifty",
-          "air_date": "August 23, 2015",
-          "created": "2017-11-10T12:56:35.364Z"
-        },
-        {
-          "name": "The Ricks Must Be Crazy",
-          "air_date": "August 30, 2015",
-          "created": "2017-11-10T12:56:35.467Z"
-        },
-        {
-          "name": "Big Trouble in Little Sanchez",
-          "air_date": "September 13, 2015",
-          "created": "2017-11-10T12:56:35.569Z"
-        },
-        {
-          "name": "Interdimensional Cable 2: Tempting Fate",
-          "air_date": "September 20, 2015",
-          "created": "2017-11-10T12:56:35.669Z"
-        },
-        {
-          "name": "Look Who's Purging Now",
-          "air_date": "September 27, 2015",
-          "created": "2017-11-10T12:56:35.772Z"
-        }
-      ] 
+const MenuItem = ({title, to}) => 
+<li>
+    <Link to={to}>{title}</Link>
+</li>
+
+const Menu = ({menuItems=defaultMenuItems}) =>
+<nav>
+    <ul>
+        {menuItems.map(item => <MenuItem {...item} />)}
+    </ul>
+</nav>
+
+const Header = () =>
+<header>
+    <Logo />
+    <Menu />
+</header>
+
+const Footer = () =>
+<footer>
+    <Logo />
+    <Route path='/' exact> 
+        вариация футера на главной
+    </Route>
+</footer>
 
-const Episode = ({name, air_date, created}) => 
-<div>
-    <h3>{name}</h3>
-    <span className='air_date'>{air_date}</span>
-    <span className='created'>{created}</span>
+const Login = () => {
+    const [login, setLogin]       = useState('')
+    const [password, setPassword] = useState('')
+    return (
+        <div className="Login">
+            <input type='text' 
+                   onChange={e => setLogin(e.target.value)} 
+                   value={login} /> 
+            <input type='password' 
+                   onChange={e => setPassword(e.target.value)} 
+                   value={password} />
+            <button disabled={!login || !password}>Login...</button>
+        </div>
+    )
+}
+
+const Home   = () =>
+<div className="Home">
+    <h1>
+        Главная нашего супер-пупер сайта
+    </h1>
+</div>
+
+const About   = () =>
+<div className="About">
+    <h1>
+        О нас
+    </h1>
+    <p>
+        тили тили трали вали
+        <img src={logo}/>
+    </p>
 </div>
 
-const KyivAddress = addresses[0]
 
-console.log(KyivAddress,addresses.length)
+const Add = ({match:{params: {a,b}}}) =>
+<pre>
+    {a} + {b} = {+a + +b}
+</pre>
+
+const Main = () =>
+<main>
+    <Route path='/' component={Home} exact/>
+    <Route path='/about' component={About} exact/>
+    <Route path='/login' component={Login} exact/>
+    <Route path='/add/:a/:b' component={Add} exact/>
+</main>
 
 
 const App = () => 
-<>
-    {/* {tags}
-    <Address Warehouses="1" Area="Харковская" Region="Мерефянский" MainDescription="Test"/>
-    <Address Warehouses={KyivAddress.Warehouses}
-             Area={KyivAddress.Area}
-             Region={KyivAddress.Region}
-             MainDescription={KyivAddress.MainDescription}/>
-    <Address {...KyivAddress}/> */ }
-{/* {addresses.map(address => <Address {...address} />)} */ }
-    {episodes.map(episode => <Episode {...episode} />)}
-</>
+<Router history={createHistory()}>
+    <Header />
+    <Main />
+    <Footer />
+</Router>
 
 export default App;

+ 71 - 0
src/App.scss

@@ -0,0 +1,71 @@
+.Logo {
+    max-width: 100px;
+}
+
+header {
+        display: flex;
+
+        nav {
+            ul {
+                display: flex;
+                justify-content: space-between;
+                width: 100%;
+                li {
+                    list-style-type: none;
+                }
+            }
+        }
+}
+
+
+h2 {
+    color: blue;
+}
+
+//button {
+    //font-size: 5em;
+//}
+
+main {
+    aside {
+
+    }
+    content {
+
+    }
+}
+
+.Good {
+    h2 {
+        text-decoration: underline;
+    }
+    img {
+        max-width: 50%;
+    }
+    p {
+        font-size: 9em;
+    }
+}
+
+.RecentlySeen {
+    display: flex;
+
+    .Good {
+        h2 {
+            color: red;
+        }
+    }
+
+}
+
+.Avatar {
+    max-width: 10%;
+}
+
+footer {
+    background-color: #444;
+    min-height: 150px;
+    color: white;
+    display: flex;
+    align-items: center;
+}