index.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. function createStore(reducer) {
  2. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  3. let cbs = [] //массив подписчиков
  4. const getState = () => state //функция, возвращающая переменную из замыкания
  5. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  6. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  7. const dispatch = action => {
  8. if (typeof action === 'function') { //если action - не объект, а функция
  9. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  10. }
  11. const newState = reducer(state, action) //пробуем запустить редьюсер
  12. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  13. state = newState //если смог, то обновляем state
  14. for (let cb of cbs) cb() //и запускаем подписчиков
  15. }
  16. }
  17. return {
  18. getState, //добавление функции getState в результирующий объект
  19. dispatch,
  20. subscribe //добавление subscribe в объект
  21. }
  22. }
  23. function promiseReducer(state = {}, { type, name, status, payload, error }) {
  24. if (type === 'PROMISE') {
  25. return {
  26. ...state,
  27. [name]: { status, payload, error }
  28. }
  29. }
  30. return state
  31. }
  32. const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
  33. const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
  34. const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
  35. const actionPromise = (name, promise) =>
  36. async dispatch => {
  37. dispatch(actionPending(name))
  38. try {
  39. let payload = await promise
  40. dispatch(actionResolved(name, payload))
  41. return payload
  42. }
  43. catch (error) {
  44. dispatch(actionRejected(name, error))
  45. }
  46. }
  47. const getGQL = url =>
  48. (query, variables = {}) =>
  49. fetch(url, {
  50. method: 'POST',
  51. headers: {
  52. "Content-Type": "application/json",
  53. ...(localStorage.authToken ? { "Authorization": "Bearer " + localStorage.authToken } : {})
  54. },
  55. body: JSON.stringify({ query, variables })
  56. })
  57. .then(res => res.json())
  58. .then(data => {
  59. if (data.errors && !data.data)
  60. throw new Error(JSON.stringify(data.errors))
  61. return data.data[Object.keys(data.data)[0]]
  62. })
  63. const backURL = 'http://shop-roles.asmer.fs.a-level.com.ua'
  64. const gql = getGQL(`${backURL}/graphql`)
  65. const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  66. function jwtDecode(token) {
  67. try {
  68. let decoded = token.split('.')
  69. decoded = decoded[1]
  70. decoded = atob(decoded)
  71. decoded = JSON.parse(decoded)
  72. return decoded
  73. } catch (e) {
  74. return;
  75. }
  76. }
  77. function authReducer(state, { type, token }) {
  78. if (!state) {
  79. if (!localStorage.authToken) {
  80. console.log('NO-TOKEN')
  81. return {}
  82. } else {
  83. type = 'AUTH_LOGIN'
  84. token = localStorage.authToken
  85. }
  86. }
  87. if (type === 'AUTH_LOGIN') {
  88. console.log('AUTH-LOGIN')
  89. let decoded = jwtDecode(token)
  90. if (decoded) {
  91. localStorage.authToken = token
  92. return { token, payload: decoded }
  93. }
  94. }
  95. if (type === 'AUTH_LOGOUT') {
  96. console.log('AUTH-LOGOUT')
  97. localStorage.removeItem('authToken')
  98. return {}
  99. }
  100. return state
  101. }
  102. function combineReducers(reducers) {
  103. return (state = {}, action) => {
  104. const newState = {}
  105. for (const [reducerName, reducer] of Object.entries(reducers)) {
  106. let newSubState = reducer(state[reducerName], action)
  107. if (newSubState !== state[reducerName]) {
  108. newState[reducerName] = newSubState
  109. }
  110. }
  111. if (Object.keys(newState).length !== 0) {
  112. return { ...state, ...newState }
  113. }
  114. return state
  115. }
  116. }
  117. const combinedReducer = combineReducers({ promise: promiseReducer, auth: authReducer, cart: cartReducer })
  118. const store = createStore(combinedReducer)
  119. const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
  120. const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
  121. console.log(store.getState()) //стартовое состояние может быть с токеном
  122. store.subscribe(() => console.log(store.getState()))
  123. const actionLogin = (login, password) =>
  124. actionPromise('login', gql(`
  125. query log($login:String, $password:String) {
  126. login(login: $login, password: $password)
  127. }`, { login, password }))
  128. const actionFullLogin = (login, password) =>
  129. async dispatch => {
  130. let token = await dispatch(actionLogin(login, password))
  131. if (token) {
  132. dispatch(actionAuthLogin(token))
  133. }
  134. }
  135. const actionGetOrders = () =>
  136. actionPromise('orders', gql(`
  137. query ord {
  138. OrderFind(query:"[{}]"){
  139. _id
  140. orderGoods {
  141. price
  142. count
  143. total
  144. good{
  145. name
  146. _id
  147. images {
  148. url
  149. }
  150. }
  151. }
  152. }
  153. }
  154. `))
  155. const actionCreateOrder = (count, id) =>
  156. actionPromise('createOrder', gql(`
  157. mutation createOrder($count:Int!, $id:ID) {
  158. OrderUpsert( order:{ orderGoods: [ {count: $count, good:{_id: $id}} ] } ) {
  159. _id
  160. total
  161. orderGoods {
  162. good { _id name }
  163. }
  164. }
  165. }
  166. `, {count, id}))
  167. const actionRegister = (login, password) =>
  168. actionPromise('registration', gql(`
  169. mutation register($login:String, $password:String) {
  170. UserUpsert(
  171. user: {
  172. login: $login,
  173. password: $password,
  174. }){
  175. login _id
  176. }
  177. }
  178. `, { login, password }))
  179. let logBtn = document.getElementById('logBtn')
  180. function cartReducer(state = {}, { type, good = {}, count = 1 }) {
  181. let { _id } = good
  182. console.log('_id from state',_id)
  183. const types = {
  184. CART_ADD() {
  185. return {
  186. ...state,
  187. [_id]: { good, count: (state[_id]?.count || 0) + count }
  188. }
  189. },
  190. CART_REMOVE() {
  191. let newState = {}
  192. for(let key in state) {
  193. if(key !== _id) {
  194. newState[key] = state[key]
  195. }
  196. }
  197. return newState
  198. },
  199. CART_CHANGE() {
  200. return {
  201. ...state,
  202. [_id]: { good, count }
  203. }
  204. },
  205. CART_CLEAR() {
  206. return {}
  207. },
  208. }
  209. if (type in types)
  210. return types[type]()
  211. return state
  212. }
  213. const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', good, count })
  214. const actionCartDel = (good) => ({ type: 'CART_REMOVE', good})
  215. const actionCartClear = () => ({type: 'CART_CLEAR'})
  216. const actionCartChange = (good, count) => ({type: 'CART_CHANGE', good, count})
  217. const actionRootCats = () =>
  218. actionPromise('rootCats', gql(`query {
  219. CategoryFind(query: "[{\\"parent\\":null}]"){
  220. _id name
  221. }
  222. }`))
  223. const actionCatById = (_id) => //добавить подкатегории
  224. actionPromise('catById', gql(`query catById($q: String){
  225. CategoryFindOne(query: $q){
  226. _id
  227. name
  228. subCategories {
  229. _id name
  230. }
  231. goods {
  232. _id name price images {
  233. url
  234. }
  235. }
  236. }
  237. }`, { q: JSON.stringify([{ _id }]) }))
  238. store.dispatch(actionRootCats())
  239. const actionGoodById = (_id) =>
  240. actionPromise('goodById', gql(`
  241. query goodById ($good:String) {
  242. GoodFindOne(query: $good) {
  243. name
  244. description
  245. price
  246. categories {
  247. name
  248. }
  249. images {
  250. url
  251. }
  252. }
  253. }`, { good: JSON.stringify([{ _id }]) }))
  254. store.subscribe(() => {
  255. const { rootCats } = store.getState().promise
  256. if (rootCats?.payload) {
  257. aside.innerHTML = ''
  258. for (const { _id, name } of rootCats?.payload) {
  259. const link = document.createElement('a')
  260. link.href = `#/category/${_id}`
  261. link.innerText = name
  262. aside.append(link)
  263. }
  264. }
  265. })
  266. window.onhashchange = () => {
  267. const [, route, _id] = location.hash.split('/')
  268. const routes = {
  269. category() {
  270. store.dispatch(actionCatById(_id))
  271. },
  272. good() {
  273. store.dispatch(actionGoodById(_id))
  274. },
  275. registration() {
  276. let navBar = document.getElementById('navBar')
  277. navBar.style.visibility = 'hidden'
  278. let pass, log
  279. aside.innerHTML = ''
  280. main.innerHTML = `
  281. <div style="border: 5px solid purple; padding: 10px; background-color: black;">
  282. <button id="returnBtnReg" style="font-size: small;">&#8656 назад</button>
  283. <input id="logInp" style="font-size: small; display:block; margin:10px" type="text" placeholder="Логин"/>
  284. <input id="passInp" style="font-size: small; display:block; margin:10px" type="password" placeholder="Пароль"/>
  285. <small id="errBox" style="display: block; width:fit-content; color: red; margin: 0 auto;"></small>
  286. <button id="registerBtn" style="font-size: small; display:block; margin:0 auto">РЕГИСТРАЦИЯ</button>
  287. </div>
  288. `
  289. let returnBtn = document.getElementById('returnBtnReg')
  290. let logInp = document.getElementById('logInp')
  291. let passInp = document.getElementById('passInp')
  292. let registerBtn = document.getElementById('registerBtn')
  293. let errBox = document.getElementById('errBox')
  294. passInp.oninput = (e) => { pass = e.target.value }
  295. logInp.oninput = (e) => { log = e.target.value }
  296. returnBtn.onclick = () => {
  297. navBar.style.visibility = 'visible'
  298. history.back()
  299. }
  300. registerBtn.onclick = () => {
  301. console.log('login clicked')
  302. if (log && pass) {
  303. (async () => {
  304. await store.dispatch(actionRegister(log, pass))
  305. aside.innerHTML = ``
  306. if (store.getState().promise.registration.payload) {
  307. errBox.innerText = ''
  308. main.innerHTML = `
  309. <h2>Пользователь под логином '${store.getState().promise.registration.payload.login} успешно зарегистрирован!'<h2>
  310. <button id="returnBtn">&#8656 Вернуться к просмотру</button>
  311. <span>&nbsp или &nbsp</span>
  312. <button id="returnBtn">
  313. <a href="#/login" style="text-decoration: none; color: black;">Авторизоваться</a>
  314. </button>
  315. `
  316. let retBtn = document.getElementById('returnBtn')
  317. retBtn.onclick = () => {
  318. navBar.style.visibility = 'visible'
  319. location.href = "#/category"
  320. }
  321. } else {
  322. errBox.innerText = 'Пользователь с таким логином уже существует'
  323. }
  324. })();
  325. }
  326. }
  327. },
  328. login() {
  329. let navBar = document.getElementById('navBar')
  330. navBar.style.visibility = 'hidden'
  331. let pass, log
  332. console.log('login')
  333. aside.innerHTML = ''
  334. main.innerHTML = `
  335. <div style="border: 5px solid purple; padding: 10px; background-color: black;">
  336. <button id="returnBtnLogin" style="font-size: small;">&#8656 назад</button>
  337. <input id="logInp" style="font-size: small; display:block; margin:10px" type="text" placeholder="Логин"/>
  338. <input id="passInp" style="font-size: small; display:block; margin:10px" type="password" placeholder="Пароль"/>
  339. <small id="errBox" style="display: block; width:fit-content; color: red; margin: 0 auto;"></small>
  340. <button id="submitBtn" style="font-size: small; display:block; margin:0 auto">ВОЙТИ</button>
  341. </div>
  342. `
  343. let returnBtn = document.getElementById('returnBtnLogin')
  344. let logInp = document.getElementById('logInp')
  345. let passInp = document.getElementById('passInp')
  346. let submitBtn = document.getElementById('submitBtn')
  347. let errBox = document.getElementById('errBox')
  348. passInp.oninput = (e) => { pass = e.target.value }
  349. logInp.oninput = (e) => { log = e.target.value }
  350. returnBtn.onclick = () => {
  351. navBar.style.visibility = 'visible'
  352. history.back()
  353. }
  354. submitBtn.onclick = () => {
  355. if (log && pass) {
  356. (async () => {
  357. await store.dispatch(actionFullLogin(log, pass))
  358. aside.innerHTML = ``
  359. if (store.getState().auth.payload) {
  360. errBox.innerText = ''
  361. store.dispatch(actionGetOrders())
  362. } else {
  363. errBox.innerText = 'Неправильный логин или пароль'
  364. }
  365. })();
  366. }
  367. }
  368. },
  369. cart() {
  370. aside.innerHTML = ''
  371. main.innerHTML = `
  372. <button onclick="history.back()" style="font-size: smaller;">&#8656 назад</button>
  373. <h2>Корзина</h2>
  374. <h4>Общая цена заказов: <span id="fullPrice"></span></h4>
  375. <button id="clearCartBtn" style="background-color: firebrick; color: white; font-size: smaller;">Очистить корзину</button>
  376. <button id="orderAll" style="font-size: small;">Заказать все</button>
  377. <br>
  378. <div id="cartContent"></div>
  379. `
  380. let cartContent = document.getElementById('cartContent')
  381. let orderAllBtn = document.getElementById('orderAll')
  382. if(localStorage.authToken) {
  383. orderAllBtn.disabled = false
  384. orderAllBtn.style.backgroundColor = "mediumseagreen"
  385. orderAllBtn.style.color = 'white'
  386. } else {
  387. orderAllBtn.disabled = true
  388. orderAllBtn.style.backgroundColor = "grey"
  389. orderAllBtn.style.color = 'whitesmoke'
  390. }
  391. orderAllBtn.onclick = () => {
  392. console.log('orderAll clicked');
  393. (async () => {
  394. let cart = store.getState().cart
  395. await store.dispatch(actionCartClear())
  396. for(let item in cart) {
  397. await store.dispatch(actionCreateOrder(cart[item].count, cart[item].good._id))
  398. drawCart()
  399. }
  400. await store.dispatch(actionGetOrders())
  401. aside.innerHTML = ''
  402. })()
  403. }
  404. let clearCartBtn = document.getElementById('clearCartBtn')
  405. clearCartBtn.onclick = () => {
  406. (async () => {
  407. await store.dispatch(actionCartClear())
  408. drawCart()
  409. })()
  410. }
  411. function drawCart() {
  412. let fullPrice = 0
  413. let cart = store.getState().cart
  414. cartContent.innerHTML = ``
  415. if(Object.keys(cart).length > 0) {
  416. for (let item in cart) {
  417. let orderPrice = cart[item].good.price * cart[item].count
  418. fullPrice += orderPrice
  419. let delOrderBtn = document.createElement('button')
  420. delOrderBtn.style.backgroundColor = "firebrick"
  421. delOrderBtn.style.color = "white"
  422. delOrderBtn.style.fontSize = "smaller"
  423. delOrderBtn.style.float = "right"
  424. delOrderBtn.innerText = "Удалить заказ [x]"
  425. delOrderBtn.onclick = () => {
  426. (async () => {
  427. await store.dispatch(actionCartDel(cart[item].good))
  428. drawCart()
  429. })()
  430. }
  431. let card = document.createElement('div')
  432. card.append(delOrderBtn)
  433. card.insertAdjacentHTML('beforeend', `
  434. <br>
  435. <h2>${cart[item].good.name}</h2>
  436. <div style="
  437. border:5px solid mediumvioletred;
  438. background-color: black;
  439. color: white;
  440. padding: 10px 5px;"
  441. >
  442. <h4>Кол-во: <button class="decBtn">-</button> ${cart[item].count} <button class="addBtn">+</button></h4>
  443. <h4>Стоимость заказа: <span style="color: gold">${orderPrice}</span></h4>
  444. <button class="makeOrderBtn" ${localStorage.authToken? 'style="background-color: mediumseagreen; color: white;"' : 'disabled'}>
  445. ${localStorage.authToken? 'Заказать' : 'Только авторизованные пользователи могут совершать заказы'}
  446. </button>
  447. </div>
  448. <br>
  449. <img style="border: 1px dashed grey;" src="${backURL}/${cart[item].good.images[0].url}" />
  450. <br>
  451. <strong>Цена за ед. товара: ${cart[item].good.price}</strong>
  452. <br>
  453. <a href="#/good/${cart[item].good._id}">На страницу товара</a>
  454. <br>
  455. `)
  456. card.style.backgroundColor = "whitesmoke"
  457. card.style.border = "1px solid black"
  458. card.style.margin = "10px"
  459. card.style.padding = "10px"
  460. card.querySelector('.decBtn').disabled = (cart[item].count <= 1)
  461. card.querySelector('.decBtn').onclick = () => {
  462. (async() => {
  463. await store.dispatch(actionCartChange(cart[item].good, cart[item].count-1))
  464. drawCart()
  465. })()
  466. }
  467. card.querySelector('.addBtn').onclick = () => {
  468. (async() => {
  469. await store.dispatch(actionCartChange(cart[item].good, cart[item].count+1))
  470. drawCart()
  471. })()
  472. }
  473. card.querySelector('.makeOrderBtn').onclick = () => {
  474. (async() => {
  475. await store.dispatch(actionCreateOrder(cart[item].count, cart[item].good._id))
  476. await store.dispatch(actionCartDel(cart[item].good))
  477. await store.dispatch(actionGetOrders())
  478. drawCart()
  479. })()
  480. }
  481. cartContent.append(card)
  482. }
  483. }
  484. aside.innerHTML = ``
  485. let fullPriceSpan = document.getElementById('fullPrice')
  486. fullPriceSpan.innerText = `${fullPrice}`
  487. }
  488. drawCart()
  489. },
  490. orders() {
  491. aside.innerHTML = ''
  492. main.innerHTML = `
  493. <button onclick="history.back()" style="font-size: smaller;">&#8656 назад</button>
  494. <h2>Список заказов ${store.getState().auth.payload.sub.login}</h2>
  495. <br>
  496. `
  497. let container = document.createElement('div')
  498. main.append(container)
  499. if (store.getState().promise.orders) {
  500. const payload = store.getState().promise.orders.payload
  501. if (payload.length > 0) {
  502. for (let { orderGoods } of payload) {
  503. for (let item of orderGoods) {
  504. try {
  505. let card = document.createElement('div')
  506. card.insertAdjacentHTML('beforeend', `
  507. <br>
  508. <h2>${item.good.name}</h2>
  509. <div style="border:5px solid mediumvioletred; background-color: black; color: white; padding: 0px 5px;">
  510. <h4>Кол-во: ${item.count}</h4>
  511. <h4>Стоимость заказа: ${item.total}</h4>
  512. </div>
  513. <br>
  514. <img style="border: 1px dashed grey;" src="${backURL}/${item.good.images[0].url}" />
  515. <br>
  516. <strong>Цена за ед. товара: ${item.price}</strong>
  517. <br>
  518. <a href="#/good/${item.good._id}">На страницу товара</a>
  519. <br>
  520. `)
  521. card.style.backgroundColor = "whitesmoke"
  522. card.style.border = "1px solid black"
  523. card.style.margin = "10px"
  524. card.style.padding = "10px"
  525. container.prepend(card)
  526. } catch (e) {
  527. console.log('nulls are ignored')
  528. }
  529. }
  530. }
  531. }
  532. }
  533. }
  534. }
  535. if (route in routes)
  536. routes[route]()
  537. }
  538. window.onhashchange()
  539. //drawing goood list of cathegory
  540. store.subscribe(() => {
  541. const { catById } = store.getState().promise
  542. const [, route, _id] = location.hash.split('/')
  543. if (catById?.payload && route === 'category') {
  544. const { name, subCategories } = catById.payload
  545. main.innerHTML = `<h1>${name}</h1>`
  546. if (subCategories) {
  547. console.log('here', subCategories)
  548. let subCats = document.createElement('div')
  549. for (let item of subCategories) {
  550. let link = document.createElement('a')
  551. link.innerHTML = `${item.name} &#9166`
  552. link.href = `#/category/${item._id}`
  553. link.style.margin = '5px'
  554. link.style.display = 'inline-block'
  555. link.style.padding = '5px'
  556. link.style.backgroundColor = 'black'
  557. link.style.color = 'white'
  558. subCats.append(link)
  559. }
  560. main.append(subCats)
  561. }
  562. main.style.padding = "10px"
  563. if (catById.payload.goods) {
  564. for (const good of catById.payload.goods) {
  565. const card = document.createElement('div')
  566. card.innerHTML = `
  567. <h2>${good.name}</h2>
  568. <img style="border: 1px dashed grey;" src="${backURL}/${good.images[0].url}" />
  569. <br>
  570. <strong>Price: ${good.price}</strong>
  571. <br>
  572. <a href="#/good/${good._id}">На страницу товара</a>
  573. <br>
  574. `
  575. card.style.backgroundColor = "whitesmoke"
  576. card.style.border = "1px solid black"
  577. card.style.margin = "10px"
  578. card.style.padding = "10px"
  579. main.append(card)
  580. let cartButton = document.createElement('button')
  581. cartButton.innerText = 'Добавить в корзину'
  582. cartButton.style.fontSize = 'smaller'
  583. cartButton.style.marginTop = '10px'
  584. cartButton.style.backgroundColor = 'gold'
  585. card.append(cartButton)
  586. cartButton.onclick = () => {
  587. store.dispatch(actionCartAdd(good))
  588. }
  589. }
  590. }
  591. }
  592. })
  593. //item page
  594. store.subscribe(() => {
  595. const { goodById } = store.getState().promise
  596. const [, route, _id] = location.hash.split('/')
  597. if (goodById?.payload && route === 'good') {
  598. const { name, categories, images, price, description } = goodById.payload
  599. main.innerHTML = `
  600. <div class="card">
  601. <button onclick="history.back()" style="font-size: smaller;">&#8656 назад</button>
  602. <h1>${name}</h1>
  603. <h4>${categories[0].name}<h4>
  604. <br>
  605. <img style="border: 1px dashed grey;" src="${backURL}/${images[0].url}" />
  606. <br>
  607. <strong>Price: ${price}</strong>
  608. <p>${description}</p>
  609. </div>
  610. `
  611. main.style.padding = "10px"
  612. }
  613. })
  614. //cntrol over login
  615. store.subscribe(() => {
  616. const { payload } = store.getState().auth
  617. const [, route, _id] = location.hash.split('/')
  618. let logBtn = document.getElementById('logBtn')
  619. let logLink = document.getElementById('logLink')
  620. let regLink = document.createElement('a')
  621. let nameField = document.getElementById('nameField')
  622. let navBar = document.getElementById('navBar')
  623. if (!payload) {
  624. nameField.innerText = ''
  625. logBtn.style.backgroundColor = 'mediumaquamarine'
  626. logLink.innerText = 'Войти'
  627. logBtn.onclick = () => {/*killing onclick login action*/ }
  628. if (!document.getElementById('regLink')) {
  629. regLink.className = 'linkDeco'
  630. regLink.innerText = 'Регистрация'
  631. regLink.href = `#/registration`
  632. regLink.style.backgroundColor = 'mediumvioletred'
  633. regLink.id = 'regLink'
  634. logBtn.after(regLink)
  635. }
  636. try {
  637. let orderBtn = document.getElementById('orderBtn')
  638. navBar.removeChild(orderBtn)
  639. } catch (e) { }
  640. } else if (payload && route === 'login') {
  641. aside.innerHTML = ``
  642. main.innerHTML = `
  643. <h2>Вы успешно вошли под логином пользователя '${payload.sub.login}'<h2>
  644. <button id="returnBtn">&#8656 Вернуться к просмотру</button>
  645. `
  646. let retBtn = document.getElementById('returnBtn')
  647. retBtn.onclick = () => {
  648. navBar.style.visibility = 'visible'
  649. location.href = "#/category/5dc49f4d5df9d670df48cc64"
  650. }
  651. } else {
  652. nameField.innerText = payload.sub.login
  653. logBtn.style.backgroundColor = 'firebrick'
  654. logBtn.innerHTML = 'Выйти'
  655. try {
  656. let _regLink = document.getElementById('regLink')
  657. _regLink.parentElement.removeChild(_regLink)
  658. } catch (e) { }
  659. if (!document.getElementById('orderBtn')) {
  660. let orderBtn = document.createElement('a')
  661. orderBtn.href = '#/orders'
  662. orderBtn.id = 'orderBtn'
  663. orderBtn.innerText = 'список заказов'
  664. orderBtn.className = 'linkDeco'
  665. navBar.append(orderBtn)
  666. }
  667. logBtn.onclick = () => {
  668. nameField.innerText = ''
  669. logBtn.style.backgroundColor = 'mediumaquamarine'
  670. logBtn.innerHTML = `<a href="#/login" style="color: white; text-decoration: none;" id="logLink">Войти</a>`
  671. store.dispatch(actionAuthLogout())
  672. store.dispatch(actionGetOrders())
  673. }
  674. }
  675. })
  676. //count cart items
  677. store.subscribe(() => {
  678. const { cart } = store.getState()
  679. let items = 0
  680. for (let item in cart) {
  681. items += cart[item].count
  682. }
  683. let itemCount = document.getElementById('itemCount')
  684. itemCount.innerText = items
  685. })
  686. window.onload = () => {
  687. location.href = "#/category/5dc49f4d5df9d670df48cc64"
  688. store.dispatch(actionGetOrders())
  689. }