Преглед на файлове

avatar split_modules demo_mytracks

mfdok43 преди 2 години
родител
ревизия
e750d59c82

+ 11 - 0
package-lock.json

@@ -11,6 +11,7 @@
         "@testing-library/jest-dom": "^5.16.1",
         "@testing-library/react": "^12.1.2",
         "@testing-library/user-event": "^13.5.0",
+        "jwt-decode": "^3.1.2",
         "node-sass": "^7.0.1",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",
@@ -11225,6 +11226,11 @@
         "node": ">=4.0"
       }
     },
+    "node_modules/jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "node_modules/kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -25850,6 +25856,11 @@
         "object.assign": "^4.1.2"
       }
     },
+    "jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",

+ 1 - 0
package.json

@@ -6,6 +6,7 @@
     "@testing-library/jest-dom": "^5.16.1",
     "@testing-library/react": "^12.1.2",
     "@testing-library/user-event": "^13.5.0",
+    "jwt-decode": "^3.1.2",
     "node-sass": "^7.0.1",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",

+ 3 - 2
src/App.js

@@ -1,10 +1,11 @@
 import './App.scss';
 import {Provider}   from 'react-redux';
-import store from "./reducers";
 import {Footer, Header, Main} from "./pages";
 import {Router} from 'react-router-dom';
-import {history} from "./reducers";
+import createHistory from "history/createBrowserHistory";
+import {store} from "./reducers";
 
+export const history = createHistory()
 
 function App() {
   return (

+ 20 - 1
src/App.scss

@@ -25,6 +25,24 @@ main {
 
 }
 
+.Avatar {
+  img {
+    min-height: 60px;
+    min-width: 60px;
+    max-height: 60px;
+    max-width: 60px;
+    border-radius: 30px;
+  }
+}
+
+.Spoiler {
+  cursor: pointer;
+}
+
+.SpoilerContent {
+  cursor: pointer;
+  background: dodgerblue;
+}
 
 footer {
   height: 200px;
@@ -54,4 +72,5 @@ footer {
 
 .Tracks {
   text-align: left;
-}
+}
+

+ 121 - 20
src/actions/index.js

@@ -1,4 +1,77 @@
-import store, {actionPromise, gql} from "../reducers";
+import {actionPromise} from '../reducers'
+import {actionAuthLogin, actionAuthLogout} from '../reducers'
+import {store} from "../reducers";
+import {connect} from "react-redux";
+
+const getGQL = url =>
+    async (query, variables = {}) => {
+        let obj = await fetch(url, {
+            method: 'POST',
+            headers: {
+                "Content-Type": "application/json",
+                Authorization: localStorage.authToken ? 'Bearer ' + localStorage.authToken : {},
+            },
+            body: JSON.stringify({ query, variables })
+        })
+        let a = await obj.json()
+        if (!a.data && a.errors)
+            throw new Error(JSON.stringify(a.errors))
+        return a.data[Object.keys(a.data)[0]]
+    }
+
+export const backURL = 'http://player.asmer.fs.a-level.com.ua'
+
+export const gql = getGQL(backURL + '/graphql');
+
+
+
+export const actionLogin = (login, password) => {
+    return actionPromise(
+        "login",
+        gql(
+            `query log($login:String!, $password:String!) {
+    login(login:$login, password:$password)
+    }`,
+            {login, password }
+        )
+    );
+};
+
+
+export const actionFullLogin = (login, password) =>
+    async function i(dispatch) {
+        let token = await dispatch(actionLogin(login, password));
+        if (token) {
+            dispatch(actionAuthLogin(token));
+            dispatch(actionAboutMe())
+        }
+    }
+
+
+export const actionFullReg = (login, password) =>
+    async function a(dispatch) {
+        try {
+            await dispatch(actionReg(login, password));
+        } catch (e) {
+            return 0;
+        }
+        await dispatch(actionFullLogin(login, password));
+    }
+
+export const actionReg = (login, password) => {
+    return actionPromise(
+        "reg",
+        gql(
+            `mutation reg($l: String!, $p: String!){
+        createUser(login: $l, password:$p){
+          _id login
+        }
+      }`,
+            { l: login, p: password }
+        )
+    );
+};
+
 
 export const actionUserFind = () => actionPromise('userFind', gql(`query {
             UserFind(query: "[{}]"){
@@ -14,28 +87,59 @@ export const actionTrackFindByOwner = (_id) => actionPromise('trackFindByOwner1'
         }`, { q: JSON.stringify([{ ___owner: _id }]) }))
 
 
-export const actionUserFindOne = (_id, name='userFindOne') => actionPromise(name, gql(`query userFindOne($myid: String) {
-    UserFindOne(query: $myid) {
-               _id createdAt login nick avatar {_id url}
-          } 
-      }`,{ myid: JSON.stringify([{ _id }]) }));
-
-export const actionAboutMe = () =>
-    async (dispatch, getState) => {
-        let { auth } = getState();
-        let id = auth?.payload?.sub.id;
-        if (id) {
-            await dispatch(actionUserFindOne(id, 'aboutMe'))
+export const actionFindMyTracks = () =>
+    actionPromise('findMyTracks1', gql(`query findMyTracks($q: String){
+            TrackFind(query: $q){
+                 _id url originalFileName
             }
-    }
+        }`, { q: JSON.stringify([{ ___owner: "61cda244e9472933a6785efc" }]) }))
+
+
+// const CactionFindMyTracks = connect (state => ({myId: state.auth?.payload.sub.id}))(actionFindMyTracks)
 
 
+export const actionUserFindOne = (_id, name = "userFindOne") =>
+    actionPromise(
+        name,
+        gql(
+            `query userFindOne($myid: String) {
+  UserFindOne(query: $myid) {
+             _id createdAt login nick avatar {url}
+        } 
+    }`,
+            { myid: JSON.stringify([{ _id }]) }
+        )
+    );
+
+export const actionAboutMe = () => async (dispatch, getState) => {
+    let { auth } = getState();
+    let id = auth?.payload?.sub.id;
+    if (id) {
+        await dispatch(actionUserFindOne(id, "aboutMe"));
+    }
+};
+
 export const actionUploadImage = (file) => {
     let fd = new FormData();
     fd.append("photo", file);
     return actionPromise(
         "uploadFile",
-        fetch("http://shop-roles.asmer.fs.a-level.com.ua/upload", {
+        fetch('http://player.asmer.fs.a-level.com.ua/upload', {
+            method: "POST",
+            headers: localStorage.authToken
+                ? { Authorization: "Bearer " + localStorage.authToken }
+                : {},
+            body: fd,
+        }).then((res) => res.json())
+    );
+};
+
+export const actionUploadTrack = (file) => {
+    let fd = new FormData();
+    fd.append("track", file);
+    return actionPromise(
+        "uploadFile",
+        fetch('http://player.asmer.fs.a-level.com.ua/track', {
             method: "POST",
             headers: localStorage.authToken
                 ? { Authorization: "Bearer " + localStorage.authToken }
@@ -54,7 +158,7 @@ export const actionSetAvatar = (file) => async (dispatch, getState) => {
         actionPromise(
             "setAvatar",
             gql(
-                `mutation setAva($userId: String, $imageId: ID){ 
+                `mutation setAva($userId: String, $imageId: ID){
         UserUpsert(user:{_id: $userId, avatar: {_id: $imageId}}){_id}}`,
                 { userId: userId, imageId: imageId }
             )
@@ -62,8 +166,5 @@ export const actionSetAvatar = (file) => async (dispatch, getState) => {
     );
     await dispatch(actionAboutMe());
 };
+store.dispatch(actionAboutMe())
 
-
-store.dispatch(actionUserFind())
-
-export const actionPlayTrack = () => console.log('kak dela kak dela');

+ 3 - 1
src/pages/aside.js

@@ -1,6 +1,7 @@
 import {connect} from "react-redux";
 import {Link} from "react-router-dom";
-import {actionPlaylistFind} from "../actions";
+import {actionUserFind} from "../actions";
+import {store} from "../reducers";
 
 const defaultPlaylists = [
     {
@@ -135,3 +136,4 @@ export const Aside = () =>
             <CPlaylists />
     </aside>
 
+store.dispatch(actionUserFind())

+ 0 - 122
src/pages/header.js

@@ -1,122 +0,0 @@
-import logo from "../logo.svg";
-import {useState,useCallback} from 'react'
-import {connect} from 'react-redux';
-import store, {actionAuthLogout, actionFullReg, actionFullLogin,history,backURL} from "../reducers"
-import {Route, Link, Switch} from 'react-router-dom';
-import {actionUploadImage,actionSetAvatar} from "../actions";
-import {useDropzone} from 'react-dropzone'
-
-export const Logo = () =>
-<Link to='/'><img src={logo} className="App-logo" alt="logo" /></Link>
-
-export const Header = () =>
-    <header className="Header">
-        <Logo />
-        <CAvatar />
-        <Switch>
-            <Route path="/login" component={CLoginForm}/>
-            <Route path="/registration" component={CRegForm}/>
-            <Route path='*' component={CLoginButtons} />
-        </Switch>
-    </header>
-
-
-const Avatar = ({ avatarURL = {} }) => {
-    return (
-        <img
-            style={{ maxWidth: "150px" }}
-            src={backURL + "/" + avatarURL.avatar?.url}
-        ></img>
-    );
-};
-
-export const CAvatar = connect((state) => ({
-    avatarURL: state.promise.aboutMe?.payload,
-}))(Avatar);
-
-const LoginButtons = ({onLogout, history, token}) => {
-    return (
-        <>
-            {!token ?
-                ( <div className='LoginButtons'>
-                    <Link to='/login'><button onClick={() => history.push('/')}>Вход</button></Link>
-                    <Link to='/registration'><button>Регистрация</button></Link></div>) :
-                (<div className='LoginColumn'><strong>{JSON.parse(atob(token.split(".")[1])).sub.login}
-                </strong>
-                    <CAvatarDropZone />
-                    <button onClick={() => {onLogout(); history.push('/')}}>Выйти</button></div>)
-            }
-        </>
-    )
-}
-const CLoginButtons = connect(state => ({token: state.auth.token}), {onLogout: actionAuthLogout})(LoginButtons)
-
-const LoginForm = ({onLogin, history}) => {
-    const [l, setL] = useState ('')
-    const [p, setP] = useState ('')
-
-
-
-    return (
-        <div className='LoginColumn'>
-            <input placeholder='Введите имя' style={{backgroundColor:"skyblue"}} onChange={e => setL(e.target.value)}></input>
-            <input type='password' placeholder='Введите пароль' style={{backgroundColor:"skyblue"}} onChange={e => setP(e.target.value)}></input>
-            <button onClick={() => {onLogin(l,p); history.push('/')}}>Войти</button>
-        </div>
-    )
-}
-
-const CLoginForm = connect (null,{onLogin: actionFullLogin})(LoginForm)
-
-const RegForm = ({ onReg }) => {
-    const [l, setL] = useState("");
-    const [p, setP] = useState("");
-    const [p2, setP2] = useState('')
-
-    return (
-        <div className='LoginButtons'>
-
-            <div className='RegColumn'>
-                         <input placeholder='Введите имя'
-                                style={{ backgroundColor: "skyblue" }}
-                                onChange={(e) => setL(e.target.value)}></input>
-
-                         <input placeholder='Введите пароль'
-                                style={{ backgroundColor: "skyblue" }}
-                                onChange={(e) => setP(e.target.value)}></input>
-            <div>{p.length < 6 ? 'Короткий пароль' : 'Хороший пароль'}</div>
-            </div>
-            <div className='RegColumn'>
-            <button disabled={p.length >= 6 && p === p2 && l !== "" ? false : true} onClick={() => {onReg(l, p); history.push('/')}}>Регистрация</button>
-                         <input placeholder='Подтвердите пароль'
-                                style={{ backgroundColor: "skyblue" }}
-                                onChange={(e) => setP2(e.target.value)}></input>
-            <div>{p === p2 ? 'Пароли совпадают' : 'Пароли не совпадают'}</div>
-            </div>
-        </div>
-    );
-};
-
-const CRegForm = connect(null,{onReg: actionFullReg}) (RegForm)
-
-const CAvatarDropZone = connect (null, {onLoad: actionUploadImage}) (AvatarDropzone)
-
-function AvatarDropzone({onLoad}) {
-    const onDrop = useCallback(acceptedFiles => {
-        onLoad(acceptedFiles[0])
-        store.dispatch(actionSetAvatar(acceptedFiles[0]));
-    }, [])
-    const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
-
-    return (
-        <div {...getRootProps()}>
-            <input {...getInputProps()} />
-            {
-                isDragActive ?
-                    <p>Перетащите файл сюда ...</p> :
-                    <p>Нажмите для загрузки или перетащите файл</p>
-            }
-        </div>
-    )
-}
-

+ 40 - 0
src/pages/header/avatar.js

@@ -0,0 +1,40 @@
+import {useCallback} from "react";
+import {store} from "../../reducers";
+import {actionSetAvatar, actionUploadImage, backURL} from "../../actions";
+import {useDropzone} from "react-dropzone";
+import {connect} from "react-redux";
+
+function AvatarDropzone({ onLoad }) {
+    const onDrop = useCallback((acceptedFiles) => {
+        // Do something with the files
+        onLoad(acceptedFiles[0]);
+        store.dispatch(actionSetAvatar(acceptedFiles[0]));
+    }, []);
+    const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
+
+    return (
+        <div {...getRootProps()}>
+            <input {...getInputProps()} />
+            {isDragActive ? (
+                <p>Перетащите файл сюда ...</p>
+            ) : (
+                <p>Сменить аву, нажмите или перетащите файл</p>
+            )}
+        </div>
+    );
+}
+
+
+export const CAvatarDropZone = connect (null, {onLoad: actionUploadImage}) (AvatarDropzone)
+
+
+const Avatar = ({ avatarURL = {} }) => {
+    console.log(avatarURL);
+    return (
+        <div className='Avatar'>
+            <img src={backURL + "/" + avatarURL.avatar?.url}></img>
+        </div>
+    )
+};
+
+export const CAvatar = connect((state) => ({avatarURL: state.promise.aboutMe?.payload}))(Avatar)

+ 57 - 0
src/pages/header/header-build.js

@@ -0,0 +1,57 @@
+import {Link, Route, Switch} from "react-router-dom";
+import {connect} from "react-redux";
+import {actionAuthLogout} from "../../reducers";
+import {CLoginForm} from "./login";
+import {CRegForm} from "./registration";
+import {useState} from "react";
+import {CAvatar,CAvatarDropZone} from "./avatar";
+import {Logo} from "./logo";
+
+
+export const Header = () =>
+    <header className="Header">
+        <Logo />
+        <Switch>
+            <Route path="/login" component={CLoginForm}/>
+            <Route path="/registration" component={CRegForm}/>
+            <Route path='*' component={CLoginButtons} />
+        </Switch>
+    </header>
+
+
+const Spoiler = ({ header, children, open=false }) => {
+    const [openSpoiler, setOpenSpoiler] = useState(open)
+    return (
+        <>
+            <section className="Spoiler" onClick={() => setOpenSpoiler(!openSpoiler)}>
+                {header}
+            </section>
+            {openSpoiler && (
+                <div className="SpoilerContent">
+                    {children}
+                </div>
+            )}
+        </>
+    );
+};
+
+
+const LoginButtons = ({onLogout, history, token}) => {
+    return (
+        <>
+            {!token ?
+                ( <div className='LoginButtons'>
+                    <Link to='/login'><button onClick={() => history.push('/')}>Вход</button></Link>
+                    <Link to='/registration'><button>Регистрация</button></Link></div>) :
+                (<div className='LoginColumn'>
+                    <Spoiler header={<CAvatar/>}>
+                        <strong>{JSON.parse(atob(token.split(".")[1])).sub.login}</strong>
+                        <CAvatarDropZone />
+                        <button onClick={() => {onLogout(); history.push('/')}}>Выйти</button>
+                    </Spoiler>
+                </div>)
+            }
+        </>
+    )
+}
+export const CLoginButtons = connect(state => ({token: state.auth.token}), {onLogout: actionAuthLogout})(LoginButtons)

+ 6 - 0
src/pages/header/index.js

@@ -0,0 +1,6 @@
+export {Logo} from "./logo";
+export {CAvatarDropZone,CAvatar} from "./avatar";
+export {CRegForm} from "./registration";
+export {CLoginForm} from "./login";
+export {Footer} from "../footer";
+export {Header} from "./header-build";

+ 23 - 0
src/pages/header/login.js

@@ -0,0 +1,23 @@
+import {Link} from "react-router-dom";
+import {connect} from "react-redux";
+import {actionAuthLogout} from "../../reducers";
+import {useState} from "react";
+import {actionFullLogin} from "../../actions";
+
+
+const LoginForm = ({onLogin, history}) => {
+    const [l, setL] = useState ('')
+    const [p, setP] = useState ('')
+
+
+
+    return (
+        <div className='LoginColumn'>
+            <input placeholder='Введите имя' style={{backgroundColor:"skyblue"}} onChange={e => setL(e.target.value)}></input>
+            <input type='password' placeholder='Введите пароль' style={{backgroundColor:"skyblue"}} onChange={e => setP(e.target.value)}></input>
+            <button onClick={() => {onLogin(l,p); history.push('/')}}>Войти</button>
+        </div>
+    )
+}
+
+export const CLoginForm = connect (null,{onLogin: actionFullLogin})(LoginForm)

+ 5 - 0
src/pages/header/logo.js

@@ -0,0 +1,5 @@
+import {Link} from "react-router-dom";
+import logo from "../../logo.svg";
+
+export const Logo = () =>
+    <Link to='/'><img src={logo} className="App-logo" alt="logo" /></Link>

+ 35 - 0
src/pages/header/registration.js

@@ -0,0 +1,35 @@
+import {useState} from "react";
+import {history} from "../../App";
+import {connect} from "react-redux";
+import {actionFullReg} from "../../actions";
+
+const RegForm = ({ onReg }) => {
+    const [l, setL] = useState("");
+    const [p, setP] = useState("");
+    const [p2, setP2] = useState('')
+
+    return (
+        <div className='LoginButtons'>
+
+            <div className='RegColumn'>
+                <input placeholder='Введите имя'
+                       style={{ backgroundColor: "skyblue" }}
+                       onChange={(e) => setL(e.target.value)}></input>
+
+                <input placeholder='Введите пароль'
+                       style={{ backgroundColor: "skyblue" }}
+                       onChange={(e) => setP(e.target.value)}></input>
+                <div>{p.length < 6 ? 'Короткий пароль' : 'Хороший пароль'}</div>
+            </div>
+            <div className='RegColumn'>
+                <button disabled={p.length >= 6 && p === p2 && l !== "" ? false : true} onClick={() => {onReg(l, p); history.push('/')}}>Регистрация</button>
+                <input placeholder='Подтвердите пароль'
+                       style={{ backgroundColor: "skyblue" }}
+                       onChange={(e) => setP2(e.target.value)}></input>
+                <div>{p === p2 ? 'Пароли совпадают' : 'Пароли не совпадают'}</div>
+            </div>
+        </div>
+    );
+};
+
+export const CRegForm = connect(null,{onReg: actionFullReg}) (RegForm)

+ 7 - 9
src/pages/index.js

@@ -1,9 +1,7 @@
-import {Header} from "./header";
-import {Main} from "./main";
-import {Footer} from "./footer";
-import {PageMain} from "./pageMain";
-import {UserTracks} from "./userTracks";
-import {Aside} from "./aside";
-import {Content} from "./content";
-
-export {Header, Main, Footer, PageMain, UserTracks, Aside, Content}
+export {Header} from "./header";
+export {Main} from "./main";
+export {Footer} from "./footer";
+export {PageMain} from "./pageMain";
+export {UserTracks} from "./userTracks";
+export {Aside} from "./aside";
+export {Content} from "./content";

+ 64 - 1
src/pages/pageMain.js

@@ -1,4 +1,67 @@
+import {useCallback} from "react";
+import {store} from "../reducers";
+import {useDropzone} from "react-dropzone";
+import {connect} from "react-redux";
+import {actionUploadTrack, actionFindMyTracks, backURL} from "../actions";
+
+const defaultTrack = {
+    "_id": "61dc5a42e9472933a6785f18",
+    "url": "track/fe15599bbb13c96d70dd5a1591a0b158",
+    "originalFileName": "cart.png",
+    "owner": {
+        "login": "mfdok43"
+    }
+}
+
 export const PageMain = () =>
     <div>
     <h1>Главная страница</h1>
-    </div>
+        <CTrackDropZone />
+
+    </div>
+
+function TrackDropZone({ onLoad }) {
+    const onDrop = useCallback((acceptedFiles) => {
+        // Do something with the files
+        onLoad(acceptedFiles[0]);
+    }, []);
+    const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
+
+    return (
+        <div {...getRootProps()}>
+            <input {...getInputProps()} />
+            {isDragActive ? (
+                <p>Перетащите файл сюда ...</p>
+            ) : (
+                <p>Для добавления трэка перетащите файлы в плейлист</p>
+
+            )}
+            <CMyTracks />
+        </div>
+    );
+
+}
+
+
+const CTrackDropZone = connect (null, {onLoad: actionUploadTrack}) (TrackDropZone)
+
+
+const Track = ({track:{url,originalFileName}={}}) => {
+    return (
+        <div className='Tracks'>
+            <audio controls src={backURL+'/'+url}></audio>
+            <strong>{originalFileName}</strong></div>
+    )
+}
+
+const MyTracks = ({tracks=defaultTrack}) => {
+    return(
+        <div>
+            {console.log(tracks,'kak dela')}
+        {tracks.map(track => <Track track={track}/> )}
+        </div>
+    )
+}
+const CMyTracks = connect(state => ({tracks: state.promise.findMyTracks1?.payload || []}))(MyTracks)
+
+store.dispatch(actionFindMyTracks())

+ 4 - 7
src/pages/userTracks.js

@@ -1,9 +1,8 @@
 import {connect} from "react-redux";
-import {actionTrackFindByOwner, actionPlayTrack} from "../actions";
-import {backURL} from "../reducers";
+import {actionTrackFindByOwner} from "../actions";
+import {backURL} from "../actions";
 import {useEffect} from 'react';
 
-import {history} from "../reducers";
 
 const defaultTracks = [
     {
@@ -32,16 +31,14 @@ const defaultTracks = [
         "originalFileName": "Фруктовый Кефир - На своей Волне (zoop.su).mp3"
     },]
 
-const Track = ({track:{_id,url,originalFileName}=defaultTracks, onPlayTrack}) =>
+const Track = ({track:{_id,url,originalFileName}=defaultTracks}) =>
     <div className='Tracks'>
        <audio controls src={backURL+'/'+url}></audio> <strong>{originalFileName}</strong>
     </div>
 
-const CTrack = connect(null, {onPlayTrack: actionPlayTrack})(Track)
-
 const Tracks = ({tracks}={}) =>
     <div>
-        {(tracks || []).map(track => <CTrack track={track}/>)}
+        {(tracks || []).map(track => <Track track={track}/>)}
     </div>
 
 const CTracks = connect(state => ({tracks: state.promise.trackFindByOwner1?.payload}))(Tracks)

+ 29 - 0
src/reducers/authReducer.js

@@ -0,0 +1,29 @@
+import jwt_decode from "jwt-decode";
+
+export function authReducer(state, { type, token }) {
+    if (!state) {
+        if (localStorage.authToken) {
+            type = 'AUTH_LOGIN'
+            token = localStorage.authToken
+        } else state = {}
+    }
+    if (type === 'AUTH_LOGIN') {
+        localStorage.setItem('authToken', token)
+        let payload = jwt_decode(token)
+        if (typeof payload === 'object') {
+            return {
+                ...state,
+                token,
+                payload
+            }
+        } else return state
+    }
+    if (type === 'AUTH_LOGOUT') {
+        localStorage.removeItem('authToken')
+        return {}
+    }
+    return state
+}
+
+export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
+export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })

+ 3 - 152
src/reducers/index.js

@@ -1,155 +1,6 @@
-import {createStore, combineReducers, applyMiddleware} from 'redux';
-import thunk from 'redux-thunk';
-import createHistory from "history/createBrowserHistory";
-
-
-export const history = createHistory()
-
-
-const getGQL = url =>
-    async (query, variables = {}) => {
-        let obj = await fetch(url, {
-            method: 'POST',
-            headers: {
-                "Content-Type": "application/json",
-                Authorization: localStorage.authToken ? 'Bearer ' + localStorage.authToken : {},
-            },
-            body: JSON.stringify({ query, variables })
-        })
-        let a = await obj.json()
-        if (!a.data && a.errors)
-            throw new Error(JSON.stringify(a.errors))
-        return a.data[Object.keys(a.data)[0]]
-    }
-
-export const backURL = 'http://player.asmer.fs.a-level.com.ua'
-
-export const gql = getGQL(backURL + '/graphql');
-
-
-const jwtDecode = token => {
-    try {
-        let arrToken = token.split('.')
-        let base64Token = atob(arrToken[1])
-        return JSON.parse(base64Token)
-    }
-    catch (e) {
-        console.log('Лажа, Бро ' + e);
-    }
-}
-
-function authReducer(state, { type, token }) {
-    if (!state) {
-        if (localStorage.authToken) {
-            type = 'AUTH_LOGIN'
-            token = localStorage.authToken
-        } else state = {}
-    }
-    if (type === 'AUTH_LOGIN') {
-        localStorage.setItem('authToken', token)
-        let payload = jwtDecode(token)
-        if (typeof payload === 'object') {
-            return {
-                ...state,
-                token,
-                payload
-            }
-        } else return state
-    }
-    if (type === 'AUTH_LOGOUT') {
-        localStorage.removeItem('authToken')
-        return {}
-    }
-    return state
-}
-
-const actionLogin = (login, password) => {
-    return actionPromise(
-        "login",
-        gql(
-            `query log($login:String!, $password:String!) {
-    login(login:$login, password:$password)
-    }`,
-            {login, password }
-        )
-    );
-};
-
-function promiseReducer(state = {}, { type, status, payload, error, name }) {
-    if (type === 'PROMISE') {
-        return {
-            ...state,
-            [name]: { status, payload, error }
-        }
-    }
-    return state;
-}
-
-
-const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
-export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
-
-export const actionFullLogin = (login, password) =>
-    async function i(dispatch) {
-        let token = await dispatch(actionLogin(login, password));
-        if (token) {
-            dispatch(actionAuthLogin(token));
-            // dispatch(actionAboutMe())
-        }
-    }
-
-
-
-const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
-const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
-const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
-export const actionPromise = (name, promise) =>
-    async dispatch => {
-        dispatch(actionPending(name))
-        try {
-            let data = await promise
-            dispatch(actionResolved(name, data))
-            return data
-        }
-        catch (error) {
-            dispatch(actionRejected(name, error))
-        }
-    }
-
-
-
-export const actionFullReg = (login, password) =>
-    async function a(dispatch) {
-        try {
-            await dispatch(actionReg(login, password));
-        } catch (e) {
-            return 0;
-        }
-        await dispatch(actionFullLogin(login, password));
-    }
-
-const actionReg = (login, password) => {
-    return actionPromise(
-        "reg",
-        gql(
-            `mutation reg($l: String!, $p: String!){
-        createUser(login: $l, password:$p){
-          _id login
-        }
-      }`,
-            { l: login, p: password }
-        )
-    );
-};
-
-
-const store = createStore(combineReducers({promise: promiseReducer,
-        auth: authReducer,}),
-        applyMiddleware(thunk))
-
-store.subscribe(() => console.log(store.getState()))
-
-export default store
+export {store} from './store'
+export {actionPromise} from './promiseReducer'
+export {actionAuthLogin, actionAuthLogout} from './authReducer'
 
 
 

+ 28 - 0
src/reducers/promiseReducer.js

@@ -0,0 +1,28 @@
+
+
+export function promiseReducer(state = {}, { type, status, payload, error, name }) {
+    if (type === 'PROMISE') {
+        return {
+            ...state,
+            [name]: { status, payload, error }
+        }
+    }
+    return state;
+}
+
+const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
+const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
+const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
+
+export const actionPromise = (name, promise) =>
+    async dispatch => {
+        dispatch(actionPending(name))
+        try {
+            let data = await promise
+            dispatch(actionResolved(name, data))
+            return data
+        }
+        catch (error) {
+            dispatch(actionRejected(name, error))
+        }
+    }

+ 11 - 0
src/reducers/store.js

@@ -0,0 +1,11 @@
+import {applyMiddleware, combineReducers, createStore} from "redux";
+import {authReducer} from "./authReducer";
+import {promiseReducer} from "./promiseReducer";
+import thunk from "redux-thunk";
+
+export const store = createStore(combineReducers({promise: promiseReducer,
+        auth: authReducer,}),
+    applyMiddleware(thunk))
+
+store.subscribe(() => console.log(store.getState()))
+