const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
function createStore(reducer) {
let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
let cbs = [] //массив подписчиков
const getState = () => state //функция, возвращающая переменную из замыкания
const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
() => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
const dispatch = action => {
if (typeof action === 'function') { //если action - не объект, а функция
return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
}
const newState = reducer(state, action) //пробуем запустить редьюсер
if (newState !== state) { //проверяем, смог ли редьюсер обработать action
state = newState //если смог, то обновляем state
/*state = {
...state,
...newState
}*/ //если смог, то обновляем state
for (let cb of cbs) cb() //и запускаем подписчиков
}
}
return {
getState, //добавление функции getState в результирующий объект
dispatch,
subscribe //добавление subscribe в объект
}
}
function promiseReducer(state = {}, { promiseName, type, status, payload, error }) {
if (type === 'PROMISE') {
return {
...state,
[promiseName]: { status, payload, error }
}
}
return state
}
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 store = createStore(promiseReducer)
// store.subscribe(() => console.log(store.getState()))
// 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())))
//по итогу должен получится какой-то такой state:
/*
{
delay: {status: 'FULFILLED', payload: 1000, error: undefined},
luke: {status: 'FULFILLED', payload: { ..... траливали про люка}, error: undefined},
tatooine: {status: 'FULFILLED', payload: { ..... траливали про планету татуин}, error: undefined},
}
*/
/* authReducer
Этот редьюсер предназначен для хранения и обработки состояния залогиненности пользователя. У него бывает два вида состояний:
Залогинен. state вида: {token: "jwt токен", payload: {.....раскодированная инфа из токена}}
Незалогинен. state вида: {} (пустой объект)
Редьюсер обрабатывает два типа экшонов:
AUTH_LOGIN. Логинимся. Редьюсер должен попытаться раскодировать токен, и если это получилось, вернуть новый стейт вида {token, payload} Если токен не удалось раскодировать, вернуть пустой объект (т. е. разлогиниться)
AUTH_LOGOUT. Разлогиниваемся. Возвращаем пустой объект.
Проверочный код (и экшенкриейторы бонусом):*/
function jwtDecode(token) {
let result;
try {
let secondPartToken = token.split('.')[1];
result = JSON.parse(atob(secondPartToken));
} catch (e) {
}
return result;
}
function authReducer(state = {}, { type, token }) {
if (type === 'AUTH_LOGIN') {
payload = jwtDecode(token)
console.log(payload)
if (payload) return { token, payload }
}
if (type === 'AUTH_LOGOUT') return {}
return state
}
const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
// const store = createStore(authReducer)
// store.subscribe(() => console.log(store.getState()))
// store.dispatch(actionAuthLogout())
// store.dispatch(actionAuthLogin(token))
/*{
token: "eyJhbGc.....",
payload: {
"sub": {
"id": "6377e133b74e1f5f2ec1c125",
"login": "test5",
"acl": [
"6377e133b74e1f5f2ec1c125",
"user"
]
},
"iat": 1668812458
}
}*/
//store.dispatch(actionAuthLogout()) // {}
/*cartReducer
Редьюсер, который хранит состояние корзины во время серфинга по интернет-магазину. Похож на редьюсер ларька, только работает немного наоборот - в то время как в ларьке товар уменьшается, тут он добавляется.
Состояние:
{
idТовара1: {count: количество1, good: {....инфа про товар с бэкэнда, включая цену, описание и картинки}},
idТовара2: {count: количество2, good: {....инфа про товар с бэкэнда, включая цену, описание и картинки}},
}
Типы экшенов
*/
// Добавление товара. Должен добавлять новый ключ в state, или обновлять, если ключа в state ранее не было, увеличивая количество
const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count, good })
// Уменьшение количества товара. Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good })
// Удаление товара. Должен удалять ключ из state
const actionCartDel = (good) => ({ type: 'CART_DEL', good })
// Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good })
// Очистка корзины. state должен стать пустым объектом {}
const actionCartClear = () => ({ type: 'CART_CLEAR' })
/*
Проверочный код
Наличие good как ключа в state немного избыточно - для оформления заказа достаточно id и количества. Однако это позволит хранить в редьюсере всю нужную информацию, например, для отображения страницы корзины без лишних запросов на сервер. На странице корзины обычно есть и описание, и цена, и фоточки.
Проверочный код ниже использует в качестве id более наглядные вещи.
*/
function cartReducer(state = {}, { type, count, good }) {
if (type === 'CART_ADD') {
if (good._id in state) {
return {
...state,
[good._id]: {
good,
count: state[good._id].count + count
}
}
} else {
return {
...state,
[good._id]: {
good,
count
}
}
}
}
if (type === 'CART_SUB') {
let result = {}
if (good._id in state) {
if ((state[good._id].count - count) <= 0) {
newState = { ...state }
delete newState[good._id]
return newState
} else {
return {
...state,
[good._id]: {
good,
count: state[good._id].count - count
}
}
}
}
}
if (type === 'CART_DEL') {
let newState = { ...state }
delete newState[good._id]
return newState
}
// Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
if (type === 'CART_SET') {
if (good._id in state && count <= 0) {
let newState = { ...state }
delete newState[good._id]
return newState
} else {
let newState = {
...state,
[good._id]: {
good,
count
}
}
return newState
}
}
if (type === 'CART_CLEAR') return {}
return state
}
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 reducers = {
promise: promiseReducer, //допилить много имен для многих промисо
auth: authReducer, //часть предыдущего ДЗ
cart: cartReducer, //часть предыдущего ДЗ
}
const totalReducer = combineReducers(reducers)
function localStoredReducer(originalReducer, localStorageKey) {
let counter = 0
function wrapper(state, action) {
if (counter === 0) {
counter++
if (localStorage[localStorageKey]) {
let result = JSON.parse(localStorage[localStorageKey])
if (result) return result
}
} else {
let result = originalReducer(state, action)
localStorage[localStorageKey] = JSON.stringify(result)
return result
}
}
return wrapper
}
const store = createStore(localStoredReducer(totalReducer, "state")) //не забудьте combineReducers если он у вас уже есть
store.subscribe(() => console.log(store.getState()))
const actionRootCats = () => actionPromise("RootCats", gqlRootCats())
store.dispatch(actionRootCats())
store.subscribe(() => {
let result = store.getState().promise.RootCats.payload
if (result) {
aside.innerHTML = ""
for (let { _id, name } of result) {
aside.innerHTML += `${name}`
}
}
})
const actionCategoryGoodsAndSubCategoryGoods = (_id) => actionPromise("CategoryGoodsAndSubCategoryGoods", gqlCategoryGoodsAndSubCategoryGoods(_id))
store.dispatch(actionCategoryGoodsAndSubCategoryGoods('62c94b10b74e1f5f2ec1a0dd'))
store.subscribe(() => {
if (location.hash === '') {
const { status, payload, error } = store.getState().promise.CategoryGoodsAndSubCategoryGoods
if (status === 'PENDING') {
main.innerHTML = ``
}
if (status === 'FULFILLED') {
if (payload) categotyToMain(payload)
}
if (status === 'REJECTED') {
main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: blablatest123@gmail.com`
}
}
})
function categotyToMain(result) {
main.innerHTML = ""
let breadcrumbsContainer = document.createElement('div')
main.append(breadcrumbsContainer)
breadcrumbsContainer.classList.add('breadcrumbsContainer')
let breadcrumbsHome = document.createElement('a')
breadcrumbsContainer.append(breadcrumbsHome)
breadcrumbsHome.innerText = 'Mystore.com'
breadcrumbsHome.href = location.origin + location.pathname
if (result.parent){
breadcrumbsContainer.innerHTML += `
>
...
>
${result.parent.name}`
}
let h1 = document.createElement('h1')
h1.innerText = result.name
main.append(h1)
if (result.subCategories && result.subCategories.length>0){
const containerSubcategoryLink = document.createElement('div')
containerSubcategoryLink.classList.add('containerSubcategoryLink')
main.append(containerSubcategoryLink)
for(const {_id, name} of result.subCategories){
console.log(name)
let subcategoryLink = document.createElement('a')
containerSubcategoryLink.append(subcategoryLink)
subcategoryLink.href = `#/category/${_id}`
subcategoryLink.classList.add('subcategoryLink')
subcategoryLink.innerText = name
}
}
if (!result.goods){
let emptyCategoryMessage = document.createElement('div')
main.append(emptyCategoryMessage)
emptyCategoryMessage.innerText = 'В этой категории пока нет товаров :('
return
}
for (let { _id, name, images, price} of result?.goods) {
let card = document.createElement('a')
card.id = _id
card.href = `#/good/${_id}`
card.classList.add('card')
main.append(card)
let cardImgWrapper = document.createElement('div')
cardImgWrapper.classList.add('cardImgWrapper')
card.append(cardImgWrapper)
let cardImg = document.createElement('img')
cardImg.classList.add('cardImg')
cardImgWrapper.append(cardImg)
if (images.length>0){
let { url } = images[0]
cardImg.src = hostname + url
} else{
cardImg.src = 'https://lukachi.com.ua/source/default-image.jpg'
}
let cardName = document.createElement('h2')
cardName.classList.add('cardName')
cardName.innerText = name
card.append(cardName)
let cardPrice = document.createElement('div')
cardPrice.classList.add('cardPrice')
cardPrice.innerText = price + " грн"
card.append(cardPrice)
}
}
let hostname = 'http://shop-roles.node.ed.asmer.org.ua/'
// store.subscribe(() => {
// let result = store.getState().promise.CategoryGoodsAndSubCategoryGoods?.payload
// const [, route, _id] = location.hash.split('/')
// if (result && route === "category") {
// categotyToMain(result)
// }
// })
store.subscribe(() => {
const [, route, _id] = location.hash.split('/')
if (route !== "category") return
const { status, payload, error } = store.getState().promise.CategoryGoodsAndSubCategoryGoods
if (status === 'PENDING') {
main.innerHTML = ``
}
if (status === 'FULFILLED' && payload) {
categotyToMain(payload)
}
if (status === 'REJECTED') {
main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: blablatest123@gmail.com`
}
})
// store.subscribe(() => {
// let result = store.getState().promise.OneGoodWithDescriptionAndImages?.payload
// const [, route, _id] = location.hash.split('/')
// if (result && route === "good") {
// main.innerHTML = ""
// let h1 = document.createElement('h1')
// h1.innerText = result.name
// main.append(h1)
// let imgSlider = document.createElement('div')
// imgSlider.classList.add('imgSlider')
// main.append(imgSlider)
// for (let { url } of result.images) {
// imgSlider.innerHTML += ``
// }
// let asideDesriptionPriceCard = document.createElement('div')
// asideDesriptionPriceCard.classList.add('asideDesriptionPriceCard')
// main.append(asideDesriptionPriceCard)
// let goodPrice = document.createElement('div')
// goodPrice.classList.add('goodPrice')
// goodPrice.innerText = result.price + ' грн'
// asideDesriptionPriceCard.append(goodPrice)
// let goodCountInput = document.createElement('input')
// goodCountInput.classList.add('goodCountInput')
// goodCountInput.type = 'number'
// goodCountInput.min = 1
// goodCountInput.value = 1
// asideDesriptionPriceCard.append(goodCountInput)
// let goodButtonAddToCart = document.createElement('a')
// goodButtonAddToCart.classList.add('goodButtonAddToCart')
// goodButtonAddToCart.innerText = 'В КОРЗИНУ'
// goodButtonAddToCart.onclick = () => store.dispatch(actionCartAdd(result, +goodCountInput.value))
// asideDesriptionPriceCard.append(goodButtonAddToCart)
// let description = document.createElement('div')
// description.classList.add('description')
// description.innerText = result.description
// asideDesriptionPriceCard.append(description)
// }
// })
store.subscribe(() => {
const [, route, _id] = location.hash.split('/')
if (route !== "good") return
const { status, payload, error } = store.getState().promise.OneGoodWithDescriptionAndImages
if (status === 'PENDING') {
main.innerHTML = ``
}
if (status === 'FULFILLED' && payload) {
main.innerHTML = ""
let h1 = document.createElement('h1')
h1.innerText = payload.name
main.append(h1)
let imgSlider = document.createElement('div')
imgSlider.classList.add('imgSlider')
main.append(imgSlider)
for (let { url } of payload.images) {
imgSlider.innerHTML += ``
}
let asideDesriptionPriceCard = document.createElement('div')
asideDesriptionPriceCard.classList.add('asideDesriptionPriceCard')
main.append(asideDesriptionPriceCard)
let goodPrice = document.createElement('div')
goodPrice.classList.add('goodPrice')
goodPrice.innerText = payload.price + ' грн'
asideDesriptionPriceCard.append(goodPrice)
let goodCountInput = document.createElement('input')
goodCountInput.classList.add('goodCountInput')
goodCountInput.type = 'number'
goodCountInput.min = 1
goodCountInput.value = 1
asideDesriptionPriceCard.append(goodCountInput)
let goodButtonAddToCart = document.createElement('a')
goodButtonAddToCart.classList.add('goodButtonAddToCart')
goodButtonAddToCart.innerText = 'В КОРЗИНУ'
goodButtonAddToCart.onclick = () => store.dispatch(actionCartAdd(payload, +goodCountInput.value))
asideDesriptionPriceCard.append(goodButtonAddToCart)
let description = document.createElement('div')
description.classList.add('description')
description.innerText = payload.description
asideDesriptionPriceCard.append(description)
}
if (status === 'REJECTED') {
main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: blablatest123@gmail.com`
}
})
const actionOneGoodWithDescriptionAndImages = (_id) => actionPromise("OneGoodWithDescriptionAndImages", gqlOneGoodWithDescriptionAndImages(_id))
store.subscribe(() => {
let result = 0
let arrResult = Object.values(store.getState().cart)
for (let { count } of arrResult) {
result += count
}
cartIcon.innerText = result
})
store.subscribe(() => {
let arrResult = Object.values(store.getState().cart)
const [, route, _id] = location.hash.split('/')
if (arrResult && route === "cart") {
cartPageAdd()
}
})
window.onhashchange = () => {
const [, route, _id] = location.hash.split('/')
const routes = {
category() {
store.dispatch(actionCategoryGoodsAndSubCategoryGoods(_id))
},
good() {
store.dispatch(actionOneGoodWithDescriptionAndImages(_id))
// тут был store.dispatch goodById
console.log('good', _id)
},
// login() {
// console.log('А ТУТ ЩА ДОЛЖНА БЫТЬ ФОРМА ЛОГИНА')
// //нарисовать форму логина, которая по нажатию кнопки Login делает store.dispatch(actionFullLogin(login, password))
// },
// register() {
// //нарисовать форму регистрации, которая по нажатию кнопки Login делает store.dispatch(actionFullRegister(login, password))
// },
cart() {
cartPageAdd()
},
orders() {
store.dispatch(actionOrderFind())
}
}
if (route in routes) {
routes[route]()
}
}
function cartPageAdd() {
let arrResult = Object.values(store.getState().cart)
const [, route, _id] = location.hash.split('/')
if (arrResult && route === "cart") {
main.innerHTML = ""
let h1 = document.createElement('h1')
h1.innerText = "Оформление заказа"
main.append(h1)
let orderTable = document.createElement('table')
main.append(orderTable)
orderTable.classList.add('table_price')
let orderTableBody = document.createElement('tbody')
orderTable.append(orderTableBody)
let firstTr = document.createElement('tr')
orderTableBody.append(firstTr)
firstTr.innerHTML = ` | Название товара | Цена шт. | Количество | Итого | | `
let counter = 1
let summ = 0
for (let { good, count } of arrResult) {
console.log(count)
let trGood = document.createElement('tr')
orderTableBody.append(trGood)
trGood.innerHTML = `
${counter} |
${good.name} |
${good.price} | `
let tdInput = document.createElement('td')
trGood.append(tdInput)
let inputCount = document.createElement('input')
inputCount.type = 'number'
inputCount.min = 1
inputCount.value = count
inputCount.oninput = () => store.dispatch(actionCartSet(good, +inputCount.value))
tdInput.append(inputCount)
let tdSummGood = document.createElement('td')
trGood.append(tdSummGood)
tdSummGood.innerText = count * good.price
let tdDelete = document.createElement('td')
trGood.append(tdDelete)
let deleteButton = document.createElement('button')
tdDelete.append(deleteButton)
deleteButton.classList.add('deleteButton')
deleteButton.innerText = 'удалить'
deleteButton.onclick = () => store.dispatch(actionCartDel(good))
//НЕ РАБОТАЕТ!? trGood.innerHTML += `${count * good.price} | `
counter += 1
summ += count * good.price
}
let trSummTotal = document.createElement('tr')
orderTableBody.append(trSummTotal)
let tdColspan = document.createElement('td')
trSummTotal.append(tdColspan)
tdColspan.colSpan = 4
let tdSummTotal = document.createElement('td')
trSummTotal.append(tdSummTotal)
tdSummTotal.innerText = summ +'грн'
tdSummTotal.classList.add('tdSumm')
let tdDeleteTotal = document.createElement('td')
trSummTotal.append(tdDeleteTotal)
let DeleteTotalButton = document.createElement('button')
tdDeleteTotal.append(DeleteTotalButton)
DeleteTotalButton.innerText = 'ОЧИСТИТЬ КОРЗИНУ'
DeleteTotalButton.onclick = () => store.dispatch(actionCartClear())
//orderTableBody.innerHTML += ` | ${summ} грн |
`
let addOrder = document.createElement('div')
addOrder.classList.add('addOrder')
addOrder.innerText = "ОФОРМИТЬ ЗАКАЗ"
main.append(addOrder)
let arrGoods = Object.values(store.getState().cart).map(({ count, good: { _id } }) => { return { count, good: { _id } } })
addOrder.onclick = () => {
store.dispatch(actionFullAddOrder(arrGoods))
}
}
}
const actionAddOrder = (arrGoods) => {
return actionPromise("orderUpsert", OrderUpsert2(arrGoods))
}
const actionFullAddOrder = (arrGoods) =>
async dispatch => {
await dispatch(actionAddOrder(arrGoods))
dispatch(actionCartClear())
location.hash = '#/orders'
}
const actionLogin = (login, password) => {
return actionPromise("logAndPass", gqllogin(login, password))
}
const actionRegistration = (login, password) => {
return actionPromise("newUser", gqlUserAdd(login, password))
}
const actionFullLogin = (login, password) =>
async dispatch => {
//dispatch возвращает то, что вернул thunk, возвращаемый actionLogin, а там промис,
//так как actionPromise возвращает асинхронную функцию
const token = await dispatch(actionLogin(login, password))
//проверьте что token - строка и отдайте его в actionAuthLogin
if (typeof token === 'string')
store.dispatch(actionAuthLogin(token))
}
const actionFullRegistration = (login, password) =>
async dispatch => {
const userAddPromis = await dispatch(actionRegistration(login, password))
if (userAddPromis) store.dispatch(actionFullLogin(login, password))
//dispatch возвращает то, что вернул thunk, возвращаемый actionLogin, а там промис,
//так как actionPromise возвращает асинхронную функцию
//const token = await dispatch(actionLogin(login, password))
//проверьте что token - строка и отдайте его в actionAuthLogin
//if (typeof token === 'string')
// store.dispatch(actionAuthLogin(token))
}
const actionOrderFind = () =>
actionPromise("OrderFind", gqlOrderFind())
function LoginFormFunc(parent, passOpenDefault = open) {
function Password(parent, open) {
const inputPass = document.createElement('input')
parent.append(inputPass)
const checkboxPass = document.createElement('input')
checkboxPass.type = 'checkbox'
parent.append(checkboxPass)
this.setValue = (value) => {
inputPass.value = value
if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
} //задает значение
this.getValue = () => inputPass.value //читает значение
this.setOpen = (open) => {
if (open) {
checkboxPass.checked = true
inputPass.type = "text"
}
if (!open) {
checkboxPass.checked = false
inputPass.type = "password"
}
if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
} //задает открытость текста в поле ввода
this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода
this.setOpen(open)
inputPass.oninput = () => this.setValue(this.getValue())
checkboxPass.oninput = () => this.setOpen(this.getOpen())
}
const LoginForm = document.createElement('div')
parent.append(LoginForm)
const inputLogin = document.createElement('input')
LoginForm.append(inputLogin)
let p = new Password(LoginForm, passOpenDefault)
const inputButton = document.createElement('input')
inputButton.type = 'button'
inputButton.value = 'войти'
inputButton.id = 'signIn'
LoginForm.append(inputButton)
inputButton.disabled = true
const newUserAddButton = document.createElement('input')
newUserAddButton.type = 'button'
newUserAddButton.value = 'зарегистрироваться'
newUserAddButton.id = 'register'
LoginForm.append(newUserAddButton)
p.onChange = () => checkButtonDisabled()
inputLogin.oninput = () => checkButtonDisabled()
function checkButtonDisabled() {
if (p.getValue() && inputLogin.value) inputButton.disabled = false
else inputButton.disabled = true
}
this.getLogin = () => inputLogin.value
this.setLogin = (value) => {
inputLogin.value = value
checkButtonDisabled()
}
this.getPass = () => p.getValue()
this.setPass = (value) => {
p.setValue(value)
checkButtonDisabled()
}
inputButton.onclick = () => {
if (typeof this.inputButtonOnclick === 'function') this.inputButtonOnclick() //функция при нажатии на кнопку войти
}
newUserAddButton.onclick = () => {
if (typeof this.newUserAddButtonOnclick === 'function') this.newUserAddButtonOnclick()
}
}
// let LoginFormInHeader = new LoginFormFunc(user)
// LoginFormInHeader.inputButtonOnclick = function () {
// store.dispatch(actionFullLogin(this.getLogin(), this.getPass()))
// }
//vasya321986320915sf5654755ssddgfg пороль
store.subscribe(() => {
let result = store.getState().auth?.payload?.sub?.login
if (result) {
user.innerHTML = result
const buttonExitLogin = document.createElement('button')
buttonExitLogin.innerHTML = 'выйти'
buttonExitLogin.classList.add('buttonExitLogin')
buttonExitLogin.onclick = () => {
store.dispatch(actionAuthLogout())
}
user.append(buttonExitLogin)
localStorage.authToken = store.getState().auth.token
const buttonOrders = document.createElement('button')
buttonOrders.innerHTML = 'история заказов'
buttonOrders.classList.add('buttonOrders')
buttonOrders.onclick = () => location.hash = '#/orders'
user.append(buttonOrders)
} else {
delete localStorage.authToken
user.innerHTML = "Unknown User"
let LoginFormInHeader = new LoginFormFunc(user)
LoginFormInHeader.inputButtonOnclick = () => {
store.dispatch(actionFullLogin(this.getLogin(), this.getPass()))
}
LoginFormInHeader.newUserAddButtonOnclick = function () {
store.dispatch(actionFullRegistration(this.getLogin(), this.getPass()))
}
}
})
// store.subscribe(() => {
// let arrResult = store.getState().promise.OrderFind?.payload
// const [, route, _id] = location.hash.split('/')
// if (arrResult && route === "orders") {
// main.innerHTML = ""
// let h1 = document.createElement('h1')
// h1.innerText = "История заказов"
// main.append(h1)
// let orderTable = document.createElement('table')
// main.append(orderTable)
// orderTable.classList.add('table_price')
// let firstTr = document.createElement('tr')
// orderTable.append(firstTr)
// firstTr.innerHTML = ` | Номер заказа | Дата | Сумма, грн | `
// let counter = 1
// let summ = 0
// for (let { _id, createdAt, total } of arrResult) {
// let createdAtFormat = new Date(+createdAt)
// let year = createdAtFormat.getFullYear()
// let month = createdAtFormat.getMonth() < 9 ? "0" + (createdAtFormat.getMonth() + 1) : createdAtFormat.getMonth() + 1
// let day = createdAtFormat.getDate() < 9 ? "0" + (createdAtFormat.getDate() + 1) : createdAtFormat.getDate() + 1
// let hours = createdAtFormat.getHours() < 10 ? "0" + (createdAtFormat.getHours()) : createdAtFormat.getHours()
// let minutes = createdAtFormat.getMinutes() < 10 ? "0" + (createdAtFormat.getMinutes()) : createdAtFormat.getMinutes()
// const createdAtForTable = `${year}.${month}.${day} ${hours}:${minutes} `
// orderTable.innerHTML += `
// ${counter} |
// ${_id} |
// ${createdAtForTable} |
// ${total} |
//
`
// counter += 1
// summ += total
// }
// orderTable.innerHTML += ` | ${summ} грн |
`
// }
// })
function ordersToHTML (payload) {
main.innerHTML = ""
let h1 = document.createElement('h1')
h1.innerText = "История заказов"
main.append(h1)
let orderTable = document.createElement('table')
main.append(orderTable)
orderTable.classList.add('table_price')
let orderTableBody = document.createElement('tbody')
orderTable.append(orderTableBody)
let firstTr = document.createElement('tr')
orderTableBody.append(firstTr)
firstTr.innerHTML = ` | Номер заказа | Дата | Сумма, грн | `
let counter = 1
let summ = 0
let arrRevers = [...payload]
for (let { _id, createdAt, total } of arrRevers.reverse()) {
let createdAtFormat = new Date(+createdAt)
let year = createdAtFormat.getFullYear()
let month = createdAtFormat.getMonth() < 9 ? "0" + (createdAtFormat.getMonth() + 1) : createdAtFormat.getMonth() + 1
let day = createdAtFormat.getDate() < 10 ? "0" + (createdAtFormat.getDate()) : createdAtFormat.getDate()
let hours = createdAtFormat.getHours() < 10 ? "0" + (createdAtFormat.getHours()) : createdAtFormat.getHours()
let minutes = createdAtFormat.getMinutes() < 10 ? "0" + (createdAtFormat.getMinutes()) : createdAtFormat.getMinutes()
const createdAtForTable = `${year}.${month}.${day} ${hours}:${minutes} `
orderTableBody.innerHTML += `
${counter} |
${_id} |
${createdAtForTable} |
${total} |
`
counter += 1
summ += total
}
orderTableBody.innerHTML += ` | ${summ} грн |
`
}
store.subscribe(() => {
const [, route, _id] = location.hash.split('/')
if (route !== "orders") return
const {status, payload, error} = store.getState().promise.OrderFind
if (status === 'PENDING') {
main.innerHTML = ``
}
if (status === 'FULFILLED' && payload) {
ordersToHTML (payload)
}
if (status === 'REJECTED') {
main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: blablatest123@gmail.com`
}
})