Browse Source

sub cathegories displayment added where needed. Link to good page and page itself now can be displayed too

miskson 3 years ago
parent
commit
ef6500c625

+ 112 - 0
hw15-gql-cathegory-pg/GQL.html

@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!-- saved from url=(0070)http://gql.asmer.fe.a-level.com.ua/#/category/5dc49f4d5df9d670df48cc64 -->
+<html>
+
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>GQL</title>
+
+  <style>
+    header {
+      color: white;
+      background-color: black;
+    }
+
+    aside a {
+      background-color: black;
+      padding: 5px;
+      margin: 5px;
+      border-right: 5px inset darkviolet;
+      color:  whitesmoke;
+    }
+
+    aside a:hover {
+      background-color: purple;
+    }
+
+    #mainContainer {
+      display: flex;
+    }
+
+    #aside {
+      width: 30%;
+    }
+
+    #aside>a {
+      display: block;
+    }
+
+    .card {
+      background-color: whitesmoke;
+      border: 1px solid black;
+      margin: 10px;
+      padding : 10px;
+    }
+  </style>
+  <style type="text/css"></style>
+</head>
+
+<body>
+  <header><h1>ГДЕ Я ОКАЗАЛСЯ?</h1></header>
+  <div id="mainContainer">
+    <aside id="aside"><a href="http://gql.asmer.fe.a-level.com.ua/#/category/5dc45acf5df9d670df48cc48">TV's</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dc49f4d5df9d670df48cc64">Airconditions</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dc458985df9d670df48cc47">Smartphones</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dc4b2553f23b553bf354101">Крупная бытовая техника</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dcac1b56d09c45440d14cf8">Макароны</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dcac6cf6d09c45440d14cfd">Drinks</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dcacaeb6d09c45440d14d04">Салаты</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/61715b92ef4e1b3e3b67703c">Приятный бонус</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dc94bd00e36db246e3049ee">Пицца</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dcabeeb6d09c45440d14cf6">Макароны</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/5dcadc906d09c45440d14d11">Сушка</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/61715d73ef4e1b3e3b67703d">Приятный бонус</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/61715f99ef4e1b3e3b67703e">Приятные бонусы</a><a
+        href="http://gql.asmer.fe.a-level.com.ua/#/category/6171616bef4e1b3e3b67703f">бонус номер 3</a></aside>
+    <main id="main">
+      <h1>Airconditions</h1>
+      <div class="card">
+        <h2>КОНДИЦИОНЕР DAIKIN FTXB35C/RXB35C</h2>
+        <img  style="border: 1px dashed grey;" src="./GQL_files/d43e1a5d6e98d799bd7afcef49abac3f">
+        <br>
+        <strong>Price: 5632</strong>
+        <br>
+        <a href="#/good/5e1f396856d8f720513e6cae">На страницу товара</a>
+      </div>
+      <div class="card">
+        <h2>MSZ-DM25VA</h2>
+        <img style="border: 1px dashed grey;" src="./GQL_files/4d3137311a7f54f1e9e8ae98c72e8f17">
+        <br>
+        <strong>6987</strong>
+        <br>
+        <a href="#/good/5e1f3e0856d8f720513e6cb0">На страницу товара</a>
+      </div>
+      <div class="card">
+        <h2>Кондиционер COOPER&amp;HUNTER CH-S12XP7</h2>
+        <img style="border: 1px dashed grey;" src="./GQL_files/8ab88e5340f9e56ec50a9d69bf890d9a">
+        <br>
+        <strong>9874</strong>
+        <br>
+        <a href="#/good/5e1f6e5f56d8f720513e6cb5">На страницу товара</a>
+      </div>
+      <div class="card">
+        <h2>КАССЕТНЫЕ КОНДИЦИОНЕРЫ GREE U-MATCH</h2>
+        <img style="border: 1px dashed grey;" src="./GQL_files/63f2139a6fda73190114ebc4647b4fa2">
+        <br>
+        <strong>12563</strong>
+        <br>
+        <a href="#/good/5e1f735b56d8f720513e6cb8">На страницу товара</a>
+      </div>
+      <div class="card">
+        <h2>OSAKARA ELITE NEW 2019</h2>
+        <img style="border: 1px dashed grey;" src="./GQL_files/cc69bbc6c39539e23ed9b15323f72e4e">
+        <br>
+        <strong>5555</strong>
+        <br>
+        <a href="#/good/5e20929156d8f720513e6cd7">На страницу товара</a>
+      </div>
+    </main>
+  </div>
+  <script src="./GQL_files/index.js"></script>
+</body>
+</html>

BIN
hw15-gql-cathegory-pg/GQL_files/4d3137311a7f54f1e9e8ae98c72e8f17


BIN
hw15-gql-cathegory-pg/GQL_files/63f2139a6fda73190114ebc4647b4fa2


BIN
hw15-gql-cathegory-pg/GQL_files/8ab88e5340f9e56ec50a9d69bf890d9a


BIN
hw15-gql-cathegory-pg/GQL_files/cc69bbc6c39539e23ed9b15323f72e4e


BIN
hw15-gql-cathegory-pg/GQL_files/d43e1a5d6e98d799bd7afcef49abac3f


+ 226 - 0
hw15-gql-cathegory-pg/GQL_files/index.js

@@ -0,0 +1,226 @@
+function createStore(reducer) {
+    let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
+    let cbs = []                     //массив подписчиков
+
+    const getState = () => state            //функция, возвращающая переменную из замыкания
+    const subscribe = cb => (cbs.push(cb),   //запоминаем подписчиков в массиве
+        () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
+
+    const dispatch = action => {
+        if (typeof action === 'function') { //если action - не объект, а функция
+            return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
+        }
+        const newState = reducer(state, action) //пробуем запустить редьюсер
+        if (newState !== state) { //проверяем, смог ли редьюсер обработать action
+            state = newState //если смог, то обновляем state 
+            for (let cb of cbs) cb() //и запускаем подписчиков
+        }
+    }
+
+    return {
+        getState, //добавление функции getState в результирующий объект
+        dispatch,
+        subscribe //добавление subscribe в объект
+    }
+}
+
+function promiseReducer(state = {}, { type, name, status, payload, error }) {
+    if (type === 'PROMISE') {
+        return {
+            ...state,
+            [name]: { status, payload, error }
+        }
+    }
+    return state
+}
+
+const store = createStore(promiseReducer)
+store.subscribe(() => console.log('state of store:', 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 actionPromise = (name, promise) =>
+    async dispatch => {
+        dispatch(actionPending(name)) // 1. {delay1000: {status: 'PENDING'}}
+        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: {
+                //заголовок content-type
+                "Content-Type": "application/json",
+                ...(localStorage.authToken ? { "Authorization": "Bearer " + localStorage.authToken } : {})
+            },
+            //body с ключами query и variables 
+            body: JSON.stringify({ query, variables })
+        })
+            .then(res => res.json())
+            .then(data => {
+                if (data.errors && !data.data)
+                    throw new Error(JSON.stringify(data.errors))
+                return data.data[Object.keys(data.data)[0]]
+            })
+
+const backURL = 'http://shop-roles.asmer.fs.a-level.com.ua'
+
+const gql = getGQL(`${backURL}/graphql`)
+
+const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
+
+const actionRootCats = () =>
+    actionPromise('rootCats', gql(`query {
+        CategoryFind(query: "[{\\"parent\\":null}]"){
+            _id name
+        }
+    }`))
+
+const actionCatById = (_id) =>  //добавить подкатегории
+    actionPromise('catById', gql(`query catById($q: String){
+        CategoryFindOne(query: $q){
+            _id 
+            name
+            subCategories {
+                _id name
+            } 
+            goods {
+                _id name price images {
+                    url
+                }
+            }
+        }
+    }`, { q: JSON.stringify([{ _id }]) }))
+
+store.dispatch(actionRootCats())
+
+const actionGoodById = (_id) => 
+    actionPromise('goodById', gql(`
+        query goodById ($good:String) {
+            GoodFindOne(query: $good) {
+                name 
+                description 
+                price
+                categories {
+                    name
+                } 
+                images {
+                    url
+                }
+            }
+        }`, { good: JSON.stringify([{ _id }]) }))
+
+
+store.subscribe(() => {
+    //console.log(location)
+    const { rootCats } = store.getState()
+
+    if (rootCats?.payload) {
+        aside.innerHTML = ''
+        for (const { _id, name } of rootCats?.payload) {
+            const link = document.createElement('a')
+            link.href = `#/category/${_id}`
+            link.innerText = name
+            aside.append(link)
+        }
+    }
+})
+
+window.onhashchange = () => {
+    const [, route, _id] = location.hash.split('/')
+
+    const routes = {
+        category() {
+            store.dispatch(actionCatById(_id))
+        },
+        good() { //задиспатчить actionGoodById
+            store.dispatch(actionGoodById(_id))
+        },
+    }
+    if (route in routes)
+        routes[route]()
+}
+window.onhashchange()
+
+
+store.subscribe(() => {
+    //console.log(location)
+    //console.log('drawing cat list')
+    const { catById } = store.getState()
+    const [, route, _id] = location.hash.split('/')
+
+    if (catById?.payload && route === 'category') {
+        const { name, subCategories } = catById.payload
+        main.innerHTML = `<h1>${name}</h1>`
+
+        if (subCategories) {
+            console.log('here')
+            let subCats = document.createElement('div')
+            for (let item of subCategories) {
+                let span = document.createElement('span')
+                span.innerText = `${item.name} | `
+                subCats.append(span)
+            }
+            main.append(subCats)
+        }
+        main.style.padding = "10px"
+
+        if (catById.payload.goods) {
+            for (const { _id, name, price, images } of catById.payload.goods) {
+                const card = document.createElement('div')
+                card.innerHTML = `
+                    <h2>${name}</h2>
+                    <img style="border: 1px dashed grey;" src="${backURL}/${images[0].url}" />
+                    <br>
+                    <strong>Price: ${price}</strong>
+                    <br>
+                    <a href="#/good/${_id}">На страницу товара</a>
+                `
+                card.style.backgroundColor = "whitesmoke"
+                card.style.border = "1px solid black"
+                card.style.margin = "10px"
+                card.style.padding = "10px"
+                main.append(card)
+            }
+        }
+    }
+})
+
+store.subscribe(() => {
+    //console.log('drawing page of good')
+    const { goodById } = store.getState()
+    const [, route, _id] = location.hash.split('/')
+
+    if (goodById?.payload && route === 'good') {
+        const { name, categories, images, price, description } = goodById.payload
+
+        main.innerHTML = `
+            <div class="card">
+                <button onclick="history.back()">&#8656 назад</button>
+                <h1>${name}</h1>
+                <h4>${categories[0].name}<h4>
+                <br>
+                <img style="border: 1px dashed grey;" src="${backURL}/${images[0].url}" />
+                <br>
+                <strong>Price: ${price}</strong>
+                <p>${description}</p>
+            </div>
+        `
+        main.style.padding = "10px"
+    }
+})
+
+window.onload = () => {
+    location.href = location.origin + "/GQL.html#/category/5dc49f4d5df9d670df48cc64"
+}