Browse Source

merging cart implementation with master branch

miskson 3 years ago
parent
commit
de9275896d
2 changed files with 175 additions and 39 deletions
  1. 16 4
      hw15-gql-cathegory-pg/GQL.html
  2. 159 35
      hw15-gql-cathegory-pg/GQL_files/index.js

+ 16 - 4
hw15-gql-cathegory-pg/GQL.html

@@ -47,12 +47,24 @@
 </head>
 
 <body>
-  <header>
+  <header style="padding: 5px;">
     <h1>ГДЕ Я ОКАЗАЛСЯ?</h1>
     <div>
-      <span>Name</span>
-      <a id="logBtn" href="#/login" style="color: hotpink;">log-in</a>
-      <!-- <button>order</button> -->
+      <div style="display: inline-block; border: 1px dashed white; padding: 5px;">
+        <span id="nameField">Name</span>
+        <button id="logBtn" style="padding: 5px; font-size: small; background-color:mediumaquamarine;">log-in/out</button>
+      </div>
+      <a 
+        href="#/cart" 
+        id="cartBtn" 
+        style="
+          color: white;
+          background-color: purple;
+          padding: 0px 5px;
+          text-decoration: none;
+        ">
+      в корзину <span id="itemCount" style="color: gold;"></span>
+      </a>
     </div>
   </header>
 

+ 159 - 35
hw15-gql-cathegory-pg/GQL_files/index.js

@@ -78,22 +78,22 @@ const gql = getGQL(`${backURL}/graphql`)
 const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
 
 /********************************MY STUFFF START****************************************************** */
-function jwtDecode(token){
+function jwtDecode(token) {
     try {
         let decoded = token.split('.')
         decoded = decoded[1]
         decoded = atob(decoded)
         decoded = JSON.parse(decoded)
         return decoded
-    
-    } catch(e) {
+
+    } catch (e) {
         return;
     }
 }
 
-function authReducer(state, {type, token}){
-    if (!state){
-        if(!localStorage.authToken) {
+function authReducer(state, { type, token }) {
+    if (!state) {
+        if (!localStorage.authToken) {
             console.log('NO-TOKEN')
             return {}
         } else {
@@ -101,15 +101,15 @@ function authReducer(state, {type, token}){
             token = localStorage.authToken
         }
     }
-    if (type === 'AUTH_LOGIN'){
+    if (type === 'AUTH_LOGIN') {
         console.log('AUTH-LOGIN')
         let decoded = jwtDecode(token)
         if (decoded) {
             localStorage.authToken = token
-            return {token, payload: decoded}
+            return { token, payload: decoded }
         }
     }
-    if (type === 'AUTH_LOGOUT'){
+    if (type === 'AUTH_LOGOUT') {
         console.log('AUTH-LOGOUT')
         localStorage.removeItem('authToken')
         return {}
@@ -118,47 +118,47 @@ function authReducer(state, {type, token}){
     return state
 }
 
-function combineReducers(reducers){
-    return (state={}, action) => {
+function combineReducers(reducers) {
+    return (state = {}, action) => {
         const newState = {}
         for (const [reducerName, reducer] of Object.entries(reducers)) {
             let newSubState = reducer(state[reducerName], action)
 
-            if(newSubState !== state[reducerName]) {
+            if (newSubState !== state[reducerName]) {
                 newState[reducerName] = newSubState
             }
         }
 
-        if(Object.keys(newState).length !== 0) {
-            return {...state, ...newState}
-        } 
-            
+        if (Object.keys(newState).length !== 0) {
+            return { ...state, ...newState }
+        }
+
         return state
     }
 }
 
-const combinedReducer = combineReducers({promise: promiseReducer, auth: authReducer})
+const combinedReducer = combineReducers({ promise: promiseReducer, auth: authReducer, cart: cartReducer })
 const store = createStore(combinedReducer)
 
-const actionAuthLogin  = token => ({type: 'AUTH_LOGIN', token})
-const actionAuthLogout = ()    => ({type: 'AUTH_LOGOUT'})
+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=undefined, password=undefined) =>
+const actionLogin = (login = undefined, password = undefined) =>
     actionPromise('login', gql(`
     query log($login:String, $password:String) {
         login(login: $login, password: $password)
-      }`, {login ,password}))
+      }`, { login, password }))
 
 
 const actionFullLogin = (login, password) =>
     async dispatch => {
         let token = await dispatch(actionLogin(login, password))
-        if (token){
+        if (token) {
             dispatch(actionAuthLogin(token))
         }
     }
@@ -167,11 +167,55 @@ const actionFullLogin = (login, password) =>
 //const actionFullRegister = (login, password) => //actionRegister + actionFullLogin
 //+ интерфейс к этому - форму логина, регистрации, может повесить это на #/login #/register 
 //+ #/orders показывает ваши бывшие заказы:
-    //сделать actionMyOrders
-    //
+//сделать 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
+    const types = {
+        CART_ADD() { //как CHANGE, только если ключ раньше был, то достать из count и добавить
+            //к count из action. Если не было, достать 0 и добавить к count из action
+            return {
+                ...state,
+                [_id]: { good, count: (state[_id]?.count || 0) + count }
+            }
+        },
+        CART_REMOVE() { //смочь скопировать объект и выкинуть ключ. как вариант через
+            //деструктуризацию
+            let { _id, ...newState } = state
+            return newState
+        },
+        CART_CHANGE() {
+            return {
+                ...state, //по аналогии с promiseReducer дописать
+                [_id]: { good, count }
+            }
+        },
+        CART_CLEAR() {
+            return {}
+        },
+    }
+
+    if (type in types)
+        return types[type]()
+
+
+    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})
+
+/********************************MY STUFFF CART END****************************************************** */
 const actionRootCats = () =>
     actionPromise('rootCats', gql(`query {
         CategoryFind(query: "[{\\"parent\\":null}]"){
@@ -197,7 +241,7 @@ const actionCatById = (_id) =>  //добавить подкатегории
 
 store.dispatch(actionRootCats())
 
-const actionGoodById = (_id) => 
+const actionGoodById = (_id) =>
     actionPromise('goodById', gql(`
         query goodById ($good:String) {
             GoodFindOne(query: $good) {
@@ -240,6 +284,66 @@ window.onhashchange = () => {
         },
         login() {
             store.dispatch(actionLogin())
+        },
+        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>
+                <button id="clearCartBtn" style="background-color: firebrick; color: white; font-size: smaller;">Очистить корзину</button>
+                <br>
+            `
+            let clearCartBtn = document.getElementById('clearCartBtn')
+            clearCartBtn.onclick = () => {
+                //clear cart action
+            }
+
+            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))
+
+                }
+
+                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.style.backgroundColor = "whitesmoke"
+                card.style.border = "1px solid black"
+                card.style.margin = "10px"
+                card.style.padding = "10px"
+                main.append(card)
+            }
+            console.log('full prise', fullPrice)
+            let fullPriceSpan = document.getElementById('fullPrice')
+            fullPriceSpan.innerText = `${fullPrice}`
         }
     }
     if (route in routes)
@@ -260,9 +364,9 @@ store.subscribe(() => {
             console.log('here', subCategories)
             let subCats = document.createElement('div')
             for (let item of subCategories) {
-                let link =document.createElement('a')
+                let link = document.createElement('a')
                 link.innerHTML = `${item.name} &#9166`
-                link.href = `#/category/${item._id}` 
+                link.href = `#/category/${item._id}`
                 link.style.margin = '10px'
                 link.style.padding = '5px'
                 link.style.backgroundColor = 'black'
@@ -274,21 +378,31 @@ store.subscribe(() => {
         main.style.padding = "10px"
 
         if (catById.payload.goods) {
-            for (const { _id, name, price, images } of catById.payload.goods) {
+            for (const good 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}" />
+                    <h2>${good.name}</h2>
+                    <img style="border: 1px dashed grey;" src="${backURL}/${good.images[0].url}" />
                     <br>
-                    <strong>Price: ${price}</strong>
+                    <strong>Price: ${good.price}</strong>
+                    <br>
+                    <a href="#/good/${good._id}">На страницу товара</a>
                     <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)
+                let cartButton = document.createElement('button')
+                cartButton.innerText = 'Добавить в корзину'
+                cartButton.style.fontSize = 'smaller'
+                card.append(cartButton)
+
+                cartButton.onclick = () => {
+                    console.log('nuaaaaaa', good)
+                    store.dispatch(actionCartAdd(good))
+                }
             }
         }
     }
@@ -303,7 +417,7 @@ store.subscribe(() => {
 
         main.innerHTML = `
             <div class="card">
-                <button onclick="history.back()">&#8656 назад</button>
+                <button onclick="history.back()" style="font-size: smaller;">&#8656 назад</button>
                 <h1>${name}</h1>
                 <h4>${categories[0].name}<h4>
                 <br>
@@ -317,7 +431,7 @@ store.subscribe(() => {
     }
 })
 
-store.subscribe(()=> {
+store.subscribe(() => {
     const { login } = store.getState().promise
     const [, route, _id] = location.hash.split('/')
     
@@ -327,7 +441,7 @@ store.subscribe(()=> {
         aside.innerHTML = ''
         main.innerHTML = `
             <div style="border: 5px solid purple; padding: 10px; background-color: black;">
-                <button id="returnBtnLogin">&#8656 назад</button>
+                <button id="returnBtnLogin" style="font-size: small;">&#8656 назад</button>
                 <input  id="logInp" style="display:block; margin:10px" type="text" placeholder="login"/>
                 <input  id="passInp" style="display:block; margin:10px" type="text" placeholder="password"/>
                 <button id="submitBtn" style="display:block; margin:0 auto">LOGIN</button>
@@ -367,6 +481,16 @@ store.subscribe(()=> {
     }
 })
 
+store.subscribe(()=> {
+    const {cart} = store.getState()
+    let items = 0
+    for(let item in cart) {
+        items += cart[item].count
+    }
+    let itemCount = document.getElementById('itemCount')
+    itemCount.innerText = items
+})
+
 window.onload = () => {
     location.href = "#/category/5dc49f4d5df9d670df48cc64"
 }