Gennadysht преди 2 години
родител
ревизия
c24f0b1c56

+ 63 - 13
src/App.js

@@ -1,26 +1,74 @@
-import logo from './logo.svg';
+import React, { useRef, createElement, Component } from 'react';
+import { Router, Route, Redirect, Switch, useParams } from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import { createStore, combineReducers, applyMiddleware } from 'redux';
+import { Provider, connect } from 'react-redux';
+import thunk from 'redux-thunk';
 import './App.css';
-import {
-  JqlTests_RootCats,
-  JqlTests_RetrieveRootCats,
-  JqlTests_AuthLogin,
-  JqlTests_Goods,
-  JqlTests_GoodFindOne,
-  JqlTests_AuthUpsert
-} from './Tests/test_jql';
-import { LoginForm, GoodExample, GoodsList, goodsExample, Category, exampleCategory, OrderGood, exampleOrderGood, Order, exampleOrder, OrderList, exampleOrderList, exampleOrderGoodsList, OrderGoodsList } from "./Components";
+import { authReducer, promiseReducer } from './reducers';
+import { actionFullLogin, actionRootCats } from './jql_actions'
+import { CLoginForm, GoodExample, GoodsList, goodsExample, Category, exampleCategory, OrderGood, exampleOrderGood, Order, exampleOrder, OrderList, exampleOrderList, exampleOrderGoodsList, OrderGoodsList } from "./Components";
+import { MyLink } from './Components';
+import { MainAppBar } from './Components';
 
 
+export const history = createHistory()
+console.log(useParams)
+const store = createStore(combineReducers({ promise: promiseReducer, auth: authReducer }), applyMiddleware(thunk))
+store.subscribe(() => console.log(store.getState()))
+
+store.dispatch(actionRootCats())
+
+
+/*const CCatMenu = connect(state => ({ cats: state.promise?.rootCats?.payload || [] }), { onLogin: actionFullLogin })(CatMenu)
+
+const CLoginForm = connect(null, { onLogin: actionFullLogin })(LoginForm)*/
+const NotFound = () =>
+    <div>
+        <h1>404 not found</h1>
+    </div>
+
 function App() {
   return (
     <>
-      {/*<GoodsList goods={goodsExample} />
-    <GoodExample />
+
+      <Router history={history}>
+        <Provider store={store}>
+          <div className="App">
+            <MainAppBar />
+            <Switch>
+              {/*<Route path="/" component={Main} exact />*/}
+              <Route path="/login" component={CLoginForm} />
+              <Route path="*" component={NotFound} />
+            </Switch>
+            {/*<CCatMenu />
+            <LoginForm onLogin={(l, p) => console.log(l, p)} />
+            <CLoginForm />
+            <MyLink to="/" activeClassName='activeLink'>Главная</MyLink>
+            <MyLink to="/aboutus" activeClassName='activeLink'>О нас</MyLink>
+            <MyLink to="/add/2/3" activeClassName='activeLink'>2 + 3</MyLink>
+            <MyLink to="/add/20/50" activeClassName='activeLink'>20 + 50</MyLink>
+
+            <h1>Этот текст будет всегда в независимости от роутинга</h1>
+            <Switch>
+              <Route path="/" component={Main} exact />
+              <Route path="/aboutus" component={AboutUs} />
+              <Route path="/add/:a/:b" component={Add} />
+              <Route path="*" component={NotFound} />
+            </Switch>
+            <h1>Роутинг выше</h1>*/}
+          </div>
+        </Provider>
+      </Router>
+      {/*
+      <GoodsList goods={goodsExample} />
+      <GoodExample />
       <Category category={exampleCategory} />
       <OrderGood orderGood={exampleOrderGood}/>
       <Order order={exampleOrder} />
-      <OrderList orders={exampleOrderList} />*/}
+      <OrderList orders={exampleOrderList} />
       <OrderGoodsList orderGoods={exampleOrderGoodsList} />
+      */}
     </>
 
   );
@@ -43,4 +91,6 @@ function App() {
       </header>
   </div>
 */}
+
+
 export default App;

+ 5 - 2
src/Components/LoginForm.js

@@ -3,6 +3,8 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
 import Button from '@mui/material/Button';
 import { Container, CssBaseline, TextField, Avatar, Typography, FormControlLabel, Checkbox, Grid, Link } from '@mui/material';
 import { Box } from '@mui/system';
+import { connect } from 'react-redux';
+import { actionFullLogin } from '../jql_actions';
 
 const LoginForm = ({ onLogin }) => {
     const [login, setLogin] = useState('');
@@ -57,7 +59,7 @@ const LoginForm = ({ onLogin }) => {
                     fullWidth
                     type="submit"
                     disabled={!isButtonActive}
-                    onClick={() => { onLogin({ login, password }) }}>
+                    onClick={() => { onLogin( login, password ) }}>
                     Login...
                 </Button>
                 <Grid container>
@@ -76,5 +78,6 @@ const LoginForm = ({ onLogin }) => {
         </Container>
     )
 }
+const CLoginForm = connect(null, {onLogin: actionFullLogin})(LoginForm)
 
-export { LoginForm };
+export { CLoginForm };

+ 48 - 0
src/Components/MainAppBar.js

@@ -0,0 +1,48 @@
+import * as React from 'react';
+import AppBar from '@mui/material/AppBar';
+import Box from '@mui/material/Box';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import IconButton from '@mui/material/IconButton';
+import MenuIcon from '@mui/icons-material/Menu';
+import { MyLink } from './MyLink';
+import { useState } from 'react';
+
+export function MainAppBar() {
+    const [auth, setAuth] = useState({});
+    let isLoggedIn = auth.token && true;
+    return (
+        <Box sx={{ flexGrow: 1 }}>
+            <AppBar position="static">
+                <Toolbar>
+                    <IconButton
+                        size="large"
+                        edge="start"
+                        color="inherit"
+                        aria-label="menu"
+                        sx={{ mr: 2 }}
+                    >
+                        <MenuIcon />
+                    </IconButton>
+                    <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
+                    </Typography>
+                    {
+                        !isLoggedIn &&
+                        <>
+                            <Button color="inherit" href="/login">Login</Button>
+                            <Button color="inherit" href="/register">Register</Button>
+                        </>
+                    }
+                    {
+                        isLoggedIn &&
+                        <>
+                            <Button color="inherit" href="/logout">Logout</Button>
+                        </>
+                    }
+                    <Button color="inherit">Cart</Button>
+                </Toolbar>
+            </AppBar>
+        </Box>
+    );
+}

+ 12 - 0
src/Components/MyLink.js

@@ -0,0 +1,12 @@
+import React, { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
+import { history } from '../App';
+
+export const MyLink = ({ activeClassName = 'activeLink', className = '', to, ...props }) => {
+  const [currentPath, setCurrentPath] = useState(window.location.pathname);
+  useEffect(() => history.listen(({ pathname }) => setCurrentPath(pathname)),
+    []);
+  return (
+    <Link className={`${className} ${to === currentPath ? activeClassName : ''}`} to={to} {...props} />
+  );
+};

+ 4 - 2
src/Components/index.js

@@ -1,8 +1,10 @@
-export { LoginForm } from './LoginForm';
+export { CLoginForm } from './LoginForm';
 export { Good, GoodExample } from './Good';
 export { goodsExample, GoodsList } from './GoodsList';
 export {Category, exampleCategory} from './Category';
 export {OrderGood, exampleOrderGood} from './OrderGood';
 export {OrderGoodsList, exampleOrderGoodsList} from './OrderGoodsList'
 export {Order, exampleOrder} from './Order';
-export {OrderList, exampleOrderList} from './OrderList'
+export {OrderList, exampleOrderList} from './OrderList';
+export {MyLink} from './MyLink';
+export {MainAppBar} from './MainAppBar';

+ 183 - 0
src/Tests/lesson_redux_react.js

@@ -0,0 +1,183 @@
+import logo from './logo.svg';
+import React, {useState, useEffect, useRef, createElement, Component} from 'react';
+import {Router, Route, Link, Redirect, Switch, useParams} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import {Provider, connect} from 'react-redux';
+import thunk from 'redux-thunk';
+
+import './App.scss';
+
+const history = createHistory()
+console.log(useParams)
+
+// setTimeout(() => history.push('/aboutus'), 5000)
+function getGql(url) {
+    return function gql(query, vars = undefined) {
+        try {
+            let fetchSettings =
+                {
+                    method: "POST",
+                    headers:
+                        {
+                            "Content-Type": "application/json",
+                            "Accept": "application/json"
+                        },
+                    body: JSON.stringify(
+                        {
+                            query: query,
+                            variables: vars
+                        })
+                };
+            let authToken = window.localStorage.authToken;
+            if (authToken) {
+                fetchSettings.headers["Authorization"] = `Bearer ${authToken}`;
+            }
+            return fetch(url, fetchSettings)
+                .then(res => {
+                    try {
+                        if (!res.ok) {
+                            throw Error(res.statusText);
+                        }
+                        return res.json();
+                    }
+                    catch (error) {
+                        throw error;
+                    }
+
+                });
+        }
+        catch (error) {
+            throw error;
+        }
+    }
+}
+const gql = getGql("http://shop-roles.node.ed.asmer.org.ua/graphql");
+const actionPromise = (name, promise) => {
+    return async (dispatch) => {
+        dispatch(actionPending(name)) //сигнализируем redux, что промис начался
+        try {
+            let payload = await promise //ожидаем промиса
+            if (payload && payload.data)
+                payload = Object.values(payload.data)[0];
+            dispatch(actionFulfilled(name, payload)) //сигнализируем redux, что промис успешно выполнен
+            return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
+        }
+        catch (error) {
+            dispatch(actionRejected(name, error)) //в случае ошибки - сигнализируем redux, что промис несложился
+        }
+    }
+}
+
+const actionPending = (name) => ({ type: 'PROMISE', name: name, status: 'PENDING' });
+const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
+const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
+///////////////////////////////////////
+
+const gqlRootCats = () => {
+    const catQuery = `query roots {
+                            CategoryFind(query: "[{\\"parent\\": null }]") {
+                                _id name
+                            }}`;
+    return gql(catQuery);
+}
+const actionRootCats = () =>
+    actionPromise('rootCats', gqlRootCats());
+
+
+function promiseReducer(state = {}, action) {                   // диспетчер обработки
+    if (action) {
+        if (action.type === 'PROMISE') {
+            let newState = { ...state };
+            newState[action.name] = { status: action.status, payload: action.payload, error: action.error };
+            return newState;
+        }
+    }
+    return state;
+}
+
+const store = createStore(combineReducers({promise:promiseReducer}), applyMiddleware(thunk))
+store.subscribe(() => console.log(store.getState()))
+
+store.dispatch(actionRootCats())
+
+const Main = () => 
+<main>
+    <h1>MAIN</h1>
+</main>
+
+const AboutUs = () => 
+<main>
+    <h1>ABOUT US</h1>
+</main>
+
+const MyLink = ({activeClassName='activeLink', className='', to, ...props}) => {
+    const [currentPath, setCurrentPath] = useState(window.location.pathname)
+    useEffect(() => 
+        history.listen(({pathname}) => setCurrentPath(pathname))
+    , [])
+    return (
+        <Link className={`${className} ${to === currentPath ? activeClassName : ''}`} to={to} {...props}/>
+    )
+}
+
+const Multiply = () =>{
+    const {a,b} = useParams()
+    return (
+        <pre>
+            a * b = {a} * {b} = {+a * +b}
+        </pre>
+    )
+}
+
+const Add = (/*props*/{match:{params:{a,b}}}) => 
+<div>
+    a + b = {a} + {b} = {+a + +b}
+    {/*JSON.stringify(props, null, 4)*/}
+    <Multiply />
+</div>
+
+const NotFound = () =>
+    <div>
+        <h1>404 not found</h1>
+    </div>
+
+const CatMenuItem = ({cat: {_id, name}}) => 
+    <li><MyLink to={`/category/${_id}`}>{name}</MyLink></li>
+
+const CatMenu = ({cats=[]}) =>
+    <ul>
+        {cats.map(cat => <CatMenuItem cat={cat} />)}
+    </ul>
+
+const CCatMenu = connect(state => ({cats: state.promise?.rootCats?.payload || []}), {onLogin: actionFullLogin})(CatMenu)
+
+const CLoginForm = connect(null, {onLogin: actionFullLogin})(LoginForm)
+
+function App() {
+    return (
+        <Router history = {history}>
+            <Provider store={store}>
+                <div className="App">
+                    <CCatMenu />
+                    <LoginForm onLogin={(l, p) => console.log(l,p)} />
+                    <CLoginForm />
+                    <MyLink to="/" activeClassName='activeLink'>Главная</MyLink>
+                    <MyLink to="/aboutus" activeClassName='activeLink'>О нас</MyLink>
+                    <MyLink to="/add/2/3" activeClassName='activeLink'>2 + 3</MyLink>
+                    <MyLink to="/add/20/50" activeClassName='activeLink'>20 + 50</MyLink>
+
+                    <h1>Этот текст будет всегда в независимости от роутинга</h1>
+                    <Switch>
+                        <Route path="/" component={Main} exact/>
+                        <Route path="/aboutus" component={AboutUs} />
+                        <Route path="/add/:a/:b" component={Add} />
+                        <Route path="*" component={NotFound} />
+                    </Switch>
+                    <h1>Роутинг выше</h1>
+                </div>
+            </Provider>
+        </Router>
+    );
+}
+export default App;

+ 3 - 3
src/Tests/test_jql.js

@@ -1,6 +1,6 @@
-import { gqlRootCats, gqlCategoryFindOne } from "../jql/gqlCategories"
-import { actionLogin, actionAuthUpsert } from "../jql/gqlAuth"
-import { gqlGoodFind, gqlGoodFindOne } from "../jql/gqlGoods"
+import { gqlRootCats, gqlCategoryFindOne } from "../jql_actions/gqlCategories"
+import { actionLogin, actionAuthUpsert } from "../jql_actions/gqlAuth"
+import { gqlGoodFind, gqlGoodFindOne } from "../jql_actions/gqlGoods"
 
 
 

+ 0 - 0
src/jql/index.js


+ 7 - 8
src/jql/gqlAuth.js

@@ -1,4 +1,6 @@
-import {gql} from "./../utills/gql";
+import {gql} from "../utills";
+import {actionAuthLogin} from '../reducers';
+
 
 export const actionLogin = (login, password) => {
     const upsertQuery = `query login($login:String, $password:String){
@@ -7,8 +9,9 @@ export const actionLogin = (login, password) => {
 
     return gql(upsertQuery, { login: login, password: password });
 }
-/*export const actionFullLogin = (login, password) => {
-    return gqlFullLogin = async (dispatch) => {
+
+export const actionFullLogin = (login, password) => {
+    return async (dispatch) => {
         try {
             delete localStorage.authToken;
             //dispatch возвращает то, что вернул thunk, возвращаемый actionLogin, а там промис, 
@@ -19,17 +22,13 @@ export const actionLogin = (login, password) => {
                 let token = Object.values(res.data)[0];
                 if (token && typeof token == 'string')
                     return dispatch(actionAuthLogin(token));
-                else
-                    addErrorAlert("User not found");
             }
         }
         catch (error) {
-            addErrorAlert(error.message);
             throw error;
         }
-        //проверьте что token - строка и отдайте его в actionAuthLogin
     }
-}*/
+}
 ////////////////////////////////////////
 export const actionAuthUpsert = (login, password) => {
     const loginQuery = `mutation UserRegistration($login: String, $password: String) {

+ 4 - 4
src/jql/gqlCategories.js

@@ -1,5 +1,5 @@
-import {gql} from "./../utills/gql";
-import {actionPromise} from "./../reducers/promiseReducer";
+import {gql} from "../utills/gql";
+import {actionPromise} from "../reducers";
 
 export const gqlRootCats = () => {
     const catQuery = `query roots {
@@ -8,7 +8,7 @@ export const gqlRootCats = () => {
                             }}`;
     return gql(catQuery);
 }
-const actionRootCats = () =>
+export const actionRootCats = () =>
     actionPromise('rootCats', gqlRootCats());
 export const gqlCategoryFindOne = (id) => {
     const catQuery = `query CategoryFindOne($q: String) {
@@ -23,5 +23,5 @@ export const gqlCategoryFindOne = (id) => {
         }`;
     return gql(catQuery, { q: `[{\"_id\": \"${id}\"}]` });
 }
-const actionCategoryFindOne = (id) =>
+export const actionCategoryFindOne = (id) =>
     actionPromise('catFindOne', gqlCategoryFindOne(id));

+ 9 - 4
src/jql/gqlGoods.js

@@ -1,4 +1,6 @@
-import {gql} from "./../utills/gql";
+import { gql } from "../utills/gql";
+import {actionPromise} from "../reducers";
+
 export const gqlGoodFindOne = (id) => {
     const catQuery = `
                 query GoodFindOne($q: String) {
@@ -10,7 +12,10 @@ export const gqlGoodFindOne = (id) => {
                 `;
     return gql(catQuery, { q: `[{\"_id\": \"${id}\"}]` });
 }
-export const gqlGoodFind = (id) => {
+export const actionGoodFindOne = (id) =>
+    actionPromise('goodFindOne', gqlGoodFindOne(id));
+
+export const gqlGoodFind = () => {
     const catQuery = `
                 query GoodFind($q: String) {
                     GoodFind(query: $q) {
@@ -21,5 +26,5 @@ export const gqlGoodFind = (id) => {
                 `;
     return gql(catQuery, { q: `[{\"name\": \"//\"}]` });
 }
-/*const actionGoodFindOne = (id) =>
-    actionPromise('goodFindOne', gqlGoodFindOne(id));*/
+export const actionGoodFind = () =>
+    actionPromise('goodFind', gqlGoodFind());

+ 14 - 4
src/jql/gqlOrders.js

@@ -1,3 +1,7 @@
+import { gql } from "../utills/gql";
+import {actionPromise} from "../reducers";
+import {actionCartClear} from '../reducers';
+
 const orderUpsert = (order, id = null) => {
     const orderUpsertQuery = `mutation OrderUpsert($order: OrderInput) {
                             OrderUpsert(order: $order) {
@@ -6,11 +10,14 @@ const orderUpsert = (order, id = null) => {
                         }`;
     return gql(orderUpsertQuery, { order: { "_id": id, "orderGoods": order } });
 }
+export const actionOrderUpsert = (order, id) =>
+    actionPromise('orderUpsert', orderUpsert(order, id));
+
 const orderFullUpsert = (then) => {
-    return gqlFullOrderUpsert = async (dispatch, getState) => {
+    return async (dispatch, getState) => {
         let state = getState();
         let order = [];
-        for (cartItem of Object.values(state.cartReducer)) {
+        for (let cartItem of Object.values(state.cartReducer)) {
             //{count: 3, good: {_id: "xxxx" }}
             order.push({ good: { _id: cartItem.good._id }, count: cartItem.count });
         }
@@ -20,7 +27,6 @@ const orderFullUpsert = (then) => {
             let promiseResult = orderUpsert(order);
             let res = await promiseResult;
             if (res && res.errors && res.errors.length > 0) {
-                addErrorAlert(res.errors[0].message);
                 throw res.errors[0];
             }
             dispatch(actionCartClear());
@@ -30,6 +36,10 @@ const orderFullUpsert = (then) => {
         //проверьте что token - строка и отдайте его в actionAuthLogin
     }
 }
+export const actionOrderFullUpsert = (then) =>
+    actionPromise('orderUpsert', orderFullUpsert(then));
+
+
 const gqlFindOrders = () => {
     const findOrdersQuery = `query OrderFind {
                             OrderFind(query: "[{}]") {
@@ -45,6 +55,6 @@ const gqlFindOrders = () => {
                             }`;
     return gql(findOrdersQuery);
 }
-const actionFindOrders = () =>
+export const actionFindOrders = () =>
     actionPromise('orders', gqlFindOrders());
 

+ 4 - 0
src/jql_actions/index.js

@@ -0,0 +1,4 @@
+export { actionAuthUpsert, actionLogin, actionFullLogin } from './gqlAuth';
+export { actionCategoryFindOne, actionRootCats } from './gqlCategories';
+export { actionGoodFind, actionGoodFindOne } from './gqlGoods';
+export { actionFindOrders, actionOrderFullUpsert, actionOrderUpsert } from './gqlOrders';

+ 4 - 4
src/reducers/authReducer.js

@@ -1,3 +1,5 @@
+import {jwtDecode} from '../utills';
+
 export function authReducer(state = {}, action) {                   // диспетчер обработки login
     if (action) {
         if (action.type === 'AUTH_LOGIN') {
@@ -11,7 +13,6 @@ export function authReducer(state = {}, action) {                   // дисп
                 localStorage.authToken = newState.token;
             else
                 delete localStorage.authToken;
-            window.onhashchange();
             return newState;
         }
         else if (action.type === 'AUTH_LOGOUT') {
@@ -19,11 +20,10 @@ export function authReducer(state = {}, action) {                   // дисп
             newState.token = undefined;
             newState.payload = undefined;
             delete localStorage.authToken;
-            window.onhashchange();
             return newState;
         }
     }
     return state;
 }
-const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token });
-const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' });
+export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token });
+export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' });

Файловите разлики са ограничени, защото са твърде много
+ 10 - 7
src/reducers/cartReducer.js


+ 4 - 0
src/reducers/index.js

@@ -0,0 +1,4 @@
+export { promiseReducer, actionPromise, actionFulfilled, actionPending, actionRejected } from "./promiseReducer";
+export { authReducer, actionAuthLogin, actionAuthLogout } from "./authReducer";
+export { cartReducer, actionCartAdd, actionCartClear, actionCartDel, actionCartSet, actionCartShow, actionCartSub } from "./cartReducer";
+export { localStoredReducer, } from "./localStoredReducer";

+ 5 - 5
src/reducers/promiseReducer.js

@@ -8,11 +8,11 @@ export function promiseReducer(state = {}, action) {                   // дис
     }
     return state;
 }
-const actionPending = (name) => ({ type: 'PROMISE', name: name, status: 'PENDING' });
-const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
-const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
+export const actionPending = (name) => ({ type: 'PROMISE', name: name, status: 'PENDING' });
+export const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
+export const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
 export const actionPromise = (name, promise) => {
-    return /*actionPromiseInt = async (dispatch) => {
+    return async (dispatch) => {
         dispatch(actionPending(name)) //сигнализируем redux, что промис начался
         try {
             let payload = await promise //ожидаем промиса
@@ -25,5 +25,5 @@ export const actionPromise = (name, promise) => {
             console.log(error.message);
             dispatch(actionRejected(name, error)) //в случае ошибки - сигнализируем redux, что промис несложился
         }
-    }*/
+    }
 }

+ 5 - 11
src/utills/gql.js

@@ -1,11 +1,8 @@
-const addErrorAlert = (error) => {
-    console.log(`ERROR ${error}`);
-}
 function jwtDecode(token) {                         // расщифровки токена авторизации
     if (!token || typeof token != "string")
         return undefined;
     let tokenArr = token.split(".");
-    if (tokenArr.length != 3)
+    if (tokenArr.length !== 3)
         return undefined;
     try {
         let tokenJsonStr = atob(tokenArr[1]);
@@ -13,11 +10,10 @@ function jwtDecode(token) {                         // расщифровки т
         return tokenJson;
     }
     catch (error) {
-        addErrorAlert(error.message);
         return undefined;
     }
 }
-function combineReducers(reducers) {
+/*function combineReducers(reducers) {
     function totalReducer(totalState = {}, action) {
         const newTotalState = {} //объект, который будет хранить только новые состояния дочерних редьюсеров
 
@@ -38,7 +34,7 @@ function combineReducers(reducers) {
     }
 
     return totalReducer
-}
+}*/
 
 function getGql(url) {
     return function gql(query, vars = undefined) {
@@ -65,25 +61,23 @@ function getGql(url) {
                 .then(res => {
                     try {
                         if (!res.ok) {
-                            addErrorAlert(res.statusText);
                             throw Error(res.statusText);
                         }
                         return res.json();
                     }
                     catch (error) {
-                        addErrorAlert(error.message);
                         throw error;
                     }
 
                 });
         }
         catch (error) {
-            addErrorAlert(error.message);
             throw error;
         }
     }
 }
-export const gql = getGql("http://shop-roles.node.ed.asmer.org.ua/graphql");
+const gql = getGql("http://shop-roles.node.ed.asmer.org.ua/graphql");
 
+export { gql, jwtDecode }
 //export default gql;
 

+ 2 - 1
src/utills/index.js

@@ -1 +1,2 @@
-export {getFullImageUrl} from './utils';
+export {getFullImageUrl} from './utils';
+export {gql, jwtDecode} from './gql';