|
@@ -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,8 +167,8 @@ const actionFullLogin = (login, password) =>
|
|
|
//const actionFullRegister = (login, password) => //actionRegister + actionFullLogin
|
|
|
//+ интерфейс к этому - форму логина, регистрации, может повесить это на #/login #/register
|
|
|
//+ #/orders показывает ваши бывшие заказы:
|
|
|
- //сделать actionMyOrders
|
|
|
- //
|
|
|
+//сделать actionMyOrders
|
|
|
+//
|
|
|
|
|
|
let logBtn = document.getElementById('logBtn')
|
|
|
logBtn.onclick = () => {
|
|
@@ -176,6 +176,50 @@ logBtn.onclick = () => {
|
|
|
store.dispatch(actionLogin())
|
|
|
}
|
|
|
/********************************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}]"){
|
|
@@ -201,7 +245,7 @@ const actionCatById = (_id) => //добавить подкатегории
|
|
|
|
|
|
store.dispatch(actionRootCats())
|
|
|
|
|
|
-const actionGoodById = (_id) =>
|
|
|
+const actionGoodById = (_id) =>
|
|
|
actionPromise('goodById', gql(`
|
|
|
query goodById ($good:String) {
|
|
|
GoodFindOne(query: $good) {
|
|
@@ -244,6 +288,66 @@ window.onhashchange = () => {
|
|
|
},
|
|
|
login() {
|
|
|
|
|
|
+ },
|
|
|
+ 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>
|
|
|
+ <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)
|
|
@@ -264,9 +368,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} ⏎`
|
|
|
- link.href = `#/category/${item._id}`
|
|
|
+ link.href = `#/category/${item._id}`
|
|
|
link.style.margin = '10px'
|
|
|
link.style.padding = '5px'
|
|
|
link.style.backgroundColor = 'black'
|
|
@@ -278,21 +382,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: ${good.price}</strong>
|
|
|
<br>
|
|
|
- <strong>Price: ${price}</strong>
|
|
|
+ <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))
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -307,7 +421,7 @@ store.subscribe(() => {
|
|
|
|
|
|
main.innerHTML = `
|
|
|
<div class="card">
|
|
|
- <button onclick="history.back()">⇐ назад</button>
|
|
|
+ <button onclick="history.back()" style="font-size: smaller;">⇐ назад</button>
|
|
|
<h1>${name}</h1>
|
|
|
<h4>${categories[0].name}<h4>
|
|
|
<br>
|
|
@@ -321,17 +435,17 @@ store.subscribe(() => {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-store.subscribe(()=> {
|
|
|
+store.subscribe(() => {
|
|
|
const { login } = store.getState().promise
|
|
|
const [, route, _id] = location.hash.split('/')
|
|
|
-
|
|
|
+
|
|
|
let passInp, logInp
|
|
|
- if(!login?.payload && route === 'login') {
|
|
|
+ if (!login?.payload && route === 'login') {
|
|
|
console.log('hire');
|
|
|
aside.innerHTML = ''
|
|
|
main.innerHTML = `
|
|
|
<div style="border: 1px solid black; padding: 10px">
|
|
|
- <button id="returnBtnLogin">⇐ назад</button>
|
|
|
+ <button id="returnBtnLogin" style="font-size: smaller;">⇐ назад</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 style="display:block; margin:0 auto">LOGIN</button>
|
|
@@ -349,6 +463,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"
|
|
|
}
|