|
@@ -13,9 +13,10 @@ function createStore(reducer){
|
|
|
const newState = reducer(state, action) //пробуем запустить редьюсер
|
|
|
if (newState !== state){ //проверяем, смог ли редьюсер обработать action
|
|
|
state = newState //если смог, то обновляем state
|
|
|
- for (let cb of cbs) cb() //и запускаем подписчиков
|
|
|
+ for (let cb of cbs) cb(state) //и запускаем подписчиков
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return {
|
|
|
getState, //добавление функции getState в результирующий объект
|
|
|
dispatch,
|
|
@@ -23,82 +24,136 @@ function createStore(reducer){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- function promiseReducer(state = {}, {promiseName, type, status, payload, error}) {
|
|
|
- if (type === 'PROMISE') {
|
|
|
- return {...state, [promiseName]: {status, payload, error}}
|
|
|
- }
|
|
|
- return state
|
|
|
+const jwtDecode = (token) => {
|
|
|
+ try {
|
|
|
+ let payload = JSON.parse(atob(token.split('.')[1]))
|
|
|
+ console.log(payload)
|
|
|
+ return payload
|
|
|
+ } catch (e) {
|
|
|
+ return undefined
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms));
|
|
|
+//---------------------------------------getGql---------------------------------------------
|
|
|
+const getGql = url =>
|
|
|
+ (query, variables) => fetch(url, {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ ...(localStorage.authToken ? { "Authorization": "Bearer " + localStorage.authToken } : {})
|
|
|
+ },
|
|
|
+ body: JSON.stringify({ query, variables })
|
|
|
+ }).then(res => res.json())
|
|
|
+ .then(data => {
|
|
|
+ if (data.data) {
|
|
|
+ return Object.values(data.data)[0]
|
|
|
+ }
|
|
|
+ else throw new Error(JSON.stringify(data.errors))
|
|
|
+ })
|
|
|
|
|
|
- const actionPending = promiseName => ({promiseName, type: 'PROMISE', status: 'PENDING'})
|
|
|
- const actionFulfilled = (promiseName, payload) => ({promiseName, type: 'PROMISE', status: 'FULFILLED', payload})
|
|
|
- const actionRejected = (promiseName, error) => ({promiseName, type: 'PROMISE', status: 'REJECTED', error})
|
|
|
|
|
|
- const actionPromise = (promiseName, promise) =>
|
|
|
- async dispatch => {
|
|
|
- dispatch(actionPending(promiseName)) //сигнализируем redux, что промис начался
|
|
|
- try {
|
|
|
- const payload = await promise //ожидаем промиса
|
|
|
- dispatch(actionFulfilled(promiseName, payload)) //сигнализируем redux, что промис успешно выполнен
|
|
|
- return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
|
|
|
- } catch (error) {
|
|
|
- dispatch(actionRejected(promiseName, error)) //в случае ошибки - сигнализируем redux, что промис несложился
|
|
|
- }
|
|
|
- }
|
|
|
+const url = 'http://shop-roles.node.ed.asmer.org.ua/'
|
|
|
+const gql = getGql(url + 'graphql')
|
|
|
+
|
|
|
|
|
|
- const store = createStore(promiseReducer)
|
|
|
+//------------------------------------------------PromiseReducer---------------------------------
|
|
|
+function promiseReducer(state={}, {type, status, payload, error, name}){
|
|
|
+ if (type === 'PROMISE'){
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [name] : {status, payload, error}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return state
|
|
|
+}
|
|
|
|
|
|
- store.subscribe(() => console.log(store.getState())) //должен запускаться 6 раз
|
|
|
+const actionPending = (name) => ({type: 'PROMISE', status: 'PENDING', name})
|
|
|
+const actionFulfilled = (name, payload) => ({type: 'PROMISE', status: 'FULFILLED', name, payload})
|
|
|
+const actionRejected = (name, error) => ({type: 'PROMISE', status: 'REJECTED', name, error})
|
|
|
|
|
|
- store.dispatch(actionPromise('delay', delay(1000)))
|
|
|
- store.dispatch(actionPromise('luke', fetch("https://swapi.dev/api/people/1").then(res => res.json())))
|
|
|
- store.dispatch(actionPromise('tatooine', fetch("https://swapi.dev/api/planets/1").then(res => res.json())))
|
|
|
|
|
|
-/////////////////////////////////////////////////////////////////////
|
|
|
-function authReducer (state={}, {token, type}){
|
|
|
- if (type === 'AUTH_LOGIN') {
|
|
|
- try {
|
|
|
- let str = token.split('.')[1];
|
|
|
- let result = JSON.parse(atob(str))
|
|
|
- return {...state, 'token': token, 'playload':result}
|
|
|
- } catch (e) {
|
|
|
- return {}
|
|
|
+//-----------------------------------------------------actionPromise-------------------------------------------
|
|
|
+const actionPromise = (name, promise) =>
|
|
|
+ async dispatch => {
|
|
|
+ dispatch(actionPending(name)) //сигнализируем redux, что промис начался
|
|
|
+ try{
|
|
|
+ const payload = await promise //ожидаем промиса
|
|
|
+ dispatch(actionFulfilled(name, payload)) //сигнализируем redux, что промис успешно выполнен
|
|
|
+ return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
|
|
|
+ }
|
|
|
+ catch (error){
|
|
|
+ dispatch(actionRejected(name, error)) //в случае ошибки - сигнализируем redux, что промис несложился
|
|
|
}
|
|
|
}
|
|
|
- else if (type === 'AUTH_LOGOUT') {
|
|
|
+
|
|
|
+
|
|
|
+//----------------------------------------------------authReducer---------------------------------------
|
|
|
+function authReducer(state={}, {type, token}) {
|
|
|
+ if (type === 'AUTH_LOGOUT'){
|
|
|
+ window.localStorage.removeItem('authToken');
|
|
|
return {}
|
|
|
}
|
|
|
+ if(type === "AUTH_LOGIN"){
|
|
|
+ try{
|
|
|
+ window.localStorage.setItem('authToken',token);
|
|
|
+ return {
|
|
|
+ token: token,
|
|
|
+ payload: jwtDecode(token)
|
|
|
+ }
|
|
|
+ }catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
return state
|
|
|
}
|
|
|
|
|
|
const actionAuthLogin = token => ({type: 'AUTH_LOGIN', token})
|
|
|
const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'})
|
|
|
|
|
|
-const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
|
|
|
|
|
|
-const storeAuth = createStore(authReducer)
|
|
|
-storeAuth.subscribe(() => console.log(storeAuth.getState()))
|
|
|
+//--------------------------------------------------cartReducer------------------------------------------
|
|
|
+function cartReducer (state = {}, {type, good, count=1}) {
|
|
|
|
|
|
-storeAuth.dispatch(actionAuthLogin(token))
|
|
|
+ if (type === 'CART_ADD') {
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [good._id]: {
|
|
|
+ good,
|
|
|
+ count: +count}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === 'CART_SUB') {
|
|
|
+ if (state([good._id].count - count) <= 0) {
|
|
|
+ delete state[good._id]
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [good._id]: {
|
|
|
+ good,
|
|
|
+ count: state[good._id].count - count}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === 'CART_DEL') {
|
|
|
+ delete state[good._id]
|
|
|
+ return {...state}
|
|
|
|
|
|
-// ///////////////////////////////////////////////////////////////////////
|
|
|
-function cartReducer (state = {}, {type, good, count}) {
|
|
|
- let goodKey, oldCount, goodValue;
|
|
|
- if (good) {
|
|
|
- goodKey = good['_id'];
|
|
|
- oldCount = state[goodKey]?.count || 0;
|
|
|
- goodValue = {good, count: oldCount}
|
|
|
}
|
|
|
- if (type === 'CARD_ADD') {
|
|
|
- goodValue.count += count;
|
|
|
- return {...state, [goodKey]: goodValue}
|
|
|
+
|
|
|
+ if (type === 'CART_SET') {
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ [good._id]: {
|
|
|
+ good,
|
|
|
+ count}
|
|
|
+ }
|
|
|
}
|
|
|
- else if (type === 'CART_DEL') {
|
|
|
- delete state[goodKey];
|
|
|
|
|
|
+ if (type === 'CART_CLEAR') {
|
|
|
+ state = {}
|
|
|
}
|
|
|
+ return state
|
|
|
}
|
|
|
|
|
|
const actionCartAdd = (good, count=1) => ({type: 'CART_ADD', count, good})
|
|
@@ -107,5 +162,506 @@ const actionCartDel = (good) => ({type: 'CART_DEL', good})
|
|
|
const actionCartSet = (good, count=1) => ({type: 'CART_SET', count, good})
|
|
|
const actionCartClear = () => ({type: 'CART_CLEAR'})
|
|
|
|
|
|
-/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
+//---------------------------------------------localStoredReducer---------------------------------
|
|
|
+function localStoredReducer(originalReducer, localStorageKey) {
|
|
|
+ function wrapper(state, action) {
|
|
|
+ if (!state) {
|
|
|
+ try {
|
|
|
+ return JSON.parse(localStorage[localStorageKey])
|
|
|
+ }
|
|
|
+ catch { }
|
|
|
+ }
|
|
|
+ let res = originalReducer(state, action)
|
|
|
+ localStorage[localStorageKey] = JSON.stringify(res)
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ return wrapper
|
|
|
+}
|
|
|
+
|
|
|
+// -------------------------------------------CombineReducers---------------------------------------
|
|
|
+function combineReducers(reducers){
|
|
|
+ function totalReducer(state={}, action){
|
|
|
+ const newTotalState = {}
|
|
|
+ for (const [reducerName, reducer] of Object.entries(reducers)){
|
|
|
+ const newSubState = reducer(state[reducerName], action)
|
|
|
+ if (newSubState !== state[reducerName]){
|
|
|
+ newTotalState[reducerName] = newSubState
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Object.keys(newTotalState).length){
|
|
|
+ return {...state, ...newTotalState}
|
|
|
+ }
|
|
|
+ return state
|
|
|
+ }
|
|
|
+ return totalReducer
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const totalReducer = combineReducers({
|
|
|
+ promise: promiseReducer,
|
|
|
+ auth: localStoredReducer(authReducer,'auth'),
|
|
|
+ cart: localStoredReducer(cartReducer,'cart')
|
|
|
+})
|
|
|
+
|
|
|
+const store = createStore(totalReducer)
|
|
|
+store.subscribe(() => console.log(store.getState()))
|
|
|
+
|
|
|
+
|
|
|
+//Запрос на список корневых категорий
|
|
|
+const actionRootCats = () =>
|
|
|
+ actionPromise('rootCats', gql(`query rootCats2{
|
|
|
+ CategoryFind(query: "[{\\"parent\\": null}]"){
|
|
|
+ _id
|
|
|
+ name
|
|
|
+ }
|
|
|
+ }`))
|
|
|
+
|
|
|
+store.dispatch(actionRootCats())
|
|
|
+
|
|
|
+//Запрос для получения одной категории с товарами и картинками
|
|
|
+const oneCatWithGoods = (_id) =>
|
|
|
+ actionPromise('oneCatWithGoods', gql(`query oneCatWithGoods ($q:String) {
|
|
|
+ CategoryFindOne (query: $q){
|
|
|
+ _id
|
|
|
+ name
|
|
|
+ parent{
|
|
|
+ _id
|
|
|
+ name}
|
|
|
+ subCategories {
|
|
|
+ _id
|
|
|
+ name
|
|
|
+ },
|
|
|
+ goods {
|
|
|
+ _id
|
|
|
+ name
|
|
|
+ price
|
|
|
+ description
|
|
|
+ images {
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }}`,
|
|
|
+ {q: JSON.stringify([{_id}])}
|
|
|
+ ))
|
|
|
+
|
|
|
+
|
|
|
+//Запрос на получение товара с описанием и картинками
|
|
|
+const goodWithDescAndImg = (_id) =>
|
|
|
+ actionPromise('goodWithDescAndImg', gql(`query goodWithDescAndImg ($q:String) {
|
|
|
+ GoodFindOne (query: $q){
|
|
|
+ _id
|
|
|
+ name
|
|
|
+ price
|
|
|
+ description
|
|
|
+ images {
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }}`,
|
|
|
+ {q: JSON.stringify([{_id}])}
|
|
|
+ ))
|
|
|
+
|
|
|
+
|
|
|
+// Запрос на регистрацию
|
|
|
+const registration = (login, password) =>
|
|
|
+ actionPromise ('registration', gql(`mutation registration ($login:String, $password: String) {
|
|
|
+ UserUpsert (user: {login: $login, password: $password}) {
|
|
|
+ _id createdAt
|
|
|
+ }
|
|
|
+ }`,
|
|
|
+ {"login" : login, "password": password}
|
|
|
+ ))
|
|
|
+
|
|
|
+
|
|
|
+// Запрос на логин
|
|
|
+const loginUser = (login, password) =>
|
|
|
+ actionPromise(
|
|
|
+ 'login',
|
|
|
+ gql(
|
|
|
+ `query log($login: String, $password: String) {
|
|
|
+ login(login: $login, password: $password)
|
|
|
+ }`,
|
|
|
+ {login, password}
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+// Запрос истории заказов
|
|
|
+const historyOfOrders = () =>
|
|
|
+ actionPromise('historyOfOrders', gql(`query historyOfOrders ($q: String) {
|
|
|
+ OrderFind(query: $q) {
|
|
|
+ _id
|
|
|
+ total
|
|
|
+ createdAt
|
|
|
+ orderGoods {
|
|
|
+ good {
|
|
|
+ name
|
|
|
+ }
|
|
|
+ price
|
|
|
+ count
|
|
|
+ total
|
|
|
+ }
|
|
|
+ total
|
|
|
+ }
|
|
|
+ }`,
|
|
|
+ {q: JSON.stringify([{}])}
|
|
|
+ ))
|
|
|
+
|
|
|
+store.dispatch(actionRootCats())
|
|
|
+
|
|
|
+
|
|
|
+// Запрос оформления заказа
|
|
|
+const NewOrder = (orderGoods) =>
|
|
|
+ actionPromise('NewOrder', gql(`mutation NewOrder($order: OrderInput) {
|
|
|
+ OrderUpsert(order: $order) {
|
|
|
+ _id
|
|
|
+ orderGoods {
|
|
|
+ _id
|
|
|
+ price
|
|
|
+ count
|
|
|
+ total
|
|
|
+ good {
|
|
|
+ name
|
|
|
+ _id
|
|
|
+ price
|
|
|
+ images {
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }`,
|
|
|
+ {order: {orderGoods}}
|
|
|
+ ))
|
|
|
+
|
|
|
+
|
|
|
+//-----------------------------------Отрисовка категорий-------------------------------------
|
|
|
+store.subscribe(() => {
|
|
|
+ const {status, payload, error} = store.getState().promise.rootCats
|
|
|
+ if (status === 'FULFILLED'){
|
|
|
+ aside.innerHTML = ''
|
|
|
+ for (const {_id, name} of payload){
|
|
|
+ aside.innerHTML += `<a href= "#/category/${_id}">${name}</a>`
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+//--------------------------------------отрисовка товаров в категории-----------------------
|
|
|
+store.subscribe(() => {
|
|
|
+ const {status, payload, error} = store.getState().promise?.oneCatWithGoods || {}
|
|
|
+ const [,route] = location.hash.split('/')
|
|
|
+ if(route !== 'category') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (status === 'FULFILLED'){
|
|
|
+ main.innerHTML = ''
|
|
|
+
|
|
|
+ const {name, goods, subCategories} = payload
|
|
|
+ main.innerHTML = `<h1>${name}</h1>`
|
|
|
+
|
|
|
+ if (subCategories !== null) {
|
|
|
+ for (const {_id, name} of subCategories) {
|
|
|
+ main.innerHTML += `<a href= "#/category/${_id}">${name}</a>`
|
|
|
+ console.log(name)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const {_id, name, price, images} of goods){
|
|
|
+
|
|
|
+ for (const img of images) {
|
|
|
+ main.innerHTML += `<img src= "${url+ img.url}"> </br>`
|
|
|
+ }
|
|
|
+ main.innerHTML += `<a href= "#/good/${_id}">${name} </br> ${price} грн</a>`
|
|
|
+ }
|
|
|
+ }}
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+//-------------------------------------Отрисовка товара------------------------------------------
|
|
|
+store.subscribe(() => {
|
|
|
+ const {status, payload, error} = store.getState().promise?.goodWithDescAndImg || { }
|
|
|
+ const [,route] = location.hash.split('/')
|
|
|
+ if(route !== 'good') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (status === 'FULFILLED'){
|
|
|
+ main.innerHTML = ''
|
|
|
+ const {name, description, images, price} = payload
|
|
|
+
|
|
|
+ main.innerHTML = `<h1>${name}</h1>`
|
|
|
+ for (const img of images) {
|
|
|
+ main.innerHTML += `<img src= "${url+ img.url}">`
|
|
|
+ }
|
|
|
+
|
|
|
+ main.innerHTML += `<p>${description}</p>
|
|
|
+ <p>${price} грн. </p>
|
|
|
+ <button id="buy"> В корзину </button>`
|
|
|
+
|
|
|
+ const buyButton = document.getElementById('buy')
|
|
|
+ cartIcon.innerHTML = ''
|
|
|
+ buyButton.onclick = function () {
|
|
|
+ store.dispatch(actionCartAdd({_id: name, price: price, img: images}))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+//----------------------------------Отрисовка цифры в корзине-------------------------------
|
|
|
+store.subscribe(() => {
|
|
|
+ const {cart} = store.getState()
|
|
|
+ let summ = 0
|
|
|
+ for(const {count} of Object.values(cart)) {
|
|
|
+ summ += +count
|
|
|
+ }
|
|
|
+ cartIcon.innerHTML = `<b>${summ}</b>`
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+//-----------------------------------------Логин----------------------------------------
|
|
|
+const loginButton = document.getElementById('login')
|
|
|
+loginForm.append(loginButton)
|
|
|
+loginButton.onclick = () => location.href = `#/login`
|
|
|
+
|
|
|
+const actionFullLogin = (login, password) =>
|
|
|
+ async (dispatch) => {
|
|
|
+ const token = await dispatch(loginUser(login, password))
|
|
|
+
|
|
|
+ if(typeof token === "string"){
|
|
|
+ dispatch(actionAuthLogin(token))
|
|
|
+ main.innerHTML = `<h1>Вы вошли на сайт</h1>`
|
|
|
+
|
|
|
+ } else {
|
|
|
+ main.innerHTML =
|
|
|
+ `<p>Вы ввели неправильные логин или пароль. Повторите попытку </p>
|
|
|
+ <button id="buttonRepeat">Повторить попытку</button>`
|
|
|
+
|
|
|
+ const loginRepeat = document.getElementById('buttonRepeat')
|
|
|
+ loginRepeat.onclick = () => {
|
|
|
+ location.reload()
|
|
|
+ location.href = `#/login`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//-----------------------------------------Авторизация-------------------------------------
|
|
|
+store.subscribe(() => {
|
|
|
+ if(!store.getState().auth) return;
|
|
|
+ const {payload} = store.getState().auth;
|
|
|
+ if(payload){
|
|
|
+ loginForm.innerHTML =
|
|
|
+ `<button id="history"> История заказов </button>
|
|
|
+ <button id="logOut"> Выйти с сайта </button>`
|
|
|
+
|
|
|
+ loginButton.hidden = true
|
|
|
+ registration.hidden = true
|
|
|
+
|
|
|
+ const historyButton = document.getElementById('history')
|
|
|
+ historyButton.onclick = function () {
|
|
|
+ location.href = `#/history`
|
|
|
+ }
|
|
|
+
|
|
|
+ const logOutButton = document.getElementById('logOut')
|
|
|
+ logOutButton.onclick = function () {
|
|
|
+ store.dispatch(actionAuthLogout())
|
|
|
+ main.innerHTML = ` `
|
|
|
+ loginForm.innerHTML = ` `
|
|
|
+ loginButton.hidden = false
|
|
|
+ registration.hidden = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+//------------------------------------Регистрация--------------------------------------------
|
|
|
+const registrationButton = document.getElementById('registration')
|
|
|
+loginForm.append(registrationButton)
|
|
|
+registrationButton.onclick = () => location.href = `#/register`
|
|
|
+
|
|
|
+const actionFullRegister = (login, password) =>
|
|
|
+ async (dispatch) => {
|
|
|
+ let userReg = await dispatch(registration(login, password))
|
|
|
+
|
|
|
+ if(userReg){
|
|
|
+ dispatch(actionFullLogin(login,password))
|
|
|
+ } else {
|
|
|
+ main.innerHTML = `Регистрация не удалась. Повторите попытку ещё раз.
|
|
|
+ <button id="buttonRepeatReg">Повторить попытку</button>`
|
|
|
+
|
|
|
+ const buttonRepeatReg = document.getElementById('buttonRepeatReg')
|
|
|
+ buttonRepeatReg.onclick = () => {
|
|
|
+ location.reload()
|
|
|
+ location.href = `#/register`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+//-------------------------------------------Заказ-------------------------------------
|
|
|
+const newOrder = () => async (dispatch, getState) => {
|
|
|
+ let { cart } = getState();
|
|
|
+ const orderGoods = Object.entries(cart).map(([_id, { count }]) => ({ good: { _id }, count }));
|
|
|
+
|
|
|
+ let result = await dispatch(NewOrder(orderGoods))
|
|
|
+ if (result?._id) {
|
|
|
+ dispatch(actionCartClear())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//--------------------------------------Корзина------------------------------------------
|
|
|
+store.subscribe ( () => {
|
|
|
+ let cartIcon = document.getElementById('cartIcon')
|
|
|
+ cartIcon.onclick = function myCart() {
|
|
|
+ location.href = `#/cartIcon`
|
|
|
+ console.log(store.getState().cart)
|
|
|
+
|
|
|
+ let storeCart = store.getState().cart
|
|
|
+ main.innerHTML = `<h1>Корзина</h1>`
|
|
|
+
|
|
|
+
|
|
|
+ for (let i=0; i<(Object.keys(storeCart).length); i++){
|
|
|
+
|
|
|
+ let div = document.createElement('div')
|
|
|
+ div.id = i
|
|
|
+ main.append(div)
|
|
|
+ let order = document.getElementById(i)
|
|
|
+
|
|
|
+ let name = Object.keys(storeCart)[i]
|
|
|
+ order.innerHTML += `<p>${store.getState().cart[name].good._id}</p>`
|
|
|
+
|
|
|
+ for (const img of store.getState().cart[name].good.img) {
|
|
|
+ order.innerHTML += `<p><img src= "${url+ img.url}"></p>`
|
|
|
+ }
|
|
|
+
|
|
|
+ order.innerHTML +=
|
|
|
+ `<p>${store.getState().cart[name].count} шт</p>
|
|
|
+ <p>Итого: ${store.getState().cart[name].count * store.getState().cart[name].good.price} </p>`
|
|
|
+
|
|
|
+ let input = document.createElement('input')
|
|
|
+ input.type = 'number'
|
|
|
+ input.value = store.getState().cart[name].count
|
|
|
+ order.append(input)
|
|
|
+
|
|
|
+ let divForBtn = document.createElement('div')
|
|
|
+ order.append(divForBtn)
|
|
|
+ let button = document.createElement('button')
|
|
|
+ button.id = 'delCartBtn'
|
|
|
+ button.innerText = 'Удалить товар'
|
|
|
+ divForBtn.append(button)
|
|
|
+
|
|
|
+ input.oninput = function () {
|
|
|
+ if (input.value <= 0){
|
|
|
+ store.dispatch(actionCartDel({_id: name}))
|
|
|
+ myCart()
|
|
|
+ }
|
|
|
+ console.log(input.value, name)
|
|
|
+
|
|
|
+ store.dispatch(actionCartSet({_id: name, price: store.getState().cart[name].good.price, img: store.getState().cart[name].good.img}, input.value))
|
|
|
+ myCart()
|
|
|
+ }
|
|
|
+
|
|
|
+ button.onclick = function () {
|
|
|
+ store.dispatch(actionCartDel({_id: name}))
|
|
|
+ myCart()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let btnCreateOrder = document.createElement('button')
|
|
|
+ btnCreateOrder.id = 'createOrder'
|
|
|
+ btnCreateOrder.innerText = 'Оформить заказ'
|
|
|
+ main.append(btnCreateOrder)
|
|
|
+
|
|
|
+ const idCreateOrderBtn = document.getElementById('createOrder')
|
|
|
+ if (Object.keys(store.getState().auth).length === 0) {
|
|
|
+ idCreateOrderBtn.disabled = true
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Object.keys(store.getState().auth).length !== 0) {
|
|
|
+ idCreateOrderBtn.disabled = false
|
|
|
+
|
|
|
+ idCreateOrderBtn.onclick = function () {
|
|
|
+ store.dispatch(newOrder())
|
|
|
+ store.dispatch(actionCartClear())
|
|
|
+ myCart()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+//--------------------------------------------История заказов--------------------------------------
|
|
|
+store.subscribe ( () => {
|
|
|
+ const {status, payload, error} = store.getState().promise?.historyOfOrders || { }
|
|
|
+ const [,route] = location.hash.split('/')
|
|
|
+ if(route !== 'history') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (status === 'FULFILLED'){
|
|
|
+ main.innerHTML = `<h1> История заказов </h1>`
|
|
|
+ const {_id, total} = payload
|
|
|
+ console.log(payload)
|
|
|
+
|
|
|
+ for(const order of payload){
|
|
|
+ const {_id, total} = order
|
|
|
+ main.innerHTML +=
|
|
|
+ `<div style="width: 300px; border: solid skyblue;">
|
|
|
+ <p>Номер заказа: ${_id}</p>
|
|
|
+ <p>Всего: ${total} денег </p>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+window.onhashchange = () => {
|
|
|
+ const [,route, _id] = location.hash.split('/')
|
|
|
+
|
|
|
+ const routes = {
|
|
|
+ category() {
|
|
|
+ store.dispatch(oneCatWithGoods(_id))
|
|
|
+ },
|
|
|
+
|
|
|
+ good(){
|
|
|
+ store.dispatch(goodWithDescAndImg(_id))
|
|
|
+ },
|
|
|
+
|
|
|
+ login(){
|
|
|
+ main.innerHTML =
|
|
|
+ `<h2 id="inputTitle">Вход на сайт:</h2>
|
|
|
+ <input id="loginInput" type="text" name="login" placeholder="Введите логин">
|
|
|
+ <input id="passwordInput" type="password" name="password" placeholder="Введите пароль">
|
|
|
+ <button id="sign_in">Войти</button>`
|
|
|
+
|
|
|
+ const sign_inBtn = document.getElementById('sign_in')
|
|
|
+ sign_inBtn.onclick = function () {
|
|
|
+ store.dispatch(actionFullLogin(loginInput.value, passwordInput.value))
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ register(){
|
|
|
+ main.innerHTML =
|
|
|
+ `<h2>Регистрация:</h2>
|
|
|
+ <input id="loginReg" type="text" name="login" placeholder="Введите логин">
|
|
|
+ <input id="passwordReg" type="password" name="password" placeholder="Введите пароль">
|
|
|
+ <button id="reg">Зарегистрироваться</button>`
|
|
|
+ const regBtn = document.getElementById('reg')
|
|
|
+
|
|
|
+ regBtn.onclick = function () {
|
|
|
+ store.dispatch(actionFullRegister(loginReg.value, passwordReg.value))
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ cart(){},
|
|
|
+
|
|
|
+ history(){
|
|
|
+ store.dispatch(historyOfOrders())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (route in routes){ //если route есть в routes
|
|
|
+ routes[route]() //то запустить функцию, которая там лежит
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+window.onhashchange()
|