Browse Source

shopGQL 1.0 done

Vadym Hlushko 3 years ago
parent
commit
1b3e4236b9
3 changed files with 301 additions and 0 deletions
  1. BIN
      shopGQL/basket.png
  2. 32 0
      shopGQL/index.html
  3. 269 0
      shopGQL/main.js

BIN
shopGQL/basket.png


+ 32 - 0
shopGQL/index.html

@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title>Doc</title>
+        <meta charset='utf8' />
+        <style>
+            #mainContainer {
+                display: flex;
+            }
+            #aside {
+                width: 30%;
+            }
+            #aside > a{
+                display: block;
+            }
+            #h1{
+                font-size: 20px;
+            }
+        </style>
+    </head>
+    <body>
+        <header><h1 id='h1'>Категории</h1></header>
+        <div id='mainContainer'>
+            <aside id='aside'>
+                Категории
+            </aside>
+            <main id='main'>
+            </main>
+        </div>
+        <script src='main.js'></script>
+    </body>
+</html>

+ 269 - 0
shopGQL/main.js

@@ -0,0 +1,269 @@
+function createStore(reducer){
+    let state = reducer(undefined, {})
+    let cbs   = []
+    function dispatch(action){
+        if (typeof action === 'function'){
+            return action(dispatch)
+        }
+        const newState = reducer(state, action)
+        if (state !== newState){
+            state = newState
+            cbs.forEach(cb => cb())
+        }
+    }
+    return {
+        dispatch,
+        subscribe(cb){
+            cbs.push(cb)
+            return () =>  cbs = cbs.filter(c => c !== cb)
+        },
+        getState(){
+            return state
+        }
+    }
+}
+function promiseReducer(state={}, {type, status, payload, error, name}){
+    if (type === 'PROMISE'){
+        return {
+            ...state,
+            [name]:{status, payload, error}
+        }
+    }
+    return state
+}
+
+
+//под товаром сделать кнопку "купить"
+
+
+const store = createStore(promiseReducer)
+const unsubscribe1 = store.subscribe(() => console.log(store.getState()))
+
+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})
+
+const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
+
+const actionPromise = (name, promise) => 
+    async dispatch => {
+        dispatch(actionPending(name))
+        try{
+            let payload = await promise
+            dispatch(actionResolved(name, payload)) 
+            return payload
+        }
+        catch(error){
+             dispatch(actionRejected(name, error))
+        }
+    }
+
+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())
+
+let shopGQL = getGQL('http://shop-roles.asmer.fs.a-level.com.ua/graphql')
+
+const goodById = id => {
+    let query = `query goodById($query:String) {
+        GoodFindOne(query: $query ) {
+            _id
+            name
+            description
+            price
+            images {
+                url
+            }
+        }
+    }`
+    let variables = {
+        query: JSON.stringify([{_id: id}]) 
+    } 
+    let res = shopGQL(query,variables)
+    return res
+}
+
+const actionGoodById = id => 
+    actionPromise('goodById', goodById(id))
+
+const actionRootCategories = () =>
+    actionPromise('rootCategories', shopGQL(`
+            query cats($query:String){
+              CategoryFind(query:$query){
+                _id name 
+              }
+            }
+        `, {query: JSON.stringify([{parent:null}])}))
+
+const actionCategoryById = (_id) => 
+    actionPromise('catById', shopGQL(`query catById($query:String){
+                                          CategoryFindOne(query:$query){
+                                            _id name goods{
+                                              _id name price description images{
+                                                url
+                                              }
+                                            }
+                                          }
+                                        }`, {query: JSON.stringify([{_id}])}))
+
+
+store.dispatch(actionRootCategories())
+
+window.onhashchange = () => {
+    let {1: route, 2:id} = location.hash.split('/')
+    if (route === 'categories'){
+        store.dispatch(actionCategoryById(id))
+    }
+
+    if (route === 'good'){
+        store.dispatch(actionGoodById(id))
+    }
+}
+
+function drawMainMenu(){
+    let cats = store.getState().rootCategories.payload
+    if (cats){ //каждый раз дорисовываются в body
+        aside.innerText = ''
+        for (let {_id, name} of cats.data.CategoryFind){
+            let catA = document.createElement('a')
+            catA.href = `#/categories/${_id}`
+            catA.innerText = name
+            aside.append(catA)
+        }
+    }
+}
+
+store.subscribe(drawMainMenu)
+
+
+store.subscribe(() => {
+    const {1: route, 2:id} = location.hash.split('/')
+    if (route === 'categories'){
+        const catById = store.getState().catById?.payload
+        if (catById){
+            main.innerText = ''
+            let h = document.createElement('h2')
+            h.style.fontSize = '30px'
+            h.style.marginTop = 0
+            h.innerHTML = catById.data.CategoryFindOne.name
+            h.style.textAlign = 'center'
+            main.append(h)
+            //вывести циклом товары со ссылками вида #/good/АЙДИШНИК
+            let goods = document.createElement('div')
+            goods.className = 'goods'
+            for (let key in catById.data.CategoryFindOne.goods) {
+                let box = document.createElement('div')
+                box.style.border = '3px solid #008B8B'
+                box.style.padding = '10px'
+                box.style.margin = '20px'
+                let img = document.createElement('img')
+                let productName = document.createElement('h3')
+                let a = document.createElement('a')
+                let price = document.createElement('p')
+                let description = document.createElement('p')
+                let btnBuy = document.createElement('button')
+                btnBuy.innerHTML = "Купить"
+                btnBuy.style.backgroundColor = '#ADFF2F'
+                btnBuy.style.display = 'block'
+                btnBuy.style.marginLeft = 'auto'
+                btnBuy.style.marginRight = 'auto'
+                btnBuy.style.marginBottom = '10px'
+                let btnAdd = document.createElement('button')
+                btnAdd.innerHTML = "Добавить в корзину"
+                btnAdd.style.backgroundColor = '#3CB371'
+                btnAdd.style.display = 'block'
+                btnAdd.style.marginLeft = 'auto'
+                btnAdd.style.marginRight = 'auto'
+                let btnMore = document.createElement('button')
+                btnMore.innerHTML = "Подробнее"
+                btnMore.style.backgroundColor = '#DCDCDC'
+                btnMore.style.display = 'block'
+                btnMore.style.marginLeft = 'auto'
+                btnMore.style.marginRight = 'auto' 
+                btnMore.style.marginTop = '20px'
+                img.src =  'http://shop-roles.asmer.fs.a-level.com.ua/' + catById.data.CategoryFindOne.goods[key].images[0].url
+                img.style.width = '300px'
+                img.style.display = 'block'
+                img.style.marginLeft = 'auto'
+                img.style.marginRight = 'auto'
+                a.href = '#/good/' + catById.data.CategoryFindOne.goods[key]._id
+                productName.innerHTML = catById.data.CategoryFindOne.goods[key].name + '<br/>'
+                price.innerHTML = "Цена:" + " " + catById.data.CategoryFindOne.goods[key].price + ' ' + 'uah'
+                a.style.textDecoration = 'none'
+                a.style.color = 'black'
+                description.innerHTML = catById.data.CategoryFindOne.goods[key].description
+                description.style.textAlign = 'center'
+                a.append(btnMore)
+                box.append(productName)
+                box.append(price)
+                box.append(img)
+                box.append(description)
+                box.append(btnBuy)
+                box.append(btnAdd)
+                box.append(a)
+                goods.append(box)
+            }
+            main.append(goods)
+            //ПРИДУМАТЬ КНОПКИ ДОБАВЛЕНИЯ В КОРЗИНУ
+            // main.innerHTML = `<pre>${JSON.stringify(catById, null ,4)}</pre>`
+        }
+    }
+    if (route === 'good'){
+        const goodById = store.getState().goodById?.payload
+        if (goodById){ //вывести в main страницу товара
+            main.innerText = " "
+            let source = goodById.data.GoodFindOne 
+            let product = document.createElement('div')
+                let page = document.createElement('div')
+                let h = document.createElement('h1')
+                h.innerHTML = source.name
+                h.style.textAlign = 'center'
+                let img = document.createElement('img')
+                img.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + source.images[0].url
+                img.style.width = '300px'
+                img.style.display = 'block'
+                img.style.marginLeft = 'auto'
+                img.style.marginRight = 'auto'
+                let description = document.createElement('p')
+                description.innerHTML = source.description
+                description.style.textAlign = 'center'
+                let price = document.createElement('p')
+                price.innerHTML = 'Цена:' + " " + source.price + 'uah'
+                price.textAlign = 'center'
+                let btnBuy = document.createElement('button')
+                btnBuy.innerHTML = "Купить"
+                btnBuy.style.backgroundColor = '#ADFF2F'
+                btnBuy.style.display = 'block'
+                btnBuy.style.marginLeft = 'auto'
+                btnBuy.style.marginRight = 'auto'
+                btnBuy.style.marginBottom = '10px'
+                btnBuy.style.marginTop = '50px'
+                btnBuy.style.width = '300px'
+                btnBuy.style.fontSize = '20px'
+                let btnAdd = document.createElement('button')
+                btnAdd.innerHTML = "Добавить в корзину"
+                btnAdd.style.backgroundColor = '#3CB371'
+                btnAdd.style.display = 'block'
+                btnAdd.style.marginLeft = 'auto'
+                btnAdd.style.marginRight = 'auto'
+                btnAdd.style.width = '300px'
+                btnAdd.style.fontSize = '20px'
+                page.append(h)
+                page.append(img)
+                page.append(description)
+                page.append(price)
+                page.append(btnBuy)
+                page.append(btnAdd)
+                product.append(page)
+                main.append(product)
+        }
+    }
+})