Browse Source

Problemasic done

maryluis 4 years ago
parent
commit
89adba425b

+ 127 - 0
shop/package-lock.json

@@ -6988,6 +6988,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",
@@ -6998,6 +7011,14 @@
         "minimalistic-crypto-utils": "^1.0.1"
       }
     },
+    "hoist-non-react-statics": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+      "requires": {
+        "react-is": "^16.7.0"
+      }
+    },
     "hoopy": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -9833,6 +9854,15 @@
       "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
       "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
     },
+    "mini-create-react-context": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
+      "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
+      "requires": {
+        "@babel/runtime": "^7.12.1",
+        "tiny-warning": "^1.0.3"
+      }
+    },
     "mini-css-extract-plugin": {
       "version": "0.11.3",
       "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz",
@@ -12268,11 +12298,69 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
       "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
     },
+    "react-redux": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz",
+      "integrity": "sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==",
+      "requires": {
+        "@babel/runtime": "^7.12.1",
+        "hoist-non-react-statics": "^3.3.2",
+        "loose-envify": "^1.4.0",
+        "prop-types": "^15.7.2",
+        "react-is": "^16.13.1"
+      }
+    },
     "react-refresh": {
       "version": "0.8.3",
       "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
       "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
     },
+    "react-router": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
+      "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "history": "^4.9.0",
+        "hoist-non-react-statics": "^3.1.0",
+        "loose-envify": "^1.3.1",
+        "mini-create-react-context": "^0.4.0",
+        "path-to-regexp": "^1.7.0",
+        "prop-types": "^15.6.2",
+        "react-is": "^16.6.0",
+        "tiny-invariant": "^1.0.2",
+        "tiny-warning": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+        },
+        "path-to-regexp": {
+          "version": "1.8.0",
+          "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+          "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+          "requires": {
+            "isarray": "0.0.1"
+          }
+        }
+      }
+    },
+    "react-router-dom": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
+      "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "history": "^4.9.0",
+        "loose-envify": "^1.3.1",
+        "prop-types": "^15.6.2",
+        "react-router": "5.2.0",
+        "tiny-invariant": "^1.0.2",
+        "tiny-warning": "^1.0.0"
+      }
+    },
     "react-scripts": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.2.tgz",
@@ -12454,6 +12542,20 @@
         "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-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.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -12709,6 +12811,11 @@
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
     },
+    "resolve-pathname": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
+      "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
+    },
     "resolve-url": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -14085,6 +14192,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",
@@ -14362,6 +14474,16 @@
       "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
     },
+    "tiny-invariant": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
+      "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
+    },
+    "tiny-warning": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+      "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+    },
     "tmpl": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -14832,6 +14954,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",

+ 4 - 0
shop/package.json

@@ -8,7 +8,11 @@
     "@testing-library/user-event": "^12.6.3",
     "react": "^17.0.1",
     "react-dom": "^17.0.1",
+    "react-redux": "^7.2.2",
+    "react-router-dom": "^5.2.0",
     "react-scripts": "4.0.2",
+    "redux": "^4.0.5",
+    "redux-thunk": "^2.3.0",
     "web-vitals": "^1.1.0"
   },
   "scripts": {

+ 19 - 2
shop/src/App.css

@@ -1,9 +1,16 @@
 * {
   padding: 0;
   margin: 0%;
+  color: rgb(229, 229, 243);
 
 }
-
+ .links {
+   text-decoration: none;
+   color: rgb(229, 229, 243);
+ }
+ .links:hover {
+  color: rgb(229, 229, 243);
+ }
 .header {
   position: fixed;
   width: 100%;
@@ -26,7 +33,7 @@
 .mobileMenu {
   position: absolute;
   background-color: rgb(58, 58, 65);
-  height: 20em;
+  height: 10em;
   border-radius: 0 0% 10% 10%;
   align-items: center;
   list-style-type: none; 
@@ -66,9 +73,19 @@
   width: 100%;
   height: 30em;
   margin-top: 50px;
+  display: flex;
 }
 
+aside {
+  width: 30%;
+}
+content {
+  width: 70%;
+}
 
+.About {
+
+}
 
 .footer {
   position: fixed;

+ 30 - 4
shop/src/App.js

@@ -2,14 +2,40 @@
 import './App.css';
 import Layout from "./components/layout.js";
 import MainImg from "./components/layout";
+import {Provider, connect} from 'react-redux';
+import {Header, Footer, catalogCard} from "./components/index"
+import {BrowserRouter as Router, Route, Link, Switch, Redirect} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import thunk from 'redux-thunk';
+
+function promiseReducer(state={}, action){
+  if (action.type === 'PROMISE'){
+      const { name="default", status, payload, error} = action
+      if (status){
+          return {
+              ...state, [name]: {status, payload: (status === 'PENDING' && state[name] && state[name].payload) || payload, error}
+          }
+      }
+  }
+  return state;
+}
+
+export const store = createStore(combineReducers({promise: promiseReducer}), 
+                        applyMiddleware(thunk))
 
 function App() {
   return (
     <>
-      <Layout>
-          <MainImg/>
-        
-      </Layout>
+      <Provider store={store}>
+      <Router history = {createHistory}>
+        <Header/>
+                  
+        <MainImg/>
+
+        <Footer/>
+      </Router>
+      </Provider>
     </>
   );
 }

+ 78 - 0
shop/src/components/MainImg.js

@@ -0,0 +1,78 @@
+import {BrowserRouter as Router, Route, Link, Switch, Redirect} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import About from "./about"
+import {Footer, catalogCard} from "./index"
+import { useState } from 'react';
+import {Provider, connect} from 'react-redux';
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import thunk from 'redux-thunk';
+
+const gql = "http://shop-roles.asmer.fs.a-level.com.ua/graphql";
+
+
+
+const getGQL = url => (query, variables = {}) => 
+        fetch(url, {
+                method: 'POST', 
+                headers: {
+                  'Accept': 'application/json',
+                  'Content-Type': 'application/json',
+                  ...(localStorage.authToken ? {Authorization: `Bearer ${localStorage.authToken}`} : {})
+                },
+                body: JSON.stringify({query, variables})
+        }).then(res => res.json())
+
+
+const Li = ({name}) => {
+    return(
+        <li>{name}</li>
+    )
+}
+
+
+
+
+const Catalog = ({getCat = () => console.log("no today")}) => {
+
+
+    return(
+        <>
+    <ul className = "catalog">
+        Работаю
+    </ul>
+     <button onClick={() => { if (!getCat){
+         debugger
+     }
+     console.log(getCat)
+         getCat()}}>mazafaca</button>
+     </>
+)}
+
+const BigCatalog = connect(() => ({}), { getCat: catalogCard })(Catalog);
+
+const MainImg = ({className = "MainImg"}) => {
+    return (
+        <div className = {className}>
+            <aside></aside>
+            <content>
+                <Switch>
+                    <Route path = "/" component = {Main} exact/>
+                    <Route path = "/catalog" component={BigCatalog}/>
+                    <Route path="/about" component = {About}/>
+                    <Route path = "/post" component = {Post}/>
+                    <Route path = "/contacts" component = {Contacts}/>
+                    <Route component = { NotFound } exact/>
+                </Switch>
+            </content>
+        </div>
+    )
+}
+const Main = () => <div>Я тут кароче самый главный страниц</div>
+const NotFound = () => <div>Да пошел ты!</div>
+
+const Post = () => <div className = "post">Точно не знаю зачем это, возможно потом уберу. Но в некоторых магазинах есть такое</div>
+const Contacts = () => <div className = "contacts">Тут будет адрес, номер телефона и соцсети</div>
+
+
+
+export default MainImg;

+ 2 - 0
shop/src/components/about.js

@@ -0,0 +1,2 @@
+const About = () => <div className = "About">Тут буде текст о том какой крутой этот магазин</div>
+export default About;

File diff suppressed because it is too large
+ 34 - 0
shop/src/components/footer.js


+ 95 - 0
shop/src/components/header.js

@@ -0,0 +1,95 @@
+import React, { useState } from 'react';
+import {Footer, catalogCard} from "./index"
+import {BrowserRouter as Router, Route, Link, Switch, Redirect} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import {Provider, connect} from 'react-redux';
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import thunk from 'redux-thunk';
+
+
+const Links = ({url, text}) => {
+    return (
+        <li>
+            <Link className = "links" to={url}>{text}</Link>
+        </li>
+    )
+}
+
+
+
+const StandartMenu = ({className = "standartMenu", getCat = null}) => {
+
+
+    return (
+        <>
+            <ul className = {className}>
+
+                <Links url = {"/catalog"} text = {"Каталог"}/>
+                <Links url = {"/about"} text = {"Про нас"}/>
+                <Links url = {"/post"} text = {"Оплата і доставка"}/>
+                <Links url = {"/contacts"} text = {"Контакти"}></Links>
+                {/* <button onClick={() => getCat()}>mazafaca</button> */}
+            </ul>
+        </>
+    )
+}
+
+//const CStandartMenu = connect(() => ({className: "standartMenu" }), { getCat: catalogCard })(StandartMenu);
+
+const TabletMenu = ({}) => {
+    const [show, setShow] = useState(false)
+    const divStyle = "mobileMenu"
+    function onClick() {
+
+        setShow(!show)
+    }
+
+    return (
+        <>
+            
+            <svg onClick = {onClick} xmlns="http://www.w3.org/2000/svg" width="50" height="50" fill="currentColor" class="bi bi-justify-left" viewBox="0 0 16 16">
+            <path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/>
+            </svg>
+            {show && <StandartMenu className = {divStyle}/>}
+        </>
+    )
+}
+
+const Header = ({}) => {
+    const [basketCount, buyDelete] = useState(0);
+    const [wishes, wishesCount] = useState(0);
+    return(
+        <>
+            <div className = "header">
+                
+                <div className = "tabletMenu">
+                    <TabletMenu/>
+                </div>
+                <StandartMenu/>
+
+                <div className = "rightSide">
+                    <div>
+                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16">
+                        <path d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/>
+                        </svg>
+                        <span>Хочу({wishes})</span>
+                    </div>
+                    <div>
+                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person" viewBox="0 0 16 16">
+                        <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/>
+                        </svg>
+                        <span>Вхід</span>
+                    </div>
+                    <div>
+                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bag" viewBox="0 0 16 16">
+                        <path d="M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z"/>
+                        </svg>
+                        <span>{basketCount}</span>
+                    </div>
+                </div>
+            </div>          
+        </>
+    )
+}
+
+export default Header;

+ 15 - 0
shop/src/components/index.js

@@ -0,0 +1,15 @@
+import React, { useState } from 'react';
+import {BrowserRouter as Router, Route, Link, Switch, Redirect} from 'react-router-dom';
+import createHistory from "history/createBrowserHistory";
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import Header from "./header";
+import Footer from "./footer";
+import MainImg from "./MainImg";
+import catalogCard from "../reducers/reducerCat";
+//import {store} from "../App";
+
+
+export {Header,Footer, MainImg, catalogCard};
+
+
+

File diff suppressed because it is too large
+ 17 - 106
shop/src/components/layout.js


+ 3 - 0
shop/src/reducers/index.js

@@ -0,0 +1,3 @@
+import catalogCard from "./reducerCat";
+
+export {catalogCard};

+ 104 - 0
shop/src/reducers/reducerCat.js

@@ -0,0 +1,104 @@
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import thunk from 'redux-thunk';
+import {Provider, connect} from 'react-redux';
+
+
+///reducer, где набор экшн.типов + функции.(если - то)
+// Экшн промис + асинх диспатч.(копия)
+//промис редюсер - копия
+//комбайн редюсер, в нем обьект разных редьюсеров. 
+//Распиоит на подобьекты, но экшены вместе. 
+//аплаймидлВар(санк) чтобы скачивать данные
+//стор.гетстейт принес обьект 1,03
+//другая гкуэль - функция,, параметр - строка из сайтагкуэль
+//параметры - то, что получаем(?). Засунуть внутрь функции(єкшн) в которой диспатч.
+
+
+const getGQL = url => 
+    (query, variables={}) => 
+        fetch(url, 
+            {method: 'POST', 
+                headers: {
+                  'Accept': 'application/json',
+                  'Content-Type': 'application/json',
+                  ...(localStorage.authToken ? {Authorization: `Bearer ${localStorage.authToken}`} : {})
+                },
+                body: JSON.stringify({query,variables})})
+        .then(res => res.json())
+
+export const actionPromise = (name, promise) => {
+    console.log(name);
+    const actionPending = () => ({type: 'PROMISE', name, status: 'PENDING', payload: null, error: null})
+    const actionResolved = payload => ({type: 'PROMISE', name, status: 'RESOLVED', payload, error: null})
+    const actionRejected = error => ({type: 'PROMISE', name, status: 'REJECTED', payload:null, error})
+
+
+    return async dispatch => {
+        dispatch(actionPending())
+        let payload
+        try {
+            payload = await promise
+            dispatch(actionResolved(payload))
+        }
+        catch (e){
+            dispatch(actionRejected(e))
+        }
+        return payload;
+    }
+}
+
+function promiseReducer(state={}, action){
+    if (action.type === 'PROMISE'){
+        const { name="default", status, payload, error} = action
+        if (status){
+            return {
+                ...state, [name]: {status, payload: (status === 'PENDING' && state[name] && state[name].payload) || payload, error}
+            }
+        }
+    }
+    return state;
+}
+
+const store = createStore(combineReducers({promise: promiseReducer}), 
+                        applyMiddleware(thunk))
+
+
+const gql = getGQL("http://shop-roles.asmer.fs.a-level.com.ua/graphql");
+
+const catalogCard = () => {
+    console.log(1);
+    return async dispatch => {
+        
+        let categories = await dispatch(actionPromise("data", gql(`
+            query categories {
+                CategoryFind(query:"[{}]") {
+                _id name 
+                goods {name, price _id, images {url}}
+                    image {
+                        _id
+                        createdAt
+                        text               
+                        originalFileName
+                    }
+                }
+            }`, )))
+        
+        console.log(categories);
+    }
+}
+
+
+
+store.subscribe(() => console.log(store.getState()))
+
+// function catalogReducer(state = {}, action) {
+//     if (action.type = "FIRSTVISIT") {
+//         catalogCard();
+//     } 
+//     return state;
+// };
+
+//const store = createStore(reducer, {});
+
+export default catalogCard;
+