RomanR 4 yıl önce
ebeveyn
işleme
948ce4d579

+ 134 - 0
my-project/package-lock.json

@@ -6496,6 +6496,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",
@@ -7980,6 +7993,11 @@
         "object.assign": "^4.1.0"
       }
     },
+    "jwt-decode": {
+      "version": "3.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.0.0-beta.2.tgz",
+      "integrity": "sha512-AnENY5syz7PzgpTzos9sxkqKTmHU0JeJOXZFHUc41bDyybC2yzZ+1r43ZLhk7+JCwF0yjISPuVK9ZWfA1nCUPA=="
+    },
     "killable": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -8419,6 +8437,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.0",
+      "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
+      "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "tiny-warning": "^1.0.3"
+      }
+    },
     "mini-css-extract-plugin": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
@@ -11494,6 +11521,64 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
       "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
     },
+    "react-redux": {
+      "version": "7.2.1",
+      "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.1.tgz",
+      "integrity": "sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "hoist-non-react-statics": "^3.3.0",
+        "loose-envify": "^1.4.0",
+        "prop-types": "^15.7.2",
+        "react-is": "^16.9.0"
+      }
+    },
+    "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": "3.4.3",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.3.tgz",
@@ -11616,6 +11701,25 @@
         "strip-indent": "^3.0.0"
       }
     },
+    "redux": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz",
+      "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==",
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "symbol-observable": "^1.2.0"
+      }
+    },
+    "redux-devtools-extension": {
+      "version": "2.13.8",
+      "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz",
+      "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg=="
+    },
+    "redux-thunk": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
+      "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
+    },
     "regenerate": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
@@ -11881,6 +11985,11 @@
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
       "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
     },
+    "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",
@@ -13159,6 +13268,11 @@
         "util.promisify": "~1.0.0"
       }
     },
+    "symbol-observable": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+      "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+    },
     "symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -13397,6 +13511,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=="
+    },
     "tinycolor2": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
@@ -13798,6 +13922,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",
@@ -13823,6 +13952,11 @@
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
       "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
     },
+    "vuex": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
+      "integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw=="
+    },
     "w3c-hr-time": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",

+ 9 - 1
my-project/package.json

@@ -2,15 +2,23 @@
   "name": "my-project",
   "version": "0.1.0",
   "private": true,
+  "proxy": "http://player.asmer.fs.a-level.com.ua/",
   "dependencies": {
     "@ant-design/icons": "^4.2.2",
     "@testing-library/jest-dom": "^4.2.4",
     "@testing-library/react": "^9.5.0",
     "@testing-library/user-event": "^7.2.1",
     "antd": "^4.6.4",
+    "jwt-decode": "^3.0.0-beta.2",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
-    "react-scripts": "3.4.3"
+    "react-redux": "^7.2.1",
+    "react-router-dom": "^5.2.0",
+    "react-scripts": "3.4.3",
+    "redux": "^4.0.5",
+    "redux-devtools-extension": "^2.13.8",
+    "redux-thunk": "^2.3.0",
+    "vuex": "^3.5.1"
   },
   "scripts": {
     "start": "react-scripts start",

+ 55 - 18
my-project/src/App.js

@@ -1,35 +1,72 @@
 // import React from "react";
-import RegisterForm from "./components/RegisterForm";
-import React, { useState } from "react";
-// import Registration from "./components/Reg";
-// import LoginForm from  "./components/Reg";
+import React from "react";
+// import React, { useState } from "react";
+// import LoginForm from "./components/Reg";
+import { BrowserRouter as Router, Route } from 'react-router-dom';
+import createHistory from 'history/createBrowserHistory';
+
+import {Provider, connect}   from 'react-redux';
+
+////////////////////////////////////////////
+import thunk from 'redux-thunk';
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import myReducers from "./components/reducers";
+import actionCreators from "./components/actionCreators";
 
+/////////////////////////////////////////////////////////////////////
+
+import "./styles/Reset.css";
 import "./styles/App.css";
 
+import RegisterForm from "./components/RegisterForm";
+// import AboutPage from "./components/AboutPage";
+import  LoginForm from "./components/LoginForm";
+import library from "./components/library";
 
 
+const history = createHistory()
+// const Header = () => {
+//   return (
+//     <div>
+//       <ul class = "main-menu">
+//         <li>gRomkoPlayer</li>
+//         <li>Библиотека</li>
+//         <li>Плайлист</li>
+//         <li>Вход/Регистрация</li>
+//       </ul>
+//     </div>
+//   );
+// }
 
-const Header = () => {
-  return (
-    <div>
-      <ul class = "main-menu">
-        <li>gRomkoPlayer</li>
-        <li>Библиотека</li>
-        <li>Плайлист</li>
-        <li>Вход/Регистрация</li>
-      </ul>
-    </div>
-  );
-}
+// const store = createStore(msgStatusReducer, applyMiddleware(thunk)) //вторым параметром идет
+const store = createStore(myReducers, applyMiddleware(thunk)) //вторым параметром идет
 
+store.subscribe(() => console.log(store.getState()))
 
 function App() {
   return (
     <div className="App">
-      <Header/>
-      <RegisterForm />
+      {/* <Header/> */}
+      {/* <RegisterForm /> */}
+      <Router history={history}> 
+        <Provider store={store}>
+      {console.log(history)}    
+            <Route exact path="/" component={RegisterForm} />        
+            <Route exact path="/login" component={LoginForm} />     
+            <Route exact path="/library" component={library} /> 
+          </Provider>     
+      </Router>    
     </div>
   );
 }
 
+// const App = () => {
+//   return (
+      // <Router>        
+      //  <Route path="/" component={RegisterForm} />        
+      //  <Route path="/about" component={AboutPage} />      
+      // </Router>    
+//   );
+// };
+
 export default App;

+ 10 - 0
my-project/src/components/AboutPage.js

@@ -0,0 +1,10 @@
+import React from "react";
+
+
+const AboutPage = () => {
+  return (
+      <div>Hello!</div>
+  );
+};
+
+export default AboutPage;

+ 193 - 0
my-project/src/components/LoginForm.js

@@ -0,0 +1,193 @@
+import React, { useState } from "react";
+import { Form, Input, Button, Checkbox } from "antd";
+import { UserOutlined, LockOutlined } from "@ant-design/icons";
+import { Link } from "react-router-dom";
+//////////////////////////////////
+import jwt_decode from "jwt-decode";
+// import store from './vuex/store';
+import thunk from 'redux-thunk';
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+/////////////////////////////////
+import "../styles/RegisterForm.css";
+
+
+// import { BrowserRouter as Router, Route } from 'react-router-dom';
+// import createHistory from 'history/createBrowserHistory';
+
+
+
+// const history = createHistory()
+
+const getGQL = (url, headers = {}) => (query = "", variables = {}) =>
+fetch(url, {
+  method: "POST",
+  headers: {
+    Accept: "application/json",
+    "Content-Type": "application/json",
+    ...headers,
+  },
+  body: JSON.stringify({ query, variables }),
+}).then((res) => res.json());
+let gql = getGQL("/graphql");
+
+//////////////////////////////////////////////////////////////
+// const store = createStore(applyMiddleware(thunk)) //вторым параметром идет миддлварь
+
+
+
+const LoginForm = ({store, history}) => {
+  const [form] = Form.useForm();
+  const [login, setLogin] = useState("");
+  const [password, setPassword] = useState("");
+
+
+
+
+
+
+
+  const onFinish = (values) => {
+    console.log("Success:", values);
+  };
+
+  const onFinishFailed = (errorInfo) => {
+    console.log("Failed:", errorInfo);
+  };
+
+  let p = getGQL('http://player.asmer.fs.a-level.com.ua/graphql')(
+    `query Login{
+    login(login: "${login}", password: "${password}")
+    }`
+  ).then((data) => 
+    console.log(data)
+)
+
+
+
+
+// store.dispatch(actionPending())
+// p.then(data => store.dispatch(actionResolved(data)))
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+  return (
+    <div className="registerForm">
+      {/* <div className="wrapperRegisterForm"> */}
+      <div>
+        <Form
+          name="basic"
+          form={form}
+          // initialValues={{
+          //   remember: true,
+          // }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+        >
+          <Form.Item
+            label="Username"
+            name="username"
+            value={login}
+            onChange={(e) => setLogin(e.target.value)}
+            rules={[
+              {
+                required: true,
+                message: "Please input your username!",
+              },
+            ]}
+          >
+            <Input
+              prefix={<UserOutlined className="site-form-item-icon" />}
+              onChange={(e) => {
+                console.log(e.target.value);
+                form.setFieldsValue({ username: e.target.value });
+              }}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label="Password"
+            name="password"
+            value={password}
+            onChange={(e) => setPassword(e.target.value)}
+            rules={[
+              {
+                required: true,
+                message: "Please input your password!",
+              },
+            ]}
+          >
+            <Input.Password
+              prefix={<LockOutlined className="site-form-item-icon" />}
+            />
+          </Form.Item>
+          {/* 
+        <Form.Item name="remember" valuePropName="checked">
+          <Checkbox>Remember me</Checkbox>
+        </Form.Item> */}
+
+          <Form.Item>
+            <Button
+              type="primary"
+              htmlType="submit"
+              onClick={async () => {
+                await getGQL("/graphql")(
+                  `query Login{
+                  login(login: "${login}", password: "${password}")
+                  }`
+                ).then((data) => {
+                  console.log(data);
+                  // console.log(data.data.login);
+                  localStorage.authToken = data.data.login;
+                  // const originalFetch = fetch;
+                  // fetch = (url, params = { headers: {} }) => {
+                  //   params.headers.Authorization =
+                  //     "Bearer " + localStorage.authToken;
+                  //   return originalFetch(url, params);
+                  // };
+                  // console.log(fetch)
+                  console.log(
+                    "localStorage.authToken: " + localStorage.authToken
+                  );
+                  if (!data.errors && login !=="" && password !== "") {
+                    history.push("/library");
+                    // window.location.assign("http://localhost:3000/library");
+                  } else {
+                    //   setError(() => true);// если поле не заполнено, то формируем ошибку
+                  }
+                });
+              }
+            }
+            >
+              Submit
+            </Button>
+            <Link to="/">Registration</Link>
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  );
+};
+
+export default LoginForm;
+
+
+// if(type == 'PROMISE') {
+//   {
+//     status PENDING ||
+//           FULFILED ||
+//           REJECTED
+//   }
+// }
+// action PENDING = () => (
+//   {type: 'promise', status: 'PENDING', payload: 'null', error: 'null'}
+// )
+// action FULFILED =() => (
+//   {type: 'SET_STATUS', status: 'RESOLVED', payload, error: null }
+// )
+// action REJECTED =() => (
+//   {type: 'SET_STATUS', status: 'REJECTED', payload: null, error}
+// )
+
+

+ 55 - 0
my-project/src/components/Reg.js

@@ -0,0 +1,55 @@
+import React, { useState, useEffect } from "react";
+
+
+// export default () => {
+
+  const LoginForm = ({ onLogin }) => {
+    const [login, setLogin] = useState("admin");
+    const [password, setPassword] = useState("123");
+    // {
+    //   console.log({ onLogin });
+    //   console.log({ props });
+    // }
+    return (
+      <div class="login">
+        <h1>{login}</h1>
+        <label htmlFor="login">Login: </label>
+        <input
+          id="login"
+          type="text"
+          value={login}
+          onChange={(e) => setLogin(e.target.value)}
+          style={{ backgroundColor: login.length <= 2 ? "#FAA" : "" }}
+        />
+        <label htmlFor="password">Password: </label>
+        <input
+          id="password"
+          type="password"
+          value={password}
+          onChange={(e) => setPassword(e.target.value)}
+        />
+        <button
+          disabled={login.length < 1 || password.length < 1}
+          onClick={() => onLogin(login, password)}
+        >
+          Submit
+        </button>
+      </div>
+    );
+  };
+// };
+export default LoginForm;
+// function App() {
+//   return (
+//     <div className="App">
+//       <header className="App-header">
+//         <img src={logo} className="App-logo" alt="logo" />
+//         <Registration />
+//         <LoginForm onLogin={(l, p) => console.log(l, p)} />
+
+//       </header>
+//     </div>
+//   );
+// }
+
+// export default App;

+ 126 - 51
my-project/src/components/RegisterForm.js

@@ -1,74 +1,149 @@
-import React from "react";
+import React, { useState } from "react";
 import { Form, Input, Button, Checkbox } from "antd";
 import { UserOutlined, LockOutlined } from "@ant-design/icons";
+import { Link } from 'react-router-dom';
+
+// import { BrowserRouter as Router, Route } from 'react-router-dom';
+// import createHistory from 'history/createBrowserHistory';
+
 
 import "../styles/RegisterForm.css";
 
-export default () => {
+// const history = createHistory()
+
+
+export default ({store, history}) => {
   const [form] = Form.useForm();
+  const [login, setLogin] = useState("");
+  const [password, setPassword] = useState("");
+  const [confPassword, setConfPassword] = useState("");
 
   const onFinish = (values) => {
-    console.log("Success:", values);
+    // console.log("Success:", values);
   };
 
   const onFinishFailed = (errorInfo) => {
-    console.log("Failed:", errorInfo);
+    // console.log("Failed:", errorInfo);
   };
 
+  const getGQL = (url, headers = {}) => (query = "", variables = {}) =>
+  fetch(url, {
+    method: "POST",
+    headers: {
+      Accept: "application/json",
+      "Content-Type": "application/json",
+      ...headers,
+    },
+    body: JSON.stringify({ query, variables }),
+  }).then((res) => res.json());
+let gql = getGQL("/graphql");
+
   return (
     <div className="registerForm">
-      <Form
-        name="basic"
-        form={form}
-        initialValues={{
-          remember: true,
-        }}
-        onFinish={onFinish}
-        onFinishFailed={onFinishFailed}
-      >
-        <Form.Item
-          label="Username"
-          name="username"
-          rules={[
-            {
-              required: true,
-              message: "Please input your username!",
-            },
-          ]}
-        >
-          <Input
-            prefix={<UserOutlined className="site-form-item-icon" />}
-            onChange={(e) => {
-                console.log(e.target.value)
-                form.setFieldsValue({ username: e.target.value })}}
-          />
-        </Form.Item>
-
-        <Form.Item
-          label="Password"
-          name="password"
-          rules={[
-            {
-              required: true,
-              message: "Please input your password!",
-            },
-          ]}
+      {/* <div className="wrapperRegisterForm"> */}
+      <div>
+        <Form
+          name="basic"
+          form={form}
+          // initialValues={{
+          //   remember: true,
+          // }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
         >
-          <Input.Password
-            prefix={<LockOutlined className="site-form-item-icon" />}
-          />
-        </Form.Item>
+          <Form.Item onChange={(e)=> setLogin(e.target.value)}
+            label="Username"
+            name="username"
+            value={login}
+            rules={[
+              {
+                required: true,
+                message: "Please input your username!",
+              },
+            ]}
+          >
+            <Input
+              prefix={<UserOutlined className="site-form-item-icon" />}
+              onChange={(e) => {
+                // console.log(e.target.value);
+                form.setFieldsValue({ username: e.target.value });
+              }}
+            />
+          </Form.Item>
 
+          <Form.Item onChange={(e)=> setPassword(e.target.value)}
+            label="Password"
+            name="password"
+            value={password}
+            rules={[
+              {
+                required: true,
+                message: "Please input your password!",
+              },
+            ]}
+          >
+            <Input.Password
+              prefix={<LockOutlined className="site-form-item-icon" />}
+            />
+          </Form.Item>
+          <Form.Item onChange={(e)=> setConfPassword(e.target.value)}
+            label="Confirm password"
+            name="Confirm password"
+            value={confPassword}
+            rules={[
+              {
+                required: true,
+                message: "Please input your password!",
+                // validator: 
+                // value: 
+              },
+            ]}
+          >
+            <Input.Password
+              prefix={<LockOutlined className="site-form-item-icon" />}
+            />
+          </Form.Item>
+          {/* 
         <Form.Item name="remember" valuePropName="checked">
           <Checkbox>Remember me</Checkbox>
-        </Form.Item>
+        </Form.Item> */}
 
-        <Form.Item>
-          <Button type="primary" htmlType="submit">
-            Submit
-          </Button>
-        </Form.Item>
-      </Form>
+          <Form.Item>
+            <Button type="primary" htmlType="submit"
+            disabled = {password !== confPassword ? true : false}
+            onClick={async () => {
+              await getGQL("/graphql")(
+                `mutation User{
+                createUser (login: "${login}", password: "${password}"){
+                _id login
+                  }
+              }`
+            //     `mutation registration{
+            //         createUser (user:{
+            //       login:"${login}", password:"${password}", nick:"${nick}"
+            //     }){
+            //       _id login nick
+            //     }
+            //   }`
+              ).then((data) => {
+                console.log(data);
+                if (!data.errors) {
+                  history.push("/login");
+                  // window.location.assign("http://localhost:3000/login");
+                } else {
+                //   setError(() => true);// если поле не заполнено, то формируем ошибку
+                }
+              });
+            }
+          }
+            type="primary"
+            >         
+              Submit
+            </Button>
+        <Link to="/login">Sign_in</Link>
+          </Form.Item>
+        </Form>
+      </div>
     </div>
   );
 };

+ 113 - 0
my-project/src/components/actionCreators.js

@@ -0,0 +1,113 @@
+/////////////////////////////////
+// function actionLogIn(token) {
+//   return {
+//     type: 'LOGIN',
+//     'token': token
+//   }
+// }
+
+//  function actionLogOut() {
+//   return {
+//     type: 'LOGOUT'
+//   };
+// }
+
+//  function actionPending(){
+//   return{
+//       status:'pending',
+//       payload:null,
+//       error:null,
+//       type:'PROMISE'
+//   }
+// }
+
+//  function  actionResolved(payload){
+//   return{
+//       status:'resolved',
+//       type:'PROMISE',
+//       payload:payload,
+//       error:null
+//   }
+// }
+//  function actionRejected(error){
+//   return{
+//       status:'rejected',
+//       type:'PROMISE',
+//       error: error,
+//       payload:null
+//   }
+// }
+
+//  function  actionFetch (queryUser){
+// const getGQL = (url, headers={}) =>
+//   (query="", variables={}) =>
+//       fetch(url,
+//                     {method: 'POST',
+//                           headers: {
+//                             'Accept': 'application/json',
+//                             'Content-Type': 'application/json',
+//                             ...headers
+//                           },
+//                          body: JSON.stringify({query,variables})
+//                         })
+//       .then(res => res.json())
+//       const originalFetch = fetch;
+//       fetch = (url, params={headers:{}}) => {
+//             params.headers.Authorization = "Bearer " + localStorage.authToken
+//             return originalFetch(url, params)
+//       }
+// const gql = getGQL('/graphql',{Authorization : "Bearer " + localStorage.authToken})
+// // const promise = gql(queryUser)
+// return async function (dispatch){
+//   dispatch(actionPending())
+//   try {
+//       dispatch(actionResolved(await gql(queryUser)))
+//   }
+//   catch (e) {
+//       dispatch(actionRejected(e))
+//   }
+// }
+// }
+
+//////////////////////////////////////////
+export default () => {
+// const actionCreators = () => {
+  const actionPending = (name) => ({
+    name,
+    type: "PROMISE",
+    status: "PENDING",
+    payload: undefined,
+    error: undefined
+  });
+  const actionResolved = (name, payload) => ({
+    name,
+    type: "PROMISE",
+    status: "RESOLVED",
+    payload,
+    error: undefined
+  });
+  const actionRejected = (name, error) => ({
+    name,
+    type: "PROMISE",
+    status: "REJECTED",
+    payload: undefined,
+    error
+  });
+
+  //   store.dispatch(actionPending())
+  //   p.then(data => store.dispatch(actionResolved(data)))
+
+  function actionPromise(name, promise) {
+    return async function (dispatch) {
+      dispatch(actionPending(name));
+      try {
+        let result = await promise;
+        dispatch(actionResolved(name, result));
+        return result; //позволяет получить результат промиса снаружи
+      } catch (e) {
+        dispatch(actionRejected(name, e));
+      }
+    };
+  }
+};
+// export default actionCreators;

+ 298 - 0
my-project/src/components/library.js

@@ -0,0 +1,298 @@
+import React, { useState, useEffect } from "react";
+
+import { Link } from "react-router-dom";
+import "../styles/library.css";
+
+
+const getGQL = (url, headers = {}) => (query = "", variables = {}) =>
+  fetch(url, {
+    method: "POST",
+    headers: {
+      Accept: "application/json",
+      "Content-Type": "application/json",
+      ...headers,
+    },
+    body: JSON.stringify({ query, variables }),
+  }).then((res) => res.json());
+  
+  let gql = getGQL("/graphql");
+
+// const CategoryItem = ({category: {_id, name}}) =>
+// <li>
+//     <Link to={`/category/${_id}`}>{name}</Link>
+// </li>
+
+// const Aside = () => {
+//     const [categories, setCategories] = useState([])
+//     console.log(categories)
+//     useEffect(async () => {
+//         let data = await getGQL('http://shop-roles.asmer.fs.a-level.com.ua/graphql')
+//               (`query MainCategories{
+//                   CategoryFind(query: "[{\\"parent\\":null}]"){
+//                     _id name
+//                   }
+//                 }`)
+//         setCategories(data.CategoryFind)
+//     },[])
+
+//     return (
+//         <aside >
+//             <ul>
+//                 {categories.map(category => <CategoryItem category={category}/>)}
+//             </ul>
+//         </aside>
+//     )
+// }
+
+export default ({history}) => {
+//   const List = ({track: {_id, url, originalFileName}}) =>
+// <li>
+//     <p>{_id} {url} {originalFileName}</p>
+// </li>
+  // const data = [];
+  // const List = ({data: {_id, url, originalFileName}}) =>
+  // <li>
+  //     <p><span>{_id}</span> 
+  //         <span>{url}</span> 
+  //         <span>{originalFileName}</span></p>
+  // </li>
+  const TrackList = () => {
+    const [tracks, setTracks] = useState([]);
+    console.log(tracks);
+    useEffect( async () => {
+      // {debugger}
+      let data = await getGQL("/graphql")
+      (`query tracksFind($query: String){
+                TrackFind(query: $query){
+                    _id
+                    url
+                    originalFileName
+                }
+        }`,{query: JSON.stringify([{}])})
+        console.log(data)
+        setTracks(data.TrackFind);
+
+        console.log(data.TrackFind);
+    },[])
+
+        return (
+        <div>
+            <ul>
+              {console.log(tracks)}
+                {/* {tracks.map(track => <List track={track}/>)} */}
+                {/* {tracks.map(track => <li>{track}</li>)} */}
+            </ul>
+        </div>
+    )
+}
+    // let data = await getGQL("/graphql")
+    //   (`query trackFind{
+    //             TrackFind(query: "[{}]"){
+    //                 _id
+    //                 url
+    //                 originalFileName
+    //             }
+    //           }`).then(data => console.log(data));
+
+        // }`).then(data.map(data => console.log(data)));
+      // }`).then((data) => data = data).then(data.map(data => console.log(data));
+          // return(
+          //   <>
+          //   <div className="allTracks">
+          //         <ul>
+          //              {data.map(data => <List data={data}/>)}
+          //         </ul>
+          //   </div>
+          //   </>
+          // );
+// };
+
+
+  // TrackList()
+  const Header = () => {
+    return (
+      <div className="header">
+        <ul className="mainMenu">
+          <li>
+            <h2>gRomkoPlayer</h2>
+          </li>
+          <li>
+            <h2>Библиотека</h2>
+          </li>
+          <li>
+            <h2>Плейлист</h2>
+          </li>
+          <li>
+            <h2>Поиск</h2>
+          </li>
+          <li>
+            <h2>Пользователь</h2>
+          </li>
+        </ul>
+      </div>
+    );
+  };
+
+  return (
+      <>
+        <Header />
+        <TrackList />
+      </>
+  );
+};
+
+// import React from 'react';
+// import { makeStyles } from '@material-ui/core/styles';
+// import List from '@material-ui/core/List';
+// import ListItem from '@material-ui/core/ListItem';
+// import ListItemText from '@material-ui/core/ListItemText';
+// import MenuItem from '@material-ui/core/MenuItem';
+// import Menu from '@material-ui/core/Menu';
+
+// const useStyles = makeStyles((theme) => ({
+//   root: {
+//     backgroundColor: theme.palette.background.paper,
+//   },
+// }));
+
+// const options = [
+//   'Show some love to Material-UI',
+//   'Show all notification content',
+//   'Hide sensitive notification content',
+//   'Hide all notification content',
+// ];
+
+// export default function SimpleListMenu() {
+//   const classes = useStyles();
+//   const [anchorEl, setAnchorEl] = React.useState(null);
+//   const [selectedIndex, setSelectedIndex] = React.useState(1);
+
+//   const handleClickListItem = (event) => {
+//     setAnchorEl(event.currentTarget);
+//   };
+
+//   const handleMenuItemClick = (event, index) => {
+//     setSelectedIndex(index);
+//     setAnchorEl(null);
+//   };
+
+//   const handleClose = () => {
+//     setAnchorEl(null);
+//   };
+
+//   return (
+//     <div className={classes.root}>
+//       <List component="nav" aria-label="Device settings">
+//         <ListItem
+//           button
+//           aria-haspopup="true"
+//           aria-controls="lock-menu"
+//           aria-label="when device is locked"
+//           onClick={handleClickListItem}
+//         >
+//           <ListItemText primary="When device is locked" secondary={options[selectedIndex]} />
+//         </ListItem>
+//       </List>
+//       <Menu
+//         id="lock-menu"
+//         anchorEl={anchorEl}
+//         keepMounted
+//         open={Boolean(anchorEl)}
+//         onClose={handleClose}
+//       >
+//         {options.map((option, index) => (
+//           <MenuItem
+//             key={option}
+//             disabled={index === 0}
+//             selected={index === selectedIndex}
+//             onClick={(event) => handleMenuItemClick(event, index)}
+//           >
+//             {option}
+//           </MenuItem>
+//         ))}
+//       </Menu>
+//     </div>
+//   );
+// }
+
+// import React from 'react';
+// import clsx from 'clsx';
+// import { makeStyles } from '@material-ui/core/styles';
+// import Drawer from '@material-ui/core/Drawer';
+// import Button from '@material-ui/core/Button';
+// import List from '@material-ui/core/List';
+// import Divider from '@material-ui/core/Divider';
+// import ListItem from '@material-ui/core/ListItem';
+// import ListItemIcon from '@material-ui/core/ListItemIcon';
+// import ListItemText from '@material-ui/core/ListItemText';
+// import InboxIcon from '@material-ui/icons/MoveToInbox';
+// import MailIcon from '@material-ui/icons/Mail';
+
+// const useStyles = makeStyles({
+//   list: {
+//     width: 250,
+//   },
+//   fullList: {
+//     width: 'auto',
+//   },
+// });
+
+// export default function TemporaryDrawer() {
+//   const classes = useStyles();
+//   const [state, setState] = React.useState({
+//     top: false,
+//     left: false,
+//     bottom: false,
+//     right: false,
+//   });
+
+//   const toggleDrawer = (anchor, open) => (event) => {
+//     if (event.type === 'keydown' && (event.key === 'Tab' || event.key === 'Shift')) {
+//       return;
+//     }
+
+//     setState({ ...state, [anchor]: open });
+//   };
+
+//   const list = (anchor) => (
+//     <div
+//       className={clsx(classes.list, {
+//         [classes.fullList]: anchor === 'top' || anchor === 'bottom',
+//       })}
+//       role="presentation"
+//       onClick={toggleDrawer(anchor, false)}
+//       onKeyDown={toggleDrawer(anchor, false)}
+//     >
+//       <List>
+//         {['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
+//           <ListItem button key={text}>
+//             <ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
+//             <ListItemText primary={text} />
+//           </ListItem>
+//         ))}
+//       </List>
+//       <Divider />
+//       <List>
+//         {['All mail', 'Trash', 'Spam'].map((text, index) => (
+//           <ListItem button key={text}>
+//             <ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
+//             <ListItemText primary={text} />
+//           </ListItem>
+//         ))}
+//       </List>
+//     </div>
+//   );
+
+//   return (
+//     <div>
+//       {['left', 'right', 'top', 'bottom'].map((anchor) => (
+//         <React.Fragment key={anchor}>
+//           <Button onClick={toggleDrawer(anchor, true)}>{anchor}</Button>
+//           <Drawer anchor={anchor} open={state[anchor]} onClose={toggleDrawer(anchor, false)}>
+//             {list(anchor)}
+//           </Drawer>
+//         </React.Fragment>
+//       ))}
+//     </div>
+//   );
+// }

+ 85 - 0
my-project/src/components/reducers.js

@@ -0,0 +1,85 @@
+
+import { combineReducers } from 'redux';
+import jwt_decode from "jwt-decode";
+import actionCreators from "./actionCreators";
+
+
+    let authReducer = (state, action) => {
+        if(state === undefined){
+            return({});
+        }
+        if(action.type === 'LOGIN'){
+            var data = jwt_decode(action.token);
+            localStorage.authToken = action.token;
+            // console.log({data : {data}, token: action.token})
+            return({data: {data}, token: action.token});
+        }
+        if(action.type === 'LOGOUT'){
+            localStorage.authToken = "";
+            return({});
+        }
+        }
+
+
+        
+            // store.dispatch(actionPending())
+            // p.then(data => store.dispatch(actionResolved(data)))
+        
+
+
+        const promiseReducer = (state, action) => {
+            if(state === undefined){
+                return({});
+            }
+            if (action.type === 'PROMISE') {
+                        //три состояния
+                        // const actionPending = (name, Pending) => ({
+                        //     name,
+                        //     type: "SET_STATUS",
+                        //     status: "Pending",
+                        //     payload: "null",
+                        //     error: "null",
+                        //   });
+                        //   const actionResolved = (name, Resolved) => ({
+                        //     name,
+                        //     type: "SET_STATUS",
+                        //     status: "Resolved",
+                        //     payload: "",
+                        //     error: "null",
+                        //   });
+                        //   const actionRejected = (name, error) => ({
+                        //     name,
+                        //     type: "SET_STATUS",
+                        //     status: "Rejected",
+                        //     payload: "null",
+                        //     error,
+                        //   });
+
+                        //   function actionPromise(promise) {
+                        //     return async function (dispatch) {
+                        //       dispatch(actionPending());
+                        //       try {
+                        //         let result = await promise;
+                        //         dispatch(actionResolved(result));
+                        //         return result; //позволяет получить результат промиса снаружи
+                        //       } catch (e) {
+                        //         dispatch(actionRejected(e));
+                        //       }
+                        //     };
+                        // }
+
+                    return {status: action.status, payload: action.payload, error: action.error}
+                    
+            }  
+        }
+
+
+
+// {           console.log(combineReducers); 
+// }
+// {debugger}
+        const myReducers = combineReducers({
+            auth: authReducer,
+            promise: promiseReducer
+        })
+export default myReducers;

+ 14 - 1
my-project/src/styles/App.css

@@ -1,8 +1,21 @@
 @import '~antd/dist/antd.css';
 
 .App {
-    height: 100%;
+    /* height: 100%; */
     display: flex;
     align-items: center;
     justify-content: center;
+    box-sizing: border-box;
+}
+h2 {
+    margin-bottom: 0em;
+    font-size: 25px;
+    line-height: 1.5;
+    font-weight: 700;
+}
+ul{
+    margin-bottom: 0em; 
+}
+li{
+    list-style-type: none;
 }

+ 17 - 1
my-project/src/styles/RegisterForm.css

@@ -1,5 +1,21 @@
 .registerForm {
+    display: flex;
+    justify-content: center;
     padding: 24px;
     border-radius: 5px;
     border: 2px solid #666666;
-}
+    margin: auto;
+    /* max-width: 300px; */
+    /* height: 100%;
+    width: 100%; */
+}
+
+/* .registerForm div{
+    margin:0 auto; 
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 24px;
+    border-radius: 5px;
+    border: 2px solid #666666;
+} */

+ 51 - 0
my-project/src/styles/Reset.css

@@ -0,0 +1,51 @@
+/* http://meyerweb.com/eric/tools/css/reset/ 
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	font: inherit;
+	vertical-align: baseline;
+	margin: 0;
+	padding-inline-start: 0;
+
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+	display: block;
+}
+body {
+	line-height: 1;
+}
+ol, ul {
+	list-style: none;
+}
+blockquote, q {
+	quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+	content: '';
+	content: none;
+}
+table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}

+ 38 - 0
my-project/src/styles/library.css

@@ -0,0 +1,38 @@
+.header {
+    display: flex;
+    border: 1px solid black;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+}
+
+/* .header ul {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+} */
+
+/* .header ul>li{
+    list-style-type: none;
+    width: 300px; 
+} */
+
+.mainMenu {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.mainMenu li {
+    /* width: 250px; */
+    padding: 15px 67px;
+    border: 1px solid black;
+    /* background-color: orange; */
+}
+.mainMenu li:hover {
+    background-color: orange;
+    /* color: white; */
+}
+/* .mainMenu h2 {
+    margin-bottom: 0em;
+} */