Selaa lähdekoodia

orders now can be made and displayed on #/orders. Cart now can be cleaned in different ways

miskson 3 vuotta sitten
vanhempi
commit
c6650e47df
2 muutettua tiedostoa jossa 165 lisäystä ja 76 poistoa
  1. 14 0
      hw15-gql-cathegory-pg/GQL.html
  2. 151 76
      hw15-gql-cathegory-pg/GQL_files/index.js

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

@@ -7,6 +7,10 @@
   <title>GQL</title>
 
   <style>
+    body {
+      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+    }
+    
     header {
       color: white;
       background-color: black;
@@ -50,6 +54,16 @@
       text-decoration: none;
       margin: 0 10px;
     }
+
+    .addBtn {
+      background-color: mediumseagreen; 
+      color: white;
+    }
+
+    .decBtn {
+      background-color: red; 
+      color: white;
+    }
   </style>
   <style type="text/css"></style>
 </head>

+ 151 - 76
hw15-gql-cathegory-pg/GQL_files/index.js

@@ -40,7 +40,7 @@ const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED',
 
 const actionPromise = (name, promise) =>
     async dispatch => {
-        dispatch(actionPending(name)) // 1. {delay1000: {status: 'PENDING'}}
+        dispatch(actionPending(name))
         try {
             let payload = await promise
             dispatch(actionResolved(name, payload))
@@ -54,14 +54,11 @@ const actionPromise = (name, promise) =>
 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())
@@ -77,7 +74,6 @@ const gql = getGQL(`${backURL}/graphql`)
 
 const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
 
-/********************************MY STUFFF START****************************************************** */
 function jwtDecode(token) {
     try {
         let decoded = token.split('.')
@@ -143,11 +139,9 @@ const store = createStore(combinedReducer)
 const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
 const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
 
-//const store = createStore(authReducer)
 console.log(store.getState()) //стартовое состояние может быть с токеном
 store.subscribe(() => console.log(store.getState()))
 
-//ПЕРЕДЕЛАТЬ ОТОБРАЖЕНИЕ с поправкой на то, что теперь промисы не в корне state а в state.promise
 const actionLogin = (login, password) =>
     actionPromise('login', gql(`
     query log($login:String, $password:String) {
@@ -184,6 +178,19 @@ const actionGetOrders = () =>
       }
     `))
 
+const actionCreateOrder = (count, id) =>
+      actionPromise('createOrder', gql(`
+        mutation createOrder($count:Int!, $id:ID) {
+            OrderUpsert( order:{ orderGoods: [ {count: $count, good:{_id: $id}} ] } ) { 
+            _id 
+            total 
+            orderGoods {
+                good { _id name }
+            }
+            }
+        }
+      `, {count, id}))
+
 const actionRegister = (login, password) =>
     actionPromise('registration', gql(`
         mutation register($login:String, $password:String) {
@@ -196,39 +203,32 @@ const actionRegister = (login, password) =>
             }
         }
       `, { login, password }))
-//const actionRegister //actionPromise
-//const actionFullRegister = (login, password) => //actionRegister + actionFullLogin
-//+ интерфейс к этому - форму логина, регистрации, может повесить это на #/login #/register 
-//+ #/orders показывает ваши бывшие заказы:
-//сделать actionMyOrders
-//
+
 
 let logBtn = document.getElementById('logBtn')
-/********************************MY STUFFF END****************************************************** */
 
-/********************************MY STUFFF CART START****************************************************** */
 function cartReducer(state = {}, { type, good = {}, count = 1 }) {
-    //{
-    //  _id1: {good, count}
-    //  _id2: {good, count}
-    //}
     let { _id } = good
+    console.log('_id from state',_id)
     const types = {
-        CART_ADD() { //как CHANGE, только если ключ раньше был, то достать из count и добавить
-            //к count из action. Если не было, достать 0 и добавить к count из action
+        CART_ADD() {
             return {
                 ...state,
                 [_id]: { good, count: (state[_id]?.count || 0) + count }
             }
         },
-        CART_REMOVE() { //смочь скопировать объект и выкинуть ключ. как вариант через
-            //деструктуризацию
-            let { _id, ...newState } = state
+        CART_REMOVE() {
+            let newState = {}
+            for(let key in state) {
+                if(key !== _id) {
+                    newState[key] = state[key]
+                }
+            }
             return newState
         },
         CART_CHANGE() {
             return {
-                ...state, //по аналогии с promiseReducer дописать
+                ...state,
                 [_id]: { good, count }
             }
         },
@@ -243,12 +243,11 @@ function cartReducer(state = {}, { type, good = {}, count = 1 }) {
 
     return state
 }
-//понаписывать action
-//прикрутить к товару кнопку которая делает store.dispatch(actionCartAdd(good))
 const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', good, count })
-const actionCartDel = (good, count = 1) => ({ type: 'CART_REMOVE', good, count })
+const actionCartDel = (good) => ({ type: 'CART_REMOVE', good})
+const actionCartClear = () => ({type: 'CART_CLEAR'})
+const actionCartChange = (good, count) => ({type: 'CART_CHANGE', good, count})
 
-/********************************MY STUFFF CART END****************************************************** */
 const actionRootCats = () =>
     actionPromise('rootCats', gql(`query {
         CategoryFind(query: "[{\\"parent\\":null}]"){
@@ -422,64 +421,136 @@ window.onhashchange = () => {
             }
         },
         cart() {
-            const { cart } = store.getState()
             aside.innerHTML = ''
             main.innerHTML = `
                 <button onclick="history.back()" style="font-size: smaller;">&#8656 назад</button>
                 <h2>Корзина</h2>
-                <h4>Общая цена заказов:<span id="fullPrice"></span></h4>
+                <h4>Общая цена заказов: <span id="fullPrice"></span></h4>
                 <button id="clearCartBtn" style="background-color: firebrick; color: white; font-size: smaller;">Очистить корзину</button>
+                <button id="orderAll" font-size: smaller;">Заказать все</button>'
                 <br>
+                <div id="cartContent"></div>
             `
+            let cartContent = document.getElementById('cartContent')
+            let orderAllBtn = document.getElementById('orderAll')
+            if(localStorage.authToken) {
+                orderAllBtn.disabled = false
+                orderAllBtn.style.backgroundColor = "mediumseagreen"
+                orderAllBtn.style.color = 'white'
+            } else {
+                orderAllBtn.disabled = true
+                orderAllBtn.style.backgroundColor = "grey"
+                orderAllBtn.style.color = 'whitesmoke'
+            }
+
+            orderAllBtn.onclick = () => {
+                console.log('orderAll clicked');
+                (async () => {
+                    let cart = store.getState().cart
+                    await store.dispatch(actionCartClear())
+                    for(let item in cart) {
+                        await store.dispatch(actionCreateOrder(cart[item].count, cart[item].good._id))
+                        drawCart()
+                    }
+                    await store.dispatch(actionGetOrders())
+                    aside.innerHTML = ''
+                })()
+            }
+
             let clearCartBtn = document.getElementById('clearCartBtn')
             clearCartBtn.onclick = () => {
-                //clear cart action
+                (async () => {
+                    await store.dispatch(actionCartClear())
+                    drawCart()
+                })()
             }
 
-            let fullPrice = 0
-            for (let item in cart) {
-                let orderPrice = cart[item].good.price * cart[item].count
-                let card = document.createElement('div')
-                fullPrice += orderPrice
-                let delOrderBtn = document.createElement('button')
-                delOrderBtn.style.backgroundColor = "firebrick"
-                delOrderBtn.style.color = "white"
-                delOrderBtn.style.fontSize = "smaller"
-                delOrderBtn.style.float = "right"
-                delOrderBtn.innerText = "Удалить заказ [x]"
-                card.append(delOrderBtn)
-
-                delOrderBtn.onclick = () => {
-                    console.log('nuaaaaaa', cart[item].good)
-                    store.dispatch(actionCartDel(cart[item].good))
-
-                }
+            function drawCart() {
+                let fullPrice = 0
+                let cart = store.getState().cart
+
+                cartContent.innerHTML = ``
+                if(Object.keys(cart).length > 0) {
+                    for (let item in cart) {
+                        let orderPrice = cart[item].good.price * cart[item].count
+                        fullPrice += orderPrice
+
+                        let delOrderBtn = document.createElement('button')
+                        delOrderBtn.style.backgroundColor = "firebrick"
+                        delOrderBtn.style.color = "white"
+                        delOrderBtn.style.fontSize = "smaller"
+                        delOrderBtn.style.float = "right"
+                        delOrderBtn.innerText = "Удалить заказ [x]"
+                        delOrderBtn.onclick = () => {
+                            (async () => {
+                                await store.dispatch(actionCartDel(cart[item].good))
+                                drawCart()
+                            })()
+                        }
+                    
+                        let card = document.createElement('div')
+                        card.append(delOrderBtn)
+    
+                        card.insertAdjacentHTML('beforeend', `
+                            <br>
+                            <h2>${cart[item].good.name}</h2>
+                            <div style="
+                                    border:5px solid mediumvioletred; 
+                                    background-color: black; 
+                                    color: white; 
+                                    padding: 10px 5px;"
+                            >
+                                <h4>Кол-во: <button class="decBtn">-</button> ${cart[item].count} <button class="addBtn">+</button></h4>
+                                <h4>Стоимость заказа: <span style="color: gold">${orderPrice}</span></h4>
+                                <button class="makeOrderBtn" ${localStorage.authToken? 'style="background-color: mediumseagreen; color: white;"' : 'disabled'}>
+                                    ${localStorage.authToken? 'Заказать' : 'Только авторизованные пользователи могут совершать заказы'}
+                                </button>
+                            </div>
+                            <br>
+                            <img style="border: 1px dashed grey;" src="${backURL}/${cart[item].good.images[0].url}" />
+                            <br>
+                            <strong>Цена за ед. товара: ${cart[item].good.price}</strong>
+                            <br>
+                            <a href="#/good/${cart[item].good._id}">На страницу товара</a>
+                            <br>
+                        `)
+                        card.style.backgroundColor = "whitesmoke"
+                        card.style.border = "1px solid black"
+                        card.style.margin = "10px"
+                        card.style.padding = "10px"
+
+                        card.querySelector('.decBtn').disabled = (cart[item].count <= 1)
+                        card.querySelector('.decBtn').onclick = () => {
+                            (async() => {
+                                await store.dispatch(actionCartChange(cart[item].good, cart[item].count-1))
+                                drawCart()
+                            })()
+                        }
 
-                card.insertAdjacentHTML('beforeend', `
-                    <br>
-                    <h2>${cart[item].good.name}</h2>
-                    <div style="border:5px solid mediumvioletred; background-color: black; color: white; padding: 0px 5px;">
-                        <h4>Кол-во: ${cart[item].count}</h4>
-                        <h4>Стоимость заказа: ${orderPrice}</h4>
-                    </div>
-                    <br>
-                    <img style="border: 1px dashed grey;" src="${backURL}/${cart[item].good.images[0].url}" />
-                    <br>
-                    <strong>Цена за ед. товара: ${cart[item].good.price}</strong>
-                    <br>
-                    <a href="#/good/${cart[item].good._id}">На страницу товара</a>
-                    <br>
-                `)
+                        card.querySelector('.addBtn').onclick = () => {
+                            (async() => {
+                                await store.dispatch(actionCartChange(cart[item].good, cart[item].count+1))
+                                drawCart()
+                            })()
+                        }
 
-                card.style.backgroundColor = "whitesmoke"
-                card.style.border = "1px solid black"
-                card.style.margin = "10px"
-                card.style.padding = "10px"
-                main.append(card)
+                        card.querySelector('.makeOrderBtn').onclick = () => {
+                            (async() => {
+                                await store.dispatch(actionCreateOrder(cart[item].count, cart[item].good._id))
+                                await store.dispatch(actionCartDel(cart[item].good))
+                                await store.dispatch(actionGetOrders())
+                                drawCart()
+                            })()
+                        }
+                        cartContent.append(card)
+                    }
+                }
+                aside.innerHTML = ``
+                
+                let fullPriceSpan = document.getElementById('fullPrice')
+                fullPriceSpan.innerText = `${fullPrice}`
             }
-            console.log('full prise', fullPrice)
-            let fullPriceSpan = document.getElementById('fullPrice')
-            fullPriceSpan.innerText = `${fullPrice}`
+            drawCart()
         },
         orders() {
             aside.innerHTML = ''
@@ -488,7 +559,8 @@ window.onhashchange = () => {
                 <h2>Список заказов ${store.getState().auth.payload.sub.login}</h2>
                 <br>
             `
-
+            let container = document.createElement('div')
+            main.append(container)
             if (store.getState().promise.orders) {
                 const payload = store.getState().promise.orders.payload
                 if (payload.length > 0) {
@@ -516,7 +588,7 @@ window.onhashchange = () => {
                                 card.style.border = "1px solid black"
                                 card.style.margin = "10px"
                                 card.style.padding = "10px"
-                                main.append(card)
+                                container.prepend(card)
                             } catch (e) {
                                 console.log('nulls are ignored')
                             }
@@ -532,6 +604,7 @@ window.onhashchange = () => {
 window.onhashchange()
 
 
+//drawing goood list of cathegory
 store.subscribe(() => {
     const { catById } = store.getState().promise
     const [, route, _id] = location.hash.split('/')
@@ -591,6 +664,7 @@ store.subscribe(() => {
     }
 })
 
+//item page
 store.subscribe(() => {
     const { goodById } = store.getState().promise
     const [, route, _id] = location.hash.split('/')
@@ -614,6 +688,7 @@ store.subscribe(() => {
     }
 })
 
+//cntrol over login
 store.subscribe(() => {
     const { payload } = store.getState().auth
     const [, route, _id] = location.hash.split('/')
@@ -685,6 +760,7 @@ store.subscribe(() => {
     }
 })
 
+//count cart items
 store.subscribe(() => {
     const { cart } = store.getState()
     let items = 0
@@ -696,7 +772,6 @@ store.subscribe(() => {
 })
 
 window.onload = () => {
-    console.log('RELOADED')
     location.href = "#/category/5dc49f4d5df9d670df48cc64"
     store.dispatch(actionGetOrders())
 }