main.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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. let unlogBtn = document.createElement('button')
  312. unlogBtn.style.marginTop = '20px'
  313. unlogBtn.style.float = 'right'
  314. unlogBtn.innerHTML = "Выйти"
  315. unlogBtn.style.marginLeft = '10px'
  316. unlogBtn.onclick = () => {
  317. let question = confirm ('Вы уверены что хотите выйти?')
  318. if (question) {
  319. store.dispatch(actionAuthLogout())
  320. location.reload()
  321. }
  322. }
  323. function drawReg() {
  324. main.innerHTML = ""
  325. let h = document.createElement('h1')
  326. h.innerHTML = 'Регистрация'
  327. main.append(h)
  328. function Password (parent , open) {
  329. let passwordInput = document.createElement ('input')
  330. let passwordCheckbox = document.createElement('input')
  331. let passwordSpan = document.createElement('span')
  332. let passwordContent = document.createElement('div')
  333. parent.append(passwordContent)
  334. passwordContent.append(passwordInput)
  335. passwordContent.append(passwordCheckbox)
  336. passwordContent.append(passwordSpan)
  337. passwordContent.style.marginTop = "15px"
  338. passwordContent.style.marginBottom = '20px'
  339. passwordInput.placeholder = "Enter a password"
  340. passwordCheckbox.type = 'checkbox'
  341. passwordCheckbox.style.marginLeft = '10px'
  342. passwordSpan.innerHTML = "Hide password"
  343. passwordSpan.style.marginLeft = "10px"
  344. passwordInput.onchange = () => {
  345. if(typeof this.onChange === 'function'){
  346. this.onChange(passwordInput.value)
  347. }
  348. }
  349. function showOrHide() {
  350. if (passwordCheckbox.checked) {
  351. passwordInput.setAttribute('type' , 'password')
  352. } else {
  353. passwordInput.setAttribute('type','text')
  354. }
  355. }
  356. passwordCheckbox.addEventListener('change' , showOrHide)
  357. this.setValue = function (text) {
  358. passwordInput.value = text
  359. }
  360. this.getValue = function () {
  361. return passwordInput.value
  362. }
  363. this.setOpen = function (checker) {
  364. showOrHide.call(this)
  365. passwordCheckbox.checked = checker
  366. }
  367. passwordCheckbox.onclick = () => {
  368. showOrHide()
  369. this.onOpenChange("нажали чекбокс")
  370. }
  371. this.getOpen = function () {
  372. return passwordCheckbox.checked
  373. }
  374. }
  375. function LoginFormConstructor (parent , open) {
  376. let passwordForm = document.createElement('div')
  377. let loginForm = document.createElement('div')
  378. let btnForm = document.createElement('div')
  379. let loginInput = document.createElement('input')
  380. loginInput.type = 'text'
  381. loginInput.style.marginBottom = '10px'
  382. loginInput.placeholder = "Enter a login"
  383. let passwordInput = document.createElement('input')
  384. passwordInput.type = 'password'
  385. passwordInput.placeholder = "Enter a password"
  386. let checkbox = document.createElement('input')
  387. checkbox.type = 'checkbox'
  388. checkbox.style.marginLeft = '7px'
  389. let btn = document.createElement('button')
  390. btn.style.marginLeft = '130px'
  391. btn.style.marginTop = '10px'
  392. btn.innerHTML = 'Log in'
  393. parent.append(loginForm)
  394. parent.append(passwordForm)
  395. parent.append(btnForm)
  396. loginForm.append(loginInput)
  397. passwordForm.append(passwordInput)
  398. passwordForm.append(checkbox)
  399. btnForm.append(btn)
  400. btn.onclick = () => {
  401. store.dispatch(actionFullRegister((loginInput.value), (passwordInput.value)))
  402. }
  403. function showOrHide() {
  404. if (checkbox.checked) {
  405. passwordInput.setAttribute('type' , 'text')
  406. } else {
  407. passwordInput.setAttribute('type','password')
  408. }
  409. }
  410. checkbox.addEventListener('change' , showOrHide)
  411. }
  412. let lfc = new LoginFormConstructor(main, true)
  413. }
  414. function drawLog() {
  415. main.innerHTML = ""
  416. let h = document.createElement('h1')
  417. h.innerHTML = 'Вход'
  418. main.append(h)
  419. function Password (parent , open) {
  420. let passwordInput = document.createElement ('input')
  421. let passwordCheckbox = document.createElement('input')
  422. let passwordSpan = document.createElement('span')
  423. let passwordContent = document.createElement('div')
  424. parent.append(passwordContent)
  425. passwordContent.append(passwordInput)
  426. passwordContent.append(passwordCheckbox)
  427. passwordContent.append(passwordSpan)
  428. passwordContent.style.marginTop = "15px"
  429. passwordContent.style.marginBottom = '20px'
  430. passwordInput.placeholder = "Enter a password"
  431. passwordCheckbox.type = 'checkbox'
  432. passwordCheckbox.style.marginLeft = '10px'
  433. passwordSpan.innerHTML = "Hide password"
  434. passwordSpan.style.marginLeft = "10px"
  435. passwordInput.onchange = () => {
  436. if(typeof this.onChange === 'function'){
  437. this.onChange(passwordInput.value)
  438. }
  439. }
  440. function showOrHide() {
  441. if (passwordCheckbox.checked) {
  442. passwordInput.setAttribute('type' , 'password')
  443. } else {
  444. passwordInput.setAttribute('type','text')
  445. }
  446. }
  447. passwordCheckbox.addEventListener('change' , showOrHide)
  448. }
  449. function LoginFormConstructor (parent , open) {
  450. let passwordForm = document.createElement('div')
  451. let loginForm = document.createElement('div')
  452. let btnForm = document.createElement('div')
  453. let loginInput = document.createElement('input')
  454. loginInput.type = 'text'
  455. loginInput.style.marginBottom = '10px'
  456. loginInput.placeholder = "Enter a login"
  457. let passwordInput = document.createElement('input')
  458. passwordInput.type = 'password'
  459. passwordInput.placeholder = "Enter a password"
  460. let checkbox = document.createElement('input')
  461. checkbox.type = 'checkbox'
  462. checkbox.style.marginLeft = '7px'
  463. let btn = document.createElement('button')
  464. btn.style.marginLeft = '130px'
  465. btn.style.marginTop = '10px'
  466. btn.innerHTML = 'Log in'
  467. parent.append(loginForm)
  468. parent.append(passwordForm)
  469. parent.append(btnForm)
  470. loginForm.append(loginInput)
  471. passwordForm.append(passwordInput)
  472. passwordForm.append(checkbox)
  473. btnForm.append(btn)
  474. btn.onclick = () => {
  475. store.dispatch(actionFullLogin((loginInput.value),(passwordInput.value)))
  476. }
  477. function showOrHide() {
  478. if (checkbox.checked) {
  479. passwordInput.setAttribute('type' , 'text')
  480. } else {
  481. passwordInput.setAttribute('type','password')
  482. }
  483. }
  484. checkbox.addEventListener('change' , showOrHide)
  485. }
  486. let lfc = new LoginFormConstructor(main, true)
  487. }
  488. const actionFullLogin = (login , password) => async dispatch => {
  489. let result = await dispatch(actionPromise("login",log(login,password)))
  490. if (result.data.login !== null){
  491. dispatch(actionAuthLogin(result.data.login))
  492. location.reload()
  493. }
  494. else {
  495. alert ('Такого пользователя не существует или вы не правильно указали логин/пароль')
  496. }
  497. }
  498. actionFullRegister = (login,password) => async dispatch => {
  499. let result = await dispatch (actionRegister(login,password))
  500. console.log(result)
  501. if (result.errors === undefined) {
  502. await dispatch (actionFullLogin(login,password))
  503. location.reload()
  504. }
  505. else {
  506. alert("Такой пользователь уже есть")
  507. }
  508. }
  509. let pLog = document.createElement('p')
  510. pLog.style.float = 'right'
  511. pLog.style.fontWeight = 'bold'
  512. pLog.style.marginTop = '20px'
  513. pLog.style.color = '#000080'
  514. if (localStorage.authToken) {
  515. regBtn.hidden = true
  516. logBtn.hidden = true
  517. header.append(unlogBtn)
  518. pLog.innerHTML = "Ваш логин:" + " " + store.getState().auth.payload.sub.login
  519. header.append(pLog)
  520. }
  521. let newOrder = async(obj) => {
  522. let option = Object.entries(obj)
  523. let orderGoods = []
  524. for (let key of option) {
  525. let iteration = {
  526. "count": key[1].count,
  527. "good":{"_id":key[0]}
  528. }
  529. orderGoods.push(iteration)
  530. }
  531. let query = `mutation newOrder($order:OrderInput) {
  532. OrderUpsert(order:$order){
  533. _id
  534. }
  535. }`
  536. let qVariables = {
  537. "order": {
  538. "orderGoods": orderGoods}
  539. }
  540. let result = await shopGQL(query,qVariables)
  541. return result
  542. }
  543. actionOrder = (obj) => async dispatch => {
  544. return await dispatch (actionPromise ('order' , newOrder(obj)))
  545. }
  546. function drawCart () {
  547. const cart = store.getState().cart
  548. if (cart) {
  549. main.innerHTML = ""
  550. let cartState = store.getState().cart
  551. for (key in cartState){
  552. let good = document.createElement('div')
  553. let goodName = document.createElement('h4')
  554. let goodImg = document.createElement('img')
  555. let btnPlus = document.createElement('button')
  556. let btnMinus = document.createElement('button')
  557. let countPriceGood = document.createElement('p')
  558. let goodA = document.createElement('a')
  559. let goodPrice = document.createElement('p')
  560. let goodCount = document.createElement('p')
  561. let btnDel = document.createElement('button')
  562. let input = document.createElement('input')
  563. input.placeholder = "Нужное количество товара"
  564. input.style.marginLeft = '10px'
  565. let btnInput = document.createElement('button')
  566. btnInput.innerHTML = 'Подтвердить'
  567. btnInput.style.marginLeft = '10px'
  568. btnInput.onclick = () => {
  569. if (input.value > 1){
  570. store.dispatch(actionCartChange(key , +input.value,cartState[key].price))
  571. }
  572. }
  573. good.style.overflow = 'hidden'
  574. btnDel.style.float = 'right'
  575. goodImg.style.width = '100px'
  576. btnPlus.innerHTML = "+"
  577. btnPlus.style.marginLeft = '10px'
  578. btnPlus.onclick = () =>{
  579. store.dispatch(actionCartChange(key,+(cartState[key].count) + 1,cartState[key].price))
  580. }
  581. btnMinus.innerHTML = "-"
  582. btnMinus.onclick = () => {
  583. if (cartState[key].count > 1){
  584. store.dispatch(actionCartChange(key , +(cartState[key].count) - 1,cartState[key].price))
  585. }
  586. else {
  587. let question = confirm("Вы хотите удалить товар?")
  588. if (question){
  589. store.dispatch(actionCartRemove(key))
  590. countBasket.innerHTML ="Товаров в корзине:" + " " + 0
  591. }
  592. }
  593. }
  594. countPriceGood.style.fontWeight = 'bold'
  595. countPriceGood.hidden = true
  596. countPriceGood.style.marginTop = '20px'
  597. countPriceGood.style.textAlign = 'center'
  598. countPriceGood.style.float = 'right'
  599. btnDel.innerHTML = "Удалить товар"
  600. btnDel.onclick = () => {
  601. let question = confirm("Вы хотите удалить товар?")
  602. if (question){
  603. store.dispatch(actionCartRemove(key))
  604. }
  605. }
  606. goodA.append(goodImg)
  607. goodA.href = '#/good/' + key
  608. if (cartState[key].count > 1) {
  609. countPriceGood.removeAttribute('hidden' , 'hidden')
  610. goodById(key).then(res => countPriceGood.innerHTML = "Общая цена товара:" + " " + (cartState[key].count) * res.data.GoodFindOne.price + "uah")
  611. }
  612. good.style.width = "50%"
  613. good.style.border = '2px solid black'
  614. good.style.marginTop = '20px'
  615. good.style.padding = '30px'
  616. goodById(key).then(res=> goodName.innerHTML = res.data.GoodFindOne.name)
  617. goodById(key).then(res=> goodImg.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + res.data.GoodFindOne.images[0].url)
  618. goodById(key).then(res=>goodPrice.innerHTML = "Цена:" + " " + res.data.GoodFindOne.price + 'uah')
  619. goodCount.innerHTML = "Количество товара:" + " " + cartState[key].count
  620. goodById(key).then()
  621. good.style.marginLeft = '100px'
  622. good.append(goodName,goodA,goodPrice,goodCount,btnMinus,input,btnInput,btnPlus,btnDel)
  623. good.append(countPriceGood)
  624. var result = []
  625. result.push(cartState[key].count)
  626. var resId = []
  627. resId.push(cartState[key])
  628. let orderPrice = document.createElement("h5")
  629. orderPrice.style.float = 'right'
  630. main.append(good)
  631. main.append(orderPrice)
  632. }
  633. if (Object.keys(cartState).length > 0){
  634. let orderPrice = document.createElement('h5')
  635. let res = []
  636. for (good in cartState) {
  637. res.push((((cartState[good].price) * (cartState[good].count))))
  638. }
  639. orderPrice.innerHTML = "Цена заказа:" + " " + res.reduce(function(a,b){
  640. return a + b
  641. }) + 'uah'
  642. orderPrice.style.fontSize = '20px'
  643. orderPrice.style.float = 'right'
  644. orderPrice.style.marginRight = '500px'
  645. let btnBuy = document.createElement('button')
  646. btnBuy.innerHTML = 'Купить'
  647. btnBuy.style.float = 'right'
  648. btnBuy.style.marginRight = '500px'
  649. btnBuy.style.marginTop = '10px'
  650. btnBuy.onclick = () => {
  651. if (!localStorage.authToken){
  652. alert('Для начала авторизуйтесь')
  653. location.href = '#/login'
  654. }
  655. else {
  656. let obj = store.getState().cart
  657. for (key in obj){
  658. store.dispatch(actionOrder(obj))
  659. }
  660. store.dispatch({type: 'CART_CLEAR'})
  661. countBasket.innerHTML ="Товаров в корзине:" + " " + 0
  662. }
  663. }
  664. main.append(orderPrice)
  665. main.append(btnBuy)
  666. }
  667. }
  668. }
  669. store.subscribe(() => {
  670. const {1: route, 2:id} = location.hash.split('/')
  671. if (route === 'categories'){
  672. const catById = store.getState().promise.catById?.payload
  673. if (catById){
  674. main.innerText = ''
  675. let h = document.createElement('h2')
  676. h.style.fontSize = '30px'
  677. h.style.marginTop = 0
  678. h.innerHTML = catById.data.CategoryFindOne.name
  679. h.style.textAlign = 'center'
  680. main.append(h)
  681. //вывести циклом товары со ссылками вида #/good/АЙДИШНИК
  682. let goods = document.createElement('div')
  683. goods.className = 'goods'
  684. for (let key in catById.data.CategoryFindOne.goods) {
  685. let box = document.createElement('div')
  686. box.style.border = '3px solid #008B8B'
  687. box.style.padding = '10px'
  688. box.style.margin = '20px'
  689. let img = document.createElement('img')
  690. let productName = document.createElement('h3')
  691. let a = document.createElement('a')
  692. let price = document.createElement('p')
  693. let description = document.createElement('p')
  694. let btnMore = document.createElement('button')
  695. btnMore.innerHTML = "Подробнее"
  696. btnMore.style.backgroundColor = '#DCDCDC'
  697. btnMore.style.display = 'block'
  698. btnMore.style.marginLeft = 'auto'
  699. btnMore.style.marginRight = 'auto'
  700. btnMore.style.marginTop = '20px'
  701. img.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + catById.data.CategoryFindOne.goods[key].images[0].url
  702. img.style.width = '300px'
  703. img.style.display = 'block'
  704. img.style.marginLeft = 'auto'
  705. img.style.marginRight = 'auto'
  706. a.href = '#/good/' + catById.data.CategoryFindOne.goods[key]._id
  707. productName.innerHTML = catById.data.CategoryFindOne.goods[key].name + '<br/>'
  708. price.innerHTML = "Цена:" + " " + catById.data.CategoryFindOne.goods[key].price + ' ' + 'uah'
  709. price.style.fontWeight = 'bold'
  710. a.style.textDecoration = 'none'
  711. a.style.color = 'black'
  712. description.innerHTML = catById.data.CategoryFindOne.goods[key].description
  713. description.style.textAlign = 'center'
  714. a.append(btnMore)
  715. box.append(productName)
  716. box.append(price)
  717. box.append(img)
  718. box.append(description)
  719. box.append(a)
  720. goods.append(box)
  721. }
  722. main.append(goods)
  723. //ПРИДУМАТЬ КНОПКИ ДОБАВЛЕНИЯ В КОРЗИНУ
  724. // main.innerHTML = `<pre>${JSON.stringify(catById, null ,4)}</pre>`
  725. }
  726. }
  727. if (route === 'good'){
  728. const goodById = store.getState().promise.goodById?.payload
  729. if (goodById){ //вывести в main страницу товара
  730. main.innerText = " "
  731. let source = goodById.data.GoodFindOne
  732. let product = document.createElement('div')
  733. let page = document.createElement('div')
  734. let h = document.createElement('h1')
  735. h.innerHTML = source.name
  736. h.style.textAlign = 'center'
  737. let img = document.createElement('img')
  738. img.src = 'http://shop-roles.asmer.fs.a-level.com.ua/' + source.images[0].url
  739. img.style.width = '300px'
  740. img.style.display = 'block'
  741. img.style.marginLeft = 'auto'
  742. img.style.marginRight = 'auto'
  743. let description = document.createElement('p')
  744. description.innerHTML = source.description
  745. description.style.textAlign = 'center'
  746. let price = document.createElement('p')
  747. price.innerHTML = 'Цена:' + " " + source.price + 'uah'
  748. price.textAlign = 'center'
  749. price.style.fontWeight = 'bold'
  750. let btnBuy = document.createElement('button')
  751. btnBuy.innerHTML = "Купить"
  752. btnBuy.style.backgroundColor = '#ADFF2F'
  753. btnBuy.style.display = 'block'
  754. btnBuy.style.marginLeft = 'auto'
  755. btnBuy.style.marginRight = 'auto'
  756. btnBuy.style.marginBottom = '10px'
  757. btnBuy.style.marginTop = '50px'
  758. btnBuy.style.width = '300px'
  759. btnBuy.style.fontSize = '20px'
  760. let btnAdd = document.createElement('button')
  761. btnAdd.innerHTML = "Добавить в корзину"
  762. btnAdd.style.backgroundColor = '#3CB371'
  763. btnAdd.style.display = 'block'
  764. btnAdd.style.marginLeft = 'auto'
  765. btnAdd.style.marginRight = 'auto'
  766. btnAdd.style.width = '300px'
  767. btnAdd.style.fontSize = '20px'
  768. btnAdd.onclick = () => {
  769. store.dispatch(actionCartAdd(source._id,1 , source.name , source.price))
  770. }
  771. page.append(h)
  772. page.append(img)
  773. page.append(description)
  774. page.append(price)
  775. page.append(btnBuy)
  776. page.append(btnAdd)
  777. product.append(page)
  778. main.append(product)
  779. // console.log(actionCartAdd.count)
  780. }
  781. }
  782. if (route === 'cart')
  783. drawCart()
  784. }
  785. )