|
@@ -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;">⇐ назад</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())
|
|
|
}
|