main.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. function createStore(reducer){
  2. let state = reducer(undefined, {})
  3. let cbs = []
  4. function dispatch(action){
  5. if (typeof action === 'function'){
  6. return action(dispatch)
  7. }
  8. const newState = reducer(state, action)
  9. if (state !== newState){
  10. state = newState
  11. cbs.forEach(cb => cb())
  12. }
  13. }
  14. return {
  15. dispatch,
  16. subscribe(cb){
  17. cbs.push(cb)
  18. return () => cbs = cbs.filter(c => c !== cb)
  19. },
  20. getState(){
  21. return state
  22. }
  23. }
  24. }
  25. function promiseReducer(state={}, {type, status, payload, error, name}){
  26. if (type === 'PROMISE'){
  27. return {
  28. ...state,
  29. [name]:{status, payload, error}
  30. }
  31. }
  32. return state
  33. }
  34. //под товаром сделать кнопку "купить"
  35. const actionPending = name => ({type: 'PROMISE', status: 'PENDING', name})
  36. const actionResolved = (name, payload) => ({type: 'PROMISE', status: 'RESOLVED', name, payload})
  37. const actionRejected = (name, error) => ({type: 'PROMISE', status: 'REJECTED', name, error})
  38. const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  39. const actionPromise = (name, promise) =>
  40. async dispatch => {
  41. dispatch(actionPending(name))
  42. try{
  43. let payload = await promise
  44. dispatch(actionResolved(name, payload))
  45. return payload
  46. }
  47. catch(error){
  48. dispatch(actionRejected(name, error))
  49. }
  50. }
  51. function cartReducer(state={},{type , count = 1, _id , name , price }) {
  52. if(type === 'CART_ADD'){
  53. return {
  54. ...state ,
  55. [_id]:{count:(state[_id]?.count || 0) + count, name , price}
  56. }
  57. }
  58. if (type === 'CART_CHANGE' ) {
  59. return {
  60. ...state,
  61. [_id]:{count:state[count] = count,price}
  62. }
  63. }
  64. if(type === 'CART_REMOVE'){
  65. let {[_id]:id , ...res} = state
  66. return res
  67. }
  68. if (type === "CART_CLEAR"){
  69. return {}
  70. }
  71. return state
  72. }
  73. // store.dispatch({type: 'CART_ADD', _id:id, count:num})
  74. // store.dispatch({type: 'CART_CHANGE', _id:id, count:count})
  75. // store.dispatch({type: 'CART_REMOVE', _id:id})
  76. // store.dispatch({type: 'CART_CLEAR'})
  77. let reducers = {
  78. promise:promiseReducer,
  79. cart:cartReducer,
  80. auth:authReducer
  81. }
  82. function combineReducers(reducers){
  83. function commonReducer(state = {} , action){
  84. let commonState = {}
  85. for(let reducerName in reducers){
  86. const reducerState = reducers[reducerName](state[reducerName],action)
  87. if (reducerState !== state[reducerName]){
  88. commonState[reducerName] = reducerState
  89. }
  90. }
  91. if (Object.keys(commonState).length == 0){
  92. return state
  93. }
  94. return {...state,...commonState}
  95. }
  96. return commonReducer
  97. }
  98. const store = createStore(combineReducers(reducers))
  99. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  100. // store.dispatch({type: 'CART_ADD', _id:'beer', count:2})
  101. const getGQL = url =>
  102. (query, variables={}) => fetch(url, {
  103. method: 'POST',
  104. headers: {
  105. // Accept: "application/json",
  106. "Content-Type": "application/json",
  107. ...(localStorage.authToken ? {Authorization: "Bearer " + localStorage.authToken} : {})
  108. },
  109. body: JSON.stringify({query, variables})
  110. }).then(res => res.json())
  111. let shopGQL = getGQL('http://shop-roles.asmer.fs.a-level.com.ua/graphql')
  112. function authReducer(state, action){ //....
  113. if (state === undefined){
  114. if (!localStorage.authToken){
  115. return {}
  116. }
  117. action.token = localStorage.authToken
  118. action.type = 'LOGIN'
  119. // добавить в action token из localStorage, и проимитировать LOGIN
  120. }
  121. if (action.type === 'LOGIN'){
  122. console.log('ЛОГИН')
  123. localStorage.authToken = action.token
  124. function jwt_decode (token) {
  125. var start64Url = token.split('.')[1]
  126. return JSON.parse(atob(start64Url))
  127. }
  128. return {token: action.token, payload: jwt_decode(action.token)}
  129. }
  130. if (action.type === 'LOGOUT'){
  131. console.log('ЛОГАУТ')
  132. localStorage.removeItem("authToken")
  133. //вернуть пустой объект
  134. return {}
  135. }
  136. return state
  137. }
  138. const actionAuthLogin = token => ({type:'LOGIN', token})
  139. const actionAuthLogout = () => ({type:'LOGOUT'})
  140. let reg = async(login,password) => {
  141. let query = `mutation reg($l:String , $p:String) {
  142. UserUpsert(user:{
  143. login:$l ,
  144. password:$p
  145. }){
  146. _id
  147. }
  148. }`
  149. let qVariables = {
  150. "l": login,
  151. "p": password
  152. }
  153. let result = await shopGQL(query,qVariables)
  154. return result
  155. }
  156. let log = async(login , password) => {
  157. let query = ` query log($l:String , $p:String){
  158. login(login:$l, password:$p)
  159. }`
  160. let qVariables = {
  161. "l": login,
  162. "p": password
  163. }
  164. let result = await shopGQL(query,qVariables)
  165. return result
  166. }
  167. actionRegister = (login,password) => async dispatch => {
  168. return await dispatch (actionPromise('register' , reg(login,password)))
  169. }
  170. const goodById = id => {
  171. let query = `query goodById($query:String) {
  172. GoodFindOne(query: $query ) {
  173. _id
  174. name
  175. description
  176. price
  177. images {
  178. url
  179. }
  180. }
  181. }`
  182. let variables = {
  183. query: JSON.stringify([{_id: id}])
  184. }
  185. let res = shopGQL(query,variables)
  186. return res
  187. }
  188. const actionGoodById = id =>
  189. actionPromise('goodById', goodById(id))
  190. const actionRootCategories = () =>
  191. actionPromise('rootCategories', shopGQL(`
  192. query cats($query:String){
  193. CategoryFind(query:$query){
  194. _id name
  195. }
  196. }
  197. `, {query: JSON.stringify([{parent:null}])}))
  198. const actionCategoryById = (_id) =>
  199. actionPromise('catById', shopGQL(`query catById($query:String){
  200. CategoryFindOne(query:$query){
  201. _id name goods{
  202. _id name price description images{
  203. url
  204. }
  205. }
  206. }
  207. }`, {query: JSON.stringify([{_id}])}))
  208. store.dispatch(actionRootCategories())
  209. actionCartAdd = (id , num=1, name, price) =>
  210. ({type: 'CART_ADD', _id:id, count:num,name , price})
  211. actionCartChange = (id,count,price) =>
  212. ({type: 'CART_CHANGE', _id:id, count,price})
  213. actionCartRemove = (id) =>
  214. ({type: 'CART_REMOVE', _id:id})
  215. actionCartClear = () =>
  216. ({type: 'CART_CLEAR'})
  217. window.onhashchange = () => {
  218. let {1: route, 2:id} = location.hash.split('/')
  219. if (route === 'categories'){
  220. main.innerHTML = ''
  221. store.dispatch(actionCategoryById(id))
  222. }
  223. if (route === 'good'){
  224. main.innerHTML = ''
  225. store.dispatch(actionGoodById(id))
  226. }
  227. if (route === 'cart'){
  228. drawCart()
  229. }
  230. if (route === 'registration'){
  231. drawReg()
  232. }
  233. if (route === 'login'){
  234. drawLog()
  235. }
  236. // if (route === 'cabinet') {
  237. // console.log('aaaa')
  238. // }
  239. }
  240. function drawMainMenu(){
  241. let cats = store.getState().promise.rootCategories.payload
  242. if (cats){ //каждый раз дорисовываются в body
  243. aside.innerText = ''
  244. for (let {_id, name} of cats.data.CategoryFind){
  245. let catA = document.createElement('a')
  246. catA.href = `#/categories/${_id}`
  247. catA.innerText = name
  248. aside.style.marginLeft = '20px'
  249. aside.append(catA)
  250. }
  251. }
  252. }
  253. store.subscribe(drawMainMenu)
  254. let aBasket = document.createElement('a')
  255. aBasket.href = "#/cart/"
  256. aBasket.style.color = '#008B8B'
  257. let imgBasket = document.createElement('img')
  258. imgBasket.style.float = 'right'
  259. let header = document.getElementById('header')
  260. header.style.height = '70px'
  261. let countBasket = document.createElement('p')
  262. let h1 = document.getElementById('h1')
  263. h1.style.float = 'left'
  264. h1.style.marginTop = '30px'
  265. countBasket.style.float = 'right'
  266. countBasket.style.marginLeft = '20px'
  267. countBasket.style.marginRight = '20px'
  268. countBasket.style.marginTop = '20px'
  269. countBasket.style.fontWeight = 'bold'
  270. countBasket.innerHTML = "Товаров в корзине:" + " " + 0
  271. imgBasket.src = "basket.png"
  272. imgBasket.style.width = '50px'
  273. imgBasket.style.marginLeft = '30px'
  274. aBasket.append(countBasket)
  275. aBasket.append(imgBasket)
  276. header.append(aBasket)
  277. const unsubscribe1 = store.subscribe(() => {
  278. let cartState = store.getState().cart
  279. var result = []
  280. for (key in cartState){
  281. result.push(cartState[key].count)
  282. if (result.length > 0) {
  283. countBasket.innerHTML ="Товаров в корзине:" + " " + result.reduce(function(a,b){
  284. return a+b
  285. })
  286. }
  287. else {
  288. countBasket.innerHTML ="Товаров в корзине:" + " " + 0
  289. }
  290. }
  291. })
  292. let aRegBtn = document.createElement('a')
  293.   let regBtn = document.createElement('button')
  294. let aLogBtn = document.createElement('a')
  295. let logBtn = document.createElement('button')
  296. aLogBtn.href = '#/login'
  297. logBtn.innerHTML = 'Вход'
  298. aRegBtn.style.marginTop = '30px'
  299. aLogBtn.style.marginTop = '30px'
  300. aLogBtn.style.marginLeft = '10px'
  301. aRegBtn.href = '#/registration'
  302. regBtn.innerHTML = "Регистрация"
  303. aRegBtn.style.float = 'right'
  304. aLogBtn.style.float = 'right'
  305. aLogBtn.append(logBtn)
  306. header.append(aLogBtn)
  307. aRegBtn.append(regBtn)
  308. header.append(aRegBtn)
  309. let aCabinet = document.createElement('a')
  310. aCabinet.href = '#/cabinet'
  311. function drawReg() {
  312. main.innerHTML = ""
  313. let h = document.createElement('h1')
  314. h.innerHTML = 'Регистрация'
  315. main.append(h)
  316. function Password (parent , open) {
  317. let passwordInput = document.createElement ('input')
  318. let passwordCheckbox = document.createElement('input')
  319. let passwordSpan = document.createElement('span')
  320. let passwordContent = document.createElement('div')
  321. parent.append(passwordContent)
  322. passwordContent.append(passwordInput)
  323. passwordContent.append(passwordCheckbox)
  324. passwordContent.append(passwordSpan)
  325. passwordContent.style.marginTop = "15px"
  326. passwordContent.style.marginBottom = '20px'
  327. passwordInput.placeholder = "Enter a password"
  328. passwordCheckbox.type = 'checkbox'
  329. passwordCheckbox.style.marginLeft = '10px'
  330. passwordSpan.innerHTML = "Hide password"
  331. passwordSpan.style.marginLeft = "10px"
  332. passwordInput.onchange = () => {
  333. if(typeof this.onChange === 'function'){
  334. this.onChange(passwordInput.value)
  335. }
  336. }
  337. function showOrHide() {
  338. if (passwordCheckbox.checked) {
  339. passwordInput.setAttribute('type' , 'password')
  340. } else {
  341. passwordInput.setAttribute('type','text')
  342. }
  343. }
  344. passwordCheckbox.addEventListener('change' , showOrHide)
  345. this.setValue = function (text) {
  346. passwordInput.value = text
  347. }
  348. this.getValue = function () {
  349. return passwordInput.value
  350. }
  351. this.setOpen = function (checker) {
  352. showOrHide.call(this)
  353. passwordCheckbox.checked = checker
  354. }
  355. passwordCheckbox.onclick = () => {
  356. showOrHide()
  357. this.onOpenChange("нажали чекбокс")
  358. }
  359. this.getOpen = function () {
  360. return passwordCheckbox.checked
  361. }
  362. }
  363. function LoginFormConstructor (parent , open) {
  364. let passwordForm = document.createElement('div')
  365. let loginForm = document.createElement('div')
  366. let btnForm = document.createElement('div')
  367. let loginInput = document.createElement('input')
  368. loginInput.type = 'text'
  369. loginInput.style.marginBottom = '10px'
  370. loginInput.placeholder = "Enter a login"
  371. let passwordInput = document.createElement('input')
  372. passwordInput.type = 'password'
  373. passwordInput.placeholder = "Enter a password"
  374. let checkbox = document.createElement('input')
  375. checkbox.type = 'checkbox'
  376. checkbox.style.marginLeft = '7px'
  377. let btn = document.createElement('button')
  378. btn.style.marginLeft = '130px'
  379. btn.style.marginTop = '10px'
  380. btn.innerHTML = 'Log in'
  381. parent.append(loginForm)
  382. parent.append(passwordForm)
  383. parent.append(btnForm)
  384. loginForm.append(loginInput)
  385. passwordForm.append(passwordInput)
  386. passwordForm.append(checkbox)
  387. btnForm.append(btn)
  388. btn.onclick = () => {
  389. store.dispatch(actionFullRegister((loginInput.value), (passwordInput.value)))
  390. }
  391. function showOrHide() {
  392. if (checkbox.checked) {
  393. passwordInput.setAttribute('type' , 'text')
  394. } else {
  395. passwordInput.setAttribute('type','password')
  396. }
  397. }
  398. checkbox.addEventListener('change' , showOrHide)
  399. }
  400. let lfc = new LoginFormConstructor(main, true)
  401. }
  402. function drawLog() {
  403. main.innerHTML = ""
  404. let h = document.createElement('h1')
  405. h.innerHTML = 'Вход'
  406. main.append(h)
  407. function Password (parent , open) {
  408. let passwordInput = document.createElement ('input')
  409. let passwordCheckbox = document.createElement('input')
  410. let passwordSpan = document.createElement('span')
  411. let passwordContent = document.createElement('div')
  412. parent.append(passwordContent)
  413. passwordContent.append(passwordInput)
  414. passwordContent.append(passwordCheckbox)
  415. passwordContent.append(passwordSpan)
  416. passwordContent.style.marginTop = "15px"
  417. passwordContent.style.marginBottom = '20px'
  418. passwordInput.placeholder = "Enter a password"
  419. passwordCheckbox.type = 'checkbox'
  420. passwordCheckbox.style.marginLeft = '10px'
  421. passwordSpan.innerHTML = "Hide password"
  422. passwordSpan.style.marginLeft = "10px"
  423. passwordInput.onchange = () => {
  424. if(typeof this.onChange === 'function'){
  425. this.onChange(passwordInput.value)
  426. }
  427. }
  428. function showOrHide() {
  429. if (passwordCheckbox.checked) {
  430. passwordInput.setAttribute('type' , 'password')
  431. } else {
  432. passwordInput.setAttribute('type','text')
  433. }
  434. }
  435. passwordCheckbox.addEventListener('change' , showOrHide)
  436. }
  437. function LoginFormConstructor (parent , open) {
  438. let passwordForm = document.createElement('div')
  439. let loginForm = document.createElement('div')
  440. let btnForm = document.createElement('div')
  441. let loginInput = document.createElement('input')
  442. loginInput.type = 'text'
  443. loginInput.style.marginBottom = '10px'
  444. loginInput.placeholder = "Enter a login"
  445. let passwordInput = document.createElement('input')
  446. passwordInput.type = 'password'
  447. passwordInput.placeholder = "Enter a password"
  448. let checkbox = document.createElement('input')
  449. checkbox.type = 'checkbox'
  450. checkbox.style.marginLeft = '7px'
  451. let btn = document.createElement('button')
  452. btn.style.marginLeft = '130px'
  453. btn.style.marginTop = '10px'
  454. btn.innerHTML = 'Log in'
  455. parent.append(loginForm)
  456. parent.append(passwordForm)
  457. parent.append(btnForm)
  458. loginForm.append(loginInput)
  459. passwordForm.append(passwordInput)
  460. passwordForm.append(checkbox)
  461. btnForm.append(btn)
  462. btn.onclick = () => {
  463. store.dispatch(actionFullLogin((loginInput.value),(passwordInput.value)))
  464. }
  465. function showOrHide() {
  466. if (checkbox.checked) {
  467. passwordInput.setAttribute('type' , 'text')
  468. } else {
  469. passwordInput.setAttribute('type','password')
  470. }
  471. }
  472. checkbox.addEventListener('change' , showOrHide)
  473. }
  474. let lfc = new LoginFormConstructor(main, true)
  475. }
  476. const actionFullLogin = (login , password) => async dispatch => {
  477. let result = await dispatch(actionPromise("login",log(login,password)))
  478. if (result.data.login !== null){
  479. dispatch(actionAuthLogin(result.data.login))
  480. logBtn.hidden = true
  481. regBtn.hidden = true
  482. main.innerHTML = ''
  483. let hLog = document.createElement('h1')
  484. hLog.innerHTML = "Вы успешно войшли в свой кабинет"
  485. hLog.style.textAlign = 'center'
  486. main.append(hLog)
  487. }
  488. else {
  489. alert ('Такого пользователя не существует или вы не правильно указали логин/пароль')
  490. }
  491. }
  492. actionFullRegister = (login,password) => async dispatch => {
  493. let result = await dispatch (actionRegister(login,password))
  494. console.log(result)
  495. if (result.errors === undefined) {
  496. await dispatch (actionFullLogin(login,password))
  497. logBtn.hidden = true
  498. regBtn.hidden = true
  499. main.innerHTML = ""
  500. let hReg = document.createElement('h1')
  501. hReg.innerHTML = "Вы успешно зарегестрированы"
  502. hReg.style.textAlign = 'center'
  503. main.append(hReg)
  504. }
  505. else {
  506. alert("Такой пользователь уже есть")
  507. }
  508. }
  509. if (localStorage.authToken) {
  510. regBtn.hidden = true
  511. logBtn.hidden = true
  512. }
  513. let newOrder = async(obj) => {
  514. let option = Object.entries(obj)
  515. let orderGoods = []
  516. for (let key of option) {
  517. let iteration = {
  518. "count": key[1].count,
  519. "good":{"_id":key[0]}
  520. }
  521. orderGoods.push(iteration)
  522. }
  523. let query = `mutation newOrder($order:OrderInput) {
  524. OrderUpsert(order:$order){
  525. _id
  526. }
  527. }`
  528. let qVariables = {
  529. "order": {
  530. "orderGoods": orderGoods}
  531. }
  532. let result = await shopGQL(query,qVariables)
  533. console.log(result)
  534. return result
  535. }
  536. actionOrder = (obj) => async dispatch => {
  537. return await dispatch (actionPromise ('order' , newOrder(obj)))
  538. }
  539. function drawCart () {
  540. const cart = store.getState().cart
  541. if (cart) {
  542. main.innerHTML = ""
  543. let cartState = store.getState().cart
  544. for (key in cartState){
  545. let good = document.createElement('div')
  546. let goodName = document.createElement('h4')
  547. let goodImg = document.createElement('img')
  548. let btnPlus = document.createElement('button')
  549. let btnMinus = document.createElement('button')
  550. let countPriceGood = document.createElement('p')
  551. let goodA = document.createElement('a')
  552. let goodPrice = document.createElement('p')
  553. let goodCount = document.createElement('p')
  554. let btnDel = document.createElement('button')
  555. let input = document.createElement('input')
  556. input.placeholder = "Нужное количество товара"
  557. input.style.marginLeft = '10px'
  558. let btnInput = document.createElement('button')
  559. btnInput.innerHTML = 'Подтвердить'
  560. btnInput.style.marginLeft = '10px'
  561. btnInput.onclick = () => {
  562. if (input.value > 1){
  563. store.dispatch(actionCartChange(key , +input.value,cartState[key].price))
  564. }
  565. }
  566. good.style.overflow = 'hidden'
  567. btnDel.style.float = 'right'
  568. goodImg.style.width = '100px'
  569. btnPlus.innerHTML = "+"
  570. btnPlus.style.marginLeft = '10px'
  571. btnPlus.onclick = () =>{
  572. store.dispatch(actionCartChange(key,+(cartState[key].count) + 1,cartState[key].price))
  573. }
  574. btnMinus.innerHTML = "-"
  575. btnMinus.onclick = () => {
  576. if (cartState[key].count > 1){
  577. store.dispatch(actionCartChange(key , +(cartState[key].count) - 1,cartState[key].price))
  578. }
  579. else {
  580. let question = confirm("Вы хотите удалить товар?")
  581. if (question){
  582. store.dispatch(actionCartRemove(key))
  583. countBasket.innerHTML ="Товаров в корзине:" + " " + 0
  584. }
  585. }
  586. }
  587. countPriceGood.style.fontWeight = 'bold'
  588. countPriceGood.hidden = true
  589. countPriceGood.style.marginTop = '20px'
  590. countPriceGood.style.textAlign = 'center'
  591. countPriceGood.style.float = 'right'
  592. btnDel.innerHTML = "Удалить товар"
  593. btnDel.onclick = () => {
  594. let question = confirm("Вы хотите удалить товар?")
  595. if (question){
  596. store.dispatch(actionCartRemove(key))
  597. }
  598. }
  599. goodA.append(goodImg)
  600. goodA.href = '#/good/' + key
  601. if (cartState[key].count > 1) {
  602. countPriceGood.removeAttribute('hidden' , 'hidden')
  603. goodById(key).then(res => countPriceGood.innerHTML = "Общая цена товара:" + " " + (cartState[key].count) * res.data.GoodFindOne.price + "uah")
  604. }
  605. good.style.width = "50%"
  606. good.style.border = '2px solid black'
  607. good.style.marginTop = '20px'
  608. good.style.padding = '30px'
  609. goodById(key).then(res=> goodName.innerHTML = res.data.GoodFindOne.name)
  610. goodById(key).then(res=> goodImg.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + res.data.GoodFindOne.images[0].url)
  611. goodById(key).then(res=>goodPrice.innerHTML = "Цена:" + " " + res.data.GoodFindOne.price + 'uah')
  612. goodCount.innerHTML = "Количество товара:" + " " + cartState[key].count
  613. goodById(key).then()
  614. good.style.marginLeft = '100px'
  615. good.append(goodName,goodA,goodPrice,goodCount,btnMinus,input,btnInput,btnPlus,btnDel)
  616. good.append(countPriceGood)
  617. var result = []
  618. result.push(cartState[key].count)
  619. var resId = []
  620. resId.push(cartState[key])
  621. let orderPrice = document.createElement("h5")
  622. orderPrice.style.float = 'right'
  623. main.append(good)
  624. main.append(orderPrice)
  625. }
  626. if (Object.keys(cartState).length > 0){
  627. let orderPrice = document.createElement('h5')
  628. let res = []
  629. for (good in cartState) {
  630. res.push((((cartState[good].price) * (cartState[good].count))))
  631. }
  632. orderPrice.innerHTML = "Цена заказа:" + " " + res.reduce(function(a,b){
  633. return a + b
  634. }) + 'uah'
  635. orderPrice.style.fontSize = '20px'
  636. orderPrice.style.float = 'right'
  637. orderPrice.style.marginRight = '500px'
  638. let btnBuy = document.createElement('button')
  639. btnBuy.innerHTML = 'Купить'
  640. btnBuy.style.float = 'right'
  641. btnBuy.style.marginRight = '500px'
  642. btnBuy.style.marginTop = '10px'
  643. btnBuy.onclick = () => {
  644. let obj = store.getState().cart
  645. for (key in obj){
  646. store.dispatch(actionOrder(obj))
  647. }
  648. store.dispatch({type: 'CART_CLEAR'})
  649. countBasket.innerHTML ="Товаров в корзине:" + " " + 0
  650. }
  651. main.append(orderPrice)
  652. main.append(btnBuy)
  653. }
  654. }
  655. }
  656. store.subscribe(() => {
  657. const {1: route, 2:id} = location.hash.split('/')
  658. if (route === 'categories'){
  659. const catById = store.getState().promise.catById?.payload
  660. if (catById){
  661. main.innerText = ''
  662. let h = document.createElement('h2')
  663. h.style.fontSize = '30px'
  664. h.style.marginTop = 0
  665. h.innerHTML = catById.data.CategoryFindOne.name
  666. h.style.textAlign = 'center'
  667. main.append(h)
  668. //вывести циклом товары со ссылками вида #/good/АЙДИШНИК
  669. let goods = document.createElement('div')
  670. goods.className = 'goods'
  671. for (let key in catById.data.CategoryFindOne.goods) {
  672. let box = document.createElement('div')
  673. box.style.border = '3px solid #008B8B'
  674. box.style.padding = '10px'
  675. box.style.margin = '20px'
  676. let img = document.createElement('img')
  677. let productName = document.createElement('h3')
  678. let a = document.createElement('a')
  679. let price = document.createElement('p')
  680. let description = document.createElement('p')
  681. let btnMore = document.createElement('button')
  682. btnMore.innerHTML = "Подробнее"
  683. btnMore.style.backgroundColor = '#DCDCDC'
  684. btnMore.style.display = 'block'
  685. btnMore.style.marginLeft = 'auto'
  686. btnMore.style.marginRight = 'auto'
  687. btnMore.style.marginTop = '20px'
  688. img.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + catById.data.CategoryFindOne.goods[key].images[0].url
  689. img.style.width = '300px'
  690. img.style.display = 'block'
  691. img.style.marginLeft = 'auto'
  692. img.style.marginRight = 'auto'
  693. a.href = '#/good/' + catById.data.CategoryFindOne.goods[key]._id
  694. productName.innerHTML = catById.data.CategoryFindOne.goods[key].name + '<br/>'
  695. price.innerHTML = "Цена:" + " " + catById.data.CategoryFindOne.goods[key].price + ' ' + 'uah'
  696. price.style.fontWeight = 'bold'
  697. a.style.textDecoration = 'none'
  698. a.style.color = 'black'
  699. description.innerHTML = catById.data.CategoryFindOne.goods[key].description
  700. description.style.textAlign = 'center'
  701. a.append(btnMore)
  702. box.append(productName)
  703. box.append(price)
  704. box.append(img)
  705. box.append(description)
  706. box.append(a)
  707. goods.append(box)
  708. }
  709. main.append(goods)
  710. //ПРИДУМАТЬ КНОПКИ ДОБАВЛЕНИЯ В КОРЗИНУ
  711. // main.innerHTML = `<pre>${JSON.stringify(catById, null ,4)}</pre>`
  712. }
  713. }
  714. if (route === 'good'){
  715. const goodById = store.getState().promise.goodById?.payload
  716. if (goodById){ //вывести в main страницу товара
  717. main.innerText = " "
  718. let source = goodById.data.GoodFindOne
  719. let product = document.createElement('div')
  720. let page = document.createElement('div')
  721. let h = document.createElement('h1')
  722. h.innerHTML = source.name
  723. h.style.textAlign = 'center'
  724. let img = document.createElement('img')
  725. img.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + source.images[0].url
  726. img.style.width = '300px'
  727. img.style.display = 'block'
  728. img.style.marginLeft = 'auto'
  729. img.style.marginRight = 'auto'
  730. let description = document.createElement('p')
  731. description.innerHTML = source.description
  732. description.style.textAlign = 'center'
  733. let price = document.createElement('p')
  734. price.innerHTML = 'Цена:' + " " + source.price + 'uah'
  735. price.textAlign = 'center'
  736. price.style.fontWeight = 'bold'
  737. let btnBuy = document.createElement('button')
  738. btnBuy.innerHTML = "Купить"
  739. btnBuy.style.backgroundColor = '#ADFF2F'
  740. btnBuy.style.display = 'block'
  741. btnBuy.style.marginLeft = 'auto'
  742. btnBuy.style.marginRight = 'auto'
  743. btnBuy.style.marginBottom = '10px'
  744. btnBuy.style.marginTop = '50px'
  745. btnBuy.style.width = '300px'
  746. btnBuy.style.fontSize = '20px'
  747. let btnAdd = document.createElement('button')
  748. btnAdd.innerHTML = "Добавить в корзину"
  749. btnAdd.style.backgroundColor = '#3CB371'
  750. btnAdd.style.display = 'block'
  751. btnAdd.style.marginLeft = 'auto'
  752. btnAdd.style.marginRight = 'auto'
  753. btnAdd.style.width = '300px'
  754. btnAdd.style.fontSize = '20px'
  755. btnAdd.onclick = () => {
  756. store.dispatch(actionCartAdd(source._id,1 , source.name , source.price))
  757. }
  758. page.append(h)
  759. page.append(img)
  760. page.append(description)
  761. page.append(price)
  762. page.append(btnBuy)
  763. page.append(btnAdd)
  764. product.append(page)
  765. main.append(product)
  766. // console.log(actionCartAdd.count)
  767. }
  768. }
  769. if (route === 'cart')
  770. drawCart()
  771. }
  772. )